# Configuration DeepSeek TUI reads configuration from a TOML file plus environment variables. At process startup it also loads a workspace-local `.env` file when present. Use the tracked `.env.example` as the template; copy it to `.env`, then edit only the provider and safety knobs you need. ## Where It Looks Default config path: - `~/.deepseek/config.toml` Overrides: - CLI: `deepseek --config /path/to/config.toml` - Env: `DEEPSEEK_CONFIG_PATH=/path/to/config.toml` If both are set, `--config` wins. Environment variable overrides are applied after the file is loaded. The `deepseek` facade and `deepseek-tui` binary share the same config file for DeepSeek auth and model defaults. `deepseek login --api-key ...` writes the root `api_key` field that `deepseek-tui` reads directly, and `deepseek --model deepseek-v4-flash` is forwarded to the TUI as `DEEPSEEK_MODEL`. For hosted or self-hosted DeepSeek V4 providers, set `provider = "nvidia-nim"`, `"fireworks"`, or `"sglang"` or pass `deepseek --provider `. The facade stores provider credentials under `[providers.]` and forwards the resolved key, base URL, provider, and model to the TUI process. Use `deepseek auth set --provider nvidia-nim --api-key "YOUR_NVIDIA_API_KEY"` or `deepseek auth set --provider fireworks --api-key "YOUR_FIREWORKS_API_KEY"` to save hosted-provider keys through the facade. SGLang is self-hosted and can run without an API key by default. To bootstrap MCP and skills directories at their resolved paths, run `deepseek-tui setup`. To only scaffold MCP, run `deepseek-tui mcp init`. Note: setup, doctor, mcp, features, sessions, resume/fork, exec, review, and eval are subcommands of the `deepseek-tui` binary. The `deepseek` dispatcher exposes a distinct set of commands (`auth`, `config`, `model`, `thread`, `sandbox`, `app-server`, `mcp-server`, `completion`) and forwards plain prompts to `deepseek-tui`. ## Profiles You can define multiple profiles in the same file: ```toml api_key = "PERSONAL_KEY" default_text_model = "deepseek-v4-pro" [profiles.work] api_key = "WORK_KEY" base_url = "https://api.deepseek.com" [profiles.nvidia-nim] provider = "nvidia-nim" api_key = "NVIDIA_KEY" base_url = "https://integrate.api.nvidia.com/v1" default_text_model = "deepseek-ai/deepseek-v4-pro" [profiles.fireworks] provider = "fireworks" default_text_model = "accounts/fireworks/models/deepseek-v4-pro" [profiles.sglang] provider = "sglang" base_url = "http://localhost:30000/v1" default_text_model = "deepseek-ai/DeepSeek-V4-Pro" ``` Select a profile with: - CLI: `deepseek --profile work` - Env: `DEEPSEEK_PROFILE=work` If a profile is selected but missing, DeepSeek TUI exits with an error listing available profiles. ## Environment Variables These override config values: - `DEEPSEEK_API_KEY` - `DEEPSEEK_BASE_URL` - `DEEPSEEK_PROVIDER` (`deepseek|nvidia-nim|openrouter|novita|fireworks|sglang`) - `DEEPSEEK_MODEL` or `DEEPSEEK_DEFAULT_TEXT_MODEL` - `NVIDIA_API_KEY` or `NVIDIA_NIM_API_KEY` (preferred when provider is `nvidia-nim`; falls back to `DEEPSEEK_API_KEY`) - `NVIDIA_NIM_BASE_URL`, `NIM_BASE_URL`, or `NVIDIA_BASE_URL` - `NVIDIA_NIM_MODEL` - `FIREWORKS_API_KEY` - `FIREWORKS_BASE_URL` - `SGLANG_BASE_URL` - `SGLANG_MODEL` - `SGLANG_API_KEY` (optional; many localhost SGLang servers do not require auth) - `DEEPSEEK_LOG_LEVEL` or `RUST_LOG` (`info`/`debug`/`trace` enables lightweight verbose logs) - `DEEPSEEK_SKILLS_DIR` - `DEEPSEEK_MCP_CONFIG` - `DEEPSEEK_NOTES_PATH` - `DEEPSEEK_MEMORY_PATH` - `DEEPSEEK_ALLOW_SHELL` (`1`/`true` enables) - `DEEPSEEK_APPROVAL_POLICY` (`on-request|untrusted|never`) - `DEEPSEEK_SANDBOX_MODE` (`read-only|workspace-write|danger-full-access|external-sandbox`) - `DEEPSEEK_MANAGED_CONFIG_PATH` - `DEEPSEEK_REQUIREMENTS_PATH` - `DEEPSEEK_MAX_SUBAGENTS` (clamped to `1..=20`) - `DEEPSEEK_TASKS_DIR` (runtime task queue/artifact storage, default `~/.deepseek/tasks`) - `DEEPSEEK_ALLOW_INSECURE_HTTP` (`1`/`true` allows non-local `http://` base URLs; default is reject) - `DEEPSEEK_CAPACITY_ENABLED` - `DEEPSEEK_CAPACITY_LOW_RISK_MAX` - `DEEPSEEK_CAPACITY_MEDIUM_RISK_MAX` - `DEEPSEEK_CAPACITY_SEVERE_MIN_SLACK` - `DEEPSEEK_CAPACITY_SEVERE_VIOLATION_RATIO` - `DEEPSEEK_CAPACITY_REFRESH_COOLDOWN_TURNS` - `DEEPSEEK_CAPACITY_REPLAN_COOLDOWN_TURNS` - `DEEPSEEK_CAPACITY_MAX_REPLAY_PER_TURN` - `DEEPSEEK_CAPACITY_MIN_TURNS_BEFORE_GUARDRAIL` - `DEEPSEEK_CAPACITY_PROFILE_WINDOW` - `DEEPSEEK_CAPACITY_PRIOR_CHAT` - `DEEPSEEK_CAPACITY_PRIOR_REASONER` - `DEEPSEEK_CAPACITY_PRIOR_V4_PRO` - `DEEPSEEK_CAPACITY_PRIOR_V4_FLASH` - `DEEPSEEK_CAPACITY_PRIOR_FALLBACK` ## Settings File (Persistent UI Preferences) DeepSeek TUI also stores user preferences in: - `~/.config/deepseek/settings.toml` Notable settings include `auto_compact` (default `false`), which opts into replacement-style summarization only near the active model limit. The default V4 path preserves the stable message prefix for cache reuse; use manual `/compact` or enable `auto_compact` only when you explicitly want automatic replacement compaction. You can inspect or update these from the TUI with `/settings` and `/config` (interactive editor). Common settings keys: - `theme` (default, dark, light, whale) - `auto_compact` (on/off, default off) - `paste_burst_detection` (on/off, default on): fallback rapid-key paste detection for terminals that do not emit bracketed-paste events. This is independent of terminal bracketed-paste mode. - `show_thinking` (on/off) - `show_tool_details` (on/off) - `locale` (`auto`, `en`, `ja`, `zh-Hans`, `pt-BR`; default `auto`): UI chrome locale. `auto` checks `LC_ALL`, `LC_MESSAGES`, then `LANG`; unsupported or missing locales fall back to English. This does not force model output language. - `default_mode` (agent, plan, yolo; legacy `normal` is accepted and normalized to `agent`) - `max_history` (number of submitted input history entries; cleared drafts are also kept locally for composer history search) - `default_model` (model name override) Only `agent`, `plan`, and `yolo` are visible modes in the UI. For compatibility, older settings files with `default_mode = "normal"` still load as `agent`, and the hidden `/normal` slash command switches to `Agent`. Localization scope is tracked in [LOCALIZATION.md](LOCALIZATION.md). The v0.7.6 core pack covers high-visibility TUI chrome only; provider/tool schemas, personality prompts, and full documentation remain English unless explicitly translated later. Readability semantics: - Selection uses a unified style across transcript, composer menus, and modals. - Footer hints use a dedicated semantic role (`FOOTER_HINT`) so hint text stays readable across themes. - The footer includes a compact `coherence` chip that describes how stable and focused the current session is right now. Possible states are `healthy`, `crowded`, `refreshing`, `verifying`, and `resetting`; these are derived from capacity and compaction events without exposing internal formulas in normal UI. ### Token Quantities and Drivers DeepSeek V4 prefix caching makes token labels matter. These quantities are kept separate: | Quantity | Meaning | Allowed to drive | |---|---|---| | Active request input estimate | Conservative estimate of the next request's live system prompt and transcript payload. | Header/footer context percent, hard-cycle trigger, opt-in Flash seam trigger, and emergency overflow preflight. | | Reserved response headroom | The requested `max_tokens` budget plus safety headroom. v0.7.5 keeps normal turns at `262144` output tokens and adds `1024` safety tokens for context-window checks. | Hard-cycle and emergency overflow budget checks only. | | Cumulative API usage | Provider-reported input plus output tokens summed across completed API calls; multi-tool turns may count the same stable prefix more than once. | Session usage and approximate cost telemetry only. | | Prompt cache hit/miss | Provider cache telemetry for the most recent call when available. | Cache-hit display and cost estimation only; never compaction, seam, or cycle triggers. | | Context percent | Active request input estimate divided by the model context window. | Display only; it mirrors the active-input basis used by context safeguards. | | Cost estimate | Approximate spend from provider usage and configured DeepSeek rates. | Display only. | For the default V4 path, hard cycles fire when active input reaches the smaller of the configured cycle threshold (`768000`) and the model window minus reserved response headroom. Replacement compaction remains opt-in (`auto_compact = false` by default), the Flash seam manager remains opt-in (`[context].enabled = false`), and the capacity controller remains disabled unless configured. ### Command Migration Notes If you are upgrading from older releases: - Old: `/deepseek` New: `/links` (aliases: `/dashboard`, `/api`) - Old: `/set model deepseek-reasoner` New: `/config` and edit the `model` row to `deepseek-v4-pro` or `deepseek-v4-flash` - Old: visible `Normal` mode or `default_mode = "normal"` New: use `Agent` / `default_mode = "agent"`; legacy `normal` still maps to `agent` - Old: discover `/set` in slash UX/help New: use `/config` for editing and `/settings` for read-only inspection ## Key Reference ### Core keys (used by the TUI/engine) - `provider` (string, optional): `deepseek` (default), `nvidia-nim`, `openrouter`, `novita`, `fireworks`, or `sglang`. `nvidia-nim` targets NVIDIA's NIM-hosted DeepSeek endpoints through `https://integrate.api.nvidia.com/v1`; `fireworks` targets `https://api.fireworks.ai/inference/v1`; `sglang` targets a self-hosted OpenAI-compatible endpoint, defaulting to `http://localhost:30000/v1`. - `api_key` (string, required): must be non-empty (or set `DEEPSEEK_API_KEY`). - `base_url` (string, optional): defaults to `https://api.deepseek.com` for DeepSeek's OpenAI-compatible Chat Completions API, or `https://integrate.api.nvidia.com/v1` for `provider = "nvidia-nim"`. `https://api.deepseek.com/v1` is also accepted for SDK compatibility; use `https://api.deepseek.com/beta` only for DeepSeek beta features such as strict tool mode, chat prefix completion, and FIM completion. - `default_text_model` (string, optional): defaults to `deepseek-v4-pro` for DeepSeek, `deepseek-ai/deepseek-v4-pro` for NVIDIA NIM, `accounts/fireworks/models/deepseek-v4-pro` for Fireworks, and `deepseek-ai/DeepSeek-V4-Pro` for SGLang. Current public DeepSeek IDs are `deepseek-v4-pro` and `deepseek-v4-flash`, both with 1M context windows and thinking mode enabled by default. Legacy `deepseek-chat` and `deepseek-reasoner` remain compatibility aliases for `deepseek-v4-flash`. Provider-specific mappings translate `deepseek-v4-pro` / `deepseek-v4-flash` to each provider's model ID where supported. Use `/models` or `deepseek models` to discover live IDs from your configured endpoint. `DEEPSEEK_MODEL` overrides this for a single process. - `reasoning_effort` (string, optional): `off`, `low`, `medium`, `high`, or `max`; defaults to the configured UI tier. DeepSeek Platform receives top-level `thinking` / `reasoning_effort` fields. NVIDIA NIM receives equivalent settings through `chat_template_kwargs`. - `allow_shell` (bool, optional): defaults to `true` (sandboxed). - `approval_policy` (string, optional): `on-request`, `untrusted`, or `never`. Runtime `approval_mode` editing in `/config` also accepts `on-request` and `untrusted` aliases. - `sandbox_mode` (string, optional): `read-only`, `workspace-write`, `danger-full-access`, `external-sandbox`. - `managed_config_path` (string, optional): managed config file loaded after user/env config. - `requirements_path` (string, optional): requirements file used to enforce allowed approval/sandbox values. - `max_subagents` (int, optional): defaults to `10` and is clamped to `1..=20`. - `subagents.*` (optional): per-role/type model defaults for `agent_spawn` and related sub-agent tools. Explicit tool `model` values win, then role/type overrides, then the parent runtime model. Supported convenience keys are `default_model`, `worker_model`, `explorer_model`, `awaiter_model`, `review_model`, `custom_model`, and `max_concurrent`. The `[subagents] max_concurrent` value overrides top-level `max_subagents` and is also clamped to `1..=20`. `[subagents.models]` accepts lower-case role or type keys such as `worker`, `explorer`, `general`, `explore`, `plan`, and `review`. Values must normalize to a supported DeepSeek model id before an agent is spawned. - `skills_dir` (string, optional): defaults to `~/.deepseek/skills` (each skill is a directory containing `SKILL.md`). Workspace-local `.agents/skills` or `./skills` are preferred when present. - `mcp_config_path` (string, optional): defaults to `~/.deepseek/mcp.json`. It is visible in `/config` and can be changed from the TUI. The new path is used immediately by `/mcp`, but rebuilding the model-visible MCP tool pool requires restarting the TUI. - `notes_path` (string, optional): defaults to `~/.deepseek/notes.txt` and is used by the `note` tool. - `memory_path` (string, optional): defaults to `~/.deepseek/memory.md`. - `snapshots.*` (optional): side-git workspace snapshots for file rollback: - `[snapshots].enabled` (bool, default `true`) - `[snapshots].max_age_days` (int, default `7`) - snapshots live under `~/.deepseek/snapshots///.git` and never use the workspace's own `.git` directory - `context.*` (optional): append-only Flash seam manager, currently opt-in. Thresholds use the active request input estimate, not lifetime summed API usage: - `[context].enabled` (bool, default `false`) - `[context].verbatim_window_turns` (int, default `16`) - `[context].l1_threshold` (int, default `192000`) - `[context].l2_threshold` (int, default `384000`) - `[context].l3_threshold` (int, default `576000`) - `[context].cycle_threshold` (int, default `768000`) - `[context].seam_model` (string, default `deepseek-v4-flash`) - `retry.*` (optional): retry/backoff settings for API requests: - `[retry].enabled` (bool, default `true`) - `[retry].max_retries` (int, default `3`) - `[retry].initial_delay` (float seconds, default `1.0`) - `[retry].max_delay` (float seconds, default `60.0`) - `[retry].exponential_base` (float, default `2.0`) - `capacity.*` (optional): runtime context-capacity controller. This is opt-in because its active interventions can rewrite the live transcript. - `[capacity].enabled` (bool, default `false`) - `[capacity].low_risk_max` (float, default `0.50`) - `[capacity].medium_risk_max` (float, default `0.62`) - `[capacity].severe_min_slack` (float, default `-0.25`) - `[capacity].severe_violation_ratio` (float, default `0.40`) - `[capacity].refresh_cooldown_turns` (int, default `6`) - `[capacity].replan_cooldown_turns` (int, default `5`) - `[capacity].max_replay_per_turn` (int, default `1`) - `[capacity].min_turns_before_guardrail` (int, default `4`) - `[capacity].profile_window` (int, default `8`) - `[capacity].deepseek_v3_2_chat_prior` (float, default `3.9`) - `[capacity].deepseek_v3_2_reasoner_prior` (float, default `4.1`) - `[capacity].deepseek_v4_pro_prior` (float, default `3.5`) - `[capacity].deepseek_v4_flash_prior` (float, default `4.2`) - `[capacity].fallback_default_prior` (float, default `3.8`) - `tui.alternate_screen` (string, optional): `auto`, `always`, or `never`. `auto` disables the alternate screen in Zellij; `--no-alt-screen` forces inline mode. Set `never` or run with `--no-alt-screen` when you want real terminal scrollback. - `tui.mouse_capture` (bool, optional, default `true` when the alternate screen is active): enable internal mouse scrolling, transcript selection, and right-click context actions. TUI-owned drag selection copies only user/assistant transcript text. Set this to `false` or run with `--no-mouse-capture` for raw terminal selection. - `tui.terminal_probe_timeout_ms` (int, optional, default `500`): startup terminal-mode probe timeout in milliseconds. Values are clamped to `100..=5000`; timeout emits a warning and aborts startup instead of hanging indefinitely. - `hooks` (optional): lifecycle hooks configuration (see `config.example.toml`). - `features.*` (optional): feature flag overrides (see below). ### Parsed but currently unused (reserved for future versions) These keys are accepted by the config loader but not currently used by the interactive TUI or built-in tools: - `tools_file` ## Feature Flags Feature flags live under the `[features]` table and are merged across profiles. Defaults are enabled for built-in tooling, so you only need to set entries you want to force on or off. ```toml [features] shell_tool = true subagents = true web_search = true # enables canonical web.run plus the compatibility web_search alias apply_patch = true mcp = true exec_policy = true ``` You can also override features for a single run: - `deepseek-tui --enable web_search` - `deepseek-tui --disable subagents` Use `deepseek-tui features list` to inspect known flags and their effective state. ## Local Media Attachments Use `@path/to/file` in the composer to add local text file or directory context to the next message. Use `/attach ` for local image/video media paths, or `Ctrl+V` to attach an image from the clipboard. DeepSeek's public Chat Completions API currently accepts text message content, so media attachments are sent as explicit local path references instead of native image/video payloads. Attachment rows appear above the composer before submit; move to the start of the composer, press `↑` to select an attachment row, then press `Backspace` or `Delete` to remove it without editing the placeholder text by hand. ## Managed Configuration and Requirements DeepSeek TUI supports a policy layering model: 1. user config + profile + env overrides 2. managed config (if present) 3. requirements validation (if present) By default on Unix: - managed config: `/etc/deepseek/managed_config.toml` - requirements: `/etc/deepseek/requirements.toml` Requirements file shape: ```toml allowed_approval_policies = ["on-request", "untrusted", "never"] allowed_sandbox_modes = ["read-only", "workspace-write"] ``` If configured values violate requirements, startup fails with a descriptive error. See `docs/capacity_controller.md` for formulas, intervention behavior, and telemetry. ## Notes On `deepseek-tui doctor` `deepseek-tui doctor` follows the same config resolution rules as the rest of the TUI. That means `--config` / `DEEPSEEK_CONFIG_PATH` are respected, and MCP/skills checks use the resolved `mcp_config_path` / `skills_dir` (including env overrides). To bootstrap missing MCP/skills paths, run `deepseek-tui setup --all`. You can also run `deepseek-tui setup --skills --local` to create a workspace-local `./skills` dir. `deepseek-tui doctor --json` prints a machine-readable report that skips the live API connectivity probe. Top-level keys: `version`, `config_path`, `config_present`, `workspace`, `api_key.source`, `base_url`, `default_text_model`, `mcp`, `skills`, `tools`, `plugins`, `sandbox`, `platform`, `api_connectivity`, `capability`. CI consumers should rely on `api_key.source` (`env`/`config`/`missing`) rather than parsing the human-readable `doctor` text. The `capability` key contains per-provider capability info derived from static knowledge (release docs, API guides) rather than live API probes. Top-level sub-keys: `resolved_provider`, `resolved_model`, `context_window`, `max_output`, `thinking_supported`, `cache_telemetry_supported`, `request_payload_mode`, and `deprecation`. When the resolved model is a known legacy alias (e.g. `deepseek-chat`, `deepseek-reasoner`), the `deprecation` sub-object carries `alias`, `replacement`, and `notice` fields. Use `capability.context_window` and `capability.max_output` for context-window budgeting in CI scripts. Use `capability.thinking_supported` to decide whether to configure reasoning effort. Use `capability.deprecation` to warn users about legacy model aliases. ## Setup status, clean, and extension dirs `deepseek-tui setup` accepts a few flags beyond the existing `--mcp`, `--skills`, `--local`, `--all`, and `--force`: - `--status` — print a compact one-screen status (api key, base URL, model, MCP/skills/tools/plugins counts, sandbox, `.env` presence). Read-only and network-free; safe to run in CI. If `.env` is missing and `.env.example` is present in the workspace, the status output points at `cp .env.example .env`. - `--tools` — scaffold `~/.deepseek/tools/` with a `README.md` describing the self-describing frontmatter convention (`# name:` / `# description:` / `# usage:`) and an `example.sh` that follows it. The directory is intentionally not auto-loaded; wire individual scripts into the agent via MCP, hooks, or skills. - `--plugins` — scaffold `~/.deepseek/plugins/` with a `README.md` and an `example/PLUGIN.md` placeholder using the same frontmatter shape as `SKILL.md`. Plugins are not loaded automatically either; reference them from a skill or MCP wrapper when you want them active. - `--all` now scaffolds MCP + skills + tools + plugins together. - `--clean` — list `~/.deepseek/sessions/checkpoints/latest.json` and `offline_queue.json` if they exist. Pass `--force` to actually remove them. This never touches real session history or the task queue. `--status` and `--clean` are mutually exclusive with the scaffold flags. ## Why the engine strips XML/`[TOOL_CALL]` text DeepSeek TUI sends and receives tool calls only over the API tool channel (structured `tool_use` / `tool_call` items). The streaming loop in `crates/tui/src/core/engine.rs` recognizes a fixed set of fake-wrapper start markers — `[TOOL_CALL]`, `` — and scrubs them from visible assistant text without ever turning them into structured tool calls. When a wrapper is stripped, the loop emits one compact `status` notice per turn so the user can see why their visible text shrank. Treat any change that re-enables text-based tool execution as a regression; the protocol-recovery tests in `crates/tui/tests/protocol_recovery.rs` lock the contract.