[FEATURE] Pure-exec slash commands (deterministic, discoverable alias for Bash mode)
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
Claude Code has three user-facing extension primitives, none of which gives a named, discoverable, deterministic command:
- Custom commands (
.claude/commands/*.md) and skills (.claude/skills/*) are markdown the model interprets — non-deterministic and a full model round-trip, which is overkill for trivial fixed actions (run a script, toggle a flag). - Hooks (
settings.json) are deterministic and model-free, but event-triggered, not user-invokable by name, and not discoverable/autocompleted. - Bash mode (the
!prefix) is deterministic and model-free, but ad-hoc: not a reusable named command, no autocomplete, not discoverable by the user or by agents.
So there is no way to expose a frequently-used fixed shell action as a first-class /command without paying for model interpretation and accepting its non-determinism.
Proposed Solution
Add a pure-exec command type — a named, discoverable alias for Bash mode. A new directory, e.g. ~/.claude/exec/<name>.sh (and project .claude/exec/), where each file is a shell script. Invoking /<name> (or a namespaced /exec:<name> to avoid collision with commands/skills) runs the script directly, streams its output, and appears in / autocomplete and discovery like commands/skills. The execution path already exists (Bash mode); this is an alias/registry layer over it plus discovery surfacing.
Output handling — a per-command frontmatter flag, since "zero model turn" and "agent can read the output" are mutually exclusive (reading output is a model turn):
capture: false(default) — pure exec. Output shown to the user only, not added to the conversation context. No model turn at all. Maximum determinism; for fire-and-forget actions (toggle flag, refresh cache, deploy).capture: true— Bash-mode parity: the script runs deterministically (no model interpreting whether/how to run it), but its output is appended to the context exactly like!cmdtoday, so the agent can read and act on it on the next turn. Gives a named, discoverable, deterministic Bash mode.
Both modes keep execution itself deterministic and model-free; the flag only controls whether the result re-enters the conversation.
Alternative Solutions
- Frontmatter flag on existing commands, e.g.
exec: true/type: command, that makes a.claude/commands/*.mdrun its single!-backtick line and return with no model interpretation. Reuses the dir but overloads its semantics. - Allow binding a name to a hook so it can be user-invoked. More invasive; conflates hooks (events) with commands (intent).
- Status quo: a commands/skills shim whose body is one
!-backtick exec plus a "reply only: done" instruction. Works but wastes a model round-trip and relies on the model behaving.
Priority
Low - Nice to have
Feature Category
Interactive mode (TUI)
Use Case Example
I maintain several fixed actions: refresh a cache, toggle a statusline flag, run a deterministic resolver script. Today these are skills (model interprets markdown — sometimes misreads intent, always a round trip) or hooks (not invokable by name).
/refresh-cachewithcapture: false→ runs~/.claude/exec/refresh-cache.shexactly and only, no tokens, no interpretation, output just shown to me./aws-whoamiwithcapture: true→ runs the script deterministically and drops its output into context so the agent can use it next turn — a named, discoverable Bash mode instead of typing!aws sts get-caller-identity.
Agents could also discover and call the capture: true ones as known deterministic actions.
Additional Context
- Naming/namespace is an open design point: flat
/nameis nicer but can collide with commands/skills;/exec:nameis unambiguous. - Thin wrapper over Bash mode — low implementation surface, high ergonomic payoff. Other agent CLIs expose exactly this (named pre-defined shell commands surfaced as slash commands).
- Claude Code version: 2.1.142.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