~/.deepagents/ directory. The main config files are:
| File | Format | Purpose |
|---|---|---|
config.toml | TOML | Model defaults, provider settings, constructor params, profile overrides, themes, update settings |
.env | Dotenv | Global API keys, secrets, and other environment variables |
hooks.json | JSON | External tool subscriptions to Deep Agents Code lifecycle events |
.mcp.json | JSON | Global MCP server definitions |
Files under
~/.deepagents/.state/ hold per-machine Deep Agents Code state and are managed automatically.Provider credentials
Deep Agents Code needs an API key for each model provider you use. The recommended way to add one is the/auth credential manager. For non-interactive runs, set environment variables instead.
If the same key is set in more than one place, see Key resolution order for which one wins.
Use /auth (recommended)
Open the credential manager from any session:
Provider row labels
Provider row labels
Each row shows the provider name followed by where its key comes from:
| Label | Meaning |
|---|---|
[stored] | A key saved in this manager via /auth |
[env: VARNAME] | The key comes from environment variable VARNAME (the resolved name, such as DEEPAGENTS_CODE_OPENAI_API_KEY or OPENAI_API_KEY) |
[missing] | No key is stored and the env var is unset; select the row to paste one |
/auth prompt also has an optional base URL field. Leave it blank to use the provider’s default endpoint, or set a custom one to use with this key. The base URL is saved alongside the key. See Endpoints, keys, and gateways for how endpoints resolve, including with gateways.
Keys are scoped to your user account on this machine — Deep Agents Code never transmits them anywhere except to the configured provider’s API.
/auth only manages LLM provider credentials. Tool credentials such as TAVILY_API_KEY (web search) and LANGSMITH_API_KEY (tracing) are read from the environment instead — set them in ~/.deepagents/.env or your shell.
Environment variables (CI and headless)
For non-interactive runs, CI/CD pipelines, or anywhere a TUI isn’t available, export the provider’s env var in your shell:.env file.
Key resolution order
When a provider’s key is set in more than one place, Deep Agents Code uses the first of these that is set:DEEPAGENTS_CODE_-prefixed env var — for exampleDEEPAGENTS_CODE_OPENAI_API_KEYas an inline shell export. TheDEEPAGENTS_CODE_prefix is the explicit “use this key in Deep Agents Code” override.- App-stored key — entered in the
/authcredential manager. - Plain provider env var — for example
OPENAI_API_KEY, from your shell or.envfiles.
DEEPAGENTS_CODE_-prefixed key wins over an app-stored key. The prefix is the way to override an already-stored key for a single run, without clearing it:
OPENAI_API_KEY used by other tools, scripts, or CI — that you do not want Deep Agents Code to reuse. An app-stored key or a DEEPAGENTS_CODE_-prefixed variable gives Deep Agents Code its own value while leaving the unprefixed one untouched for everything else, so the two never mix.
Each provider’s API key and its endpoint (base_url) resolve as a pair from the same source. See Endpoints, keys, and gateways.
Enable web search with Tavily
The built-inweb_search tool uses Tavily. Deep Agents Code shows a “Web search disabled — TAVILY_API_KEY is not set” notification on startup until you provide a key. Unlike model provider keys, Tavily is not managed by /auth; it is read directly from the environment.
Get a key
Sign up at tavily.com and copy the key (it starts with
tvly-). The free tier is sufficient for most Deep Agents Code usage.Add it to your environment
Add the key to Or export it in your shell for a one-off session:Shell exports take precedence over
~/.deepagents/.env so every session picks it up:~/.deepagents/.env
.env values (see Loading order and precedence). To scope a key to Deep Agents Code only without affecting other tools that read TAVILY_API_KEY, use the DEEPAGENTS_CODE_ prefix: DEEPAGENTS_CODE_TAVILY_API_KEY=tvly-....Environment variables
In addition to shell exports, Deep Agents Code reads environment variables from dotenv files, so you can keep API keys out of your shell profile and avoid duplicating.env files across projects.
~/.deepagents/.env
Loading order and precedence
At startup, Deep Agents Code reads the nearest project.env, found by searching the directory you launch from and walking up through its parents (the first .env found wins), then ~/.deepagents/.env as a global fallback for all projects. A project .env wins over the global one, and neither overrides a value already set in your shell. Running /reload re-reads both .env files so you can change keys without restarting, with shell values still taking precedence. This applies to every variable Deep Agents Code reads (for example, TAVILY_API_KEY or the DEEPAGENTS_CODE_* settings). Provider API keys have additional resolution rules; see Provider credentials.
DEEPAGENTS_CODE_ prefix
All Deep Agents Code-specific environment variables use a DEEPAGENTS_CODE_ prefix (e.g., DEEPAGENTS_CODE_AUTO_UPDATE, DEEPAGENTS_CODE_DEBUG). See the environment variable reference for the full list.
The prefix also works as an override mechanism for any environment variable Deep Agents Code reads, including third-party credentials. Deep Agents Code checks DEEPAGENTS_CODE_{NAME} first, then falls back to {NAME}:
~/.deepagents/.env
Config file
~/.deepagents/config.toml lets you customize model providers, set defaults, and pass extra parameters to model constructors. This section covers:
- Defaults: pin a default model or agent.
- Provider setup: the
[models.providers.<name>]table, constructor params, profile overrides, and adding models to the/modelswitcher. - Custom endpoints and providers: custom base URLs, OpenAI- or Anthropic-compatible APIs, and arbitrary providers.
- Endpoints and gateways: how API keys and base URLs resolve together, including through a managed gateway.
Default and recent model
[models].default always takes priority over [models].recent. The /model command only writes to [models].recent, so your configured default is never overwritten by mid-session switches. To remove the default, use /model --default --clear or delete the default key from the config file.
Default and recent agent
[agents].default always takes priority over [agents].recent. Selecting an agent in the /agents picker with Enter writes to recent; pressing Ctrl+S on the highlighted row pins it as default. Pressing Ctrl+S again on the same row clears the default.
Explicit -a/--agent always overrides both, and -r/--resume bypasses both so the thread’s original agent is restored. See Command reference for related flags.
Provider configuration
Each provider is a TOML table under[models.providers]:
A list of model names to show in the interactive
/model switcher for the provider defined as <name>. For providers that already ship with model profiles, any names you add here appear in addition to bundled ones (useful for newly released models that haven’t been added to the package yet). For arbitrary providers, this list is the only source of models in the switcher.Models listed here bypass any applied profile-based filtering criteria, always appearing in the switcher. This makes it the recommended way to surface models that are excluded because their profile lacks tool_calling support or doesn’t exist yet.This key is optional. You can always pass any model name directly to /model or --model regardless of whether it appears in the switcher; the provider validates the name at request time.The name of the environment variable that holds the API key (e.g.,
"OPENAI_API_KEY"). Deep Agents Code reads the credential from this env var at startup to verify access before creating the model.Most chat model packages read from a default env var automatically. See the Provider reference table for which variable name each built-in provider checks. For a provider not in that table, set api_key_env to its variable name (see Arbitrary providers).Override the base URL used by the provider, if supported. Refer to your provider packages’ reference docs for more info.See Compatible APIs for pointing a built-in provider at a wire-compatible endpoint, or Arbitrary providers for one configured via
class_path.Name of the environment variable that holds this provider’s base URL, parallel to
api_key_env. Reach for this instead of base_url when the endpoint comes from the environment rather than a fixed value — for example a gateway URL that differs by machine or CI job — so it can change without editing config.toml and can take part in endpoint resolution and key/endpoint pairing (see Endpoints, keys, and gateways). It also extends those to providers outside the built-in set; see Arbitrary providers.If both are set, the static base_url wins:Extra keyword arguments forwarded to the model constructor. Flat keys (e.g.,
temperature = 0) apply to every model from this provider. Model-keyed sub-tables (e.g., [params."gpt-4o"]) override individual values for that model only; the merge is shallow (model wins on conflict).Do not put credentials (e.g., api_key) in params. Use api_key_env to point at an environment variable instead.(Advanced) Override fields in the model’s runtime profile (e.g.,
max_input_tokens). Flat keys apply to every model from this provider. Model-keyed sub-tables (e.g., [profile."claude-sonnet-4-5"]) override individual values for that model only; the merge is shallow (model wins on conflict). These overrides are applied after the model is created, so they take effect for context-limit display, auto-summarization, and any other feature that reads the profile. See Profile overrides for examples and the --profile-override flag.Used for arbitrary model providers. Fully-qualified Python class in
module.path:ClassName format. When set, Deep Agents Code imports and instantiates this class directly for provider <name>. The class must be a BaseChatModel subclass.Whether this provider appears in the
/model selector. Set to false to hide a provider that was auto-discovered from an installed package (e.g., a transitive dependency you don’t want cluttering the model switcher). You can still use a disabled provider directly via /model provider:model or --model.Model constructor params
Theparams field forwards extra arguments to the model constructor. To give one model different values, add a model-keyed sub-table so you do not have to duplicate the whole provider config:
ollama:qwen3:4bgets{temperature: 0.5, num_ctx: 4000}— model overrides win.ollama:llama3gets{temperature: 0, num_ctx: 8192}— no override, provider-level params only.
Profile overrides (Advanced)
Override fields in the model’s runtime profile to change how Deep Agents Code interprets model capabilities. SeeModelProfile for the full list of overridable fields. The most common use case is lowering max_input_tokens to trigger auto-summarization earlier — useful for testing or for constraining context usage:
params — the model-level value wins on conflict:
CLI profile overrides with --profile-override
CLI profile overrides with --profile-override
To override model profile fields at runtime without editing the config file, pass a JSON object via These are merged on top of config file profile overrides (CLI wins). The priority chain is: model default < config.toml profile < CLI
--profile-override:--profile-override.--profile-override values persist across mid-session /model hot-swaps — switching models re-applies the override to the new model.Adding models to the interactive switcher
Some providers (e.g.langchain-ollama) don’t bundle model profile data (see Provider reference for full listing). When this is the case, the interactive /model switcher won’t list models for that provider. You can fill in the gap by defining a models list in your config file for the provider:
/model switcher will now include an Ollama section with these models listed.
This is entirely optional. You can always switch to any model by specifying its full name directly:
When
langchain-ollama is installed and the daemon is reachable, Deep Agents Code auto-discovers locally pulled models and merges them into the switcher—no models list required. Run /reload to refresh after pulling new models, or set DEEPAGENTS_CODE_OLLAMA_DISCOVERY=0 to opt out.Custom base URL
Some provider packages accept abase_url to override the default endpoint. For example, langchain-ollama defaults to http://localhost:11434 via the underlying ollama client. To point it elsewhere, set base_url in your configuration:
Compatible APIs
For providers that expose APIs that are wire-compatible with OpenAI or Anthropic, you can use the existinglangchain-openai or langchain-anthropic packages by pointing base_url at the provider’s endpoint:
Any features added on top of the official spec by the provider will not be captured. If the provider offers a dedicated LangChain integration package, prefer that instead.
Arbitrary providers
Deep Agents Code works with any tool calling LLM available as a LangChainBaseChatModel. The built-in providers work out of the box; a less common or in-house model takes a little more setup. Point class_path at its BaseChatModel subclass and Deep Agents Code imports and instantiates the class directly.
api_key_env and base_url are optional. To read the endpoint from an environment variable instead of hardcoding base_url, use base_url_env; it then resolves and pairs with the key the same way as for the built-in providers (see Endpoints, keys, and gateways).
class_path providers are expected to handle their own authentication internally — useful when your model uses custom auth (JWT tokens, proprietary headers, mTLS, etc.) rather than a standard API key:
/model xyz:abc-xyz-1 or --model xyz:abc-xyz-1.
Deep Agents Code requires tool calling support. If your custom model supports tool calling but Deep Agents Code doesn’t know about it, declare it in the provider profile:Although optional, setting
max_input_tokens to your model’s context window is strongly encouraged. Without it, Deep Agents Code cannot show how full the context is, and auto-summarization falls back to a fixed trigger (around 170,000 tokens) instead of a fraction of your model’s window. For a model with a smaller window, summarization may not run before you reach the model’s hard limit, so requests start failing once the conversation grows.class_path class at startup, the package that defines it must be importable from the same environment that runs dcode. Built-in providers ship as install extras, but a custom or in-house package is not one. Install it into the dcode environment with the --package flag:
/install my_package --package --force. Both install the package alongside dcode. If the package is missing or cannot be imported, Deep Agents Code skips the provider and its models do not appear in /model.
When you switch to my_custom:my-model-v1 (via /model or --model), the model name (my-model-v1) is passed as the model kwarg:
_PROFILES dict in <package>.data._profiles in lieu of defining them under the models key. See LangChain model profiles for more info.
Endpoints, keys, and gateways
An API key and the endpoint it is sent to have to match: the endpoint has to accept that key, or the request will likely fail. Deep Agents Code resolves the key and endpoint together, so overriding one updates the other to match. For example, if you replace a gateway-provisioned key with your own, Deep Agents Code also drops the gateway endpoint, so your key goes to the provider directly instead of to a gateway that would reject it.How base_url resolves
Deep Agents Code resolves a provider’s endpoint in this order (first match wins):
base_urlinconfig.tomlfor the provider.- The
DEEPAGENTS_CODE_-prefixed endpoint variable. - The plain endpoint variable in the environment (for example,
OPENAI_BASE_URL). - The endpoint saved with a
/authcredential. This step applies the saved endpoint for a provider that has no endpoint variable—such as a provider you add without declaringbase_url_env. Steps 2-3 have no variable to read for these, so the saved endpoint is used directly here. For a provider that does have an endpoint variable, the saved endpoint already took effect at step 2 or 3 (it is written to that variable), so this step changes nothing. Either way, an endpoint entered in/authapplies. - The provider SDK’s own default endpoint, when none of the above is set.
Resolved endpoints are delivered to the model as the
base_url constructor argument.DEEPAGENTS_CODE_ prefix scopes the endpoint to Deep Agents Code without affecting other tools. For any other provider, declare the name with base_url_env and the endpoint resolves and pairs the same way:
base_url wins over base_url_env, so set only the one you need:
Overrides keep the pair together
When you store a key with/auth, the endpoint you enter (or the provider’s default, if left blank) is applied together with the key. Storing a key with a blank base URL also clears any endpoint already set in your environment (for example, a gateway OPENAI_BASE_URL your shell exports), so your key goes to the provider’s default endpoint instead of to that gateway.
Scope both the key and the endpoint to Deep Agents Code
Managed gateways
On a machine provisioned with a model gateway (for example, the LangSmith gateway), the gateway typically exports a gateway key and the matching endpoint variable (OPENAI_BASE_URL, ANTHROPIC_BASE_URL, or GOOGLE_GEMINI_BASE_URL) together. Deep Agents Code uses that pair by default, so no configuration is needed.
To use your own key instead, store it with /auth (leave the base URL blank for the provider default, or set it explicitly), or set the DEEPAGENTS_CODE_ prefixed key and endpoint. Both override the gateway pair without leaving a mismatched endpoint behind.
Skill directory allowlist
By default, when Deep Agents Code loads skills it validates that a resolved skill file path stays inside one of the standard skill directories. This prevents symlinks inside skill directories from reading arbitrary files outside those roots. If you store shared skill assets in a non-standard location and use symlinks from a standard skill directory to reference them, you can add that location to the containment allowlist. This does not add a new skill discovery location: skills are still only discovered from the standard directories.Paths added to the skill containment allowlist. Supports
~ expansion.DEEPAGENTS_CODE_EXTRA_SKILLS_DIRS environment variable as a colon-separated list:
/reload.
Themes
Use/theme to open an interactive theme selector. Navigate the list to preview themes in real-time, press Enter to persist your choice to config.toml.
Deep Agents Code ships with many built-in themes. The default theme is langchain, a dark theme with LangChain-branded colors. The selected theme is persisted under [ui]:
User-defined themes
Define custom themes under[themes.<name>] sections in config.toml. Each section requires label (str). dark (bool) defaults to false if omitted — set to true for dark themes. All color fields are optional — omitted fields fall back to the built-in dark or light palette based on the dark flag.
/theme selector.
Override built-in theme colors
To tweak a built-in theme’s colors without creating a new theme, use a[themes.<builtin-name>] section. Only color fields are read — label and dark are inherited from the built-in:
[themes.*] sections take effect on /reload.
Map themes to terminals
If you switch between terminals with different color schemes (for example, a dark iTerm and a light Apple Terminal), map each one to a theme under[ui.terminal_themes]. Deep Agents Code matches the shell’s TERM_PROGRAM and applies the mapped theme automatically:
T in the /theme picker to save the highlighted theme for the current terminal, or run echo $TERM_PROGRAM to find your terminal’s identifier and add it by hand.
Advanced: picker shortcuts, resolution order, terminal identifiers
Advanced: picker shortcuts, resolution order, terminal identifiers
Picker shortcuts
In the/theme selector:Ntoggles between display labels and canonical registry keys—the keys are what[ui] themeand[ui.terminal_themes]accept.Tsaves the highlighted theme into[ui.terminal_themes]for the currentTERM_PROGRAM. The mapped theme is badged(default)in the picker.
Common TERM_PROGRAM values
Keys are matched verbatim against the environment variable—quote them in TOML when they contain dots or special characters.| Terminal | TERM_PROGRAM |
|---|---|
| Apple Terminal | Apple_Terminal |
| iTerm2 | iTerm.app |
| WezTerm | WezTerm |
| VS Code integrated terminal | vscode |
| Ghostty | ghostty |
Resolution order
Deep Agents Code resolves a theme on every launch using this precedence:DEEPAGENTS_CODE_THEMEenvironment variable (explicit override).[ui.terminal_themes]mapping for the currentTERM_PROGRAM.[ui] themesaved preference (set by/theme).- The built-in default (
langchain).
Auto-update
Deep Agents Code can automatically check for and install updates.- Config file
- Environment variable
/update slash command, which bypasses the cache and reports success or failure inline.
After an upgrade, Deep Agents Code shows a “what’s new” banner on the next launch with a link to the changelog.
At session exit, if a newer version was detected during the session, an update banner is displayed as a reminder.
Uninstall
To remove thedcode and deepagents-code binaries and the isolated tool environment, run:
~/.deepagents/, including config.toml, hooks.json, the global .env, and .state/ contents such as saved sessions and credentials. To delete that data as well, run:
Managed deployments
The install script supports running as root, targeting macOS MDM tools (Kandji, Jamf, etc.) that execute scripts in a minimal root environment. Whenid -u is 0, the script:
- Resolves the real console user’s
HOME(via/dev/consoleor a/Usersdirectory scan) chowns all created files back to the target user after each install step
DEEPAGENTS_CODE_AUTO_UPDATE=1 in the user’s shell profile or deploy a config.toml with [update] auto_update = true to ~/.deepagents/config.toml. To suppress automatic updates and update checks entirely, set DEEPAGENTS_CODE_NO_UPDATE_CHECK=1.
To route every user’s model traffic through a managed gateway (provisioning a gateway key and base URL fleet-wide), see Managed gateways.
Environment variable reference
All Deep Agents Code-specific environment variables use theDEEPAGENTS_CODE_ prefix. See DEEPAGENTS_CODE_ prefix for how the prefix also works as an override for third-party credentials.
Enable automatic Deep Agents Code updates (
1, true, or yes).Enable verbose debug logging to a file. Accepts
1, true, yes, on (case-insensitive) as enabled; 0, false, no, off, empty string, or unset disables it. When enabled, the per-session server log file is preserved on shutdown and its path is printed to stderr for triage.Path for the debug log file.
Colon-separated paths added to the skill containment allowlist.
Override the LangSmith project name for agent traces. See Trace with LangSmith.
Disable automatic update checking when set.
Comma-separated shell commands to allow (or
recommended / all).Attach a user identifier to LangSmith trace metadata.
External editor
PressCtrl+X or type /editor to compose prompts in an external editor. Deep Agents Code checks $VISUAL, then $EDITOR, then falls back to vi (macOS/Linux) or notepad (Windows). GUI editors (VS Code, Cursor, Zed, Sublime Text, Windsurf) automatically receive a --wait flag so Deep Agents Code blocks until you close the file.
Hooks
Hooks let external programs react to Deep Agents Code lifecycle events. Configure commands in~/.deepagents/hooks.json and it pipes a JSON payload to each matching command’s stdin whenever an event fires.
Hooks run fire-and-forget in a background thread — they never block Deep Agents Code and failures are logged without interrupting your session.
Setup
Create~/.deepagents/hooks.json:
~/deepagents-events.log.
Hook configuration
The config file contains a singlehooks array. Each entry has:
Command and arguments to run. No shell expansion: use
["bash", "-c", "..."] if needed.Event names to subscribe to. Omit or leave empty to receive all events.
events filter, so it receives every event Deep Agents Code emits.
Payload format
Each hook command receives a JSON object on stdin with an"event" key plus event-specific fields:
Events reference
session.start
Fired when an agent session begins (both interactive and non-interactive modes).
The session thread identifier.
session.end
Fired when a session exits.
The session thread identifier.
user.prompt
Fired in interactive mode when the user submits a chat message.
No additional fields.
input.required
Fired when the agent requires human input (human-in-the-loop interrupt).
No additional fields.
permission.request
Fired before the approval dialog when one or more tool calls need user permission.
Names of the tools requesting approval.
tool.error
Fired when a tool call returns an error.
Names of the tool(s) that errored.
task.complete
Fired when the agent finishes its current task (the streaming loop ends without further interrupts).
The session thread identifier.
context.compact
Fired before Deep Agents Code compacts (summarizes) the conversation context.
No additional fields.
Execution model
- Background thread: Hook subprocesses run in a thread via
asyncio.to_threadso the main event loop is never blocked. - Concurrent dispatch: When multiple hooks match an event, they run concurrently in a thread pool.
- 5-second timeout: Each command has a 5-second timeout. Commands that exceed this are killed.
- Fire-and-forget: Errors are caught per-hook and logged at debug/warning level. A failing hook never crashes or stalls Deep Agents Code.
- Lazy loading: The config file is read once on the first event dispatch and cached for the rest of the session.
- No shell expansion: Commands are executed directly (not through a shell). Wrap in
["bash", "-c", "..."]if you need shell features like pipes or variable expansion.
Hook examples
Log all events to a file
Log all events to a file
Desktop notification on task completion (macOS)
Desktop notification on task completion (macOS)
Python handler
Python handler
Write a handler script that reads the JSON payload from stdin:
my_handler.py
~/.deepagents/hooks.json
Security considerations
Hooks follow the same trust model as Git hooks or shell aliases — any user who can write to~/.deepagents/hooks.json can execute arbitrary commands. This is by design:
- No command injection: Payload data flows only to stdin as JSON, never to command-line arguments.
json.dumpshandles escaping. - No shell by default: Commands run with
shell=False, preventing shell injection. - Malformed config: Invalid JSON or unexpected types produce logged warnings, not security issues.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

