codemini-cli 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/OPERATIONS.md CHANGED
@@ -110,6 +110,7 @@ Use this when you want to separate:
110
110
  ```text
111
111
  /help
112
112
  /commands
113
+ /brainstorm <question>
113
114
  /config list
114
115
  /config get <key>
115
116
  /history list
@@ -144,6 +145,14 @@ Continue into the relevant files and explain how skill loading works.
144
145
  Find where shell.default is used and summarize the config path.
145
146
  ```
146
147
 
148
+ ### Brainstorm before coding
149
+
150
+ ```text
151
+ /brainstorm Should login retry stay local or become a shared helper?
152
+ ```
153
+
154
+ Use this when the implementation path is still fuzzy and you want the CLI to compare a few approaches before any code change.
155
+
147
156
  ### Spec and plan flow
148
157
 
149
158
  ```text
@@ -170,12 +179,18 @@ Execute this plan step by step.
170
179
  ```powershell
171
180
  codemini skill list
172
181
  codemini skill inspect superpowers-lite
173
- codemini skill enable brainstorming-lite
174
- codemini skill disable brainstorming-lite
182
+ codemini skill enable brainstorm
183
+ codemini skill disable brainstorm
175
184
  codemini skill reindex
176
185
  ```
177
186
 
178
187
  ## Better Prompt Patterns
188
+ ## Release Management
189
+
190
+ ### Release Checklist
191
+
192
+ For information on how to perform a release, please see the [Release Checklist](RELEASE_CHECKLIST.md) document.
193
+
179
194
 
180
195
  These usually work better:
181
196
 
package/README.md CHANGED
@@ -23,6 +23,10 @@ It is designed for teams that want a coding assistant that feels practical, cont
23
23
  - Windows-aware shell profile with PowerShell-focused defaults
24
24
  - Safe mode enabled by default
25
25
  - Built-in lite skills for planning, execution, and collaboration
26
+ - Configurable reply language through `ui.reply_language` (`zh` / `en`)
27
+ - Richer slash completion with priority sorting, inline descriptions, and left/right paging
28
+ - Structured code tools for small models: `locate`, `open_target`, `edit_target`
29
+ - More conservative `plan auto` acceptance checks with reviewer/tester goal checklists
26
30
  - Tone presets through `soul`, without changing plans or code behavior
27
31
  - Sub-agents for planning, coding, review, and testing
28
32
 
@@ -32,6 +36,7 @@ It is designed for teams that want a coding assistant that feels practical, cont
32
36
  codemini config set gateway.base_url http://your-internal-gateway/v1
33
37
  codemini config set gateway.api_key your_token
34
38
  codemini config set shell.default powershell
39
+ codemini config set ui.reply_language zh
35
40
  codemini config set model.name your-30b-model
36
41
  codemini doctor
37
42
  codemini
@@ -54,7 +59,44 @@ codemini doctor
54
59
  codemini skill list|install|enable|disable|inspect|reindex
55
60
  ```
56
61
 
62
+ ### Notable Workflow Features
63
+
64
+ - `ui.reply_language` controls the assistant reply language at the prompt layer and also nudges generated docs and code comments to match
65
+ - Slash completion now prioritizes important commands and config keys, shows short descriptions, and supports `←/→` page switching
66
+ - Ambiguous feature requests can pause for lightweight brainstorming first, and `/brainstorm <question>` gives an explicit way to compare options before coding
67
+ - `plan auto` now turns the original goal into an acceptance checklist, uses a lighter chain only for truly tiny tasks, and treats unmet checklist items as failure signals
68
+ - Structured code tools reduce shell-noise for small models by preferring `locate -> open_target -> edit_target`
69
+
70
+ ### Skill Loading
71
+
72
+ CodeMini CLI loads skills from these locations:
73
+
74
+ - Bundled repo skills: `skills/<name>/SKILL.md`
75
+ - Installed global skills: `<base-config-dir>/skills/<name>/SKILL.md`
76
+ - Project-scoped legacy skills: `.coder/skills/<name>/SKILL.md`
77
+
78
+ The base config directory is resolved in this order:
79
+
80
+ - `CODEMINI_CONFIG_DIR`
81
+ - `COMPANY_CODER_CONFIG_DIR`
82
+ - Windows: `%APPDATA%\\codemini-cli\\`
83
+ - macOS: `~/Library/Preferences/codemini-cli`
84
+ - Linux/XDG: `$XDG_CONFIG_HOME/codemini-cli`
85
+ - Fallback in restricted environments: `.codemini-cli/`
86
+
87
+ ### Brainstorming
88
+
89
+ Use `/brainstorm <question>` when you want the assistant to stop before coding, compare 2-3 approaches, and choose one direction first.
90
+
91
+ ```text
92
+ /brainstorm Should login retry stay local or become a shared helper?
93
+ ```
94
+
57
95
  ### Documentation
