Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
2f33293
feat(cli): 添加可插拔状态栏 (statusline)
dengmik-commits Jun 23, 2026
01b6805
chore(vscode-ide-companion): 更新 package.json 配置
hqwlkj Jun 23, 2026
ae85c2c
Merge branch 'lessweb:main' into main
hqwlkj Jun 23, 2026
ad11d9a
feat(cli): 支持通过 --resume 参数恢复会话
hqwlkj Jun 23, 2026
361f2b1
fix(cli): 验证 --resume 参数中的会话ID有效性
hqwlkj Jun 23, 2026
dc068a6
fix: prevent duplicate statusline when user/project settings are the …
dengmik-commits Jun 23, 2026
a2c74df
fix: statusline provider id dedup, newLine support, and CI type errors
dengmik-commits Jun 23, 2026
2329f8f
merge: resolve esbuild.config.js conflict with upstream/main
dengmik-commits Jun 23, 2026
afc5ca8
fix: resolve permissions.test.ts type errors from upstream merge
dengmik-commits Jun 23, 2026
a3952e1
refactor(cli): 删除未使用的 existsSync 导入
hqwlkj Jun 24, 2026
f4ded9a
feat(cli): 增加Git提交信息和改进界面显示
hqwlkj Jun 24, 2026
637e26d
merge: resolve permissions.test.ts conflict with upstream/main
dengmik-commits Jun 24, 2026
428fd51
Refactor DeepCode server package
Ri0n72Y Jun 24, 2026
3be3140
Harden server auth header parsing
Ri0n72Y Jun 24, 2026
14a4bbb
Use async filesystem reads for server images
Ri0n72Y Jun 24, 2026
5a4e6e2
Make server prompt content image normalization async
Ri0n72Y Jun 24, 2026
b4db5a9
Await async prompt content normalization in routes
Ri0n72Y Jun 24, 2026
26f6470
Add server help version and project root options
Ri0n72Y Jun 24, 2026
5efe0f8
Add server test script
Ri0n72Y Jun 24, 2026
d87ae28
Add server auth tests
Ri0n72Y Jun 24, 2026
46adcdc
Add server option tests
Ri0n72Y Jun 24, 2026
e5dae44
Add server image normalization tests
Ri0n72Y Jun 24, 2026
45638ce
Clarify server JSON body size limit
Ri0n72Y Jun 24, 2026
b2b4b81
Add server request body tests
Ri0n72Y Jun 24, 2026
4aa8d11
Restore core ESM import rewrite script
Ri0n72Y Jun 24, 2026
35fc90b
Add package-local server ESM import rewrite script
Ri0n72Y Jun 24, 2026
3dcfdeb
Use package-local server ESM rewrite script
Ri0n72Y Jun 24, 2026
346ecee
refactor(cli): 重构命令行参数解析并优化启动流程
hqwlkj Jun 25, 2026
24a2ad9
refactor(cli): 重构命令行参数解析和主入口逻辑
hqwlkj Jun 25, 2026
43d0c11
fix: update code examples in statusline documentation and improve mod…
qorzj Jun 25, 2026
f279c83
Merge pull request #193 from dengmik-commits/feat/statusline
qorzj Jun 25, 2026
12b2c09
fix(cli): 修复 Windows Shell 配置时的命令行参数处理顺序
hqwlkj Jun 25, 2026
7c8ece9
refactor(cli): 删除未使用的 PackageInfo 类型定义
hqwlkj Jun 25, 2026
9594f83
Merge branch 'lessweb:main' into main
hqwlkj Jun 25, 2026
05de64c
Merge pull request #194 from hqwlkj/main
qorzj Jun 25, 2026
2fa60d5
style(MessageView): 在消息视图组件中添加左边距
hqwlkj Jun 25, 2026
545a4f5
test(cli): 调整 MessageView 组件中的缩进格式
hqwlkj Jun 25, 2026
7a447b8
refactor(cli): 统一stdio辅助函数导入路径风格
hqwlkj Jun 25, 2026
34ea71f
refactor(cli): 统一stdio辅助函数导入路径风格
hqwlkj Jun 25, 2026
da9f099
feat: move the resume hint out of the exit summary box
qorzj Jun 26, 2026
377e041
fix: the new left margin need to be included in width calculations
qorzj Jun 26, 2026
1050e65
Merge pull request #197 from hqwlkj/main
qorzj Jun 26, 2026
ada6ca7
feat: update AGENTS.md
qorzj Jun 26, 2026
83c139e
fix: initial-session Markdown rendering for VSCode extension
qorzj Jun 26, 2026
f2972d4
chore: update package versions to 0.1.32 for deepcode-cli and deepcod…
qorzj Jun 26, 2026
e47ef58
chore: update package versions to 0.1.33 for deepcode-cli and deepcod…
qorzj Jun 26, 2026
c18d0d8
refactor(ui): 替换所有 process.stdout.write 为统一的写入方法
hqwlkj Jun 26, 2026
47d1f03
feat: enhance prompt attachment manager to support multiple image att…
qorzj Jun 26, 2026
7723ddd
Merge branch 'lessweb:main' into main
hqwlkj Jun 26, 2026
888a20a
feat: added writeStdout() for exact stdout writes with no trailing ne…
qorzj Jun 29, 2026
41115cb
Merge pull request #201 from hqwlkj/main
qorzj Jun 29, 2026
8625cb3
style(cli): 优化选项描述的布局间距
hqwlkj Jun 29, 2026
ed2aa23
Merge pull request #209 from hqwlkj/main
qorzj Jun 29, 2026
1af23b6
Merge 3dcfdebd7b5a4f4764ad0ee301983daa95d459d2 into ed2aa23882d82096c…
Ri0n72Y Jun 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .deepcode/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ packages/
│ ├── prompt.ts # System prompt builder & tool definitions
│ └── settings.ts # Settings resolution from ~/.deepcode/settings.json
├── cli/src/ # Terminal UI (Ink/React)
│ ├── cli.tsx # Entry point — parses args (-p, -v), renders AppContainer
│ ├── ui/views/ # Top-level screens (App, PromptInput, SessionList, PermissionPrompt, etc.)
│ ├── cli.tsx # Entry point — renders AppContainer
│ ├── cli-args.ts # CLI argument parsing (yargs: -p, -r, -v, -h)
│ ├── common/ # Update checker
│ ├── utils/ # stdio helpers, version, package info
│ ├── generated/ # Build-time git commit info
│ ├── ui/views/ # Top-level screens (App, PromptInput, SessionList, PermissionPrompt, WelcomeScreen, UpdatePrompt, McpStatusList, etc.)
│ ├── ui/components/ # Reusable Ink components (MessageView, DropdownMenu, ModelsDropdown, etc.)
│ ├── ui/core/ # Prompt buffer, slash commands, file mentions, clipboard, undo/redo
│ ├── ui/hooks/ # Custom hooks (cursor, history navigation, paste handling, terminal input)
│ ├── ui/hooks/ # Custom hooks (cursor, history navigation, paste handling, terminal input, statusline)
│ ├── ui/contexts/ # React contexts (AppContext, RawModeContext)
│ ├── ui/statusline/ # Pluggable statusline providers (command, module)
│ └── tests/ # UI-focused tests with run-tests.mjs runner
├── vscode-ide-companion/ # VSCode extension companion
│ └── src/ # extension.ts, provider.ts, utils.ts
Expand All @@ -45,6 +50,7 @@ All commands run from the repo root.
| `npm run check` | Runs typecheck + lint + format:check together |
| `npm run build` | Orchestrates full build (scripts/build.js) — compiles core + bundles CLI + copies assets |
| `npm run bundle` | Generates git commit info + esbuild bundle + copies bundled assets |
| `npm run build:vscode` | Builds the VSCode extension companion |
| `npm test` | Runs all workspace tests (`npm run test --workspaces --if-present`) |
| `npm run start` | Runs the locally built CLI (`scripts/start.js`) |
| `npm run build-and-start` | Builds then starts the CLI |
Expand Down Expand Up @@ -115,9 +121,9 @@ A **file history system** (`packages/core/src/common/file-history.ts`) provides

