[FEATURE] Mods API: report each simple command that a Bash call's shell runs, after expansion

Status Open
Reported on v2.1.296
Maintainer reply None cached
Activity 0 comments · opened Oct 11, 2026

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

Arrester is a mod that stops Bash calls on blocked paths. On Claude Code 2.1.296 (macOS), it gets the command as one string before the shell runs:

'tool.call': ToolCallInput;   // Bash: { command: string, ... }

What runs depends on values the string hides: $(...) output, ${p:-x}, environment values, and snapshot aliases and functions (even Claude Code's find/grep, #69736). No API gives these:

  • 'process.spawn': ProcessSpawnRequest; is "The argument of $.process.spawn(request)", so mod-started processes only.
  • $.env.get: "name must be a string literal".
  • No declaration names an alias table, a function table or the snapshot.

Proposed Solution

  1. Small step: $.shell.definitions(): Promise<{ aliases: Record<string, string>; functions: Record<string, string> }>, from the Bash tool's snapshot.
  2. Full step: the tool shell raises an event before each simple command (DEBUG trap or preexec), after alias, function and word expansion:
'bash.exec': { tool_use_id: string; agentId?: string; argv: string[]; cwd: string };

{ deny: reason } fails that command with status 126 and ends the call.

Alternative Solutions

  • Parsing the string (current) leaves dynamic values unknown.
  • Inject a trap through tool.call. $BASH_COMMAND is unexpanded, zsh -c runs no preexec, and the command can remove the trap.

Priority

Medium - Would be very helpful

Feature Category

Developer tools/SDK

Use Case Example

Arrester's documented limits:

  • "Parameter operators such as ${p:-default} ... are not resolved, and neither is command output ... such as $(cat list)."
  • "Aliases, shell functions, unlisted runners, and unlisted program options can escape detection."
  • A nested claude flag from ${mode:-bypassPermissions} passes.

With bash.exec, Arrester checks the real argv and cwd before each program runs.

Additional Context

  • #79440 (closed, not planned) asked to disable alias expansion. This asks for visibility, which also covers functions and $(...).
  • Two #91870 comments ask for a parsed argv on Bash tool.call. A static parse cannot resolve these values.

View original on GitHub ↗