nah nah

NAH(1) · CONCEPTS

Core concepts

Effects and coverage

nah lowers calls into typed invocation, filesystem, Git, network, and system-state effects. Observation resolves cwd, roots, paths, and environment.

full coverage preserves every guard-relevant visible input, without claiming to understand opaque programs. Unresolved arguments, code, or fields are partial.

Bash pipelines, control flow, subshells, and redirects become stages and data-flow edges. Unresolved shell state makes coverage partial.

Visible source stays a code-execution effect. Python and JavaScript/TypeScript use owned HIRs and bounded interpreters without execution. PowerShell and cmd use static tokenizers; IPython handles magics. TypeScript/TSX ignore reviewed type-only syntax, following JavaScript semantics without type-checking or the TypeScript compiler. Other languages use narrow detectors.

Profiles own only proven Node, Deno, Bun, OpenClaw QuickJS, or Prime current-cell APIs. Rebinding or visible mutation removes ownership; hidden state is unknown. Generic JavaScript owns none.

Exact child argv/cwd are nested; missing or non-directory cwd prevents the child. Unawaited JavaScript applies state only through its first await. Deno.Command reads options and cwd when consumed.

Only proven Bash lowers fully. sh is a portable subset; dialect-sensitive state and redirects stay partial. powershell, pwsh, and cmd share reviewed typed effects. Other syntax, custom shells, Bun's $, and bun exec stay partial; sinks vanish only after a proven throw.

Per source, the public ActionStream (custom guards, dry-run JSON, records) admits 64 modeled language calls; overflow makes coverage partial. Built-ins retain a separate 256-call, 4,096-flow projection to block later danger. Fail-closed records these bounds as language-call-limit or language-safety-limit analysis refusals. Command-like arguments to unknown programs trigger analysis refusal; reviewed subcommand programs are exempt if their first argument is a static verb that cannot run a command (no leading options).

Verdicts and failures

  • block — an active guard or structural self-protection found definite danger.
  • delegate — nothing blocked; the runtime keeps control.

Evaluation failure is diagnostic, not a third verdict. By default it adds no finding. --fail-closed blocks explicit failures/refusals, not ordinary uncertainty. See nah docs security.

nah never approves. Delegation returns control to the runtime's permission or execution behavior; nah is neither an approval UI nor a sandbox.

Guards

A guard blocks a narrow danger such as remote content flowing into execution, destructive Git, or sensitive-path access. Guards compose by union: any may block, and none may approve.

An activated custom guard answers block or abstain. Abstain is no finding, not approval. Failure or invalid output adds a typed failure only.

Definite evidence may block a partial stream; uncertainty alone never blocks.

Run nah docs guards for the catalog and tested examples.

Trust and activation

User guards require activation. Project guards require trust plus activation; nah does not read manifests before trust. Activation pins the manifest, executable, and data. Changed or missing bytes do not run and add a failure.

Before trust, .nah/project.toml may enable built-ins but cannot disable guards or execute code. Agents may edit inert proposals; a human performs trust and activation out of band. nah blocks understood intercepted attempts to cross that boundary or disable active wiring.

nah nap starts a 10-minute, user-global maintenance window: plain nap pauses self-protection; --all pauses every non-permanent layer. Nap-state protection remains. See nah docs configuration and nah docs security.

Audit records

Live decisions attempt a redacted audit append; failure does not change the verdict. Records name the runtime (unknown for nah decide). nah why <id> explains one; nah log lists recent decisions, --blocked lists blocks, and --json emits JSON Lines.