**Slash commands**: `/skills`, `/model`, `/new`, `/init`, `/resume`, `/continue`, `/undo`, `/mcp`, `/raw`, `/exit`, plus dynamic `/skill-name` for each loaded skill.

**Key UI features**: `@` file mentions in the prompt input, `Ctrl+O` to view live process stdout, `Ctrl+V` to paste images, Shift+Enter for newlines, MCP server status display, undo selector, and permission prompts.
**Key UI features**: `@` file mentions in the prompt input, `Ctrl+O` to view live process stdout, `Ctrl+V` to paste images, `Ctrl+X` to clear images, Shift+Enter for newlines, pluggable statusline, MCP server status display, undo selector, and permission prompts.

**CLI flags**: `-p <prompt>` / `--prompt` to auto-submit a prompt on launch, `-v` / `--version`, `-h` / `--help`.
**CLI flags**: `-p <prompt>` / `--prompt` to auto-submit a prompt on launch, `-r [sessionId]` / `--resume [sessionId]` to resume a session or show the session picker, `-v` / `--version`, `-h` / `--help`.

## Agent-Specific Instructions

Expand Down
7 changes: 7 additions & 0 deletions .deepcode/plugins/cwd.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function cwdProvider({ projectRoot }) {
const cwd = process.cwd() || projectRoot || "";
if (!cwd) return "";
const home = process.env.HOME || process.env.USERPROFILE || "";
const display = home && cwd.startsWith(home) ? "~" + cwd.slice(home.length) : cwd;
return display;
}
16 changes: 16 additions & 0 deletions .deepcode/plugins/git-branch.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { execFileSync } from "node:child_process";

