Post-merge review feedback on #583 surfaced four small accuracy gaps: 1. The narrative docs in `docs/CONFIGURATION.md` and the inline comment in `config.example.toml` said the notification fires "when a turn takes longer than a threshold" — but the call site in `tui/ui.rs:928` is gated on `TurnOutcomeStatus::Completed`. Failed and cancelled turns are silent on purpose. Spell that out so users don't expect alerts on long failures. 2. The `notify_done` rustdoc still summarised `Auto` as "Osc9 for known terminals, Bel otherwise" — internally inconsistent with the new Windows-aware fallback documented one screen earlier on the `Method::Auto` enum and on `resolve_method`. Update the public rustdoc to point at the canonical resolution table on `resolve_method` and call out the `Off`-on-Windows branch. 3. The `## Key Reference` list in `docs/CONFIGURATION.md` had no entries for `[notifications].method`, `[notifications].threshold_secs`, or `[notifications].include_summary`. Other features with a dedicated subsection (e.g. `[memory].enabled`) are listed there too, so readers scanning the canonical key list could not discover the notification knobs. Added the three keys with cross-references to the Notifications subsection. 4. The Windows-only test only covered the unknown-`TERM_PROGRAM` → `Off` fallback. The positive path (known OSC-9 terminal still resolves to `Osc9`) was only tested via `iTerm.app`, which is a macOS-only program — Windows CI would still pass if the `WezTerm` arm of the match disappeared. Added `auto_detect_picks_osc9_for_wezterm_on_windows` so the WezTerm-on-Windows compatibility guarantee is exercised on the Windows runner. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
29 KiB
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.
Per-project overlay (#485)
When the TUI starts in a workspace that contains a
<workspace>/.deepseek/config.toml file, the values declared in that
file are merged on top of the global config. This lets a repo lock its
own provider, model, sandbox policy, or approval policy without
touching the user's ~/.deepseek/config.toml. Pass
--no-project-config to skip the overlay for one launch.
Supported keys in the project overlay (top-level fields only):
| Key | Effect |
|---|---|
provider |
switch backend (e.g. "nvidia-nim" for an enterprise repo) |
model |
override default_text_model |
api_key |
use a per-repo key (typically read from .env, not committed) |
base_url |
point at a self-hosted endpoint |
reasoning_effort |
force "high" / "max" for a complex repo |
approval_policy |
"never" / "on-request" / "untrusted" for opinionated repos |
sandbox_mode |
"read-only" / "workspace-write" / "danger-full-access" |
mcp_config_path |
per-repo MCP server set |
notes_path |
keep notes in-repo |
max_subagents |
clamp concurrency for a constrained repo (clamped to 1..=20) |
allow_shell |
gate shell tool access on false |
The overlay is intentionally narrow — it covers the fields a repo maintainer is most likely to want to standardize across contributors. Other settings (skills_dir, hooks, capacity, retry, etc.) stay user-global. If your repo needs more, file an issue describing the specific use case.
The deepseek facade and deepseek-tui binary share the same config file for
DeepSeek auth and model defaults. deepseek auth set --provider deepseek (and
the legacy deepseek login --api-key ... alias) saves the key to
~/.deepseek/config.toml, 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 <name>. The facade
saves provider credentials to the shared user config 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:
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_KEYDEEPSEEK_BASE_URLDEEPSEEK_PROVIDER(deepseek|nvidia-nim|openrouter|novita|fireworks|sglang)DEEPSEEK_MODELorDEEPSEEK_DEFAULT_TEXT_MODELNVIDIA_API_KEYorNVIDIA_NIM_API_KEY(preferred when provider isnvidia-nim; falls back toDEEPSEEK_API_KEY)NVIDIA_NIM_BASE_URL,NIM_BASE_URL, orNVIDIA_BASE_URLNVIDIA_NIM_MODELFIREWORKS_API_KEYFIREWORKS_BASE_URLSGLANG_BASE_URLSGLANG_MODELSGLANG_API_KEY(optional; many localhost SGLang servers do not require auth)DEEPSEEK_LOG_LEVELorRUST_LOG(info/debug/traceenables lightweight verbose logs)DEEPSEEK_SKILLS_DIRDEEPSEEK_MCP_CONFIGDEEPSEEK_NOTES_PATHDEEPSEEK_MEMORY(1|on|true|yes|y|enabledturns user memory on)DEEPSEEK_MEMORY_PATHDEEPSEEK_ALLOW_SHELL(1/trueenables)DEEPSEEK_APPROVAL_POLICY(on-request|untrusted|never)DEEPSEEK_SANDBOX_MODE(read-only|workspace-write|danger-full-access|external-sandbox)DEEPSEEK_MANAGED_CONFIG_PATHDEEPSEEK_REQUIREMENTS_PATHDEEPSEEK_MAX_SUBAGENTS(clamped to1..=20)DEEPSEEK_TASKS_DIR(runtime task queue/artifact storage, default~/.deepseek/tasks)DEEPSEEK_ALLOW_INSECURE_HTTP(1/trueallows non-localhttp://base URLs; default is reject)DEEPSEEK_CAPACITY_ENABLEDDEEPSEEK_CAPACITY_LOW_RISK_MAXDEEPSEEK_CAPACITY_MEDIUM_RISK_MAXDEEPSEEK_CAPACITY_SEVERE_MIN_SLACKDEEPSEEK_CAPACITY_SEVERE_VIOLATION_RATIODEEPSEEK_CAPACITY_REFRESH_COOLDOWN_TURNSDEEPSEEK_CAPACITY_REPLAN_COOLDOWN_TURNSDEEPSEEK_CAPACITY_MAX_REPLAY_PER_TURNDEEPSEEK_CAPACITY_MIN_TURNS_BEFORE_GUARDRAILDEEPSEEK_CAPACITY_PROFILE_WINDOWDEEPSEEK_CAPACITY_PRIOR_CHATDEEPSEEK_CAPACITY_PRIOR_REASONERDEEPSEEK_CAPACITY_PRIOR_V4_PRODEEPSEEK_CAPACITY_PRIOR_V4_FLASHDEEPSEEK_CAPACITY_PRIOR_FALLBACKNO_ANIMATIONS(1|true|yes|onforceslow_motion = trueandfancy_animations = falseat startup, regardless of the saved settings; seedocs/ACCESSIBILITY.md).SSL_CERT_FILE— corporate-proxy / TLS-inspecting MITM users point this at a PEM bundle (or single DER cert) and the cert(s) get added alongside the platform's system trust store. Failures log a warning and continue — the existing system roots still apply.
Instruction sources (instructions = [...], #454)
Add a list of additional system-prompt sources that get
concatenated, in declared order, alongside the auto-loaded
AGENTS.md:
instructions = [
"./AGENTS.md",
"~/.deepseek/global.md",
"~/team/agents-shared.md",
]
Rules:
- Paths run through
expand_pathso~and env vars work. - Each file is capped at 100 KiB; oversized files are
truncated with a
[…elided]marker rather than skipped. - Missing files are skipped with a tracing warning so a stale entry doesn't fail the launch.
- Project config (
<workspace>/.deepseek/config.toml) replaces the user array wholesale rather than merging. If you want both, list~/global.mdinside the project array. Setinstructions = []in the project to clear the user list for that repo.
/hooks listing
Run /hooks (or /hooks list) inside the TUI to see every
configured lifecycle hook grouped by event, including each
hook's name, command preview, timeout, and condition. The
[hooks].enabled flag's state is shown at the top so it's
obvious when hooks are globally suppressed. Hooks are
configured under [[hooks.hooks]] entries — see the existing
hook-system documentation for the full schema.
Composer stash (/stash, Ctrl+S)
Press Ctrl+S in the composer to park the current draft to
~/.deepseek/composer_stash.jsonl. /stash list shows parked
drafts with one-line previews and timestamps; /stash pop
restores the most recently parked draft (LIFO); /stash clear
wipes the file. Capped at 200 entries; multiline drafts
round-trip intact.
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; defaultauto): UI chrome locale.autochecksLC_ALL,LC_MESSAGES, thenLANG; unsupported or missing locales fall back to English. This does not force model output language.default_mode(agent, plan, yolo; legacynormalis accepted and normalized toagent)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. 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
coherencechip that describes how stable and focused the current session is right now. Possible states arehealthy,crowded,refreshing,verifying, andresetting; 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:
/deepseekNew:/links(aliases:/dashboard,/api) - Old:
/set model deepseek-reasonerNew:/configand edit themodelrow todeepseek-v4-proordeepseek-v4-flash - Old: visible
Normalmode ordefault_mode = "normal"New: useAgent/default_mode = "agent"; legacynormalstill maps toagent - Old: discover
/setin slash UX/help New: use/configfor editing and/settingsfor read-only inspection
Key Reference
Core keys (used by the TUI/engine)
provider(string, optional):deepseek(default),nvidia-nim,openrouter,novita,fireworks, orsglang.nvidia-nimtargets NVIDIA's NIM-hosted DeepSeek endpoints throughhttps://integrate.api.nvidia.com/v1;fireworkstargetshttps://api.fireworks.ai/inference/v1;sglangtargets a self-hosted OpenAI-compatible endpoint, defaulting tohttp://localhost:30000/v1.api_key(string, required): must be non-empty (or setDEEPSEEK_API_KEY).base_url(string, optional): defaults tohttps://api.deepseek.comfor DeepSeek's OpenAI-compatible Chat Completions API, orhttps://integrate.api.nvidia.com/v1forprovider = "nvidia-nim".https://api.deepseek.com/v1is also accepted for SDK compatibility; usehttps://api.deepseek.com/betaonly for DeepSeek beta features such as strict tool mode, chat prefix completion, and FIM completion.default_text_model(string, optional): defaults todeepseek-v4-profor DeepSeek,deepseek-ai/deepseek-v4-profor NVIDIA NIM,accounts/fireworks/models/deepseek-v4-profor Fireworks, anddeepseek-ai/DeepSeek-V4-Profor SGLang. Current public DeepSeek IDs aredeepseek-v4-proanddeepseek-v4-flash, both with 1M context windows and thinking mode enabled by default. Legacydeepseek-chatanddeepseek-reasonerremain compatibility aliases fordeepseek-v4-flash. Provider-specific mappings translatedeepseek-v4-pro/deepseek-v4-flashto each provider's model ID where supported. Use/modelsordeepseek modelsto discover live IDs from your configured endpoint.DEEPSEEK_MODELoverrides this for a single process.reasoning_effort(string, optional):off,low,medium,high, ormax; defaults to the configured UI tier. DeepSeek Platform receives top-levelthinking/reasoning_effortfields. NVIDIA NIM receives equivalent settings throughchat_template_kwargs.allow_shell(bool, optional): defaults totrue(sandboxed).approval_policy(string, optional):on-request,untrusted, ornever. Runtimeapproval_modeediting in/configalso acceptson-requestanduntrustedaliases.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 to10and is clamped to1..=20.subagents.*(optional): per-role/type model defaults foragent_spawnand related sub-agent tools. Explicit toolmodelvalues win, then role/type overrides, then the parent runtime model. Supported convenience keys aredefault_model,worker_model,explorer_model,awaiter_model,review_model,custom_model, andmax_concurrent. The[subagents] max_concurrentvalue overrides top-levelmax_subagentsand is also clamped to1..=20.[subagents.models]accepts lower-case role or type keys such asworker,explorer,general,explore,plan, andreview. 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 containingSKILL.md). Workspace-local.agents/skillsor./skillsare preferred when present.mcp_config_path(string, optional): defaults to~/.deepseek/mcp.json. It is visible in/configand 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.txtand is used by thenotetool.[memory].enabled(bool, optional): defaults tofalse. Whentrue, the TUI loads the user memory file into a<user_memory>prompt block, enables# fooquick-capture in the composer, surfaces the/memoryslash command, and registers theremembertool. The same toggle is available viaDEEPSEEK_MEMORY=on.memory_path(string, optional): defaults to~/.deepseek/memory.md. Used by the user-memory feature when enabled — seeMEMORY.mdfor the full feature surface (# foocomposer prefix,/memoryslash command,remembertool, opt-in toggle).snapshots.*(optional): side-git workspace snapshots for file rollback:[snapshots].enabled(bool, defaulttrue)[snapshots].max_age_days(int, default7)- snapshots live under
~/.deepseek/snapshots/<project_hash>/<worktree_hash>/.gitand never use the workspace's own.gitdirectory
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, defaultfalse)[context].verbatim_window_turns(int, default16)[context].l1_threshold(int, default192000)[context].l2_threshold(int, default384000)[context].l3_threshold(int, default576000)[context].cycle_threshold(int, default768000)[context].seam_model(string, defaultdeepseek-v4-flash)
retry.*(optional): retry/backoff settings for API requests:[retry].enabled(bool, defaulttrue)[retry].max_retries(int, default3)[retry].initial_delay(float seconds, default1.0)[retry].max_delay(float seconds, default60.0)[retry].exponential_base(float, default2.0)
capacity.*(optional): runtime context-capacity controller. This is opt-in because its active interventions can rewrite the live transcript.[capacity].enabled(bool, defaultfalse)[capacity].low_risk_max(float, default0.50)[capacity].medium_risk_max(float, default0.62)[capacity].severe_min_slack(float, default-0.25)[capacity].severe_violation_ratio(float, default0.40)[capacity].refresh_cooldown_turns(int, default6)[capacity].replan_cooldown_turns(int, default5)[capacity].max_replay_per_turn(int, default1)[capacity].min_turns_before_guardrail(int, default4)[capacity].profile_window(int, default8)[capacity].deepseek_v3_2_chat_prior(float, default3.9)[capacity].deepseek_v3_2_reasoner_prior(float, default4.1)[capacity].deepseek_v4_pro_prior(float, default3.5)[capacity].deepseek_v4_flash_prior(float, default4.2)[capacity].fallback_default_prior(float, default3.8)
[notifications].method(string, optional):auto,osc9,bel, oroff. Defaults toauto. The TUI fires this on completed (successful) turns whose elapsed time meetsthreshold_secs; failed and cancelled turns are silent.autoresolves toosc9foriTerm.app,Ghostty, andWezTerm(detected via$TERM_PROGRAM). Otherwise the fallback isbelon macOS / Linux andoffon Windows (where BEL maps to the system error chime — see the Notifications section for the full rationale, #583).[notifications].threshold_secs(int, optional): defaults to30. Only completed turns whose elapsed time meets or exceeds this fire a notification.[notifications].include_summary(bool, optional): defaults tofalse. Whentrue, the notification body includes the elapsed duration and the turn's USD cost.tui.alternate_screen(string, optional):auto,always, ornever.autodisables the alternate screen in Zellij;--no-alt-screenforces inline mode. Setneveror run with--no-alt-screenwhen you want real terminal scrollback.tui.mouse_capture(bool, optional, defaulttruewhen 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 tofalseor run with--no-mouse-capturefor raw terminal selection.tui.terminal_probe_timeout_ms(int, optional, default500): startup terminal-mode probe timeout in milliseconds. Values are clamped to100..=5000; timeout emits a warning and aborts startup instead of hanging indefinitely.tui.osc8_links(bool, optional, defaulttrue): emit OSC 8 escape sequences around URLs in transcript output so terminals that support them (iTerm2, Terminal.app 13+, Ghostty, Kitty, WezTerm, Alacritty, recent gnome-terminal/konsole) render them as Cmd+click hyperlinks. Terminals without OSC 8 support render the plain URL and ignore the escape. Setfalsefor terminals that misrender the sequence; selection/clipboard output always strips the escapes.hooks(optional): lifecycle hooks configuration (seeconfig.example.toml).features.*(optional): feature flag overrides (see below).
User memory
User memory is split across one top-level path setting and one opt-in toggle table:
memory_path = "~/.deepseek/memory.md"
[memory]
enabled = true
Notes:
memory_pathstays at the top level besidenotes_pathandskills_dir; it is not nested under[memory].DEEPSEEK_MEMORY_PATHoverrides the file path from the environment.DEEPSEEK_MEMORY=on(also1,true,yes,y, orenabled) flips the feature on without editingconfig.toml.- The feature is inert when disabled: no file is injected,
# foofalls through to normal message submission, and the model does not see theremembertool. - See
MEMORY.mdfor examples and the full/memorycommand surface.
Notifications
The TUI can emit a desktop notification (OSC 9 escape or plain BEL) when a turn completes successfully and took longer than a threshold, so you can tab away while a long task runs. Failed or cancelled turns are intentionally silent — the notification is a "your task is ready" cue, not a generic ping. Configuration lives under [notifications]:
[notifications]
method = "auto" # auto | osc9 | bel | off
threshold_secs = 30 # only notify when the turn took >= this many seconds
include_summary = false # include elapsed time + cost in the notification body
Method semantics:
auto(default) — picksosc9foriTerm.app,Ghostty, andWezTerm(detected via$TERM_PROGRAM). On macOS and Linux it falls back tobel. On Windows the fallback isoffinstead ofbel, because the Windows audio stack maps\x07to theSystemAsterisk/MB_OKchime — the same sound application error popups use, so a successful-turn notification ends up sounding like an error (#583).osc9— emit\x1b]9;<msg>\x07. Inside tmux the sequence is wrapped in DCS passthrough so it reaches the outer terminal.bel— emit a single\x07byte. Use this on Windows only if you actively want the chime back.off— disable post-turn notifications entirely.
Windows users who run inside a known OSC-9 terminal (e.g. WezTerm on Windows) keep getting OSC-9 notifications; the off fallback only applies when no recognised TERM_PROGRAM is detected.
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.
[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_searchdeepseek-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 <path> 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:
- user config + profile + env overrides
- managed config (if present)
- requirements validation (if present)
By default on Unix:
- managed config:
/etc/deepseek/managed_config.toml - requirements:
/etc/deepseek/requirements.toml
Requirements file shape:
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,.envpresence). Read-only and network-free; safe to run in CI. If.envis missing and.env.exampleis present in the workspace, the status output points atcp .env.example .env.--tools— scaffold~/.deepseek/tools/with aREADME.mddescribing the self-describing frontmatter convention (# name:/# description:/# usage:) and anexample.shthat 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 aREADME.mdand anexample/PLUGIN.mdplaceholder using the same frontmatter shape asSKILL.md. Plugins are not loaded automatically either; reference them from a skill or MCP wrapper when you want them active.--allnow scaffolds MCP + skills + tools + plugins together.--clean— list~/.deepseek/sessions/checkpoints/latest.jsonandoffline_queue.jsonif they exist. Pass--forceto 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], <deepseek:tool_call, <tool_call, <invoke ,
<function_calls> — 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.