Breaking
- Target-first install/update/uninstall commands —
nah install,nah update, andnah uninstallnow require an explicit target instead of defaulting to Claude Code. Usenah install claude,nah update claude, andnah uninstall claudefor direct Claude hooks; shell and provider targets use the same shape. Barenah installexits nonzero with a guided target list, and the old--agentlifecycle shape is no longer the documented product surface. (nah-882)
Added
- Human-friendly safety explanations — terminal guard prompts, Claude Code permission reasons,
nah test, and compactnah logoutput now show shortnah paused:/nah blocked:messages such as “this can rewrite Git history” while preserving the technicalreason, action type, hints, and JSON/log diagnostics alongside a newhuman_reasonfield. (nah-884) - Opt-in bash and zsh terminal guard — added
nah install bashandnah install zshto protect interactive shell sessions with managed rc-file snippets that classify complete single-line commands before execution. The guard supports status/doctor diagnostics, prompt-on-ask behavior, fail-closed handling for unsupported multiline/here-doc/continuation input, explicit bypass vianah-bypass <command>orNAH_TERMINAL_BYPASS=1, and terminal decision logging for blocks, denied asks, confirmed asks, bypasses, and errors while keeping allowed terminal commands out of the nah log by default. (nah-882) - Target-aware dry runs and config overrides — added
nah test --target <target>and--json, plus target-scoped config undertargets.<target>for runtime-specific policies. Bash and zsh targets default to LLM mode off even when a global provider is configured, unless explicitly enabled under their target override. (nah-882) - Codex native hook support — added
nah run codexfor local interactive Codex sessions using CodexPermissionRequesthooks instead of shell-wrapper prompts. The runner injects nah-owned hook, sandbox, approval, and dynamic-MCP-disabling overrides, rejects unsafe Codex launch modes, routes Bash and MCP permission requests through nah classification, and addsnah codex doctor/nah codex repairto block and repair remembered Codex approvals or MCP approval modes that could bypass nah. (nah-897, nah-898) - Guarded Codex edit auto-allow — added
nah run codex --auto-editsto auto-allow safe project-localapply_patchadd/update edits after nah path, content, and LLM checks, while default sessions still ask and dangerous patches remain blocked or ask-only. (nah-904) - Codex flow mode — added
nah run codex --flowas a shortcut for no Codex filesystem sandbox plus safeapply_patchauto-allow. Use--no-sandboxseparately when you want to remove the Codex sandbox without also auto-accepting edits. (nah-906) - MCP threat-model audit coverage — added
mcp_permissionstonah audit-threat-model, covering core MCP permission/runtime tests for Claude Code matcher registration, global-only MCP classification, wildcard safety, database/browser MCP action typing, Codex MCP PermissionRequest hooks, and Codex MCP approval-mode preflight/repair. README and public docs now report 1,807 category coverage hits across 13 tested danger classes. (nah-905) - OS keyring-backed LLM secrets — added
nah key set,nah key status,nah key import-env, andnah key rmfor storing optional LLM
provider keys outside the process environment. Keyring support remains an
optionalkeysextra, with env-var fallback for existing setups. Thanks
@ZhangJiaLong90524 for the initial PR and direction.
(#65, nah-889)
Changed
- License transition for future releases — future source snapshots and
releases are fair-source under FSL-1.1-MIT and convert to MIT two years after
they are made available. Versions and source snapshots made available under
MIT before this transition, includingv0.7.1and earlier tagged releases,
remain MIT. - Agent session launchers use
nah run— the one-shot Claude Code launcher
is nownah run claude, matchingnah run codex. Legacynah claudeexits
with a pointer to the new command. - README and public docs rebranded for coding agents — refreshed README, site install/CLI/privacy/how-it-works/getting-started docs, and package metadata around “Context aware safety guard for coding agents” instead of a Claude-only positioning, with the user terminal guard treated as an optional bonus. Updated examples to current
nah paused:/nah blocked:copy and documented Codex doctor/repair plusnah log --llm. (nah-899) - Terminal guard documented as opt-in shell protection — README, install docs, configuration docs, privacy copy, and lifecycle target help now describe bash/zsh terminal protection as opt-in per shell without preview labeling.
- Minimal taxonomy profile deprecated —
profile: minimalnow warns and behaves likeprofile: full, leavingfullandnoneas the two supported profile shapes. The old minimal classification data has been removed so custom classifiers are not evaluated against a weaker built-in baseline. - Install lifecycle targets stay runtime-only — removed the unreleased
nah install openrouter/nah uninstall openrouterconvenience path so lifecycle commands only install or remove nah from guarded runtimes (claude,bash,zsh). LLM providers remain configured through global config. (nah-882 follow-up) - Install docs now start with a chooser — README and site install docs now separate the Claude Code plugin, PyPI CLI/direct-hook, terminal guard, config extra, and LLM provider configuration more clearly, and stale setup examples now use explicit target-first lifecycle commands instead of bare
nah install. (nah-885)
Fixed
- Windows drive-letter paths route through trusted paths —
nah trust C:/Projectsandnah trust D:\worknow write totrusted_pathsinstead of
being mistaken for network hosts inknown_registries. Thanks @enermark.
(#69) - Sparse environments keep useful log user attribution — structured
decision logs now fall back fromUSERtoLOGNAME,USERNAME, and finally
getpass.getuser()before leaving the user field empty. - Codex flow edit approval race — safe
apply_patchedits innah run codex --flownow trust direct Codex patch payloads and retry the Codex transcript briefly when direct patch text is unavailable, fixing cases where the PermissionRequest hook fell back to the native edit prompt before nah could inspect the patch. (nah-907) - Quoted output text no longer becomes a fake redirect — Bash classification
now preserves>characters that appear inside quoted or backslash-escaped
printf/echotext before redirect decomposition, so prose such as
<key>or->no longer prompts as a filesystem write while real unquoted
redirects to sensitive paths still block. (nah-902) - Claude launcher rejects unsafe bypass modes —
nah run claudenow refuses
--dangerously-skip-permissions,--enable-auto-mode, and
--permission-mode bypassPermissionsbecause those modes can run tool calls
outside the guarded permission path. - Shell control-flow bodies are classified by payload —
for ...; do ...; done,while ...; do ...; done, andif ...; then ...; finow expose their executable inner commands to the classifier instead of stopping at reserved words likefor,do, anddone. Literalforitem lists are expanded into the loop body so safe batch GitHub/GitLab CLI API reads can allow while sensitive paths still block; dynamic loop values and control-flow body command substitutions fail closed. Tracks #78. - Unwrapped shell bodies mirror top-level variable expansion —
bash -c 'BAD=/etc/shadow; rm "$BAD"'and control-flow variants now apply the same intra-chain$VARexpansion used for top-level Bash commands, closing a sensitive-path bypass inside shell wrappers. - GitLab API form writes ask cleanly —
glab api --form ...now classifies asnetwork_write, including multipart file-upload forms, andgh/glabAPI prompt copy no longer mistakes field values such asfile=@image.pngfor network hosts. - Bash terminal ask denials clear the prompt line — denied ask decisions now cancel and return to an empty prompt instead of restoring the same command line and making the shell look stuck. (nah-882 follow-up)
- Terminal guard reload hint replaces active snippets —
nah install bash/nah update bashnow print a reload command that clears terminal guard environment and replaces the shell, so an already-running shell can load the updated guard without running startup files inside the old in-memory Readline hook. (nah-882 follow-up) - Bash terminal guard preserves normal prompt redraws — bash now filters the Readline buffer and lets Bash execute accepted commands normally, instead of running commands inside the Readline callback. Confirmed commands run through normal Bash execution, preserving shell state such as
cdandsource. (nah-882 follow-up) nah updateno longer looks like a project file write —nah install/nah updatenow classify as nah lifecycle commands instead of treating target names such asbashorupdateas filesystem paths like~/bashor~/updatewhen the terminal guard runs outside a Git project. (nah-882 follow-up)- Bash rc reloads replace the active guard — sourcing
.bashrcin an already-guarded bash shell now refreshes nah's active function and key bindings instead of skipping the snippet becauseNAH_TERMINAL_GUARD_ACTIVEwas already set. The original pre-nah binding metadata is still captured only once for diagnostics. (nah-882 follow-up) - Bash ask prompts use the hidden decision helper — bash ask decisions now prompt through
nah _terminal-decision --confirminstead of shellreadinside the Readline callback or a pendingy/ncommand line. This keeps normalRun anyway? [y/N]prompts responsive without leaking helper commands into the prompt or history. (nah-882 follow-up) - Bash ask confirmations read raw terminal keys — the hidden terminal prompt now reads a single
y,n, Enter, or Ctrl-C key so confirmation works while Bash Readline has the tty in raw mode. (nah-882 follow-up) - Bash accept-line newlines are normalized — the terminal guard now trims the single trailing newline that Bash Readline can pass to the hidden helper, so commands like
nah test '...' --jsonare classified normally instead of being mistaken for multiline input. (nah-882 follow-up) - LLM provider setup warnings stay out of guard prompts — missing LLM API keys no longer create noisy standalone stderr lines in terminal guard prompts or Codex permission hook output; expected provider/key misses are logged as quiet review metadata instead. (nah-897)