export default function gitBranchProvider({ projectRoot }) {
try {
const out = execFileSync("git", ["branch", "--show-current"], {
cwd: projectRoot || process.cwd(),
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
timeout: 1500,
}).trim();
if (!out) return "";
return `git:${out}`;
} catch {
return "";
}
}
13 changes: 13 additions & 0 deletions .deepcode/plugins/model-info.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default function modelInfoProvider({ session }) {
if (!session) return "";
const parts = [];
if (session.model) {
parts.push(session.model);
}
if (session.thinkingEnabled && session.reasoningEffort) {
parts.push(`thinking:${session.reasoningEffort}`);
} else if (session.thinkingEnabled) {
parts.push("thinking");
}
return parts.join(" ");
}
22 changes: 22 additions & 0 deletions .deepcode/plugins/session-stats.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
function formatTokens(n) {
if (n >= 1000) return (n / 1000).toFixed(1).replace(/\.0$/, "") + "k";
return String(n);
}

export default function sessionStatsProvider({ session }) {
if (!session || !session.activeSessionId) {
return "no session";
}
const parts = [];
parts.push(`msgs:${session.messageCount}`);
if (session.requestCount > 0) {
parts.push(`reqs:${session.requestCount}`);
}
if (session.activeTokens > 0 && session.maxContextTokens > 0) {
const pct = Math.round((session.activeTokens / session.maxContextTokens) * 100);
parts.push(`ctx:${formatTokens(session.activeTokens)}/${formatTokens(session.maxContextTokens)} ${pct}%`);
} else if (session.totalTokens > 0) {
parts.push(`tokens:${formatTokens(session.totalTokens)}`);
}
return parts.join(" ");
}
23 changes: 23 additions & 0 deletions .deepcode/plugins/tool-usage.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const TOOL_ORDER = ["bash", "edit", "read", "write", "AskUserQuestion", "UpdatePlan", "WebSearch"];

export default function toolUsageProvider({ session }) {
if (!session || !session.activeSessionId) {
return "";
}
const usage = session.toolUsage;
if (!usage || Object.keys(usage).length === 0) {
return "";
}
// Sort: preferred order first, then by count desc
const sorted = Object.entries(usage).sort((a, b) => {
const ai = TOOL_ORDER.indexOf(a[0]);
const bi = TOOL_ORDER.indexOf(b[0]);
if (ai !== -1 && bi !== -1) return ai - bi;
if (ai !== -1) return -1;
if (bi !== -1) return 1;
return b[1] - a[1];
});

const shortNames = sorted.slice(0, 6);
return shortNames.map(([name, count]) => `${name}×${count}`).join(" ");
}
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,18 @@ cd deepcode-cli
# 安装依赖
npm install

