Skip to content

Custom Taxonomy

nah's classification is fully customizable. You can add commands to existing types, create new types, and control how the three-phase lookup works.

Adding commands to existing types

Use the classify config key to map command prefixes to action types:

# ~/.config/nah/config.yaml
classify:
  container_destructive:
    - "docker rm"
    - "docker system prune"
    - "kubectl delete"
  filesystem_delete:
    - "terraform destroy"
  db_write:
    - "psql -c DROP"
    - "mysql -e DROP"

Each entry is a prefix"docker rm" matches docker rm my-container, docker rm -f abc, etc.

CLI shortcut:

nah classify "docker rm" container_destructive
nah classify "terraform destroy" filesystem_delete

Creating custom action types

You can use any string as an action type — it doesn't have to be one of the 20 built-in types:

nah classify "terraform" infra_modify
nah deny infra_modify

nah will ask for confirmation since infra_modify is not a built-in type. Custom types default to ask policy.

Three-phase lookup

Understanding the lookup order is key to effective customization:

Phase 1: Global config (highest priority)

Your classify: entries in ~/.config/nah/config.yaml are checked first. They override everything — built-in tables and flag classifiers.

# Global config: this overrides the built-in curl flag classifier
classify:
  network_outbound:
    - curl    # all curl commands → network_outbound, even curl -X POST

Warning

A single-token global entry like curl will shadow the built-in flag classifier that distinguishes curl (read) from curl -X POST (write). Use nah status to see shadow warnings.

Phase 2: Flag classifiers (built-in)

Nine commands have flag-dependent classification (find, sed, awk, tar, git, curl, wget, httpie, global_install). These run after global config but before the built-in prefix tables.

Skipped entirely when profile: none.

Phase 3: Built-in + Project

Built-in prefix tables (from the selected profile) are checked, followed by project .nah.yaml entries.

Project entries are Phase 3 — they can add new commands but cannot override built-in classification for the same prefix.

Global vs project classify

Aspect Global Project
Phase 1 (first) 3 (last)
Can override built-in Yes No
Can override flag classifiers Yes No
Use case Personal preferences, org standards Project-specific commands
Security Trusted (your machine) Untrusted (supply-chain risk)

Example: project-specific rules

# .nah.yaml (in project root)
classify:
  db_write:
    - "psql -c ALTER"
    - "psql -c DROP"
  filesystem_delete:
    - "make clean"

actions:
  db_write: block    # tighten: block all DB writes in this project

Project config can tighten actions (escalate askblock) but cannot relax them.

Checking your rules

# See all custom rules with shadow warnings
nah status

# See all types with override annotations
nah types

# Test a specific command
nah test "docker rm my-container"

nah status shows shadow warnings when your global classify entries override finer-grained built-in rules or flag classifiers. Use nah forget <prefix> to remove a shadow.