96
+ ### Release Checklist
97
+
98
+ For information on how to perform a release, please see the [Release Checklist](RELEASE_CHECKLIST.md) document.
99
+
58
100
 
59
101
  - Operator guide and common command patterns: [OPERATIONS.md](/mnt/e/Git%20Projects/qurio-coder/OPERATIONS.md)
60
102
  - Packaging and deployment guide: [deployment.md](/mnt/e/Git%20Projects/qurio-coder/deployment.md)
@@ -95,6 +137,10 @@ CodeMini CLI 是一个为小模型工作流优化过的代码助手 CLI,重点
95
137
  - 面向 Windows 的 PowerShell 默认配置
96
138
  - safe mode 默认开启
97
139
  - 内置 lite skills,覆盖规划、执行和协作
140
+ - 支持通过 `ui.reply_language` 配置回复语言,当前支持 `zh` / `en`
141
+ - slash 补全支持优先级排序、右侧简短说明和左右分页
142
+ - 为小模型补了结构化代码工具:`locate`、`open_target`、`edit_target`
143
+ - `plan auto` 会基于原始目标生成验收清单,并更保守地处理 reviewer/tester 结果
98
144
  - `soul` 只影响语气,不影响计划和代码行为
99
145
  - 支持 planner、coder、reviewer、tester 多角色 sub-agent
100
146
 
@@ -104,6 +150,7 @@ CodeMini CLI 是一个为小模型工作流优化过的代码助手 CLI,重点
104
150
  codemini config set gateway.base_url http://your-internal-gateway/v1
105
151
  codemini config set gateway.api_key your_token
106
152
  codemini config set shell.default powershell
153
+ codemini config set ui.reply_language zh
107
154
  codemini config set model.name your-30b-model
108
155
  codemini doctor
109
156
  codemini
@@ -126,6 +173,39 @@ codemini doctor
126
173
  codemini skill list|install|enable|disable|inspect|reindex