# 本地开发(类型检查 + lint + 格式检查 + 构建)
npm run build

# 运行测试
npm test

# 链接到全局(即本地全局安装)
# CLI本地开发(类型检查 + lint + 格式检查 + 构建)
npm run build

# CLI链接到全局(即本地全局安装)
npm link

# VSCode插件本地开发
npm run build:vscode

```

- 提交 PR 前请确保 `npm run check` 通过(类型检查 + lint + 格式检查)
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Deep Code 使用 `settings.json` 设置文件进行持久化配置,支持两
| `mcpServers` | object | MCP 服务器配置(键为服务名,值为 McpServerConfig 对象) |
| `temperature` | number | 模型采样温度,范围 `0` 到 `2` |
| `enabledSkills` | object | 按 skill 名称启用或禁用 skill 的配置 |
| `statusline` | object | 状态栏插件配置(参见 [statusline.md](./statusline.md)) |

#### `env` 子字段

Expand Down
1 change: 1 addition & 0 deletions docs/configuration_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The following are all the top-level fields supported in `settings.json`, along w
| `mcpServers` | object | MCP server configurations (keys are service names, values are McpServerConfig objects) |
| `temperature` | number | Sampling temperature for LLM, from `0` to `2` |
| `enabledSkills` | object | Per-skill enable/disable map, keyed by skill name |
| `statusline` | object | Status line plugins (see [statusline_en.md](./statusline_en.md)) |

#### `env` Sub-fields

Expand Down
23 changes: 23 additions & 0 deletions docs/server-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# DeepCode Server API

[English](./server-api_en.md) · 中文

```bash
deepcode-server --port 8787
```

默认开启 token 鉴权。stdout 会打印类似:

```text
deepcode server listening on http://127.0.0.1:8787 token=<token>
```

通过以下任一方式传递:

- `?token=<token>`
- `x-deepcode-token: <token>`
- `Authorization: Bearer <token>`

## 范围

Server 暴露现有 DeepCode runtime / CLI-TUI 已有能力作为 http api。斜杠命令含义参考 [README 的“斜杠命令与按键功能”](../README.md#斜杠命令与按键功能)。
23 changes: 23 additions & 0 deletions docs/server-api_en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# DeepCode Server API

English · [中文](./server-api.md)

```bash
deepcode-server --port 8787
```

Token authentication is enabled by default. stdout prints a line similar to:

```text
deepcode server listening on http://127.0.0.1:8787 token=<token>
```

Pass the token with any of:

- `?token=<token>`
- `x-deepcode-token: <token>`
- `Authorization: Bearer <token>`

## Scope

The server exposes existing DeepCode runtime / CLI-TUI capabilities as HTTP APIs. For slash command meanings, see [README “Slash Commands & Keyboard Shortcuts”](../README-en.md#slash-commands--keyboard-shortcuts).
149 changes: 149 additions & 0 deletions docs/statusline.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# 状态栏插件

Deep Code CLI 支持通过插件向终端底部状态栏注入自定义信息(Git 分支、当前时间、token 用量等),无需修改 CLI 源码。状态栏行展示在输入框下方的快捷键提示行下方,所有 provider 的输出会用分隔符拼接后渲染。

## 配置

在 `~/.deepcode/settings.json`(或项目级 `.deepcode/settings.json`)中添加 `statusline` 字段:

```json
{
"statusline": {
"enabled": true,
"refreshMs": 2000,
"separator": " · ",
"providers": [
{
"type": "command",
"id": "git",
"command": "git branch --show-current",
"color": "cyan"
},
{
"type": "module",
"id": "tokens",
"path": "./.deepcode/plugins/tokens.mjs",
"color": "yellow"
}
]
}
}
```

### 字段

| 字段 | 类型 | 说明 |
| ------------- | --------- | ------------------------------------------------------------------- |
| `enabled` | boolean | 是否启用。省略时,只要存在至少一个 provider 即视为启用 |
| `refreshMs` | number | 拉取间隔毫秒。最小 500,默认 2000 |
| `separator` | string | 多个 provider 输出之间的分隔符,默认 `" · "` |
| `providers` | array | provider 列表,按声明顺序渲染 |

## Provider 类型

### `command` —— 执行外部命令

每隔 `refreshMs` 在 shell 中执行一次命令,取 stdout 第一行作为状态栏 segment。

| 字段 | 类型 | 必填 | 说明 |
| ----------- | ------- | ---- | ----------------------------------------------------------------- |
| `type` | string | 是 | 固定为 `"command"` |
| `command` | string | 是 | shell 命令(支持管道、重定向等) |
| `id` | string | 否 | 唯一标识。省略时按下标自动生成 |
| `cwd` | string | 否 | 执行目录。相对路径相对于项目根目录,省略时使用项目根目录 |
| `timeoutMs` | number | 否 | 超时毫秒,默认 1500。超时返回空串 |
| `color` | string | 否 | ink 支持的颜色名(如 `"red"`、`"#229ac3"`) |

示例:

```json
{ "type": "command", "id": "git", "command": "git status -sb | head -1" }
{ "type": "command", "id": "time", "command": "date +%H:%M" }
{ "type": "command", "id": "node", "command": "node -v", "color": "green" }
```

### `module` —— 加载 JS 模块

加载本地 JS/MJS 模块,调用其默认导出函数,把返回值作为 segment 文本。

| 字段 | 类型 | 必填 | 说明 |
| ----------- | ------- | ---- | ----------------------------------------------------------------------------------- |
| `type` | string | 是 | 固定为 `"module"` |
| `path` | string | 是 | 模块路径。相对路径相对于项目根目录 |
| `id` | string | 否 | 唯一标识 |
| `timeoutMs` | number | 否 | 超时毫秒,默认 2000 |
| `color` | string | 否 | ink 支持的颜色 |

模块需导出一个 `default` 函数(或具名 `provider`):

```js
// .deepcode/plugins/tokens.mjs
export default function tokensProvider({ projectRoot, session }) {
// 返回字符串(同步或异步)
if (session?.activeSessionId) {
return `msgs:${session.messageCount} reqs:${session.requestCount} tokens:${session.totalTokens}`;
}
return `tokens: 1.2k`;
}
```

函数接收一个对象 `{ projectRoot: string, session: SessionInfo | null }`,返回 `string` 或 `Promise<string>`。

`SessionInfo` 结构:

| 字段 | 类型 | 说明 |
| ----------------- | ------------------ | --------------------------------------------------- |
| `activeSessionId` | `string \| null` | 当前活跃会话的 ID,无会话时为 `null` |
| `messageCount` | `number` | 当前会话中的消息总数 |
| `requestCount` | `number` | 当前会话中的 LLM API 请求次数 |
| `totalTokens` | `number` | 当前会话中消耗的 token 总数 |

## 安全限制

- **module provider 路径必须位于项目根目录或用户home目录之下**,绝对路径在这两个范围之外会被拒绝加载(防止从任意位置执行代码)。
- 单个 segment 文本被自动:
- 取第一个非空行
- 去除 ANSI 转义序列
- 折叠空白字符
- 截断到 40 个字符(超出加 `…`)
- command provider 的 stdout 最多读取 4 KB。
- 任何 provider 抛错、超时、或返回空字符串,**只跳过该 segment**,不影响其它 provider。

## 行为

- 启动 CLI 后立即触发一次拉取,之后按 `refreshMs` 周期刷新。
- 用户级与项目级配置的 `providers` 数组会**合并**(用户先、项目后);其他字段以项目级为优先。
- 状态栏行在任何场景下都显示(包括 busy、permission prompt 等),不影响 busy 提示。
- 修改配置文件后需重启 CLI 生效(不会热加载)。

## 完整示例

```json
{
"statusline": {
"enabled": true,
"refreshMs": 3000,
"providers": [
{
"type": "command",
"id": "branch",
"command": "git branch --show-current",
"color": "cyan"
},
{
"type": "command",
"id": "dirty",
"command": "git status --porcelain | wc -l | xargs -I{} echo '{} files changed'",
"color": "yellow"
},
{
"type": "module",
"id": "ts-errors",
"path": "./.deepcode/plugins/ts-errors.mjs",
"color": "red",
"timeoutMs": 5000
}
]
}
}
```
Loading