Help us shape the future of Go! Take the 2026 Go Developer Survey

deepseek-cli

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: MIT

README

deepseek

The whole DeepSeek API, from the terminal.
Four wire formats, one binary. Multi-turn that survives the reasoning round-trip. And it tells you what every call cost.

Release CI
Implemented against the DeepSeek API docs of 2026-08-02 Go MIT License

Badges that could rot are held down by tests: TestCheckCoversEveryEndpoint fails if an endpoint is added without deepseek check probing it, and make cover-gate fails CI if coverage drops below its floor.


Unofficial tool. Not affiliated with DeepSeek.

DeepSeek serves the same two models through four different wire formats — OpenAI chat, OpenAI Responses, Anthropic Messages, and FIM. Every other client picks one. This speaks all four, so you can send the same prompt down each and see what actually differs.

It also does the two things curl will not:

  • Keeps multi-turn correct. With tools in play, DeepSeek returns 400 unless every assistant message's reasoning_content is replayed on every later request. --continue handles that; without tools it strips the same field, because replaying it there just burns tokens.
  • Prices every call. DeepSeek's disk KV-cache makes a cached input token 50× cheaper than an uncached one. That split is invisible unless something reads prompt_cache_hit_tokens and does the arithmetic. This does, on every call, and keeps a local ledger.
$ deepseek chat "explain this diff" --file changes.patch
The patch swaps the retry loop for exponential backoff...
· flash · 3.2k in (87% cached) · 412 out (180 think) · ~$0.000178 · 2.1s

Install

One line — detects your platform, installs the binary and both aliases:

curl -sL https://raw.githubusercontent.com/thevibeworks/deepseek-cli/main/install.sh | sh

Or download a binary from Releases:

# macOS (Apple Silicon)
curl -sL https://github.com/thevibeworks/deepseek-cli/releases/latest/download/deepseek_darwin_arm64.tar.gz | tar xz
sudo mv deepseek /usr/local/bin/

# Linux (x86_64)
curl -sL https://github.com/thevibeworks/deepseek-cli/releases/latest/download/deepseek_linux_amd64.tar.gz | tar xz
sudo mv deepseek /usr/local/bin/

Or with Go:

go install github.com/thevibeworks/deepseek-cli/cmd/deepseek@latest

ds and dscli

deepseek is eight characters to type many times a day. The binary answers to ds and dscli as well — not shell aliases, but symlinks to the same binary, so they work in scripts, cron, Makefiles and anywhere a shell alias would not:

ds chat "why is the sky blue"
ds usage --since 7d

install.sh and make install create them. If you installed by hand:

sudo ln -sf deepseek /usr/local/bin/ds
sudo ln -sf deepseek /usr/local/bin/dscli

The binary notices which name invoked it, so ds --help says ds.

Quick start

export DEEPSEEK_API_KEY=sk-...          # https://platform.deepseek.com/api_keys
deepseek check                          # is everything reachable?
deepseek chat "why is the sky blue"

check calls all six endpoints once and reports which answered. Run it first when something is wrong and you do not yet know whether the problem is the key, the balance, the network, a proxy, or one endpoint:

$ deepseek check
https://api.deepseek.com

ok    GET /models                  141ms  deepseek-v4-flash, deepseek-v4-pro
ok    GET /user/balance            126ms  18.48 CNY
ok    POST /chat/completions       651ms  5 in / 1 out
ok    POST /anthropic/v1/messages  590ms  5 in / 1 out
ok    POST /responses              595ms  5 in / 9 out
ok    POST /beta/completions       379ms  4 in / 1 out

all endpoints reachable

Commands

One command per endpoint, named for what it does.

Command Endpoint What it is for
chat POST /chat/completions The default. OpenAI format, the one most tools speak.
anthropic POST /anthropic/v1/messages The format Claude Code and the Anthropic SDKs speak.
respond POST /responses The format Codex speaks. JSON Schema output and server-side web_search live only here.
fim POST /beta/completions Fill in the middle — the shape editors use for inline completion.
models GET /models Available models, joined with the published rate card.
balance GET /user/balance What is left, per currency.
usage (local) What this CLI has spent, from its own ledger.
session (local) The conversations chat --continue replays.
check (all six) Preflight.
raw (anything) Escape hatch — any path, with auth and retries.

Talking to models

deepseek chat "why is the sky blue"
git diff | deepseek chat "write a commit message"
deepseek chat "explain" --file server.go --file server_test.go
deepseek chat "review this" --model deepseek-v4-pro --effort max
deepseek chat "summarise" --system @house-style.md

Arguments are the instruction, pipes and --file are the material. Answers stream to stdout; the chain of thought, the usage line and any warnings go to stderr — so redirecting stdout gets you the answer alone.

Multi-turn

The API is stateless in every format. Conversations live on your machine.

deepseek chat "walk me through this codebase" --file main.go --continue
deepseek chat "now what would you change first"   --continue
deepseek session ls
deepseek session show last

Use --session <name> to keep threads apart. --continue is the session named last.

The other three formats

# Anthropic Messages. Claude model names are accepted and remapped
# server-side; the usage line shows both so cost stays traceable.
deepseek anthropic "hello" --model claude-opus-4-1
# · claude-opus-4-1→pro · 10 in · 8 out · ~$0.000011 · 0.9s

# Responses: JSON Schema output, and a web_search tool DeepSeek runs
deepseek respond "what shipped in Go 1.26" --web-search
deepseek respond "Berlin" -s "Return city and country." --schema @city.json