127
174
  ```
128
175
 
176
+ ### 近期工作流增强
177
+
178
+ - `ui.reply_language` 通过 prompt 层控制模型回复语言,也会尽量让生成文档和代码注释跟随该语言
179
+ - slash 补全会优先展示更重要的命令和配置项,显示简短说明,并支持 `←/→` 翻页
180
+ - 对于需求仍不明确的功能请求,CLI 会先偏向轻量 brainstorm;也可以显式使用 `/brainstorm <问题>` 先比较方案再决定是否编码
181
+ - `plan auto` 会先把原始目标展开成验收清单;只有真正很小的任务才会走轻量链路;如果 reviewer 或 tester 标记了未满足或未验证的验收项,就不会按成功处理
182
+ - 为了减少小模型被 shell 原始输出干扰,新增了 `locate -> open_target -> edit_target` 这套结构化代码工具流
183
+
184
+ ### Skill 加载位置
185
+
186
+ CodeMini CLI 会从这些位置读取 skill:
187
+
188
+ - 仓库内置 skill:`skills/<name>/SKILL.md`
189
+ - 全局已安装 skill:`<base-config-dir>/skills/<name>/SKILL.md`
190
+ - 项目级旧式 skill:`.coder/skills/<name>/SKILL.md`
191
+
192
+ `base-config-dir` 的解析顺序是:
193
+
194
+ - `CODEMINI_CONFIG_DIR`
195
+ - `COMPANY_CODER_CONFIG_DIR`
196
+ - Windows:`%APPDATA%\\codemini-cli\\`
197
+ - macOS:`~/Library/Preferences/codemini-cli`
198
+ - Linux / XDG:`$XDG_CONFIG_HOME/codemini-cli`
199
+ - 受限环境回退:`.codemini-cli/`
200
+
201
+ ### Brainstorm 用法
202
+
203
+ 当你希望助手先收敛方向、不要立即写代码时,可以使用:
204
+
205
+ ```text
206
+ /brainstorm Should login retry stay local or become a shared helper?
207
+ ```
208
+
129
209
  ### 文档入口
130
210
 
131
211
  - 操作手册与常见命令组合:[OPERATIONS.md](/mnt/e/Git%20Projects/qurio-coder/OPERATIONS.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codemini-cli",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Coding CLI optimized for small-model workflows and Windows PowerShell",
5
5
  "keywords": [
6
6
  "cli",
@@ -1,11 +1,16 @@
1
1
  ---
2
- name: brainstorming-lite
3
- description: Lightweight brainstorming skill for 30B-class models. Clarify scope, ask one question at a time, compare a few options, and converge before implementation.
2
+ name: brainstorm
3
+ description: Lightweight brainstorming skill for 30B-class models. Use when a feature or behavior request is still unclear and the agent should compare a few approaches before coding.
4
4
  version: 0.1.0
5
5
  ---
6
6
 
7
7
  Use this skill before adding new behavior, new features, or meaningful workflow changes.
8
8
 
9
+ Primary purpose:
10
+ - stop premature coding when the request is still fuzzy
11
+ - narrow the decision to a small number of approaches
12
+ - leave with one chosen direction
13
+
9
14
  Rules:
10
15
 
11
16
  1. Ask one question at a time.
@@ -23,12 +28,39 @@ Write only enough design for the current scope. Do not inflate a simple task int
23
28
  5. Confirm before implementation.
24
29
  Summarize the chosen direction in a few bullets or a short paragraph, then move to execution only after alignment.
25
30
 
31
+ 6. No code before convergence.
32
+ Do not write implementation code, pseudo-code, or file edits while the direction is still being chosen.
33
+
34
+ Output format:
35
+
36
+ Option 1:
37
+ - idea:
38
+ - pros:
39
+ - cons:
40
+
41
+ Option 2:
42
+ - idea:
43
+ - pros:
44
+ - cons:
45
+
46
+ Option 3 (optional):
47
+ - idea:
48
+ - pros:
49
+ - cons:
50
+
51
+ Decision:
52
+ - chosen:
53
+ - reason:
54
+
55
+ After decision:
56
+ - stop after the chosen direction unless the user clearly asks to continue into implementation
57
+
26
58
  Suggested flow:
27
59
  - Restate the task briefly
28
- - Ask the next best question
60
+ - Ask the next best question when a key uncertainty blocks implementation
29
61
  - Propose options with tradeoffs
30
62
  - Confirm the chosen approach
31
- - Hand off to plan execution
63
+ - Stop at a clear decision point
32
64
 
33
65
  Avoid:
34
66
  - large ceremonies
@@ -6,6 +6,12 @@ version: 0.1.0
6
6
 
7
7
  Use this skill as the default lightweight operating style for coding work.
8
8
 
9
+ Primary behavior:
10
+ - keep momentum on clear tasks
11
+ - slow down before coding when the request is ambiguous
12
+ - keep edits local
13
+ - verify before claiming success
14
+
9
15
  Core rules:
10
16
 
11
17
  1. Search first.
@@ -21,15 +27,19 @@ When a task can be split cleanly, use sub-agents for bounded subtasks so the mai
21
27
  - a tiny file evidence packet
22
28
  - a concrete expected output
23
29
 
24
- 4. Read and write with intent.
30
+ 4. Do not code against unclear requirements.
31
+ If the requested behavior, scope, or acceptance is unclear, do not jump into implementation. Ask the next best question or use `brainstorm` to compare a few small options and converge first.
32
+
33
+ 5. Read and write with intent.
25
34
  Use `read_file` only when shell output is not enough. Use `write_file` for edits. Avoid unnecessary tool calls and avoid rereading the same file without a reason.
26
35
 
27
- 5. Verify before claiming success.
36
+ 6. Verify before claiming success.
28
37
  Run the relevant test, check, or command before saying work is fixed or complete.
29
38
 
30
39
  Default workflow:
31
40
  - Search with `rg`
32
41
  - Inspect local context
42
+ - If the request is unclear, pause for clarification or brainstorm
33
43
  - Plan the next smallest step
34
44
  - Delegate if the work is independent
35
45
  - Edit
package/src/cli.js CHANGED
@@ -4,7 +4,7 @@ import { handleConfig } from './commands/config.js';
4
4
  import { handleDoctor } from './commands/doctor.js';
5
5
  import { handleSkill } from './commands/skill.js';
6
6
 
7
- const VERSION = '0.1.0';
7
+ const VERSION = '0.1.15';
8
8
 
9
9
  function printHelp() {
10
10
  console.log(`codemini ${VERSION}
@@ -61,6 +61,24 @@ function summarizeToolResult(result) {
61
61
  if (stderr) return `${lead}exit ${obj.code ?? 0}\nstderr: ${stderr}`;
62
62
  return `${lead}exit ${obj.code ?? 0}`;
63
63
  }
64
+ if ('task_id' in obj && 'startup_confirmed' in obj) {
65
+ const status = trimInline(obj.status || 'unknown', 32);
66
+ const taskId = trimInline(obj.task_id || '', 24);
67
+ const source = trimInline(obj.startup_source || '', 24);
68
+ const logs = Array.isArray(obj.recent_logs) ? trimInline(obj.recent_logs.slice(-1)[0] || '', 96) : '';
69
+ return `${taskId || 'service'} ${status}${source ? ` (${source})` : ''}${logs ? `\n${logs}` : ''}`;
70
+ }
71
+ if ('services' in obj && Array.isArray(obj.services)) {
72
+ const count = obj.services.length;
73
+ const first = obj.services[0];
74
+ const lead = first?.task_id ? `${trimInline(first.task_id, 24)} ${trimInline(first.status || 'unknown', 24)}` : '';
75
+ return `services(${count})${lead ? `\n${lead}` : ''}`;
76
+ }
77
+ if ('task_id' in obj && 'recent_logs' in obj) {
78
+ const taskId = trimInline(obj.task_id || '', 24);
79
+ const logs = Array.isArray(obj.recent_logs) ? trimInline(obj.recent_logs.slice(-1)[0] || '', 96) : '';
80
+ return `${taskId || 'service logs'}${logs ? `\n${logs}` : ''}`;
81
+ }
64
82
  if ('created' in obj && Array.isArray(obj.created)) {
65
83
  return `created ${obj.created.length} task(s)`;
66
84
  }
@@ -96,6 +114,17 @@ function formatToolDisplayName(name, args) {
96
114
  const command = trimInline(args?.command || '', 96);
97
115
  return command ? `${name}(${command})` : name;
98
116
  }
117
+ if (name === 'start_service') {
118
+ const command = trimInline(args?.command || args?.cmd || '', 96);
119
+ return command ? `${name}(${command})` : name;
120
+ }
121
+ if (name === 'list_services') {
122
+ return name;
123
+ }
124
+ if (name === 'get_service_status' || name === 'get_service_logs' || name === 'stop_service') {
125
+ const taskId = trimInline(args?.task_id || args?.taskId || '', 96);
126
+ return taskId ? `${name}(${taskId})` : name;
127
+ }
99
128
  if (
100
129
  name === 'locate' ||
101
130
  name === 'open_target' ||
@@ -106,8 +106,6 @@ const SUB_AGENT_CONTEXT_MAX_MESSAGES = 4;
106
106
  const SUB_AGENT_CONTEXT_MAX_CHARS = 1200;
107
107
  const SUB_AGENT_EVIDENCE_MAX_ITEMS = 3;
108
108
  const SUB_AGENT_HANDOFF_MAX_ITEMS = 6;
109
- const AUTO_SKILL_NAMES = ['superpowers-lite', 'brainstorming-lite', 'executing-plan-lite'];
110
-
111
109
  function getSubAgentRolePrompt(role) {
112
110
  if (role === 'planner') {
113
111
  return 'You are a planning sub-agent. Produce a concrete implementation plan with risks and verification.';
@@ -430,6 +428,40 @@ function buildGoalRequirementPacket(goal, role) {
430
428
  return lines.join('\n');
431
429
  }
432
430
 
431
+ function buildAutoPlanPlannerGuidance() {
432
+ return [
433
+ 'Auto-plan planning rules:',
434
+ '- If the goal still leaves room for multiple approaches, choose one practical direction before planning execution.',
435
+ '- Prefer the smallest local approach that satisfies the goal.',
436
+ '- Do not output multiple alternative branches in the final plan.',
437
+ '- Turn the chosen direction into concrete execution steps for coder, reviewer, and tester.',
438
+ '- Keep the plan ordered, implementation-oriented, and easy for small sub-agents to follow.'
439
+ ].join('\n');
440
+ }
441
+
442
+ function buildAutoPlanExecutionGuidance(role) {
443
+ const common = [
444
+ 'Auto-plan execution rules:',
445
+ '- Work in the smallest useful step.',
446
+ '- Read the target code before editing.',
447
+ '- Prefer local changes over broad refactors.',
448
+ '- Prefer narrow verification with concrete evidence before claiming success.'
449
+ ];
450
+
451
+ if (role === 'coder') {
452
+ common.push('- Keep edits tightly scoped to the chosen plan direction.');
453
+ common.push('- Avoid speculative cleanup or unrelated improvements.');
454
+ } else if (role === 'reviewer') {
455
+ common.push('- Review against the chosen plan direction and the acceptance checklist.');
456
+ common.push('- Call out missing requested behavior, regression risk, and unverified claims.');
457
+ } else if (role === 'tester') {
458
+ common.push('- Prefer running the narrowest real verification command that matches the changed area.');
459
+ common.push('- Distinguish clearly between verified behavior and assumptions.');
460
+ }
461
+
462
+ return common.join('\n');
463
+ }
464
+
433
465
  async function pathExists(targetPath) {
434
466
  try {
435
467
  await fs.access(targetPath);
@@ -536,15 +568,19 @@ function isSkillEnabled(config, name) {
536
568
  function selectAutoSkillNames(text = '') {
537
569
  const input = String(text || '').toLowerCase();
538
570
  const selected = ['superpowers-lite'];
539
- if (
540
- /(brainstorm|头脑风暴|方案|思路|设计一下|设计方案|怎么做|如何做|approach|options?)/i.test(input)
541
- ) {
542
- selected.push('brainstorming-lite');
543
- }
544
- if (
545
- /(按计划|执行计划|继续执行|下一步|implement|execute|carry out|完成验证|verify|plan)/i.test(input)
546
- ) {
547
- selected.push('executing-plan-lite');
571
+
572
+ const explicitBrainstorm =
573
+ /(brainstorm|头脑风暴|方案|思路|设计一下|设计方案|怎么做|如何做|approach|options?)/i.test(input);
574
+ const ambiguitySignals =
575
+ /(not sure|unsure|unclear|help me think|let'?s think|should we|which (?:approach|option|way)|best way|trade-?off|vs\b|versus|or should|要不要|不确定|不明确|先别写|先不要写|先讨论|先想一下|哪个方案|怎么设计|如何设计|取舍|还是)/i.test(
576
+ input
577
+ );
578
+ const featureRequest =
579
+ /\b(add|build|create|implement|support|introduce|design|refactor|change|update)\b/i.test(input) ||
580
+ /(新增|增加|实现|支持|设计|重构|改造|调整)/i.test(input);
581
+
582
+ if (explicitBrainstorm || (ambiguitySignals && featureRequest)) {
583
+ selected.push('brainstorm');
548
584
  }
549
585
  return selected;
550
586
  }
@@ -953,6 +989,7 @@ async function buildPlanFromSpecWithModel({
953
989
  model,
954
990
  systemPrompt
955
991
  }) {
992
+ const projectConstraints = await inferProjectImplementationConstraints(process.cwd());
956
993
  const prompt = [
957
994
  'Convert the provided engineering spec into an implementation plan in markdown.',
958
995
  'Use this structure exactly:',
@@ -972,7 +1009,7 @@ async function buildPlanFromSpecWithModel({
972
1009
  { role: 'system', content: `${systemPrompt}\n${prompt}` },
973
1010
  {
974
1011
  role: 'user',
975
- content: `Spec path: ${specPath || '(inline)'}\n\n${specText}`
1012
+ content: `Spec path: ${specPath || '(inline)'}\n\nProject implementation constraints:\n${projectConstraints}\n\n${specText}`
976
1013
  }
977
1014
  ],
978
1015
  timeoutMs: config.gateway.timeout_ms || 90000,
@@ -981,6 +1018,84 @@ async function buildPlanFromSpecWithModel({
981
1018
  return String(result.text || '').trim();
982
1019
  }
983
1020
 
1021
+ async function collectLikelyImplementationFiles(cwd) {
1022
+ const candidates = [];
1023
+ const roots = ['src', 'app', 'lib'];
1024
+ const preferredExts = new Set(['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs']);
1025
+
1026
+ async function visit(dir) {
1027
+ let entries = [];
1028
+ try {
1029
+ entries = await fs.readdir(dir, { withFileTypes: true });
1030
+ } catch {
1031
+ return;
1032
+ }
1033
+ for (const entry of entries) {
1034
+ if (entry.name === 'node_modules' || entry.name === '.git' || entry.name === '.coder') continue;
1035
+ const abs = path.join(dir, entry.name);
1036
+ if (entry.isDirectory()) {
1037
+ await visit(abs);
1038
+ continue;
1039
+ }
1040
+ if (!preferredExts.has(path.extname(entry.name).toLowerCase())) continue;
1041
+ candidates.push(path.relative(cwd, abs).replace(/\\/g, '/'));
1042
+ if (candidates.length >= 8) return;
1043
+ }
1044
+ }
1045
+
1046
+ for (const root of roots) {
1047
+ const absRoot = path.join(cwd, root);
1048
+ if (!(await pathExists(absRoot))) continue;
1049
+ await visit(absRoot);
1050
+ if (candidates.length >= 8) break;
1051
+ }
1052
+ return candidates.slice(0, 8);
1053
+ }
1054
+
1055
+ async function inferProjectImplementationConstraints(cwd) {
1056
+ const hints = [];
1057
+ const packageJsonPath = path.join(cwd, 'package.json');
1058
+ const pyprojectPath = path.join(cwd, 'pyproject.toml');
1059
+ const cargoPath = path.join(cwd, 'Cargo.toml');
1060
+ const goModPath = path.join(cwd, 'go.mod');
1061
+
1062
+ if (await pathExists(packageJsonPath)) {
1063
+ hints.push('- Detected package.json in the workspace.');
1064
+ hints.push('- Prefer JavaScript/TypeScript style paths and file names that fit the existing repo.');
1065
+ hints.push('- Reuse existing src/*.js, src/*.ts, or neighboring modules before inventing new utility modules.');
1066
+ }
1067
+ if (await pathExists(pyprojectPath)) {
1068
+ hints.push('- Detected pyproject.toml in the workspace.');
1069
+ hints.push('- Prefer Python modules and package layout that already exist in this repo.');
1070
+ }
1071
+ if (await pathExists(cargoPath)) {
1072
+ hints.push('- Detected Cargo.toml in the workspace.');
1073
+ hints.push('- Prefer Rust crate/module layout that matches the current workspace.');
1074
+ }
1075
+ if (await pathExists(goModPath)) {
1076
+ hints.push('- Detected go.mod in the workspace.');
1077
+ hints.push('- Prefer Go package paths and file names already present in the repo.');
1078
+ }
1079
+
1080
+ if (hints.length === 0) {
1081
+ hints.push('- No strong language marker was detected automatically.');
1082
+ hints.push('- Infer the implementation language from the referenced files in the spec and preserve that language family.');
1083
+ }
1084
+
1085
+ const likelyFiles = await collectLikelyImplementationFiles(cwd);
1086
+ if (likelyFiles.length > 0) {
1087
+ hints.push('- Likely existing implementation files to reuse first:');
1088
+ for (const file of likelyFiles) {
1089
+ hints.push(` - ${file}`);
1090
+ }
1091
+ hints.push('- Prefer updating one of the listed files when the feature naturally fits there before inventing new modules.');
1092
+ }
1093
+
1094
+ hints.push('- Do not invent files in another language family unless the spec explicitly requires it.');
1095
+ hints.push('- If the spec references existing files, keep the plan anchored to those exact files or their immediate neighbors.');
1096
+ return hints.join('\n');
1097
+ }
1098
+
984
1099
  function clampRange(start, end, max) {
985
1100
  const s = Math.max(1, Math.min(start, max));
986
1101
  const e = Math.max(s, Math.min(end, max));
@@ -1268,7 +1383,8 @@ async function runSubAgentTask({
1268
1383
  config,
1269
1384
  model,
1270
1385
  systemPrompt,
1271
- onAgentEvent
1386
+ onAgentEvent,
1387
+ extraRolePrompt = ''
1272
1388
  }) {
1273
1389
  const subSession = { id: `sub-${Date.now()}`, messages: [] };
1274
1390
  const rolePrompt = getSubAgentRolePrompt(role);
@@ -1320,7 +1436,7 @@ async function runSubAgentTask({
1320
1436
  session: subSession,
1321
1437
  config,
1322
1438
  model,
1323
- systemPrompt: `${systemPrompt}\n${rolePrompt}`,
1439
+ systemPrompt: `${systemPrompt}\n${rolePrompt}${extraRolePrompt ? `\n${extraRolePrompt}` : ''}`,
1324
1440
  onAgentEvent: wrappedOnAgentEvent,
1325
1441
  persistSession: false,
1326
1442
  executionMode: 'auto'
@@ -1346,8 +1462,10 @@ async function buildAutoPlanAndRun({
1346
1462
  sessionId
1347
1463
  }) {
1348
1464
  const requirementPacket = buildGoalRequirementPacket(goal, 'planner');
1349
- const plannerPrompt =
1350
- 'Return strict JSON only with shape {"summary":"...","steps":[{"title":"...","role":"planner|coder|reviewer|tester","task":"..."}]}. No markdown. Always include final reviewer and tester steps.';
1465
+ const plannerPrompt = [
1466
+ buildAutoPlanPlannerGuidance(),
1467
+ 'Return strict JSON only with shape {"summary":"...","steps":[{"title":"...","role":"planner|coder|reviewer|tester","task":"..."}]}. No markdown. Always include final reviewer and tester steps.'
1468
+ ].join('\n');
1351
1469
  let autoPlan = {
1352
1470
  summary: `Auto plan for: ${goal}`,
1353
1471
  steps: [
@@ -1406,7 +1524,8 @@ async function buildAutoPlanAndRun({
1406
1524
  config,
1407
1525
  model,
1408
1526
  systemPrompt,
1409
- onAgentEvent
1527
+ onAgentEvent,
1528
+ extraRolePrompt: buildAutoPlanExecutionGuidance(step.role)
1410
1529
  });
1411
1530
  const outputLooksSuccessful = looksLikeSuccessfulStepOutput(stepResult.text);
1412
1531
  const outputHasFailureSignals = stepOutputHasFailureSignals(step.role, stepResult.text);
@@ -2414,10 +2533,16 @@ export async function createChatRuntime({
2414
2533
  return { type: 'system', text: `Skill is disabled: ${custom.name}` };
2415
2534
  }
2416
2535
 
2417
- const rendered = await expandFileMentions(
2418
- renderCommandPrompt(custom, parsedInput.args),
2419
- process.cwd()
2420
- );
2536
+ const customPrompt =
2537
+ custom.name === 'brainstorm'
2538
+ ? [
2539
+ renderCommandPrompt(custom, []),
2540
+ parsedInput.args.length > 0 ? `Current question:\n${parsedInput.args.join(' ')}` : ''
2541
+ ]
2542
+ .filter(Boolean)
2543
+ .join('\n\n')
2544
+ : renderCommandPrompt(custom, parsedInput.args);
2545
+ const rendered = await expandFileMentions(customPrompt, process.cwd());
2421
2546
  if (custom.metadata.type === 'skill' && onAgentEvent) {
2422
2547
  onAgentEvent({ type: 'skill:start', name: custom.name });
2423
2548
  }
@@ -46,6 +46,11 @@ const DEFAULT_CONFIG = {
46
46
  'insert_before',
47
47
  'insert_after',
48
48
  'generate_diff',
49
+ 'start_service',
50
+ 'list_services',
51
+ 'get_service_status',
52
+ 'get_service_logs',
53
+ 'stop_service',
49
54
  'run_command',
50
55
  'read_file',
51
56
  'write_file'
@@ -141,6 +146,11 @@ function normalizePolicyLists(config) {
141
146
  'insert_before',
142
147
  'insert_after',
143
148
  'generate_diff',
149
+ 'start_service',
150
+ 'list_services',
151
+ 'get_service_status',
152
+ 'get_service_logs',
153
+ 'stop_service',
144
154
  'run_command',
145
155
  'read_file',
146
156
  'write_file',
@@ -118,5 +118,5 @@ export function getEffectivePolicy(config) {
118
118
 
119
119
  export function getShellSystemPrompt(value) {
120
120
  const profile = getShellProfile(value);
121
- return `You are CodeMini CLI working in a ${profile.label} shell environment. Prefer the high-level structured workflow first: use locate to find candidates, open_target to inspect the smallest useful block and receive edit metadata, and edit_target to apply minimal edits. When you need lower-level control, use search_code, read_block, read_symbol_context, validate_edit, replace_block, replace_text, insert_before, insert_after, and generate_diff. Use run_command only when those structured tools are not enough. Use read_file only when structured reads are not enough. Use write_file only for full-file writes and always provide a concrete file path, not a directory. Avoid unnecessary tool calls.`;
121
+ return `You are CodeMini CLI working in a ${profile.label} shell environment. Prefer the high-level structured workflow first: use locate to find candidates, open_target to inspect the smallest useful block and receive edit metadata, and edit_target to apply minimal edits. When you need lower-level control, use search_code, read_block, read_symbol_context, validate_edit, replace_block, replace_text, insert_before, insert_after, and generate_diff. Use start_service, list_services, get_service_status, get_service_logs, and stop_service for long-running servers or watchers. Use run_command only for one-shot commands that should exit on their own. Use read_file only when structured reads are not enough. Use write_file only for full-file writes and always provide a concrete file path, not a directory. Avoid unnecessary tool calls.`;
122
122
  }