Skip to content

[FEATURE] Persistent shell context (CWD, env vars) across Bash tool calls #28228

@nexus-marbell

Description

@nexus-marbell

Preflight Checklist

  • I have searched existing requests and this feature hasn't been requested yet
  • This is a single feature request (not multiple features)

Problem Statement

Shell state (working directory, environment variables, virtualenv activation) does not persist between Bash tool calls. Every call resets to the project root. This creates a constant operational tax for any workflow that requires positional state.

Concrete impacts:

  1. Every Bash call must re-establish position: Commands that should be a single line become cd /path && source venv/bin/activate && <actual command>. This adds noise to every invocation and wastes tokens on boilerplate.

  2. Git operations are unsafe: The CWD reset can silently change which branch is active when using git worktrees. A commit intended for a feature branch can land on main with no warning. We maintain a dedicated rule file that mandates: "verify branch in the SAME command chain as git add and git commit" solely because of this behavior.

  3. Git stash is hazardous: git stash does not save untracked files, and stash pop after a state reset can destroy work. Another safety rule exists solely for this.

  4. Virtualenv activation is lost between every call: Projects using Python virtualenvs require redundant source venv/bin/activate && prefixes on every Bash invocation. This is especially painful for multi-environment workflows.

  5. Environment variables set in one call are invisible to the next: Any export done in a Bash call is gone by the next call, making iterative shell workflows impossible without chaining everything into a single invocation.

Proposed Solution

Any of these would significantly improve the experience, listed from highest to lowest impact:

  1. Persistent CWD across Bash calls (highest impact). After cd /some/path, subsequent Bash calls should start in /some/path instead of resetting to the project root. This single change would eliminate the most common workaround pattern.

  2. Persistent env vars / virtualenv state. Environment variables set via export and virtualenv activations (which are just env var changes) should survive across Bash tool calls.

  3. Named shell sessions. Allow creating a named shell session that maintains full state between invocations. Example: {"session": "my-project", "command": "pytest"} would run in whatever state my-project session has accumulated.

  4. Configurable anchor directory. A setting (e.g., CLAUDE_BASH_ANCHOR_DIR) that auto-restores a specific directory after each call, rather than always resetting to the project root.

Alternative Solutions

We have built the following workarounds, all of which add complexity and cognitive load:

  • A git-branch-safety rule that auto-loads every session, enforcing branch verification in the same command chain as git operations
  • A git stash safety rule requiring git add of untracked files before any stash, because state loss makes stash dangerous
  • Convention of chaining all related commands with && in a single Bash call to maintain state within one invocation
  • Absolute paths everywhere to avoid CWD ambiguity
  • System prompt instructions telling the model to never use cd alone and to always use absolute paths

These workarounds consume token budget on every invocation and add fragility to every shell interaction.

Note: CLAUDE_BASH_MAINTAIN_PROJECT_WORKING_DIR exists but its behavior is the opposite of what is needed here -- it forces CWD back to the project root, rather than allowing CWD to persist.

Also see #26652 which proposes a per-call workingDirectory parameter. That is complementary to this request: per-call overrides are useful, but persistent state across calls eliminates the need to specify the directory at all after the first cd.

Priority

High - Significant impact on productivity

Feature Category

CLI commands and flags

Use Case Example

Scenario: Multi-agent orchestrator with specialist subagents

Our system runs 10+ specialist subagents, each operating in different directories and virtualenvs on the same machine:

  1. Agent A needs to work in /root/projects/project-alpha with its virtualenv
  2. Agent B needs to work in /root/projects/project-beta with a different virtualenv
  3. Each agent makes 20-50 Bash calls per task

Current behavior (every single call):

cd /root/projects/project-alpha && source venv/bin/activate && pytest tests/
cd /root/projects/project-alpha && source venv/bin/activate && python -m mymodule
cd /root/projects/project-alpha && source venv/bin/activate && pip install -e ".[dev]"

With persistent shell context:

# First call establishes state
cd /root/projects/project-alpha && source venv/bin/activate
# All subsequent calls just run the actual command
pytest tests/
python -m mymodule
pip install -e ".[dev]"

Across 10 agents making 50 calls each, that is 500 redundant cd && source prefixes per session. The token cost and error surface are substantial.

Additional Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions