@deepseekcode/cli
v1.0.29
Published
DeepSeekCode TypeScript CLI
Readme
@deepseekcode/cli
Terminal UI (TUI) for the DeepSeekCode TypeScript runtime. Built on Ink (React-for-terminal).
Usage
bun --filter @deepseekcode/cli build
node packages/cli/dist/cli.js run # Connect to remote server
node packages/cli/dist/cli.js start # Start local in-process runtime
node packages/cli/dist/cli.js exec <cmd> # Non-interactive execution
node packages/cli/dist/cli.js codeview # AI code review
node packages/cli/dist/cli.js --resume # Resume last sessionArchitecture
packages/cli/src/
main.ts # Entry point — CLI arg parser, startup lifecycle
App.tsx # Root React component (connected gating, animation clock control)
client.ts # WebSocket client (DeepSeekCodeClient)
localClient.ts # In-process runtime client (LocalRuntimeClient)
store.ts # Microtask-batched state store
ink/ # Forked Ink renderer (frame budget, Yoga caching)
hooks/ # React hooks for state, animation, WebSocket, mouse, keyboard
components/ # UI components (ChatArea, StatusLine, TextInput, etc.)
tui/ # Interaction primitives (selection, navigation, search)
commands/ # Slash command registry and handlers
utils/ # Utilities (session persistence, logging, config)Performance: OOM Prevention
The Ink renderer + React reconciler creates significant memory pressure per rendered frame. The following measures prevent OOM in large/heavy sessions:
Animation Clock Governance
- Global gate:
setAnimationsEnabled(false)pauses ALL animation subscribers during startup. Animations only activate after WebSocketconnected. - Dynamic tick rate: idle (2fps) → active (5fps) → streaming (10fps). Default changed from 50ms/20fps to 200ms/5fps.
- Auto-stop: Clock stops entirely when last subscriber unsubscribes.
Frame Budget Control
- Ink's
onRendermeasures frame generation time; if a frame completes faster than 100ms since the last, it's skipped (up to 3 consecutive skips before force-render). - Combined with
FRAME_INTERVAL_MS=500throttle on the render scheduler.
Yoga Layout Versioning
onComputeLayouttracks alayoutVersioncounter; if no DOM mutations happened since last computation,calculateLayout()(the most expensive per-frame operation) is skipped entirely.
Lazy Hook Mounting
- Interaction hooks (mouse wheel, text selection, keyboard selection, message navigation) only mount after
connected === true. - Startup state updates are batched into a single
updateAppState()call (from 3-5 sequential calls).
Theme System
The CLI supports multi-theme with dynamic switching, a t Proxy for live access, and JSON file loading compatible with MiMo-Code / opencode format.
Built-in Themes
| Theme | Env Value | Style |
|-------|-----------|-------|
| Dark (default) | dark | ANSI named colors, broad compat |
| Light | light | Light terminal variant |
| Nord | nord | ❄️ Arctic blue-grey palette |
| Dracula | dracula | 🧛 Dark purple-vibrant |
| Monokai | monokai | 🎨 Classic code editor |
| One Dark | one-dark | 🌙 Atom's iconic dark |
| Tokyo Night | tokyo-night | 🌃 Deep navy + vibrant accents |
Usage
# Via environment variable
DEEPSEEKCODE_THEME=nord node packages/cli/dist/cli.js run
DEEPSEEKCODE_THEME=dracula node packages/cli/dist/cli.js start
DEEPSEEKCODE_THEME=/path/to/my-theme.json node packages/cli/dist/cli.js run
# Custom color overrides (partial merge on current theme)
DEEPSEEKCODE_THEME_COLORS='{"primary":"#ff0000"}' node packages/cli/dist/cli.js runProgrammatic API
import { t, setTheme, getTheme, registerTheme, listThemes } from './theme.js'
// Components always use the live theme via Proxy
<Text color={t.primary}>Brand</Text>
<Text color={t.error}>Error</Text>
<Text backgroundColor={t.success}>Success</Text>
// Switch at runtime
setTheme('nord')
// Register a custom theme
registerTheme('my-theme', { primary: '#ff6600', bg: '#1a1a2e', ... })
setTheme('my-theme')
// Enumerate all registered themes
listThemes() // ['dark', 'dracula', 'light', 'monokai', ...]Architecture
src/theme/
├── types.ts # ThemeColors interface (60+ color keys)
├── registry.ts # Theme registry + t Proxy
├── detect.ts # Terminal background detection (OSC 11)
├── loader.ts # JSON theme file loader
└── builtins/ # Built-in theme factories
├── index.ts, dark.ts, light.ts,
├── nord.ts, dracula.ts, monokai.ts,
├── one-dark.ts, tokyo-night.tsThe t Proxy (src/theme/registry.ts) forwards every property access to the active theme via getTheme(), so t.primary always returns the current theme's primary color even after setTheme() — no re-import needed.
Config
The CLI reads ~/.agent/config.yaml.
backend_url: http://localhost:8080
ws_url: ws://localhost:8081/ws
workspace_dir: /path/to/workspaceAuto-Update
dscode 每次启动会异步查询 npm 上的最新版本(不阻塞启动)。当发现新版本时,
默认会在后台自动重装全局包(npm install -g @deepseekcode/cli@latest),
新版本在下次启动时生效,升级结果会在下一次启动时报告。
- 仅对「全局 npm 安装」生效;源码开发环境、
npx/bunx临时缓存不会误升级。 - 关闭自动安装(保留版本提示):
DEEPSEEKCODE_NO_AUTO_UPDATE=1或--no-auto-update - 连版本检查一起关闭:
DEEPSEEKCODE_NO_UPDATE_CHECK=1或--no-update-check
Development
bun --filter @deepseekcode/cli typecheck
bun --filter @deepseekcode/cli build
bun --filter @deepseekcode/cli test