@kkelly-offical/kkcode 0.1.7 → 0.2.3-preview.1

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.
Files changed (166) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +474 -387
  3. package/package.json +50 -46
  4. package/src/agent/agent.mjs +228 -220
  5. package/src/agent/custom-agent-loader.mjs +6 -3
  6. package/src/agent/generator.mjs +2 -2
  7. package/src/agent/prompt/assistant.txt +12 -0
  8. package/src/agent/prompt/bug-hunter.txt +89 -89
  9. package/src/agent/prompt/frontend-designer.txt +58 -58
  10. package/src/agent/prompt/guide.txt +1 -1
  11. package/src/agent/prompt/longagent-blueprint-agent.txt +83 -83
  12. package/src/agent/prompt/longagent-coding-agent.txt +37 -37
  13. package/src/agent/prompt/longagent-debugging-agent.txt +46 -46
  14. package/src/agent/prompt/longagent-preview-agent.txt +63 -63
  15. package/src/command/custom-commands.mjs +2 -2
  16. package/src/commands/agent.mjs +1 -1
  17. package/src/commands/background.mjs +145 -4
  18. package/src/commands/chat.mjs +117 -76
  19. package/src/commands/config.mjs +148 -1
  20. package/src/commands/doctor.mjs +30 -6
  21. package/src/commands/init.mjs +32 -6
  22. package/src/commands/longagent.mjs +117 -0
  23. package/src/commands/mcp.mjs +275 -43
  24. package/src/commands/permission.mjs +1 -1
  25. package/src/commands/session.mjs +195 -140
  26. package/src/commands/skill.mjs +63 -0
  27. package/src/commands/theme.mjs +1 -1
  28. package/src/commands/update.mjs +32 -0
  29. package/src/config/defaults.mjs +289 -260
  30. package/src/config/import-config.mjs +1 -1
  31. package/src/config/load-config.mjs +61 -4
  32. package/src/config/schema.mjs +604 -574
  33. package/src/context.mjs +4 -1
  34. package/src/core/constants.mjs +97 -91
  35. package/src/core/types.mjs +1 -1
  36. package/src/github/api.mjs +78 -78
  37. package/src/github/auth.mjs +294 -286
  38. package/src/github/flow.mjs +298 -298
  39. package/src/github/workspace.mjs +225 -212
  40. package/src/index.mjs +87 -82
  41. package/src/knowledge/frontend-aesthetics.txt +38 -38
  42. package/src/mcp/client-http.mjs +139 -141
  43. package/src/mcp/client-sse.mjs +297 -288
  44. package/src/mcp/client-stdio.mjs +534 -533
  45. package/src/mcp/constants.mjs +4 -2
  46. package/src/mcp/registry.mjs +498 -479
  47. package/src/mcp/stdio-framing.mjs +135 -133
  48. package/src/mcp/tool-result.mjs +24 -24
  49. package/src/observability/edit-diagnostics.mjs +449 -0
  50. package/src/observability/index.mjs +42 -42
  51. package/src/observability/metrics.mjs +165 -137
  52. package/src/observability/tracer.mjs +137 -137
  53. package/src/onboarding.mjs +209 -0
  54. package/src/orchestration/background-manager.mjs +567 -372
  55. package/src/orchestration/background-worker.mjs +419 -305
  56. package/src/orchestration/interruption-reason.mjs +21 -0
  57. package/src/orchestration/longagent-manager.mjs +197 -171
  58. package/src/orchestration/stage-scheduler.mjs +733 -728
  59. package/src/orchestration/subagent-router.mjs +7 -1
  60. package/src/orchestration/task-scheduler.mjs +219 -7
  61. package/src/permission/engine.mjs +1 -1
  62. package/src/permission/exec-policy.mjs +370 -370
  63. package/src/permission/file-edit-policy.mjs +108 -0
  64. package/src/permission/prompt.mjs +1 -1
  65. package/src/permission/rules.mjs +116 -7
  66. package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
  67. package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
  68. package/src/plugin/hook-bus.mjs +19 -5
  69. package/src/plugin/manifest-loader.mjs +222 -0
  70. package/src/provider/anthropic.mjs +396 -390
  71. package/src/provider/ollama.mjs +7 -1
  72. package/src/provider/openai.mjs +382 -340
  73. package/src/provider/retry-policy.mjs +74 -68
  74. package/src/provider/router.mjs +242 -241
  75. package/src/provider/sse.mjs +104 -104
  76. package/src/provider/wizard.mjs +556 -0
  77. package/src/repl/capability-facade.mjs +30 -0
  78. package/src/repl/command-surface.mjs +23 -0
  79. package/src/repl/controller-entry.mjs +40 -0
  80. package/src/repl/core-shell.mjs +208 -0
  81. package/src/repl/dialog-router.mjs +87 -0
  82. package/src/repl/input-engine.mjs +76 -0
  83. package/src/repl/keymap.mjs +7 -0
  84. package/src/repl/operator-surface.mjs +15 -0
  85. package/src/repl/permission-flow.mjs +49 -0
  86. package/src/repl/runtime-facade.mjs +36 -0
  87. package/src/repl/slash-router.mjs +62 -0
  88. package/src/repl/state-store.mjs +29 -0
  89. package/src/repl/turn-controller.mjs +58 -0
  90. package/src/repl/verification.mjs +23 -0
  91. package/src/repl.mjs +3371 -2981
  92. package/src/rules/load-rules.mjs +3 -3
  93. package/src/runtime.mjs +1 -1
  94. package/src/session/agent-transaction.mjs +86 -0
  95. package/src/session/checkpoint.mjs +302 -302
  96. package/src/session/compaction.mjs +298 -298
  97. package/src/session/engine.mjs +417 -232
  98. package/src/session/longagent-4stage.mjs +467 -460
  99. package/src/session/longagent-hybrid.mjs +1344 -1097
  100. package/src/session/longagent-plan.mjs +376 -365
  101. package/src/session/longagent-project-memory.mjs +53 -53
  102. package/src/session/longagent-scaffold.mjs +291 -291
  103. package/src/session/longagent-task-bus.mjs +138 -54
  104. package/src/session/longagent-utils.mjs +828 -472
  105. package/src/session/longagent.mjs +911 -900
  106. package/src/session/loop.mjs +1005 -930
  107. package/src/session/prompt/agent.txt +25 -25
  108. package/src/session/prompt/anthropic.txt +150 -150
  109. package/src/session/prompt/beast.txt +1 -1
  110. package/src/session/prompt/plan.txt +31 -31
  111. package/src/session/prompt/qwen.txt +46 -46
  112. package/src/session/recovery.mjs +21 -0
  113. package/src/session/rollback.mjs +196 -195
  114. package/src/session/routing-observability.mjs +72 -0
  115. package/src/session/runtime-state.mjs +47 -0
  116. package/src/session/store.mjs +523 -519
  117. package/src/session/system-prompt.mjs +308 -273
  118. package/src/session/task-validator.mjs +267 -267
  119. package/src/session/usability-gates.mjs +2 -2
  120. package/src/skill/builtin/commit.mjs +64 -64
  121. package/src/skill/builtin/design.mjs +76 -76
  122. package/src/skill/generator.mjs +18 -2
  123. package/src/skill/registry.mjs +642 -390
  124. package/src/storage/audit-store.mjs +18 -11
  125. package/src/storage/event-log.mjs +7 -1
  126. package/src/storage/ghost-commit-store.mjs +243 -245
  127. package/src/storage/paths.mjs +17 -0
  128. package/src/theme/default-theme.mjs +1 -1
  129. package/src/theme/markdown.mjs +4 -0
  130. package/src/theme/schema.mjs +1 -1
  131. package/src/theme/status-bar.mjs +162 -158
  132. package/src/tool/audit-wrapper.mjs +18 -2
  133. package/src/tool/edit-transaction.mjs +23 -0
  134. package/src/tool/executor.mjs +26 -1
  135. package/src/tool/file-read-state.mjs +65 -0
  136. package/src/tool/git-auto.mjs +526 -526
  137. package/src/tool/git-full-auto.mjs +487 -478
  138. package/src/tool/mutation-guard.mjs +54 -0
  139. package/src/tool/prompt/edit.txt +3 -3
  140. package/src/tool/prompt/multiedit.txt +1 -0
  141. package/src/tool/prompt/notebookedit.txt +2 -1
  142. package/src/tool/prompt/patch.txt +25 -24
  143. package/src/tool/prompt/read.txt +3 -3
  144. package/src/tool/prompt/sysinfo.txt +29 -0
  145. package/src/tool/prompt/task.txt +66 -4
  146. package/src/tool/prompt/write.txt +2 -2
  147. package/src/tool/question-prompt.mjs +99 -93
  148. package/src/tool/registry.mjs +1701 -1343
  149. package/src/tool/task-tool.mjs +14 -6
  150. package/src/ui/activity-renderer.mjs +667 -664
  151. package/src/ui/repl-background-panel.mjs +7 -0
  152. package/src/ui/repl-capability-panel.mjs +9 -0
  153. package/src/ui/repl-dashboard.mjs +54 -4
  154. package/src/ui/repl-help.mjs +110 -0
  155. package/src/ui/repl-operator-panel.mjs +12 -0
  156. package/src/ui/repl-route-feedback.mjs +35 -0
  157. package/src/ui/repl-status-view.mjs +76 -0
  158. package/src/ui/repl-task-panel.mjs +5 -0
  159. package/src/ui/repl-transcript-panel.mjs +56 -0
  160. package/src/ui/repl-turn-summary.mjs +135 -0
  161. package/src/update/checker.mjs +184 -0
  162. package/src/usage/pricing.mjs +122 -121
  163. package/src/usage/usage-meter.mjs +1 -0
  164. package/src/util/git.mjs +562 -519
  165. package/src/util/template.mjs +6 -1
  166. package/src/version.mjs +3 -0
package/package.json CHANGED
@@ -1,46 +1,50 @@
1
- {
2
- "name": "@kkelly-offical/kkcode",
3
- "version": "0.1.7",
4
- "description": "Team-first terminal AI coding agent CLI with LongAgent orchestration, GitHub integration and themed UX.",
5
- "type": "module",
6
- "packageManager": "pnpm@10.5.2",
7
- "license": "GPL-3.0",
8
- "author": "kkelly-offical",
9
- "repository": {
10
- "type": "git",
11
- "url": "https://github.com/kkelly-offical/kkcode.git"
12
- },
13
- "homepage": "https://github.com/kkelly-offical/kkcode",
14
- "bugs": {
15
- "url": "https://github.com/kkelly-offical/kkcode/issues"
16
- },
17
- "keywords": [
18
- "ai",
19
- "coding-agent",
20
- "cli",
21
- "terminal",
22
- "github",
23
- "longagent",
24
- "code-review",
25
- "mcp"
26
- ],
27
- "bin": {
28
- "kkcode": "./src/index.mjs"
29
- },
30
- "files": [
31
- "src/",
32
- "LICENSE"
33
- ],
34
- "engines": {
35
- "node": ">=22"
36
- },
37
- "scripts": {
38
- "start": "node ./src/index.mjs",
39
- "test": "node --test",
40
- "test:e2e": "node --test test/e2e/"
41
- },
42
- "dependencies": {
43
- "commander": "^13.1.0",
44
- "yaml": "^2.8.2"
45
- }
46
- }
1
+ {
2
+ "name": "@kkelly-offical/kkcode",
3
+ "version": "0.2.3-preview.1",
4
+ "description": "CLI-first personal assistant with dedicated coding and LongAgent modes for governed terminal workflows, MCP integrations, and extensible automation.",
5
+ "type": "module",
6
+ "packageManager": "pnpm@10.5.2",
7
+ "license": "GPL-3.0",
8
+ "author": "kkelly-offical",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/kkelly-offical/kkcode.git"
12
+ },
13
+ "homepage": "https://github.com/kkelly-offical/kkcode",
14
+ "bugs": {
15
+ "url": "https://github.com/kkelly-offical/kkcode/issues"
16
+ },
17
+ "keywords": [
18
+ "ai",
19
+ "coding-agent",
20
+ "cli",
21
+ "terminal",
22
+ "github",
23
+ "longagent",
24
+ "code-review",
25
+ "mcp"
26
+ ],
27
+ "bin": {
28
+ "kkcode": "./src/index.mjs"
29
+ },
30
+ "files": [
31
+ "src/",
32
+ "LICENSE"
33
+ ],
34
+ "engines": {
35
+ "node": ">=22"
36
+ },
37
+ "scripts": {
38
+ "start": "node ./src/index.mjs",
39
+ "lint": "node ./scripts/check-node-syntax.mjs",
40
+ "test": "node ./scripts/run-node-tests.mjs",
41
+ "test:e2e": "node --test test/e2e/*.mjs",
42
+ "typecheck": "node ./scripts/check-types.mjs",
43
+ "coverage": "node ./scripts/run-node-tests.mjs --coverage",
44
+ "release:verify": "node ./scripts/release-verify.mjs"
45
+ },
46
+ "dependencies": {
47
+ "commander": "^13.1.0",
48
+ "yaml": "^2.8.2"
49
+ }
50
+ }
@@ -1,220 +1,228 @@
1
- import { readFile } from "node:fs/promises"
2
- import path from "node:path"
3
- import { fileURLToPath } from "node:url"
4
-
5
- const __dirname = path.dirname(fileURLToPath(import.meta.url))
6
-
7
- const registry = new Map()
8
-
9
- function promptPath(name) {
10
- return path.join(__dirname, "prompt", `${name}.txt`)
11
- }
12
-
13
- async function loadPrompt(name) {
14
- try {
15
- return (await readFile(promptPath(name), "utf8")).trim()
16
- } catch {
17
- return ""
18
- }
19
- }
20
-
21
- export function defineAgent(spec) {
22
- const agent = {
23
- name: spec.name,
24
- description: spec.description || "",
25
- mode: spec.mode || "primary",
26
- permission: spec.permission || "default",
27
- tools: spec.tools || null,
28
- model: spec.model || null,
29
- temperature: spec.temperature ?? null,
30
- maxTurns: spec.maxTurns || null,
31
- hidden: spec.hidden || false,
32
- promptFile: spec.promptFile || spec.name,
33
- _promptCache: spec._promptCache ?? null,
34
- _customAgent: spec._customAgent || false,
35
- _scope: spec._scope || null,
36
- _source: spec._source || null
37
- }
38
- registry.set(agent.name, agent)
39
- return agent
40
- }
41
-
42
- export async function getAgentPrompt(name) {
43
- const agent = registry.get(name)
44
- if (!agent) return ""
45
- if (agent._promptCache !== null) return agent._promptCache
46
- agent._promptCache = await loadPrompt(agent.promptFile)
47
- return agent._promptCache
48
- }
49
-
50
- export function getAgent(name) {
51
- return registry.get(name) || null
52
- }
53
-
54
- export function listAgents({ includeHidden = false } = {}) {
55
- const agents = [...registry.values()]
56
- return includeHidden ? agents : agents.filter((a) => !a.hidden)
57
- }
58
-
59
- export function resolveAgentForMode(mode) {
60
- if (registry.has(mode)) return registry.get(mode)
61
- const modeMap = { ask: "build", plan: "plan", agent: "build", longagent: "longagent" }
62
- const mapped = modeMap[mode]
63
- return mapped ? registry.get(mapped) || null : null
64
- }
65
-
66
- defineAgent({
67
- name: "build",
68
- description: "Default agent with full tool access for code development",
69
- mode: "primary",
70
- permission: "full",
71
- tools: null
72
- })
73
-
74
- defineAgent({
75
- name: "plan",
76
- description: "Read-only analysis agent, no file editing allowed",
77
- mode: "primary",
78
- permission: "readonly",
79
- tools: ["read", "glob", "grep", "list", "bash"]
80
- })
81
-
82
- defineAgent({
83
- name: "explore",
84
- description: "Fast file search subagent for codebase exploration",
85
- mode: "subagent",
86
- permission: "readonly",
87
- tools: ["read", "glob", "grep", "list", "bash"]
88
- })
89
-
90
- defineAgent({
91
- name: "longagent",
92
- description: "Persistent iterative execution agent for complex multi-step tasks",
93
- mode: "primary",
94
- permission: "full",
95
- tools: null
96
- })
97
-
98
- defineAgent({
99
- name: "reviewer",
100
- description: "Code review specialist for analyzing code quality, bugs, and security issues",
101
- mode: "subagent",
102
- permission: "readonly",
103
- tools: ["read", "glob", "grep", "list", "bash"]
104
- })
105
-
106
- defineAgent({
107
- name: "researcher",
108
- description: "Deep codebase research and web-augmented exploration agent",
109
- mode: "subagent",
110
- permission: "readonly",
111
- tools: ["read", "glob", "grep", "list", "bash", "websearch", "codesearch", "webfetch"]
112
- })
113
-
114
- defineAgent({
115
- name: "architect",
116
- description: "Feature architecture designer. Analyzes codebase patterns, designs implementation blueprints with specific files, component designs, data flows.",
117
- mode: "subagent",
118
- permission: "readonly",
119
- tools: ["read", "glob", "grep", "list", "bash"]
120
- })
121
-
122
- defineAgent({
123
- name: "guide",
124
- description: "kkcode self-help guide. Answers questions about kkcode features, tools, configuration, modes, skills, hooks, MCP servers, and usage patterns by searching the kkcode source code.",
125
- mode: "subagent",
126
- permission: "readonly",
127
- tools: ["read", "glob", "grep", "list", "webfetch", "websearch"]
128
- })
129
-
130
- defineAgent({
131
- name: "security-reviewer",
132
- description: "Security audit specialist. Performs OWASP Top 10 checks, hardcoded secret scans, dependency audits, and authentication/authorization reviews.",
133
- mode: "subagent",
134
- permission: "readonly",
135
- tools: ["read", "glob", "grep", "list", "bash"]
136
- })
137
-
138
- defineAgent({
139
- name: "tdd-guide",
140
- description: "TDD specialist. Guides and executes test-driven development: scaffold interfaces, write failing tests (RED), implement minimum code (GREEN), refactor (IMPROVE). Targets 80%+ coverage.",
141
- mode: "subagent",
142
- permission: "full",
143
- tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
144
- })
145
-
146
- defineAgent({
147
- name: "build-fixer",
148
- description: "Build error diagnosis and repair. Analyzes build failures, identifies root causes, applies fixes, and verifies the build succeeds. Supports TypeScript, Python, Go, Rust, Java.",
149
- mode: "subagent",
150
- permission: "full",
151
- tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
152
- })
153
-
154
- defineAgent({
155
- name: "frontend-designer",
156
- description: "Frontend design specialist. Creates polished, distinctive UIs with strong aesthetics — typography, color, motion, layout. Avoids generic AI-style designs. Reads project design system (Tailwind, CSS vars, component libraries) and produces production-grade frontend code.",
157
- mode: "subagent",
158
- permission: "full",
159
- tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
160
- })
161
-
162
- defineAgent({
163
- name: "compaction",
164
- description: "Conversation summarizer for context compression",
165
- mode: "subagent",
166
- permission: "none",
167
- tools: [],
168
- hidden: true
169
- })
170
-
171
- defineAgent({
172
- name: "title",
173
- description: "Session title generator",
174
- mode: "subagent",
175
- permission: "none",
176
- tools: [],
177
- hidden: true
178
- })
179
-
180
- // 4-Stage LongAgent agents
181
- defineAgent({
182
- name: "preview-agent",
183
- description: "4-Stage LongAgent: Stage 1 - Previewing Agent. Explores codebase, extracts requirements, no editing allowed.",
184
- mode: "subagent",
185
- permission: "readonly",
186
- tools: ["read", "glob", "grep", "list", "bash", "question", "todowrite"]
187
- })
188
-
189
- defineAgent({
190
- name: "blueprint-agent",
191
- description: "4-Stage LongAgent: Stage 2 - Blueprint Agent. Creates detailed implementation plan, function designs, architecture.",
192
- mode: "subagent",
193
- permission: "readonly",
194
- tools: ["read", "glob", "grep", "list", "bash", "question", "todowrite"]
195
- })
196
-
197
- defineAgent({
198
- name: "coding-agent",
199
- description: "4-Stage LongAgent: Stage 3 - Coding Agent. Implements code strictly according to blueprint.",
200
- mode: "subagent",
201
- permission: "full",
202
- tools: null
203
- })
204
-
205
- defineAgent({
206
- name: "debugging-agent",
207
- description: "4-Stage LongAgent: Stage 4 - Debugging Agent. Verifies implementation, runs tests, finds and fixes bugs.",
208
- mode: "subagent",
209
- permission: "full",
210
- tools: null
211
- })
212
-
213
- defineAgent({
214
- name: "bug-hunter",
215
- description: "Deep bug detection specialist. Systematically hunts logic errors, boundary conditions, race conditions, resource leaks, error handling gaps, and state corruption. Reports only HIGH/MEDIUM confidence bugs with concrete trigger paths.",
216
- mode: "subagent",
217
- permission: "full",
218
- maxTurns: 30,
219
- tools: ["read", "glob", "grep", "list", "bash"]
220
- })
1
+ import { readFile } from "node:fs/promises"
2
+ import path from "node:path"
3
+ import { fileURLToPath } from "node:url"
4
+
5
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
6
+
7
+ const registry = new Map()
8
+
9
+ function promptPath(name) {
10
+ return path.join(__dirname, "prompt", `${name}.txt`)
11
+ }
12
+
13
+ async function loadPrompt(name) {
14
+ try {
15
+ return (await readFile(promptPath(name), "utf8")).trim()
16
+ } catch {
17
+ return ""
18
+ }
19
+ }
20
+
21
+ export function defineAgent(spec) {
22
+ const agent = {
23
+ name: spec.name,
24
+ description: spec.description || "",
25
+ mode: spec.mode || "primary",
26
+ permission: spec.permission || "default",
27
+ tools: spec.tools || null,
28
+ model: spec.model || null,
29
+ temperature: spec.temperature ?? null,
30
+ maxTurns: spec.maxTurns || null,
31
+ hidden: spec.hidden || false,
32
+ promptFile: spec.promptFile || spec.name,
33
+ _promptCache: spec._promptCache ?? null,
34
+ _customAgent: spec._customAgent || false,
35
+ _scope: spec._scope || null,
36
+ _source: spec._source || null
37
+ }
38
+ registry.set(agent.name, agent)
39
+ return agent
40
+ }
41
+
42
+ export async function getAgentPrompt(name) {
43
+ const agent = registry.get(name)
44
+ if (!agent) return ""
45
+ if (agent._promptCache !== null) return agent._promptCache
46
+ agent._promptCache = await loadPrompt(agent.promptFile)
47
+ return agent._promptCache
48
+ }
49
+
50
+ export function getAgent(name) {
51
+ return registry.get(name) || null
52
+ }
53
+
54
+ export function listAgents({ includeHidden = false } = {}) {
55
+ const agents = [...registry.values()]
56
+ return includeHidden ? agents : agents.filter((a) => !a.hidden)
57
+ }
58
+
59
+ export function resolveAgentForMode(mode) {
60
+ if (registry.has(mode)) return registry.get(mode)
61
+ const modeMap = { assistant: "assistant", plan: "plan", agent: "build", longagent: "longagent" }
62
+ const mapped = modeMap[mode]
63
+ return mapped ? registry.get(mapped) || null : null
64
+ }
65
+
66
+ defineAgent({
67
+ name: "assistant",
68
+ description: "Default CLI personal assistant for terminal-native personal work, local tasks, research, and lightweight automation",
69
+ mode: "primary",
70
+ permission: "full",
71
+ tools: null
72
+ })
73
+
74
+ defineAgent({
75
+ name: "build",
76
+ description: "Default agent with full tool access for code development",
77
+ mode: "primary",
78
+ permission: "full",
79
+ tools: null
80
+ })
81
+
82
+ defineAgent({
83
+ name: "plan",
84
+ description: "Read-only analysis agent, no file editing allowed",
85
+ mode: "primary",
86
+ permission: "readonly",
87
+ tools: ["read", "glob", "grep", "list", "webfetch", "websearch", "question", "enter_plan", "exit_plan"]
88
+ })
89
+
90
+ defineAgent({
91
+ name: "explore",
92
+ description: "Fast file search subagent for codebase exploration",
93
+ mode: "subagent",
94
+ permission: "readonly",
95
+ tools: ["read", "glob", "grep", "list", "bash"]
96
+ })
97
+
98
+ defineAgent({
99
+ name: "longagent",
100
+ description: "Persistent iterative execution agent for complex multi-step tasks",
101
+ mode: "primary",
102
+ permission: "full",
103
+ tools: null
104
+ })
105
+
106
+ defineAgent({
107
+ name: "reviewer",
108
+ description: "Code review specialist for analyzing code quality, bugs, and security issues",
109
+ mode: "subagent",
110
+ permission: "readonly",
111
+ tools: ["read", "glob", "grep", "list", "bash"]
112
+ })
113
+
114
+ defineAgent({
115
+ name: "researcher",
116
+ description: "Deep codebase research and web-augmented exploration agent",
117
+ mode: "subagent",
118
+ permission: "readonly",
119
+ tools: ["read", "glob", "grep", "list", "bash", "websearch", "codesearch", "webfetch"]
120
+ })
121
+
122
+ defineAgent({
123
+ name: "architect",
124
+ description: "Feature architecture designer. Analyzes codebase patterns, designs implementation blueprints with specific files, component designs, data flows.",
125
+ mode: "subagent",
126
+ permission: "readonly",
127
+ tools: ["read", "glob", "grep", "list", "bash"]
128
+ })
129
+
130
+ defineAgent({
131
+ name: "guide",
132
+ description: "kkcode self-help guide. Answers questions about kkcode features, tools, configuration, modes, skills, hooks, MCP servers, and usage patterns by searching the kkcode source code.",
133
+ mode: "subagent",
134
+ permission: "readonly",
135
+ tools: ["read", "glob", "grep", "list", "webfetch", "websearch"]
136
+ })
137
+
138
+ defineAgent({
139
+ name: "security-reviewer",
140
+ description: "Security audit specialist. Performs OWASP Top 10 checks, hardcoded secret scans, dependency audits, and authentication/authorization reviews.",
141
+ mode: "subagent",
142
+ permission: "readonly",
143
+ tools: ["read", "glob", "grep", "list", "bash"]
144
+ })
145
+
146
+ defineAgent({
147
+ name: "tdd-guide",
148
+ description: "TDD specialist. Guides and executes test-driven development: scaffold interfaces, write failing tests (RED), implement minimum code (GREEN), refactor (IMPROVE). Targets 80%+ coverage.",
149
+ mode: "subagent",
150
+ permission: "full",
151
+ tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
152
+ })
153
+
154
+ defineAgent({
155
+ name: "build-fixer",
156
+ description: "Build error diagnosis and repair. Analyzes build failures, identifies root causes, applies fixes, and verifies the build succeeds. Supports TypeScript, Python, Go, Rust, Java.",
157
+ mode: "subagent",
158
+ permission: "full",
159
+ tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
160
+ })
161
+
162
+ defineAgent({
163
+ name: "frontend-designer",
164
+ description: "Frontend design specialist. Creates polished, distinctive UIs with strong aesthetics — typography, color, motion, layout. Avoids generic AI-style designs. Reads project design system (Tailwind, CSS vars, component libraries) and produces production-grade frontend code.",
165
+ mode: "subagent",
166
+ permission: "full",
167
+ tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
168
+ })
169
+
170
+ defineAgent({
171
+ name: "compaction",
172
+ description: "Conversation summarizer for context compression",
173
+ mode: "subagent",
174
+ permission: "none",
175
+ tools: [],
176
+ hidden: true
177
+ })
178
+
179
+ defineAgent({
180
+ name: "title",
181
+ description: "Session title generator",
182
+ mode: "subagent",
183
+ permission: "none",
184
+ tools: [],
185
+ hidden: true
186
+ })
187
+
188
+ // 4-Stage LongAgent agents
189
+ defineAgent({
190
+ name: "preview-agent",
191
+ description: "4-Stage LongAgent: Stage 1 - Previewing Agent. Explores codebase, extracts requirements, no editing allowed.",
192
+ mode: "subagent",
193
+ permission: "readonly",
194
+ tools: ["read", "glob", "grep", "list", "bash", "question", "todowrite"]
195
+ })
196
+
197
+ defineAgent({
198
+ name: "blueprint-agent",
199
+ description: "4-Stage LongAgent: Stage 2 - Blueprint Agent. Creates detailed implementation plan, function designs, architecture.",
200
+ mode: "subagent",
201
+ permission: "readonly",
202
+ tools: ["read", "glob", "grep", "list", "bash", "question", "todowrite"]
203
+ })
204
+
205
+ defineAgent({
206
+ name: "coding-agent",
207
+ description: "4-Stage LongAgent: Stage 3 - Coding Agent. Implements code strictly according to blueprint.",
208
+ mode: "subagent",
209
+ permission: "full",
210
+ tools: null
211
+ })
212
+
213
+ defineAgent({
214
+ name: "debugging-agent",
215
+ description: "4-Stage LongAgent: Stage 4 - Debugging Agent. Verifies implementation, runs tests, finds and fixes bugs.",
216
+ mode: "subagent",
217
+ permission: "full",
218
+ tools: null
219
+ })
220
+
221
+ defineAgent({
222
+ name: "bug-hunter",
223
+ description: "Deep bug detection specialist. Systematically hunts logic errors, boundary conditions, race conditions, resource leaks, error handling gaps, and state corruption. Reports only HIGH/MEDIUM confidence bugs with concrete trigger paths.",
224
+ mode: "subagent",
225
+ permission: "full",
226
+ maxTurns: 30,
227
+ tools: ["read", "glob", "grep", "list", "bash"]
228
+ })
@@ -3,6 +3,7 @@ import { access, readdir, readFile } from "node:fs/promises"
3
3
  import { pathToFileURL } from "node:url"
4
4
  import { parseYaml } from "../util/yaml.mjs"
5
5
  import { defineAgent, getAgent } from "./agent.mjs"
6
+ import { userRootDir } from "../storage/paths.mjs"
6
7
 
7
8
  const state = {
8
9
  agents: new Map(),
@@ -82,12 +83,15 @@ async function loadMdAgent(filePath, scope) {
82
83
 
83
84
  async function loadAgentsFromDir(dir, scope) {
84
85
  if (!(await exists(dir))) return []
86
+ const resolvedDir = path.resolve(dir)
85
87
  const entries = await readdir(dir, { withFileTypes: true })
86
88
  const agents = []
87
89
  for (const entry of entries) {
88
90
  if (!entry.isFile()) continue
89
91
  const ext = path.extname(entry.name).toLowerCase()
90
- const full = path.join(dir, entry.name)
92
+ const full = path.resolve(dir, entry.name)
93
+ // Path boundary check: ensure resolved path is within expected directory
94
+ if (!full.startsWith(resolvedDir + path.sep) && full !== resolvedDir) continue
91
95
  try {
92
96
  if (ext === ".yaml" || ext === ".yml") {
93
97
  const agent = await loadYamlAgent(full, scope)
@@ -107,8 +111,7 @@ async function loadAgentsFromDir(dir, scope) {
107
111
  export const CustomAgentRegistry = {
108
112
  async initialize(cwd = process.cwd()) {
109
113
  state.agents.clear()
110
- const userRoot = process.env.USERPROFILE || process.env.HOME || cwd
111
- const globalDir = path.join(userRoot, ".kkcode", "agents")
114
+ const globalDir = path.join(userRootDir(), "agents")
112
115
  const projectDir = path.join(cwd, ".kkcode", "agents")
113
116
 
114
117
  const [globalAgents, projectAgents] = await Promise.all([
@@ -1,7 +1,7 @@
1
1
  import { writeFile, mkdir } from "node:fs/promises"
2
2
  import { join } from "node:path"
3
- import { homedir } from "node:os"
4
3
  import { requestProvider } from "../provider/router.mjs"
4
+ import { userRootDir } from "../storage/paths.mjs"
5
5
 
6
6
  const AGENT_GEN_SYSTEM = `You are an agent definition generator for kkcode, a terminal AI coding agent.
7
7
  Your task is to generate an agent definition file in YAML format based on the user's description.
@@ -96,7 +96,7 @@ export async function generateAgent({ description, configState, providerType, mo
96
96
  * Save an agent definition to the global agents directory.
97
97
  */
98
98
  export async function saveAgentGlobal(filename, content) {
99
- const dir = join(homedir(), ".kkcode", "agents")
99
+ const dir = join(userRootDir(), "agents")
100
100
  await mkdir(dir, { recursive: true })
101
101
  const filePath = join(dir, filename)
102
102
  await writeFile(filePath, content, "utf-8")
@@ -0,0 +1,12 @@
1
+ You are kkcode in ASSISTANT mode: a CLI-first personal assistant for terminal-native work. You can help with local files, directories, logs, system/runtime checks, web lookup/fetch, Git/GitHub assistance, notes, task organization, and bounded automation through the available tools.
2
+
3
+ # Operating Contract
4
+ - Prefer the lightest terminal-native path that fully answers or completes the user request.
5
+ - Use existing permission, budget, audit, and tool boundaries; never bypass approvals.
6
+ - Treat ordinary local inspection, summarization, command checks, repo hygiene, and research as first-class assistant work.
7
+ - When the request is clearly code mutation, debugging, refactoring, or test repair, use the dedicated coding lane semantics from `agent` / `code` / `coding`.
8
+ - When the request is broad, cross-module, staged, or needs ownership gates, recommend or use LongAgent rather than improvising.
9
+ - Do not imply unsupported surfaces such as GUI desktop automation, IDE integration, remote platform control, or marketplace install flows.
10
+
11
+ # Response Style
12
+ Be concise, outcome-first, and practical. State what you checked, what changed or did not change, and the next useful action only when it matters.