Commands
Thirteen commands: seven wrap an endpoint, three read
local state, two are health checks, one is an escape hatch.
--help on any of them carries the same detail.
chat
POST /chat/completions — the default door, and the only
format that supports chat prefix completion.
ds chat "why is the sky blue"
git diff | ds chat "write a commit message"
ds chat "explain" --file server.go --file server_test.go
ds chat "review this" --model deepseek-v4-pro --effort max
ds chat "and now in one line" --continue
Arguments are the instruction; piped stdin and --file are the
material. All three compose.
| Flag | Effect |
|---|---|
-m, --model | deepseek-v4-flash (default) or deepseek-v4-pro |
-s, --system | System prompt, inline or @file |
--think on|off | Thinking mode. Default is the API's own, which is on |
-e, --effort | low, high or max |
--max-tokens | Cap generated tokens |
--temperature, --top-p | Sampling. Both ignored in thinking mode |
--stop | Stop sequence, repeatable, max 16 |
--response-format | text or json_object |
--tool | Tool definition as JSON or @file, repeatable |
--tool-choice | none, auto, required, or a JSON object |
--prefix | Beta: force the answer to start with this text |
-f, --file | Attach a file's contents, repeatable |
-c, --continue | Continue the conversation named last |
--session NAME | Read and write a named conversation |
--stream=false | Wait for the whole answer |
--reasoning=false | Hide the chain of thought |
--logprobs, --top-logprobs | Token log probabilities |
--user-id | Cache and scheduling isolation |
Multi-turn
The API stores nothing, in any format, so conversations live on your machine.
ds chat "read this spec" --file spec.md --session review
ds chat "now list the risks" --session review
ds session ls
ds session show review
ds session rm review
--continue is the session named last.
Interactive
-i keeps the conversation open and prompts for the next
turn, instead of retyping --continue:
$ ds chat -i "walk me through this codebase" --file main.go
The entry point wires three things together...
· flash · 2.1k in · 180 out · ~$0.000302 · 1.8s
› now what would you change first
The retry loop, because...
› /model pro
model deepseek-v4-pro
› ^D
bye — 4 messages saved as "last"; resume with: deepseek chat -c
It is the same session machinery, so nothing is lost on exit —
ds chat -c resumes it and ds session show last
reads it. /help lists the slash commands: /model,
/think, /effort, /system,
/file, /tokens, /docs,
/new, /save.
^C during an answer abandons that answer and keeps the
conversation; ^D leaves. It needs a terminal and refuses to
combine with --json — for scripted multi-turn use
--session, which is what it is built on.
Tools
ds chat "weather in Hangzhou?" --tool @weather.json
# tool_call call_00_hUj... get_weather({"city": "Hangzhou"})
One tool file works against every format — both the OpenAI
parameters and the Anthropic input_schema spellings
are accepted. The calls are printed, never executed.
anthropic
POST /anthropic/v1/messages — the format Claude Code, the
Anthropic SDKs and the Claude desktop app speak.
ds anthropic "hello"
ds anthropic "hello" --model claude-opus-4-1 --json
Claude model names are accepted and remapped server-side. The usage line shows both names so the cost stays traceable to the model that actually ran. See formats for the mapping.
respond
POST /responses — the format Codex speaks. Two things
live only here: JSON Schema structured output, and a web_search
tool DeepSeek runs server-side.
ds respond "what shipped in Go 1.26" --web-search
ds respond "Berlin" -s "Return city and country." --schema @city.json
--web-search is the whole setup: the search runs on
DeepSeek's side, there is nothing to execute locally, and the searches the
model makes are reported on stderr as they happen. It is the one tool in the
whole API that this CLI can “run” for you, because DeepSeek runs
it. The API ignores the OpenAI knobs (search_context_size,
user_location), and in multi-turn use the server restores
search results replayed from earlier turns by itself.
Flash only, for now.
fim
POST /beta/completions — give it a prefix and an optional
suffix; it writes the middle.
ds fim "def add(a, b):" --suffix " return result"
ds fim --prefix @head.go --suffix @tail.go --max-tokens 200
Beta, with two hard limits: output caps at 4K tokens, and it never thinks.
tokens
Exact token counts, from the tokenizer that will bill you.
ds tokens "why is the sky blue"
ds tokens --file main.go --file main_test.go
git diff | ds tokens
ds tokens --offline --file huge.log # free local estimate
DeepSeek ships no count-tokens endpoint and no Go tokenizer — only a
Python demo and two rules of thumb. But the FIM endpoint takes a raw prompt
with no chat template around it and reports prompt_tokens for
exactly the bytes sent, plus one BOS token. Subtract the one and the count
is exact.
That measurement is a real request: the text goes to
DeepSeek and is billed as input, the same as sending it would have been.
The cost prints on stderr every time. --offline uses
DeepSeek's published character ratios instead — free, and an upper
bound that says so.
docs
DeepSeek's own API documentation, compiled into the binary.
ds docs # every page
ds docs search "context cache"
ds docs show guides/thinking_mode
ds docs ask "does FIM support thinking?"
ds docs changelog # releases, newest first
ds docs sync # refresh from the mirror
67 pages, about 85KB compressed: every page of api-docs.deepseek.com plus the FAQ, which lives outside that site as a JSON blob inside a JavaScript bundle and is not otherwise readable as text.
Only ask costs anything. It selects pages locally, sends
them whole, and instructs the model to answer from them and cite the page,
so a claim can be checked against a URL. Every command here prints how old
the snapshot is, and every page keeps the upstream URL it came from.
status
ds status
Is the API reachable right now, with this key, from this machine. Two calls that generate no tokens, so it is free and safe to run in a loop. That is a different question from DeepSeek's incident page, which reports outages affecting everyone — a working API behind a broken proxy looks fine there and broken here.
models
ds models
The API's model list joined with the published rate card, so the price is on
screen next to the model you are about to pick. --json returns the
API's list alone.
balance
ds balance
Lists every currency the account holds — a real account returns both a USD and a CNY row. Exits 3 when exhausted, the same code a 402 produces anywhere else, so a script can check once up front.
usage
ds usage # today
ds usage --since 7d
ds usage --entries --json # individual calls
Reports the local ledger. See cost.
check
ds check
Calls all six endpoints once. Every probe runs even after one fails,
because "all six rejected the key" is a different diagnosis from "only
/responses is unhappy".
raw
ds raw /models
ds raw /chat/completions --data @request.json
ds raw /anthropic/v1/messages --data @req.json --anthropic-auth
Any path, with this CLI's auth, base URL, retries and error reporting. Every other command is a typed convenience over this one, so an endpoint DeepSeek ships tomorrow is reachable today.
Global flags
| Flag | Effect |
|---|---|
--json | Print the API's own response body, unwrapped |
--jq EXPR | Filter that body through jq |
--api-key, --base-url | Override the resolved values |
--timeout | Default 10m, matching how long the API may hold a connection before inference starts |
-v, -vv | Log HTTP to stderr; -vv adds bodies |
--no-stats | Suppress the token/cost line |
--no-ledger | Do not record the call |
Exit codes
| Code | Meaning | What to do |
|---|---|---|
| 0 | success | — |
| 1 | error | Read stderr |
| 2 | auth | Key missing or rejected. Do not retry |
| 3 | no balance | Top up. Do not retry |
| 4 | rate limited | Back off, then retry |
| 130 | interrupted | — |
Transport failures and 429/5xx are already retried internally with backoff, so a non-zero exit means your own retry loop probably will not help either.