[FEATURE] Mods API: give the working directory for each tool call and each configured command hook

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

A guard mod resolves relative paths. On Claude Code 2.1.296 (macOS), the Mods API gives one folder per session:

/** Returns the directory the session runs in, absolute. */
cwd: () => Promise<string>;   // $.session.cwd()

tool.call input holds tool, tool_use_id, the arguments and agentId?. ToolCheckInput holds tool, input, tool_use_id?, agentId?, ceiling?. Neither names the calling loop's folder.

  1. A subagent in a worktree resolves relative paths in its own folder. rg pattern, or Grep with no path, searches a folder the mod cannot name.
  2. A command hook such as python3 .claude/hooks/guard.py spawns in a folder the engine picks. #91226 shows it follows the Bash tool's cd. $.settings.read() returns the command as written, so the mod cannot tell which script runs.

Settings hooks get cwd on stdin. Module hooks do not: "classic.PreToolUse alone differs: its e is ToolCallEnvelope, no more."

Proposed Solution

  1. Add a read-only cwd: string to tool.call and tool.check input: the folder where this call resolves relative paths.
  2. Add $.hooks.list(args?: { agentId?: string }): Promise<CommandHookInfo[]>, each { event, matcher?, command, source: SettingsSource | 'plugin', cwd }, where cwd is the folder the engine spawns that hook in for that loop.

Alternative Solutions

  • agent.spawn's cwd? is set only when the call names a folder, not for isolation: "worktree".
  • The Agent result's worktreePath arrives after a foreground agent's tools ran.
  • For part 2, documenting that hooks spawn in the call's cwd would do.

Priority

Medium - Would be very helpful

Feature Category

Developer tools/SDK

Use Case Example

Arrester (github.com/dot-agi/arrester) stops detours after a block. This closes two README limits:

  • "Searches that name no folder" can read a blocked file.
  • "A relative path, such as python3 .claude/hooks/guard.py, adds no guard."

Additional Context

Related, not the same: #83952 (show people the resolved hook file in /hooks) and #87890 (hook spawn folder ignores EnterWorktree).

View original on GitHub ↗