# FIM: prefix in, suffix optional, the middle comes back
deepseek fim "def add(a, b):" --suffix "    return result"

Tools

Declare a tool once; it works against every format. Both the wrapped OpenAI shape and the bare input_schema Anthropic shape are accepted.

deepseek chat "weather in Hangzhou?" --tool @weather.json
# tool_call call_00_hUj... get_weather({"city": "Hangzhou"})

deepseek anthropic "weather in Hangzhou?" --tool @weather.json   # same file

This prints the calls the model wants made. It does not run them — executing model-chosen commands is an agent's job and a much larger set of safety questions. This is for developing and debugging tool schemas.

Raw

deepseek raw /models
deepseek raw /chat/completions --data @request.json

Every other command is a typed convenience over this one, so anything DeepSeek ships tomorrow is reachable today.

What things cost

Every call prints a usage line to stderr and appends a row to a local JSONL ledger:

$ deepseek usage --since 7d
                   CALLS  IN     CACHED  OUT    COST
deepseek-v4-flash  184    2.1M   78%     94k    $0.19
deepseek-v4-pro    12     88k    41%     11k    $0.03
total              196    2.2M   77%     105k   $0.22

by format: chat 170, anthropic 14, responses 8, fim 4
context cache saved ~$0.23 (1.7M of 2.2M prompt tokens replayed)
costs are estimates from the published USD rate card, not billed amounts

That last line is the point. Cached input costs $0.0028/M against $0.14/M for a miss — structuring prompts so the stable part comes first is worth real money, and this is how you see whether it worked.

Honest limits:

  • Costs are estimates from the published USD rate card, not billed amounts. Token counts are exact, and they are what the ledger stores, so old rows can be repriced when the card changes.
  • DeepSeek has announced peak/off-peak pricing (2× during 09:00–12:00 and 14:00–18:00 Beijing time) with no effective date. It is deliberately not applied — guessing that a call was billed double would be inventing data.
  • --no-ledger skips the write; --no-stats hides the line.

For agents

Built to be scripted. See AGENTS.md for the full contract and skill/SKILL.md for a drop-in agent skill.

deepseek chat "..." --json | jq -r '.choices[0].message.content'
deepseek chat "..." --jq '.usage'
deepseek models --json
  • stdout is data, stderr is status. Safe to pipe.
  • --json prints the API's own response, unwrapped and unmodified, so jq recipes written against the OpenAI or Anthropic APIs keep working.
  • Exit codes carry meaning: 0 ok · 1 error · 2 auth · 3 no balance · 4 rate limited · 130 interrupted.
  • Errors say what to do, not just what broke:
$ deepseek chat hi
Error: Insufficient Balance (HTTP 402)
  out of balance: deepseek balance — top up at https://platform.deepseek.com/top_up

Configuration

Variable Purpose
DEEPSEEK_API_KEY API key.
DEEPSEEK_BASE_URL Override the base URL (proxies, gateways).
DEEPSEEK_CONFIG_DIR Where the key file lives. Default ~/.config/deepseek.
DEEPSEEK_STATE_DIR Ledger and sessions. Default ~/.local/state/deepseek.

Both directories respect XDG_CONFIG_HOME / XDG_STATE_HOME. To keep the key out of the environment, put it in a file instead:

mkdir -p ~/.config/deepseek && chmod 700 ~/.config/deepseek
printf 'sk-...' > ~/.config/deepseek/api_key && chmod 600 ~/.config/deepseek/api_key

Global flags: --api-key --base-url --json --jq --timeout --verbose/-v (-vv adds bodies) --no-stats --no-ledger.

Good to know

Things the API does that surprise people, and that this tool surfaces rather than hides:

  • Thinking is on by default and costs a flat 79 extra input tokens per request for its template — measured, and constant regardless of prompt length — before a single reasoning token is generated. On short factual work that is most of the bill; --think off removes it.
  • Text only. DeepSeek rejects image, document and search-result content blocks in every format.
  • The Responses endpoint is flash-only for now.
  • FIM caps output at 4K tokens and ignores thinking entirely.
  • Slow starts are normal. The API holds the connection with : keep-alive comments for up to ten minutes before inference begins. The default --timeout matches.

Development

make            # build
make check      # fmt + vet + test + build
make test       # 103 tests, no network required
make cover-gate # fails under the coverage floor

Zero runtime dependencies beyond cobra and golang.org/x/term; the API client is hand-rolled. --jq shells out to jq if you use it.

Design rulings and the reasons behind them: TASTE.md.

License

MIT — see LICENSE.

Directories

Path Synopsis
cmd
deepseek command
Command deepseek talks to the DeepSeek API from the shell.
Command deepseek talks to the DeepSeek API from the shell.
internal
cli
Package cli assembles the deepseek command tree.
Package cli assembles the deepseek command tree.
deepseek
Package deepseek is a hand-rolled client for the whole DeepSeek API: the OpenAI-format chat and FIM endpoints, the OpenAI Responses format, the Anthropic Messages format, plus models and balance.
Package deepseek is a hand-rolled client for the whole DeepSeek API: the OpenAI-format chat and FIM endpoints, the OpenAI Responses format, the Anthropic Messages format, plus models and balance.
ledger
Package ledger records what every API call cost, as an append-only JSONL file.
Package ledger records what every API call cost, as an append-only JSONL file.
session
Package session persists chat conversations between invocations.
Package session persists chat conversations between invocations.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL