Skip to content

Add Claude Code slash commands for in-session rule management#77

Open
moyukhc wants to merge 350 commits into
manuelschipper:mainfrom
moyukhc:claude-commands
Open

Add Claude Code slash commands for in-session rule management#77
moyukhc wants to merge 350 commits into
manuelschipper:mainfrom
moyukhc:claude-commands

Conversation

@moyukhc
Copy link
Copy Markdown

@moyukhc moyukhc commented Apr 18, 2026

Summary

  • Ship four slash commands (/nah-classify, /nah-allow, /nah-status, /nah-log) as markdown files in src/nah/commands/, distributed with the package so users can manage nah rules without leaving Claude Code.
  • Extend nah install with --skills (and --force) to symlink the commands into ~/.claude/commands/.
  • Add site/guides/claude-commands.md and wire it into the mkdocs nav.

Test plan

  • pytest tests/ --ignore=tests/test_llm_live.py
  • nah install --skills creates symlinks into ~/.claude/commands/; rerun without --force is a no-op, --force overwrites
  • Each /nah-* command runs in Claude Code
  • mkdocs build succeeds with the new guide in nav

By submitting this pull request, I confirm that I have read and agree to the Contributor License Agreement.

manuelschipper and others added 30 commits March 17, 2026 09:02
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-redirect-write-classification

Classify shell redirects as filesystem writes with content inspection
…cking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The active_allow config option was underdocumented — README had a
one-liner with no example, and the site install page showed YAML
without explaining what active_allow does or why you'd use it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
db_write had full context-resolution machinery (db_targets, schema
matching) but defaulted to "ask", bypassing it entirely. Users who
configured db_targets still got prompted unless they also discovered
they needed actions: {db_write: context}.

Changed default to "context" — consistent with filesystem_write,
filesystem_delete, network_outbound, network_write. Unconfigured
users see no change (resolve_database_context returns ask when
db_targets is empty).

Also fixes stale README classify example (database_destructive →
realistic custom commands).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…allow-examples

Docs: add active_allow examples
…db-write-context-default

db_write default policy: ask → context (nah-10a)
…llow docs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Safe-list /dev/null, /dev/stderr, /dev/stdout, /dev/tty, /dev/fd/* in
_check_redirect so common patterns like 2>/dev/null no longer prompt.
Add redirect_target field to StageResult so the hint generator can
suggest nah trust <dir> instead of broad nah allow filesystem_write.
Guard against suggesting nah trust / for root paths. Add 389-case
hint correctness test battery (nah-gwm, nah-4tk, nah-2ig).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rectness-battery

Fix redirect hint correctness and add 389-case test battery
New tagline: "Safeguard your vibes. Keep your flow state."
Updated across README, site, mkdocs.yml, pyproject.toml, CLAUDE.md.

Added CLA.md, CONTRIBUTING.md, and PR template to support future
contributor licensing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Classify python/node/ruby/bash/perl/php script execution as lang_exec
via Phase 2 flag classifier. Change lang_exec default policy from ask
to context. Context resolution reads script files and runs content
inspection — clean scripts inside the project auto-allow, dangerous
patterns escalate to ask/block. LLM prompt enriched with script content
when the LLM fires.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix extension detection for basename-normalized paths (./script.py was
not caught because classify_tokens strips ./ via basename). Update hint
battery tests for reclassified script commands.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
~/.azure (ask), ~/.docker/config.json (ask),
~/.terraform.d/credentials.tfrc.json (ask), ~/.terraformrc (ask).

Based on autoresearch/hackathon commits b5a51e2 and 80c6185,
applied manually due to merge conflicts from C1 path changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Expand git global flag stripping to handle --no-pager, --bare,
--no-replace-objects, --literal-pathspecs and value-prefix forms.

Cherry-picked from autoresearch/hackathon (9bc89af).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add --config-env and --exec-path= support to git global flag stripping.
Validate config-env values, fail closed on malformed input.

Cherry-picked from autoresearch/hackathon (9c4d04a).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cherry-picked from autoresearch/hackathon (13d6d13).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cherry-picked from autoresearch/hackathon (7e93ee9).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Validate git -c key=value format. Stop stripping on malformed values
so classification fails closed instead of silently allowing.

Cherry-picked from autoresearch/hackathon (e6fa82e).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cherry-picked from autoresearch/hackathon (3565a91).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add --force-with-lease=, --delete/-d long-form, +refspec/:refspec for
push. Add ~/.config/gh to sensitive paths.

Cherry-picked from autoresearch/hackathon (90c2de6).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add _git_has_short_flag for detecting flags in combined clusters.
Refactor branch, push, and clean classifiers.

Cherry-picked from autoresearch/hackathon (deabee3).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Full tag classifier (force/delete/listing), --mirror/--prune for push,
_git_has_short_flag for push/add.

Cherry-picked from autoresearch/hackathon (0ee5715).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
creatbot-ai and others added 26 commits April 14, 2026 09:31
Add `_expand_intra_chain_vars` pre-classification pass that propagates
literal env assignments across `&&` / `||` / `;` chain stages and
expands `$NAME` / `${NAME}` in later consumer tokens. Bypass closure:
`BAD=/etc/shadow && cat "$BAD"` now classifies the same as direct
`cat /etc/shadow`. Handles both bare and `export NAME=value` forms.
Pipe `|` clears the var map (subshell boundary); unsafe RHS values
($, backticks, command-substitution placeholders) are never
propagated; the executed command string is never mutated.

Credit: srgvg (manuelschipper#74) for identifying the bypass.
Add trailing-* wildcard support to classify entries. Adds
_validate_classify_pattern helper, extends build_user_table with
validation-and-skip behavior + exact-before-wildcard tie-break, and
teaches _prefix_match to match wildcards via startswith on the last
prefix token. Write-time validation in remember.write_classify rejects
bad entries at the CLI before touching YAML.

Existing exact-match semantics untouched — FD-024 adversarial test
remains green.
Taxonomy: validator unit tests, build_user_table skip-with-warning,
exact-beats-wildcard tie-break, single/multi-token wildcard matching,
FD-024 exact-match invariant still green.

Hook: mcp__github* covers multiple server tools, does not leak across
servers, exact entry still overrides wildcard at equal length, project
classify for MCP remains ignored.

Remember: write_classify accepts valid wildcards, rejects every invalid
shape at write time, never persists malformed entries.
Adds an example block showing mcp__github* and mcp__github__delete_repo
together, plus a note on YAML alias semantics and exact-beats-wildcard
precedence.
Replace truncate-then-write with the standard write-temp-then-rename
pattern so concurrent readers never observe an empty intermediate
file. Fixes the data-loss window reported in manuelschipper#66.

Extract _atomic_write_text(path, text, *, mode) as a reusable helper:
resolve symlinks on the target, mkstemp in the parent, UTF-8 fdopen,
fsync, chmod-then-replace, fsync parent dir on POSIX, cleanup on
error. _write_config becomes a thin wrapper that captures the
existing file mode (default 0o644) and renders YAML to a string
before handing off.

Scope stops at atomic visibility and durability. Lost-update
protection via fcntl.flock is explicitly deferred, and ACL/xattr
preservation is out of scope (st_mode only).
Covers: output regression (byte-identical YAML), default and preserved
modes, no stray .tmp files after a successful write, yaml.dump failure
leaves the original file intact with no tmp residue, os.replace failure
cleans up the tmp and preserves the target, writing through a symlink
replaces the real file not the link node, and the concurrent-read
invariant that guards issue manuelschipper#66 — readers in a parallel thread never
observe an empty dict or a missing baseline key during 200 overlapping
writes.
Ship four slash commands (/nah-classify, /nah-allow, /nah-status,
/nah-log) as markdown files in src/nah/commands/. Extend 'nah install'
with --skills (and --force) to symlink them into ~/.claude/commands/.
Wire them into the mkdocs guide nav and document the feature in
CHANGELOG.md under [Unreleased].
@manuelschipper
Copy link
Copy Markdown
Owner

Thanks for putting this together. I like the direction here: being able to manage nah from inside an agent session is useful.

I’m still thinking through the right shape for this now that nah also supports Codex and terminal guard flows, and I want to make sure we don’t lock the UX too tightly to one runtime too early.

I’ll leave this open for now and come back soon with a clearer path.

@moyukhc
Copy link
Copy Markdown
Author

moyukhc commented May 10, 2026

Makes total sense, happy to refactor to make things more provider-agnostic as well.

@manuelschipper manuelschipper force-pushed the main branch 2 times, most recently from e5ade83 to 223356e Compare May 19, 2026 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants