The Third Leash
An illustrative PATH wrapper selects an authorized Claude Code identity and model at process launch. Its scope, inheritance limits and failure policy explained.
Routing an AI coding tool means choosing both a model and an authorized identity for a workflow. This article uses a hypothetical directory example to explain process configuration and its limits.
Model availability, authentication, and billing are separate controls. A project may need a distinct authorized identity while retaining the same reasoning effort and verification rules. The challenge is making that selection consistent across interactive and automated invocations.
Consider a normal Claude Code login and a separately authorized identity for a project. The wrapper selects the project configuration when a process starts inside that tree. It is not a security boundary that follows later directory changes.
What “route” has to actually mean
Say the requirement out loud and it splits into parts that do not share a mechanism:
The example selects identity and default model at process launch, including for headless workers. It must fail clearly if required credentials cannot be loaded, and its callers must understand how environment variables propagate to descendants.
Project settings and inherited process environments have different scopes. Test the actual launcher and working directory rather than assuming that a parent repository’s settings govern every nested repository.
The one knob for the account
Claude Code documents CLAUDE_CODE_OAUTH_TOKEN for supported OAuth authentication and provides claude setup-token for obtaining a token through its login flow. Check the current authentication documentation, account eligibility and token expiry before using this approach.
The switch is scoped to each process. A process with the explicitly configured OAuth environment variable uses that credential; a process without it uses its normal authentication path. The example does not require changing the global keychain login.
Authentication sources can compete. Inspect the effective configuration and provider documentation, and avoid supplying an unrelated API key alongside an OAuth design. Verify the resulting identity through supported status and usage records; a successful text response alone does not establish billing attribution.
Why the obvious approaches don't work
Project settings are useful, but their discovery and precedence must be checked for the process being launched.
This example supplies credentials before starting the executable and keeps them out of a repository settings file. It does not rely on an assertion that every client loads settings or authentication in the same order.
Environment variables normally propagate to child processes. That helps detached workers, but also means a child can retain project credentials after changing directories. Test nested-repository settings separately from process inheritance.
direnv’s automatic prompt hook does not run merely because a noninteractive process changes directories. An already configured environment can be inherited, and direnv exec is an explicit noninteractive alternative.
And apiKeyHelper? It vends API keys, not subscription OAuth tokens. Wrong currency.
| Mechanism | Useful property | Limit to verify |
|---|---|---|
| Project settings | Repository-scoped configuration | Discovery and precedence for each client |
| direnv | Environment loading; explicit direnv exec | Hooks and inheritance in the actual launcher |
| apiKeyHelper | Supported API credential helper | Not a general subscription identity router |
| PATH wrapper | Explicit configuration before exec | PATH resolution and descendant inheritance |
A PATH wrapper is one explicit launch mechanism. A dedicated launcher or direnv exec may also fit the workflow. Choose the one whose configuration and inheritance you can inspect and test.
The shim
The wrapper checks the directory at launch, loads a required credential, supplies model and effort defaults, and executes the real binary by absolute path. Outside that tree it passes through the environment it received.
#!/bin/bash
set -eu
REAL="$HOME/.local/bin/claude" # Configure an absolute path distinct from this wrapper.
PROJECT_ROOT="$HOME/work/the-project"
TOKEN_FILE="$HOME/.config/work/oauth-token"
case "$PWD/" in
"$PROJECT_ROOT"/*)
[ -r "$TOKEN_FILE" ] || { printf '%s\n' 'Required credential unavailable.' >&2; exit 1; }
PROJECT_TOKEN="$(cat "$TOKEN_FILE")" || exit 1
[ -n "$PROJECT_TOKEN" ] || { printf '%s\n' 'Required credential empty.' >&2; exit 1; }
case "$PROJECT_TOKEN" in *$'\n'*|*$'\r'*) exit 1 ;; esac
export CLAUDE_CODE_OAUTH_TOKEN="$PROJECT_TOKEN"
unset ANTHROPIC_API_KEY
export ANTHROPIC_MODEL="claude-fable-5"
export CLAUDE_CODE_EFFORT_LEVEL="max"
;;
esac
# Descendants inherit this environment, even after changing directories.
exec "$REAL" "$@"That is the entire mechanism. A few things it gets right on purpose.
The prefix test controls initial selection only. Descendants inherit the selected environment and can carry it outside the tree. Launch unrelated work from a clean environment or implement an explicit, provenance-aware restoration mechanism. This snippet does not provide credential isolation.
It execs the real binary by absolute path, so there is no recursion despite both being named claude, and upgrades to the real installer are transparent.
The wrapper above fails if the credential file is missing, unreadable, empty or contains more than one line. Those checks only validate credential loading. This schematic assumes a clean, pre-audited authentication configuration: other provider flags, gateway tokens, helpers, settings or command-line overrides can affect the effective route. It does not inspect every competing source or prove account attribution. Verify the supported route and resulting identity before using it for required account separation.
For PATH ordering, the wrapper's directory just has to come before the real binary's. One line in your shell profile prepends it. which claude should resolve to the shim; if it resolves to the real binary you are in an old shell that has not re-read the profile.
The hard part is the headless loop
Everything above is table stakes for the interactive case. The reason this took real thought is the automation.
For a hypothetical autonomous loop, each worker may start a fresh claude -p process inside a nested repository. The routing mechanism must therefore work without an interactive prompt hook and without assuming that a parent repository’s settings are automatically applied.
The wrapper relies on two explicit conditions: the worker resolves claude through the intended PATH, and its working directory is inside the configured project tree. Test those conditions in the actual launcher environment, including detached processes.
An explicit --model flag takes precedence over an environment default. If a launcher pins the model on its command line, configure that launcher as well. Authentication and model selection are separate inputs; verifying one does not establish the other.
Authentication modes must be checked independently. A mode that requires API-key authentication is incompatible with a subscription OAuth routing design unless the workflow deliberately changes its authentication strategy.
The carve-outs
Two small decisions separate “works” from “works and isn't wasteful.”
Provider-managed utility models are separate from the main worker’s model and effort settings. Do not assume that changing the main model changes every background operation.
Reasoning effort is another inherited setting. Export it explicitly in the wrapper when the project requires a fixed level, so detached workers do not depend on an interactive shell profile having run.
One command to arm it
Initialize the authorized credential through the provider’s supported login flow, store it in a restricted file, and keep it out of logs and source control. Then verify the wrapper’s path, selected model, and behavior from representative interactive and headless working directories. A sample response alone cannot prove which account was billed.
Verifying the account is the one thing the probe can't fully prove on its own — a headless response looks the same whichever subscription answered. The honest confirmations are /status, which prints the logged-in account, and the billing dashboard, which is the only source of truth about whose credits got spent. Trust the invoice, not the vibes.
Why any of this is worth it
Continuous agent work makes attribution important. Even a short prompt may carry substantial context and trigger reasoning or tool activity. Route deliberately, verify the authenticated identity through supported account status, and check the provider’s usage records when validating the accounting boundary.
Hot takes
Explicit launch configuration is easier to inspect than an implicit shell assumption. It still needs tests for PATH resolution, inherited variables, nested working directories and detached execution.
Neither environment variables nor settings files are universally superior. Use the documented mechanism for each client and verify the effective configuration in the launcher that will actually run the work.
Fail closed when the selected identity is required but unavailable. Passing through with a different credential can change attribution and access in ways the caller did not intend.
The point
A small wrapper can select process defaults. Reliable account isolation needs more: a defined inheritance policy, supported authentication, restricted credential storage and independent checks of effective identity.
The useful property is explicit configuration at launch. The directory test is a routing convenience, not a guarantee that credentials cannot reach another directory or child process.
Sources: Claude Code authentication; direnv exec reference. Documentation checked September 20, 2026.