min-agent 0.2.1 → 0.4.0

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 (137) hide show
  1. package/README.md +242 -31
  2. package/dist/agent.js +1233 -485
  3. package/dist/assistant-stream.js +11 -7
  4. package/dist/cli/commands/chat.js +10 -0
  5. package/dist/cli/commands/exec.js +32 -0
  6. package/dist/cli/commands/history.js +58 -0
  7. package/dist/cli/commands/index.js +224 -0
  8. package/dist/cli/commands/init.js +18 -0
  9. package/dist/cli/commands/mcp.js +173 -0
  10. package/dist/cli/commands/memory.js +69 -0
  11. package/dist/cli/commands/models.js +21 -0
  12. package/dist/cli/commands/permission.js +12 -0
  13. package/dist/cli/commands/rules.js +33 -0
  14. package/dist/cli/commands/sandbox.js +13 -0
  15. package/dist/cli/commands/serve.js +9 -0
  16. package/dist/cli/commands/setup.js +4 -0
  17. package/dist/cli/commands/shared.js +16 -0
  18. package/dist/cli/commands/skills.js +119 -0
  19. package/dist/cli/commands/update.js +7 -0
  20. package/dist/cli/commands/write-config.js +30 -0
  21. package/dist/cli/errors.js +36 -0
  22. package/dist/cli/exec-prompt.js +26 -0
  23. package/dist/cli/option-helpers.js +53 -0
  24. package/dist/cli/program.js +180 -0
  25. package/dist/cli.js +7 -632
  26. package/dist/clipboard.js +59 -23
  27. package/dist/code-mode.js +35 -17
  28. package/dist/compaction.js +457 -169
  29. package/dist/config.js +298 -38
  30. package/dist/confirm.js +105 -9
  31. package/dist/context-window.js +156 -75
  32. package/dist/doom-loop.js +268 -26
  33. package/dist/fetch-timeout.js +152 -0
  34. package/dist/http-approvals.js +60 -0
  35. package/dist/http.js +119 -0
  36. package/dist/instructions.js +72 -33
  37. package/dist/logger.js +95 -0
  38. package/dist/markdown.js +35 -50
  39. package/dist/mcp.js +847 -102
  40. package/dist/memory.js +128 -45
  41. package/dist/output.js +42 -31
  42. package/dist/paste-handler.js +3 -3
  43. package/dist/permission-cli.js +43 -0
  44. package/dist/plugins.js +76 -11
  45. package/dist/pricing.js +119 -0
  46. package/dist/provider.js +34 -15
  47. package/dist/question-format.js +60 -0
  48. package/dist/sandbox-cli.js +82 -0
  49. package/dist/sandbox.js +403 -0
  50. package/dist/save-throttle.js +45 -0
  51. package/dist/serve/common.js +404 -0
  52. package/dist/serve/routes-chat.js +347 -0
  53. package/dist/serve/routes-mcp.js +212 -0
  54. package/dist/serve/routes-memory.js +66 -0
  55. package/dist/serve/routes-meta.js +205 -0
  56. package/dist/serve/routes-sessions.js +61 -0
  57. package/dist/serve/routes-skills.js +70 -0
  58. package/dist/serve.js +74 -635
  59. package/dist/sessions.js +197 -15
  60. package/dist/skills.js +531 -77
  61. package/dist/synthetic.js +7 -0
  62. package/dist/title-gen.js +9 -2
  63. package/dist/token-display.js +36 -0
  64. package/dist/tool-display.js +178 -0
  65. package/dist/tool-output.js +53 -46
  66. package/dist/tools/apply_patch.js +265 -0
  67. package/dist/tools/atomic-file.js +35 -0
  68. package/dist/tools/backend.js +61 -0
  69. package/dist/tools/bash.js +186 -71
  70. package/dist/tools/code_search.js +13 -6
  71. package/dist/tools/edit.js +26 -9
  72. package/dist/tools/explore.js +144 -16
  73. package/dist/tools/glob.js +7 -3
  74. package/dist/tools/grep.js +153 -14
  75. package/dist/tools/index.js +9 -24
  76. package/dist/tools/question.js +31 -30
  77. package/dist/tools/read.js +77 -15
  78. package/dist/tools/search-searxng.js +223 -0
  79. package/dist/tools/search-serper.js +189 -0
  80. package/dist/tools/task.js +100 -33
  81. package/dist/tools/todo.js +178 -67
  82. package/dist/tools/web_fetch.js +158 -46
  83. package/dist/tools/web_search.js +217 -29
  84. package/dist/tools/write.js +34 -11
  85. package/dist/tui/App.js +89 -6
  86. package/dist/tui/ConfirmBar.js +57 -4
  87. package/dist/tui/InputBar.js +504 -44
  88. package/dist/tui/MessageList.js +674 -20
  89. package/dist/tui/ModelPicker.js +113 -0
  90. package/dist/tui/QuestionBar.js +136 -0
  91. package/dist/tui/SessionPicker.js +79 -0
  92. package/dist/tui/StatusBar.js +14 -12
  93. package/dist/tui/agent-runner.js +223 -0
  94. package/dist/tui/caret-pos.js +177 -0
  95. package/dist/tui/caret.js +69 -0
  96. package/dist/tui/click-count.js +13 -0
  97. package/dist/tui/diff-view.js +61 -0
  98. package/dist/tui/drag-state.js +49 -0
  99. package/dist/tui/hydrate.js +129 -0
  100. package/dist/tui/index.js +189 -31
  101. package/dist/tui/input-history.js +125 -0
  102. package/dist/tui/layout.js +88 -0
  103. package/dist/tui/mouse.js +46 -0
  104. package/dist/tui/prompt-queue.js +24 -0
  105. package/dist/tui/selection.js +226 -0
  106. package/dist/tui/session-switch.js +28 -0
  107. package/dist/tui/slash-commands.js +106 -0
  108. package/dist/tui/slash-handler.js +545 -0
  109. package/dist/tui/text-width.js +113 -0
  110. package/dist/tui/theme.js +12 -0
  111. package/dist/tui/token-info.js +7 -0
  112. package/dist/tui/tool-children.js +19 -0
  113. package/dist/tui/undo-stack.js +14 -0
  114. package/dist/tui/use-sgr-mouse.js +29 -0
  115. package/dist/tui-chat.js +346 -330
  116. package/dist/updater.js +116 -0
  117. package/dist/xml-search.js +194 -0
  118. package/docs/API.md +410 -32
  119. package/docs/superpowers/plans/2026-08-16-batch1-tui-improvements.md +1510 -0
  120. package/docs/superpowers/plans/2026-08-16-batch2-cli-tools-api.md +2105 -0
  121. package/docs/superpowers/plans/2026-08-16-batch3-config-engineering.md +1595 -0
  122. package/docs/superpowers/plans/2026-08-16-input-caret.md +782 -0
  123. package/docs/superpowers/plans/2026-08-20-tui-completeness.md +873 -0
  124. package/docs/superpowers/plans/2026-08-20-unified-tui-default.md +631 -0
  125. package/docs/superpowers/specs/2026-08-16-batch1-tui-improvements-design.md +183 -0
  126. package/docs/superpowers/specs/2026-08-16-batch2-cli-tools-api-design.md +220 -0
  127. package/docs/superpowers/specs/2026-08-16-batch3-config-engineering-design.md +196 -0
  128. package/docs/superpowers/specs/2026-08-16-input-caret-design.md +63 -0
  129. package/docs/superpowers/specs/2026-08-17-mouse-selection-design.md +116 -0
  130. package/docs/superpowers/specs/2026-08-20-config-http-alignment-design.md +47 -0
  131. package/docs/superpowers/specs/2026-08-20-mcp-plugins-alignment-design.md +37 -0
  132. package/docs/superpowers/specs/2026-08-20-sandbox-permissions-design.md +68 -0
  133. package/docs/superpowers/specs/2026-08-20-tui-completeness-design.md +273 -0
  134. package/docs/superpowers/specs/2026-08-20-unified-tui-default-design.md +165 -0
  135. package/package.json +12 -8
  136. package/skills/self-config/SKILL.md +90 -0
  137. package/skills/self-config/reference.md +149 -0
package/dist/cli.js CHANGED
@@ -1,637 +1,12 @@
1
- import { runAgent } from "./agent.js";
2
- import { loadMcpConfig, saveMcpConfig, checkMcpServer, checkAllMcpServers, formatMcpServerBinding, } from "./mcp.js";
3
- import { discoverSkills, getSkills } from "./skills.js";
4
- import { loadMemories, addMemory, deleteMemory, searchMemories } from "./memory.js";
5
- import { runSetup, isConfigured, loadConfig, saveConfig, fetchModels, getConfigDir, getRulesFile } from "./config.js";
6
- import { setAutoApprove } from "./confirm.js";
7
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
8
- import path from "path";
9
- const rawArgs = process.argv.slice(2);
10
- // Extract leading global flags only, so subcommands can still use "-y"
11
- const args = [...rawArgs];
12
- let hasYes = false;
13
- while (args[0] === "--yes" || args[0] === "-y") {
14
- hasYes = true;
15
- args.shift();
16
- }
17
- if (hasYes)
18
- setAutoApprove(true);
19
- function printUsage() {
20
- console.log(`
21
- min-agent - Minimal AI coding agent
22
-
23
- Usage:
24
- min-agent init Initialize .min-agent/ in current directory
25
- min-agent chat <message> Send a message to the agent
26
- min-agent chat Start interactive multi-turn chat
27
- min-agent chat --resume <id> Resume a previous session
28
- min-agent code AI coding mode (project-aware)
29
- min-agent setup Configure API provider (interactive)
30
- min-agent models List available models
31
- min-agent history List saved sessions
32
- min-agent rules Show loaded instruction rules
33
- min-agent rules edit Edit global rules file
34
- min-agent memory List all memories
35
- min-agent memory add <text> Add a memory manually
36
- min-agent memory search <query> Search memories
37
- min-agent memory delete <index> Delete a memory by number
38
- min-agent mcp add <name> <cmd> Add a local MCP server (stdio)
39
- min-agent mcp add <name> --url <url> [--sse] [--token <t>] Add remote MCP (HTTP)
40
- min-agent mcp remove <name> Remove an MCP server
41
- min-agent mcp list List configured MCP servers
42
- min-agent mcp check Check MCP server availability
43
- min-agent skills list List available skills
44
- min-agent serve [--host H] [--port P] HTTP API (see docs/API.md)
45
-
46
- Options:
47
- --model, -m <model> Override model for this request
48
- --image, -i <path> Attach an image (can be used multiple times)
49
- --yes, -y Auto-approve all confirmations (dangerous commands, file overwrites)
50
-
51
- Permission modes (set in ~/.min-agent/config.json):
52
- "permission": "ask" Prompt before dangerous operations (default)
53
- "permission": "allow-all" Auto-approve everything (same as --yes permanently)
54
-
55
- Rules (loaded as system instructions):
56
- Global: ~/.min-agent/rules.md
57
- Project: ./AGENTS.md or ./RULES.md or ./.min-agent/AGENTS.md
58
- Config: "instructions" array in ~/.min-agent/config.json
59
-
60
- Examples:
61
- min-agent setup
62
- min-agent chat "hello"
63
- min-agent chat
64
- min-agent serve --port 8787
65
- min-agent rules edit
66
- min-agent mcp add filesystem npx -y @modelcontextprotocol/server-filesystem /tmp
67
- min-agent mcp add remote --url https://example.com/mcp --token "$TOKEN"
68
- `);
69
- }
70
- function parseMcpAddArgs(argv) {
71
- let skipCheck = false;
72
- let url;
73
- let token;
74
- let sse = false;
75
- const cmd = [];
76
- for (let i = 0; i < argv.length; i++) {
77
- const a = argv[i];
78
- if (a === "--skip-check") {
79
- skipCheck = true;
80
- continue;
81
- }
82
- if (a === "--sse") {
83
- sse = true;
84
- continue;
85
- }
86
- if (a === "--url" && argv[i + 1]) {
87
- url = argv[++i];
88
- continue;
89
- }
90
- if (a === "--token" && argv[i + 1]) {
91
- token = argv[++i];
92
- continue;
93
- }
94
- cmd.push(a);
95
- }
96
- return { skipCheck, url, token, sse, cmd };
97
- }
98
- function ensureProjectDefaults() {
99
- const projectConfigDir = path.join(process.cwd(), ".min-agent");
100
- const projectSkillsDir = path.join(projectConfigDir, "skills");
101
- const projectMcpFile = path.join(projectConfigDir, "mcp.json");
102
- if (!existsSync(projectSkillsDir)) {
103
- mkdirSync(projectSkillsDir, { recursive: true });
104
- }
105
- if (!existsSync(projectMcpFile)) {
106
- mkdirSync(projectConfigDir, { recursive: true });
107
- writeFileSync(projectMcpFile, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
108
- }
109
- }
1
+ import { runProgram } from "./cli/program.js";
2
+ import { registerCommands } from "./cli/commands/index.js";
3
+ import { initLogger, log } from "./logger.js";
110
4
  async function main() {
111
- if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
112
- printUsage();
113
- process.exit(0);
114
- }
115
- if (args[0] === "--version" || args[0] === "-v") {
116
- const pkgPath = path.resolve(path.dirname(new URL(import.meta.url).pathname), "../package.json");
117
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
118
- console.log(pkg.version);
119
- process.exit(0);
120
- }
121
- const command = args[0];
122
- switch (command) {
123
- case "setup": {
124
- await runSetup();
125
- break;
126
- }
127
- case "models": {
128
- const config = loadConfig();
129
- if (!config.provider?.baseURL || !config.provider?.apiKey) {
130
- console.error("Not configured. Run: min-agent setup");
131
- process.exit(1);
132
- }
133
- console.log("Fetching models...");
134
- const models = await fetchModels(config.provider.baseURL, config.provider.apiKey);
135
- if (models.length === 0) {
136
- console.log("No models found or unable to fetch model list.");
137
- }
138
- else {
139
- console.log(`\nAvailable models (${models.length}):`);
140
- for (const m of models) {
141
- const marker = m === config.provider.defaultModel ? " ← default" : "";
142
- console.log(` ${m}${marker}`);
143
- }
144
- }
145
- break;
146
- }
147
- case "chat": {
148
- if (!isConfigured()) {
149
- console.error("Not configured. Run: min-agent setup");
150
- process.exit(1);
151
- }
152
- // Parse --model / -m, --resume, and --image / -i flags
153
- let modelOverride;
154
- let resumeId;
155
- const images = [];
156
- const chatArgs = [];
157
- for (let i = 1; i < args.length; i++) {
158
- if ((args[i] === "--model" || args[i] === "-m") && args[i + 1]) {
159
- modelOverride = args[++i];
160
- }
161
- else if (args[i] === "--resume" && args[i + 1]) {
162
- resumeId = args[++i];
163
- }
164
- else if ((args[i] === "--image" || args[i] === "-i") && args[i + 1]) {
165
- images.push(args[++i]);
166
- }
167
- else {
168
- chatArgs.push(args[i]);
169
- }
170
- }
171
- const message = chatArgs.join(" ");
172
- if (!message) {
173
- const { runTui } = await import("./tui-chat.js");
174
- await runTui({ modelId: modelOverride, resumeSessionId: resumeId, mode: "chat" });
175
- }
176
- else {
177
- await runAgent(message, modelOverride, images.length > 0 ? images : undefined);
178
- }
179
- break;
180
- }
181
- case "code": {
182
- if (!isConfigured()) {
183
- console.error("Not configured. Run: min-agent setup");
184
- process.exit(1);
185
- }
186
- let modelOverride;
187
- let resumeId;
188
- for (let i = 1; i < args.length; i++) {
189
- if ((args[i] === "--model" || args[i] === "-m") && args[i + 1]) {
190
- modelOverride = args[++i];
191
- }
192
- else if (args[i] === "--resume" && args[i + 1]) {
193
- resumeId = args[++i];
194
- }
195
- }
196
- const { runTui } = await import("./tui-chat.js");
197
- await runTui({ modelId: modelOverride, resumeSessionId: resumeId, mode: "code" });
198
- break;
199
- }
200
- case "serve": {
201
- if (!isConfigured()) {
202
- console.error("Not configured. Run: min-agent setup");
203
- process.exit(1);
204
- }
205
- let servePort;
206
- let serveHost;
207
- for (let i = 1; i < args.length; i++) {
208
- if ((args[i] === "--port" || args[i] === "-p") && args[i + 1]) {
209
- servePort = parseInt(args[++i], 10);
210
- }
211
- else if (args[i] === "--host" && args[i + 1]) {
212
- serveHost = args[++i];
213
- }
214
- }
215
- const { runServe } = await import("./serve.js");
216
- await runServe({ port: servePort, host: serveHost });
217
- break;
218
- }
219
- case "mcp": {
220
- const subcommand = args[1];
221
- if (subcommand === "-h" || subcommand === "--help" || !subcommand) {
222
- console.log(`Usage: min-agent mcp <command>
223
-
224
- Commands:
225
- list List configured MCP servers (name + status)
226
- info <name> Show details of a server
227
- add <name> ... Add a new server (stdio or remote)
228
- remove <name> Remove a server
229
- enable <name> Enable a disabled server
230
- disable <name> Disable a server
231
- check Test connectivity of all servers`);
232
- process.exit(0);
233
- }
234
- switch (subcommand) {
235
- case "add": {
236
- const name = args[2];
237
- if (!name) {
238
- console.error("Usage: min-agent mcp add <name> [--skip-check] <command...>");
239
- console.error(" or: min-agent mcp add <name> --url <https://host/mcp> [--sse] [--token <bearer>] [--skip-check]");
240
- process.exit(1);
241
- }
242
- const { skipCheck, url, token, sse, cmd } = parseMcpAddArgs(args.slice(3));
243
- let entry;
244
- if (url?.trim()) {
245
- entry = {
246
- url: url.trim(),
247
- enabled: true,
248
- remoteTransport: sse ? "sse" : "auto",
249
- };
250
- if (token?.trim())
251
- entry.token = token.trim();
252
- }
253
- else if (cmd.length > 0) {
254
- entry = { command: cmd, enabled: true };
255
- }
256
- else {
257
- console.error("Usage: min-agent mcp add <name> [--skip-check] <command...>");
258
- console.error(" or: min-agent mcp add <name> --url <https://host/mcp> [--sse] [--token <bearer>] [--skip-check]");
259
- process.exit(1);
260
- }
261
- let detectedTools = 0;
262
- if (!skipCheck) {
263
- console.log(`Validating MCP server "${name}"...`);
264
- const checkResult = await checkMcpServer(name, entry);
265
- if (!checkResult.ok) {
266
- console.error(`MCP server "${name}" validation failed: ${checkResult.error ?? "unknown error"}`);
267
- process.exit(1);
268
- }
269
- detectedTools = checkResult.toolCount;
270
- }
271
- else {
272
- console.log(`Skipping MCP validation for "${name}" (--skip-check).`);
273
- }
274
- const config = loadMcpConfig();
275
- config.mcpServers[name] = entry;
276
- saveMcpConfig(config);
277
- const toolsSuffix = skipCheck ? "" : ` (${detectedTools} tools detected)`;
278
- console.log(`✓ MCP server "${name}" added: ${formatMcpServerBinding(entry)}${toolsSuffix}`);
279
- break;
280
- }
281
- case "remove": {
282
- const name = args[2];
283
- if (!name) {
284
- console.error("Usage: min-agent mcp remove <name>");
285
- process.exit(1);
286
- }
287
- const config = loadMcpConfig();
288
- if (!config.mcpServers[name]) {
289
- console.error(`MCP server "${name}" not found`);
290
- process.exit(1);
291
- }
292
- delete config.mcpServers[name];
293
- saveMcpConfig(config);
294
- console.log(`✓ MCP server "${name}" removed`);
295
- break;
296
- }
297
- case "list": {
298
- const config = loadMcpConfig();
299
- const servers = Object.entries(config.mcpServers);
300
- if (servers.length === 0) {
301
- console.log("No MCP servers configured.");
302
- console.log("Add one with: min-agent mcp add <name> <command...>");
303
- }
304
- else {
305
- console.log("MCP Servers:");
306
- for (const [name, cfg] of servers) {
307
- const status = cfg.enabled === false ? "\x1b[90mdisabled\x1b[0m" : "\x1b[32menabled\x1b[0m";
308
- console.log(` ${name} ${status}`);
309
- }
310
- console.log("\nUse: min-agent mcp info <name> for details");
311
- }
312
- break;
313
- }
314
- case "info": {
315
- const name = args[2];
316
- if (!name) {
317
- console.error("Usage: min-agent mcp info <name>");
318
- process.exit(1);
319
- }
320
- const config = loadMcpConfig();
321
- const cfg = config.mcpServers[name];
322
- if (!cfg) {
323
- console.error(`MCP server "${name}" not found`);
324
- process.exit(1);
325
- }
326
- console.log(`Name: ${name}`);
327
- console.log(`Status: ${cfg.enabled === false ? "disabled" : "enabled"}`);
328
- console.log(`Binding: ${formatMcpServerBinding(cfg)}`);
329
- if (cfg.command)
330
- console.log(`Command: ${Array.isArray(cfg.command) ? cfg.command.join(" ") : `${cfg.command} ${(cfg.args ?? []).join(" ")}`.trim()}`);
331
- if (cfg.url)
332
- console.log(`URL: ${cfg.url}`);
333
- if (cfg.token)
334
- console.log(`Token: ***`);
335
- if (cfg.environment)
336
- console.log(`Env: ${Object.keys(cfg.environment).join(", ")}`);
337
- if (cfg.timeout)
338
- console.log(`Timeout: ${cfg.timeout}ms`);
339
- break;
340
- }
341
- case "check": {
342
- const results = await checkAllMcpServers();
343
- if (results.length === 0) {
344
- console.log("No MCP servers configured.");
345
- console.log("Add one with: min-agent mcp add <name> <command...> or --url <https://...>");
346
- break;
347
- }
348
- let failed = 0;
349
- console.log("MCP Check Results:");
350
- for (const result of results) {
351
- if (!result.enabled) {
352
- console.log(` ${result.name}: skipped (disabled)`);
353
- continue;
354
- }
355
- if (result.ok) {
356
- console.log(` ${result.name}: ok (${result.toolCount} tools)`);
357
- }
358
- else {
359
- failed++;
360
- console.log(` ${result.name}: failed${result.error ? ` - ${result.error}` : ""}`);
361
- }
362
- }
363
- if (failed > 0) {
364
- console.error(`\n${failed} MCP server(s) failed.`);
365
- process.exit(1);
366
- }
367
- else {
368
- console.log("\nAll enabled MCP servers are available.");
369
- }
370
- break;
371
- }
372
- case "enable": {
373
- const names = args.slice(2);
374
- if (names.length === 0) {
375
- console.error("Usage: min-agent mcp enable <name...>");
376
- process.exit(1);
377
- }
378
- const config = loadMcpConfig();
379
- for (const name of names) {
380
- if (!config.mcpServers[name]) {
381
- console.error(`MCP server "${name}" not found`);
382
- continue;
383
- }
384
- config.mcpServers[name].enabled = true;
385
- console.log(`✓ MCP server "${name}" enabled`);
386
- }
387
- saveMcpConfig(config);
388
- break;
389
- }
390
- case "disable": {
391
- const names = args.slice(2);
392
- if (names.length === 0) {
393
- console.error("Usage: min-agent mcp disable <name...>");
394
- process.exit(1);
395
- }
396
- const config = loadMcpConfig();
397
- for (const name of names) {
398
- if (!config.mcpServers[name]) {
399
- console.error(`MCP server "${name}" not found`);
400
- continue;
401
- }
402
- config.mcpServers[name].enabled = false;
403
- console.log(`✓ MCP server "${name}" disabled`);
404
- }
405
- saveMcpConfig(config);
406
- break;
407
- }
408
- default:
409
- console.error("Usage: min-agent mcp -h");
410
- process.exit(1);
411
- }
412
- break;
413
- }
414
- case "history": {
415
- const { listSessions } = await import("./sessions.js");
416
- const sessions = listSessions();
417
- if (sessions.length === 0) {
418
- console.log("No saved sessions.");
419
- console.log("Sessions are auto-saved when you exit interactive chat.");
420
- }
421
- else {
422
- console.log(`Sessions (${sessions.length}):`);
423
- for (const s of sessions.slice(0, 20)) {
424
- const date = s.updated.split("T")[0];
425
- console.log(` ${s.id} ${date} ${s.title} (${s.messageCount} msgs)`);
426
- }
427
- console.log("\nResume with: min-agent chat --resume <id>");
428
- }
429
- break;
430
- }
431
- case "memory": {
432
- const subcommand = args[1];
433
- switch (subcommand) {
434
- case "add": {
435
- const text = args.slice(2).join(" ");
436
- if (!text) {
437
- console.error("Usage: min-agent memory add <text>");
438
- process.exit(1);
439
- }
440
- addMemory(text);
441
- console.log(`✓ Memory saved: "${text}"`);
442
- break;
443
- }
444
- case "search": {
445
- const query = args.slice(2).join(" ");
446
- if (!query) {
447
- console.error("Usage: min-agent memory search <query>");
448
- process.exit(1);
449
- }
450
- const results = searchMemories(query);
451
- if (results.length === 0) {
452
- console.log(`No memories matching "${query}"`);
453
- }
454
- else {
455
- console.log(`Found ${results.length} memory(s):`);
456
- for (const m of results) {
457
- const tags = m.tags.length > 0 ? ` [${m.tags.join(", ")}]` : "";
458
- console.log(` #${m.index + 1}: ${m.content}${tags}`);
459
- }
460
- }
461
- break;
462
- }
463
- case "delete": {
464
- const idx = parseInt(args[2]);
465
- if (isNaN(idx)) {
466
- console.error("Usage: min-agent memory delete <number>");
467
- process.exit(1);
468
- }
469
- if (deleteMemory(idx - 1)) {
470
- console.log(`✓ Memory #${idx} deleted`);
471
- }
472
- else {
473
- console.error(`Memory #${idx} not found`);
474
- }
475
- break;
476
- }
477
- default: {
478
- // List all memories
479
- const memories = loadMemories();
480
- if (memories.length === 0) {
481
- console.log("No memories stored.");
482
- console.log("The agent will automatically save memories during conversations.");
483
- console.log("Or add manually: min-agent memory add \"prefer TypeScript over JavaScript\"");
484
- }
485
- else {
486
- console.log(`Memories (${memories.length}):`);
487
- for (let i = 0; i < memories.length; i++) {
488
- const m = memories[i];
489
- const tags = m.tags.length > 0 ? ` [${m.tags.join(", ")}]` : "";
490
- const date = m.created.split("T")[0];
491
- console.log(` #${i + 1}: ${m.content}${tags} (${date})`);
492
- }
493
- }
494
- break;
495
- }
496
- }
497
- break;
498
- }
499
- case "skills": {
500
- const subcommand = args[1];
501
- if (subcommand === "-h" || subcommand === "--help" || !subcommand) {
502
- console.log(`Usage: min-agent skills <command>
503
-
504
- Commands:
505
- list List skills (name + status)
506
- info <name> Show details of a skill
507
- enable <name> Enable a disabled skill
508
- disable <name> Disable a skill`);
509
- process.exit(0);
510
- }
511
- switch (subcommand) {
512
- case "info": {
513
- const name = args[2];
514
- if (!name) {
515
- console.error("Usage: min-agent skills info <name>");
516
- process.exit(1);
517
- }
518
- discoverSkills({ silent: true });
519
- const { getSkill } = await import("./skills.js");
520
- const skill = getSkill(name);
521
- if (!skill) {
522
- console.error(`Skill "${name}" not found`);
523
- process.exit(1);
524
- }
525
- const config = loadConfig();
526
- const isDisabled = (config.disabledSkills ?? []).includes(name);
527
- console.log(`Name: ${skill.name}`);
528
- console.log(`Status: ${isDisabled ? "disabled" : "enabled"}`);
529
- console.log(`Description: ${skill.description}`);
530
- console.log(`Location: ${skill.location}`);
531
- break;
532
- }
533
- case "enable": {
534
- const names = args.slice(2);
535
- if (names.length === 0) {
536
- console.error("Usage: min-agent skills enable <name...>");
537
- process.exit(1);
538
- }
539
- const config = loadConfig();
540
- config.disabledSkills = (config.disabledSkills ?? []).filter((s) => !names.includes(s));
541
- saveConfig(config);
542
- for (const name of names)
543
- console.log(`✓ Skill "${name}" enabled`);
544
- break;
545
- }
546
- case "disable": {
547
- const names = args.slice(2);
548
- if (names.length === 0) {
549
- console.error("Usage: min-agent skills disable <name...>");
550
- process.exit(1);
551
- }
552
- const config = loadConfig();
553
- const disabled = config.disabledSkills ?? [];
554
- for (const name of names) {
555
- if (!disabled.includes(name))
556
- disabled.push(name);
557
- console.log(`✓ Skill "${name}" disabled`);
558
- }
559
- config.disabledSkills = disabled;
560
- saveConfig(config);
561
- break;
562
- }
563
- case "list": {
564
- discoverSkills({ silent: true });
565
- const skills = getSkills();
566
- const config = loadConfig();
567
- const disabledNames = config.disabledSkills ?? [];
568
- if (skills.length === 0 && disabledNames.length === 0) {
569
- console.log("No skills found. Add SKILL.md files in .min-agent/skills/<name>/");
570
- break;
571
- }
572
- console.log("Skills:");
573
- for (const skill of skills) {
574
- console.log(` ${skill.name} \x1b[32menabled\x1b[0m`);
575
- }
576
- for (const n of disabledNames) {
577
- console.log(` ${n} \x1b[90mdisabled\x1b[0m`);
578
- }
579
- console.log("\nUse: min-agent skills info <name> for details");
580
- break;
581
- }
582
- default:
583
- console.error("Usage: min-agent skills -h");
584
- process.exit(1);
585
- }
586
- break;
587
- }
588
- case "init": {
589
- ensureProjectDefaults();
590
- console.log(`✓ Initialized .min-agent/ in ${process.cwd()}`);
591
- break;
592
- }
593
- case "rules": {
594
- const subcommand = args[1];
595
- if (subcommand === "edit") {
596
- const rulesFile = getRulesFile();
597
- if (!existsSync(rulesFile)) {
598
- mkdirSync(getConfigDir(), { recursive: true });
599
- writeFileSync(rulesFile, `# Global Agent Rules\n\n<!-- Add your custom instructions here. They will be included in every conversation. -->\n`, "utf-8");
600
- }
601
- const editor = process.env.EDITOR || "vi";
602
- const { execSync } = await import("child_process");
603
- execSync(`${editor} "${rulesFile}"`, { stdio: "inherit" });
604
- }
605
- else {
606
- const { loadInstructions } = await import("./instructions.js");
607
- const instructions = await loadInstructions();
608
- if (instructions.length === 0) {
609
- console.log("No instruction rules loaded.");
610
- console.log("");
611
- console.log("Add rules by creating:");
612
- console.log(` Global: ${getRulesFile()}`);
613
- console.log(" Project: ./AGENTS.md or ./RULES.md");
614
- console.log("");
615
- console.log("Or add paths/URLs in ~/.min-agent/config.json:");
616
- console.log(' { "instructions": ["./docs/rules.md", "https://..."] }');
617
- }
618
- else {
619
- console.log(`Loaded ${instructions.length} instruction source(s):\n`);
620
- for (const inst of instructions) {
621
- const firstLine = inst.split("\n")[0];
622
- console.log(` ${firstLine}`);
623
- }
624
- }
625
- }
626
- break;
627
- }
628
- default:
629
- console.error(`Unknown command: ${command}`);
630
- printUsage();
631
- process.exit(1);
632
- }
5
+ initLogger();
6
+ log("info", "min-agent started");
7
+ await runProgram(process.argv.slice(2), registerCommands);
633
8
  }
634
9
  main().catch((err) => {
635
10
  console.error(`\x1b[31mFatal error: ${err.message}\x1b[0m`);
636
- process.exit(1);
11
+ process.exitCode = 1;
637
12
  });