min-agent 0.5.1 → 0.6.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 (169) hide show
  1. package/README.md +18 -18
  2. package/dist/cli.js +538 -12
  3. package/docs/API.md +6 -6
  4. package/package.json +6 -6
  5. package/skills/self-config/SKILL.md +4 -2
  6. package/skills/self-config/reference.md +4 -1
  7. package/dist/agent.js +0 -1388
  8. package/dist/assistant-stream.js +0 -131
  9. package/dist/cli/commands/chat.js +0 -13
  10. package/dist/cli/commands/ctx.js +0 -7
  11. package/dist/cli/commands/exec.js +0 -35
  12. package/dist/cli/commands/history.js +0 -58
  13. package/dist/cli/commands/index.js +0 -249
  14. package/dist/cli/commands/init.js +0 -18
  15. package/dist/cli/commands/mcp.js +0 -173
  16. package/dist/cli/commands/memory.js +0 -87
  17. package/dist/cli/commands/models.js +0 -21
  18. package/dist/cli/commands/permission.js +0 -12
  19. package/dist/cli/commands/rules.js +0 -33
  20. package/dist/cli/commands/sandbox.js +0 -13
  21. package/dist/cli/commands/serve.js +0 -9
  22. package/dist/cli/commands/setup.js +0 -56
  23. package/dist/cli/commands/shared.js +0 -25
  24. package/dist/cli/commands/skills.js +0 -119
  25. package/dist/cli/commands/think.js +0 -12
  26. package/dist/cli/commands/update.js +0 -7
  27. package/dist/cli/commands/write-config.js +0 -52
  28. package/dist/cli/errors.js +0 -36
  29. package/dist/cli/exec-prompt.js +0 -26
  30. package/dist/cli/option-helpers.js +0 -65
  31. package/dist/cli/program.js +0 -223
  32. package/dist/cli/setup/detect.js +0 -17
  33. package/dist/cli/setup/flags.js +0 -12
  34. package/dist/cli/setup/flow.js +0 -108
  35. package/dist/cli/setup/provider-form.js +0 -102
  36. package/dist/cli/setup/ui.js +0 -534
  37. package/dist/clipboard.js +0 -142
  38. package/dist/code-mode.js +0 -184
  39. package/dist/compaction.js +0 -644
  40. package/dist/config.js +0 -363
  41. package/dist/confirm.js +0 -172
  42. package/dist/context-window.js +0 -256
  43. package/dist/ctx-cli.js +0 -30
  44. package/dist/ctx.js +0 -80
  45. package/dist/doom-loop.js +0 -278
  46. package/dist/fetch-timeout.js +0 -152
  47. package/dist/http-approvals.js +0 -60
  48. package/dist/http.js +0 -119
  49. package/dist/instructions.js +0 -196
  50. package/dist/logger.js +0 -95
  51. package/dist/markdown.js +0 -259
  52. package/dist/mcp.js +0 -1036
  53. package/dist/memory-cli.js +0 -33
  54. package/dist/memory.js +0 -295
  55. package/dist/model-catalog.js +0 -285
  56. package/dist/ollama-model.js +0 -234
  57. package/dist/ollama-openai-bridge.js +0 -383
  58. package/dist/output.js +0 -76
  59. package/dist/paste-handler.js +0 -41
  60. package/dist/permission-cli.js +0 -40
  61. package/dist/plugins.js +0 -131
  62. package/dist/pricing.js +0 -119
  63. package/dist/provider.js +0 -63
  64. package/dist/question-format.js +0 -60
  65. package/dist/reasoning-stream.js +0 -158
  66. package/dist/sandbox-cli.js +0 -79
  67. package/dist/sandbox.js +0 -403
  68. package/dist/save-throttle.js +0 -45
  69. package/dist/scope.js +0 -23
  70. package/dist/serve/common.js +0 -425
  71. package/dist/serve/routes-chat.js +0 -367
  72. package/dist/serve/routes-mcp.js +0 -212
  73. package/dist/serve/routes-memory.js +0 -95
  74. package/dist/serve/routes-meta.js +0 -268
  75. package/dist/serve/routes-sessions.js +0 -61
  76. package/dist/serve/routes-skills.js +0 -70
  77. package/dist/serve.js +0 -138
  78. package/dist/sessions.js +0 -265
  79. package/dist/skills.js +0 -599
  80. package/dist/structured-output.js +0 -29
  81. package/dist/synthetic.js +0 -7
  82. package/dist/think-cli.js +0 -36
  83. package/dist/thinking-wire.js +0 -239
  84. package/dist/thinking.js +0 -166
  85. package/dist/title-gen.js +0 -55
  86. package/dist/token-display.js +0 -39
  87. package/dist/tool-display.js +0 -178
  88. package/dist/tool-output.js +0 -126
  89. package/dist/tools/apply_patch.js +0 -265
  90. package/dist/tools/atomic-file.js +0 -35
  91. package/dist/tools/backend.js +0 -61
  92. package/dist/tools/bash.js +0 -231
  93. package/dist/tools/code_search.js +0 -98
  94. package/dist/tools/edit.js +0 -68
  95. package/dist/tools/explore.js +0 -232
  96. package/dist/tools/glob.js +0 -40
  97. package/dist/tools/grep.js +0 -174
  98. package/dist/tools/index.js +0 -34
  99. package/dist/tools/question.js +0 -54
  100. package/dist/tools/read.js +0 -109
  101. package/dist/tools/search-searxng.js +0 -223
  102. package/dist/tools/search-serper.js +0 -189
  103. package/dist/tools/task.js +0 -165
  104. package/dist/tools/todo.js +0 -213
  105. package/dist/tools/web_fetch.js +0 -195
  106. package/dist/tools/web_search.js +0 -228
  107. package/dist/tools/write.js +0 -55
  108. package/dist/tui/App.js +0 -138
  109. package/dist/tui/ConfirmBar.js +0 -66
  110. package/dist/tui/CtxPicker.js +0 -68
  111. package/dist/tui/InputBar.js +0 -618
  112. package/dist/tui/MessageList.js +0 -718
  113. package/dist/tui/ModelPicker.js +0 -113
  114. package/dist/tui/QuestionBar.js +0 -136
  115. package/dist/tui/SessionPicker.js +0 -79
  116. package/dist/tui/Spinner.js +0 -6
  117. package/dist/tui/StatusBar.js +0 -22
  118. package/dist/tui/ThinkPicker.js +0 -75
  119. package/dist/tui/agent-runner.js +0 -223
  120. package/dist/tui/bracketed-paste.js +0 -37
  121. package/dist/tui/caret-pos.js +0 -179
  122. package/dist/tui/caret.js +0 -69
  123. package/dist/tui/click-count.js +0 -13
  124. package/dist/tui/diff-view.js +0 -61
  125. package/dist/tui/drag-state.js +0 -49
  126. package/dist/tui/hydrate.js +0 -129
  127. package/dist/tui/index.js +0 -264
  128. package/dist/tui/input-history.js +0 -125
  129. package/dist/tui/layout.js +0 -105
  130. package/dist/tui/mouse.js +0 -46
  131. package/dist/tui/overlay-input.js +0 -12
  132. package/dist/tui/paste-draft.js +0 -173
  133. package/dist/tui/prompt-queue.js +0 -24
  134. package/dist/tui/selection.js +0 -232
  135. package/dist/tui/session-switch.js +0 -28
  136. package/dist/tui/slash-commands.js +0 -129
  137. package/dist/tui/slash-handler.js +0 -615
  138. package/dist/tui/text-width.js +0 -113
  139. package/dist/tui/theme.js +0 -12
  140. package/dist/tui/token-info.js +0 -7
  141. package/dist/tui/tool-children.js +0 -19
  142. package/dist/tui/types.js +0 -1
  143. package/dist/tui/undo-stack.js +0 -14
  144. package/dist/tui/use-sgr-mouse.js +0 -29
  145. package/dist/tui-chat.js +0 -478
  146. package/dist/updater.js +0 -116
  147. package/dist/xml-search.js +0 -194
  148. package/docs/superpowers/plans/2026-08-16-batch1-tui-improvements.md +0 -1510
  149. package/docs/superpowers/plans/2026-08-16-batch2-cli-tools-api.md +0 -2105
  150. package/docs/superpowers/plans/2026-08-16-batch3-config-engineering.md +0 -1595
  151. package/docs/superpowers/plans/2026-08-16-input-caret.md +0 -782
  152. package/docs/superpowers/plans/2026-08-20-tui-completeness.md +0 -873
  153. package/docs/superpowers/plans/2026-08-20-unified-tui-default.md +0 -631
  154. package/docs/superpowers/plans/2026-08-23-cli-setup.md +0 -501
  155. package/docs/superpowers/plans/2026-08-23-input-paste-attachments.md +0 -475
  156. package/docs/superpowers/plans/2026-08-23-thinking-wire-profile.md +0 -450
  157. package/docs/superpowers/specs/2026-08-16-batch1-tui-improvements-design.md +0 -183
  158. package/docs/superpowers/specs/2026-08-16-batch2-cli-tools-api-design.md +0 -220
  159. package/docs/superpowers/specs/2026-08-16-batch3-config-engineering-design.md +0 -196
  160. package/docs/superpowers/specs/2026-08-16-input-caret-design.md +0 -63
  161. package/docs/superpowers/specs/2026-08-17-mouse-selection-design.md +0 -116
  162. package/docs/superpowers/specs/2026-08-20-config-http-alignment-design.md +0 -47
  163. package/docs/superpowers/specs/2026-08-20-mcp-plugins-alignment-design.md +0 -37
  164. package/docs/superpowers/specs/2026-08-20-sandbox-permissions-design.md +0 -68
  165. package/docs/superpowers/specs/2026-08-20-tui-completeness-design.md +0 -273
  166. package/docs/superpowers/specs/2026-08-20-unified-tui-default-design.md +0 -165
  167. package/docs/superpowers/specs/2026-08-23-cli-setup-design.md +0 -282
  168. package/docs/superpowers/specs/2026-08-23-input-paste-attachments-design.md +0 -174
  169. package/docs/superpowers/specs/2026-08-23-thinking-wire-profile-design.md +0 -140
@@ -1,173 +0,0 @@
1
- import { loadMcpConfigFile, loadMcpConfigEntries, saveMcpConfig, checkMcpServer, checkAllMcpServers, formatMcpServerBinding, getMcpStatus, listMcpCatalog, } from "../../mcp.js";
2
- import { CliError } from "../errors.js";
3
- function parseEnvPairs(pairs) {
4
- const environment = {};
5
- for (const kv of pairs ?? []) {
6
- const eq = kv.indexOf("=");
7
- if (eq <= 0)
8
- throw new CliError(`Invalid --env format: ${kv}`, { hint: "use KEY=VALUE" });
9
- environment[kv.slice(0, eq)] = kv.slice(eq + 1);
10
- }
11
- return environment;
12
- }
13
- export async function runMcpAdd(name, cmd, opts) {
14
- const scope = opts.project ? "project" : "global";
15
- if (opts.sse && opts.streamableHttp) {
16
- throw new CliError("--sse and --streamable-http are mutually exclusive");
17
- }
18
- const usage = "Usage: min-agent mcp add <name> [--project] [--skip-check] <command...>\n" +
19
- " or: min-agent mcp add <name> --url <https://host/mcp> [--sse|--streamable-http] [--token <bearer>] [--project] [--skip-check]";
20
- let entry;
21
- if (opts.url?.trim()) {
22
- entry = {
23
- url: opts.url.trim(),
24
- enabled: true,
25
- remoteTransport: opts.streamableHttp ? "streamable-http" : opts.sse ? "sse" : "auto",
26
- ...(opts.timeout ? { timeout: opts.timeout } : {}),
27
- };
28
- if (opts.token?.trim())
29
- entry.token = opts.token.trim();
30
- }
31
- else if (cmd.length > 0) {
32
- entry = { command: cmd, enabled: true, ...(opts.timeout ? { timeout: opts.timeout } : {}) };
33
- }
34
- else {
35
- throw new CliError(usage);
36
- }
37
- const environment = parseEnvPairs(opts.env);
38
- if (Object.keys(environment).length > 0)
39
- entry.environment = environment;
40
- let detectedTools = 0;
41
- if (!opts.skipCheck) {
42
- console.log(`Validating MCP server "${name}"...`);
43
- const checkResult = await checkMcpServer(name, entry);
44
- if (!checkResult.ok) {
45
- throw new CliError(`MCP server "${name}" validation failed: ${checkResult.error ?? "unknown error"}`, {
46
- exitCode: 2,
47
- });
48
- }
49
- detectedTools = checkResult.toolCount;
50
- }
51
- else {
52
- console.log(`Skipping MCP validation for "${name}" (--skip-check).`);
53
- }
54
- const config = loadMcpConfigFile(scope);
55
- config.mcpServers[name] = entry;
56
- saveMcpConfig(config, scope);
57
- const toolsSuffix = opts.skipCheck ? "" : ` (${detectedTools} tools detected)`;
58
- const scopeSuffix = opts.project ? " [project]" : "";
59
- console.log(`✓ MCP server "${name}" added${scopeSuffix}: ${formatMcpServerBinding(entry)}${toolsSuffix}`);
60
- }
61
- export async function runMcpRemove(name, opts) {
62
- const scope = opts.project ? "project" : "global";
63
- const config = loadMcpConfigFile(scope);
64
- if (!config.mcpServers[name]) {
65
- const elsewhere = loadMcpConfigEntries().find((e) => e.name === name);
66
- throw new CliError(elsewhere
67
- ? `MCP server "${name}" is defined in ${elsewhere.scope} scope, not ${scope}.`
68
- : `MCP server "${name}" not found`);
69
- }
70
- delete config.mcpServers[name];
71
- saveMcpConfig(config, scope);
72
- console.log(`✓ MCP server "${name}" removed${opts.project ? " [project]" : ""}`);
73
- }
74
- export async function runMcpList() {
75
- const entries = loadMcpConfigEntries();
76
- if (entries.length === 0) {
77
- console.log("No MCP servers configured.");
78
- console.log("Add one with: min-agent mcp add <name> <command...>");
79
- return;
80
- }
81
- console.log("MCP Servers:");
82
- for (const { name, config, scope } of entries) {
83
- const status = config.enabled === false ? "\x1b[90mdisabled\x1b[0m" : "\x1b[32menabled\x1b[0m";
84
- const scopeMark = scope === "project" ? " \x1b[90m[project]\x1b[0m" : "";
85
- console.log(` ${name} ${status}${scopeMark}`);
86
- }
87
- console.log("\nUse: min-agent mcp info <name> for details");
88
- }
89
- export async function runMcpInfo(name) {
90
- const found = loadMcpConfigEntries().find((e) => e.name === name);
91
- if (!found)
92
- throw new CliError(`MCP server "${name}" not found`);
93
- const cfg = found.config;
94
- console.log(`Name: ${name}`);
95
- console.log(`Scope: ${found.scope}`);
96
- console.log(`Status: ${cfg.enabled === false ? "disabled" : "enabled"}`);
97
- console.log(`Binding: ${formatMcpServerBinding(cfg)}`);
98
- if (cfg.command)
99
- console.log(`Command: ${Array.isArray(cfg.command) ? cfg.command.join(" ") : `${cfg.command} ${(cfg.args ?? []).join(" ")}`.trim()}`);
100
- if (cfg.url) {
101
- console.log(`URL: ${cfg.url}`);
102
- if (cfg.remoteTransport)
103
- console.log(`Transport: ${cfg.remoteTransport}`);
104
- if (cfg.oauth === false)
105
- console.log(`OAuth: disabled`);
106
- else if (cfg.oauth)
107
- console.log(`OAuth: enabled${cfg.oauth.clientId ? ` (clientId set)` : ""}`);
108
- }
109
- if (cfg.headers)
110
- console.log(`Headers: ${Object.keys(cfg.headers).join(", ")} (values hidden)`);
111
- if (cfg.token)
112
- console.log(`Token: ***`);
113
- if (cfg.environment)
114
- console.log(`Env: ${Object.keys(cfg.environment).join(", ")}`);
115
- if (cfg.timeout)
116
- console.log(`Timeout: ${cfg.timeout}ms`);
117
- if (cfg.connectTimeout)
118
- console.log(`ConnectTimeout: ${cfg.connectTimeout}ms`);
119
- if (cfg.callTimeout)
120
- console.log(`CallTimeout: ${cfg.callTimeout}ms`);
121
- const st = getMcpStatus()[name];
122
- if (st?.connected) {
123
- const catalog = listMcpCatalog(name).servers[0];
124
- if (catalog) {
125
- console.log(`Tools: ${st.tools.join(", ") || "(none)"}`);
126
- console.log(`Resources: ${catalog.resources.length === 0 ? "(none)" : catalog.resources.map((r) => r.uri).join(", ")}`);
127
- console.log(`Prompts: ${catalog.prompts.length === 0 ? "(none)" : catalog.prompts.map((p) => p.name).join(", ")}`);
128
- }
129
- }
130
- }
131
- export async function runMcpCheck() {
132
- const results = await checkAllMcpServers();
133
- if (results.length === 0) {
134
- console.log("No MCP servers configured.");
135
- console.log("Add one with: min-agent mcp add <name> <command...> or --url <https://...>");
136
- return;
137
- }
138
- let failed = 0;
139
- console.log("MCP Check Results:");
140
- for (const result of results) {
141
- if (!result.enabled) {
142
- console.log(` ${result.name}: skipped (disabled)`);
143
- continue;
144
- }
145
- if (result.ok) {
146
- console.log(` ${result.name}: ok (${result.toolCount} tools)`);
147
- }
148
- else {
149
- failed++;
150
- console.log(` ${result.name}: failed${result.error ? ` - ${result.error}` : ""}`);
151
- }
152
- }
153
- if (failed > 0) {
154
- throw new CliError(`${failed} MCP server(s) failed.`, { exitCode: 1 });
155
- }
156
- console.log("\nAll enabled MCP servers are available.");
157
- }
158
- export async function runMcpToggle(names, enabled, opts) {
159
- const scope = opts.project ? "project" : "global";
160
- const verb = enabled ? "enable" : "disable";
161
- if (names.length === 0)
162
- throw new CliError(`Usage: min-agent mcp ${verb} <name...> [--project]`);
163
- const config = loadMcpConfigFile(scope);
164
- for (const name of names) {
165
- if (!config.mcpServers[name]) {
166
- console.error(`MCP server "${name}" not found${opts.project ? " in project scope" : ""}`);
167
- continue;
168
- }
169
- config.mcpServers[name].enabled = enabled;
170
- console.log(`✓ MCP server "${name}" ${verb}d${opts.project ? " [project]" : ""}`);
171
- }
172
- saveMcpConfig(config, scope);
173
- }
@@ -1,87 +0,0 @@
1
- import { loadMemories, addMemory, deleteMemory, searchMemories, defaultMemoryScope, formatMemoryLine, parseMemoryMode, resolveMemoryMode, memoryModeLabel, memorySourceLabel, isMemoryEnabled, } from "../../memory.js";
2
- import { runMemoryCli } from "../../memory-cli.js";
3
- import { CliError } from "../errors.js";
4
- function printList(which) {
5
- const memories = loadMemories(which);
6
- const label = which === "project" ? "Project memories" : "Global memories";
7
- if (memories.length === 0) {
8
- console.log(`${label}: none`);
9
- return;
10
- }
11
- console.log(`${label} (${memories.length}):`);
12
- for (const line of memories.map((m, i) => formatMemoryLine(m, i, { date: true }))) {
13
- console.log(line);
14
- }
15
- }
16
- export async function runMemoryMode(state, scope, flagMode) {
17
- if (!state && flagMode === undefined)
18
- return false;
19
- if (state && state !== "list" && !parseMemoryMode(state))
20
- return false;
21
- if (state === "list")
22
- return false;
23
- const result = runMemoryCli({
24
- positionals: state ? [state] : [],
25
- flagMode,
26
- scope,
27
- });
28
- console.log(result.lines.join("\n"));
29
- if (!result.ok)
30
- process.exitCode = 1;
31
- return true;
32
- }
33
- export async function runMemoryList(scope) {
34
- const { memory, source } = resolveMemoryMode();
35
- console.log(`Current memory: ${memoryModeLabel(memory)} (${memorySourceLabel(source)})`);
36
- if (!scope && loadMemories("project").length === 0 && loadMemories("global").length === 0) {
37
- console.log("No memories stored.");
38
- if (!isMemoryEnabled())
39
- console.log("Turn on with: min-agent memory on");
40
- console.log('Or add manually: min-agent memory add "prefer TypeScript over JavaScript"');
41
- return;
42
- }
43
- const scopes = scope ? [scope] : ["project", "global"];
44
- for (const s of scopes)
45
- printList(s);
46
- if (!isMemoryEnabled())
47
- console.log("Memories are stored but not used in chat until you run: min-agent memory on");
48
- }
49
- export async function runMemoryAdd(textTokens, scope) {
50
- const text = textTokens.join(" ");
51
- if (!text)
52
- throw new CliError("Usage: min-agent memory add <text> [--project|--global]");
53
- const resolved = scope ?? defaultMemoryScope();
54
- addMemory(text, [], resolved);
55
- const hint = isMemoryEnabled() ? "" : " (memory is off — turn on with: min-agent memory on)";
56
- console.log(`✓ ${resolved === "project" ? "Project" : "Global"} memory saved: "${text}"${hint}`);
57
- }
58
- export async function runMemorySearch(queryTokens, scope) {
59
- const query = queryTokens.join(" ");
60
- if (!query)
61
- throw new CliError("Usage: min-agent memory search <query> [--project|--global]");
62
- const scopes = scope ? [scope] : ["project", "global"];
63
- const lines = scopes.flatMap((s) => searchMemories(query, s).map((m) => {
64
- const tags = m.tags.length > 0 ? ` [${m.tags.join(", ")}]` : "";
65
- return ` [${s}] #${m.index + 1}: ${m.content}${tags}`;
66
- }));
67
- if (lines.length === 0) {
68
- console.log(`No memories matching "${query}"`);
69
- }
70
- else {
71
- console.log(`Found ${lines.length} memory(s):`);
72
- for (const line of lines)
73
- console.log(line);
74
- }
75
- }
76
- export async function runMemoryDelete(indexArg, scope) {
77
- const idx = Number.parseInt(indexArg, 10);
78
- if (Number.isNaN(idx))
79
- throw new CliError("Usage: min-agent memory delete <number> [--project|--global]");
80
- const resolved = scope ?? defaultMemoryScope();
81
- if (deleteMemory(idx - 1, resolved)) {
82
- console.log(`✓ ${resolved === "project" ? "Project" : "Global"} memory #${idx} deleted`);
83
- }
84
- else {
85
- throw new CliError(`${resolved === "project" ? "Project" : "Global"} memory #${idx} not found`);
86
- }
87
- }
@@ -1,21 +0,0 @@
1
- import { loadConfig, fetchModels, getActiveProvider } from "../../config.js";
2
- import { CliError } from "../errors.js";
3
- export async function runModelsCommand(opts) {
4
- const config = loadConfig();
5
- const provider = opts.provider ? config.providers?.find((p) => p.name === opts.provider) : getActiveProvider(config);
6
- if (!provider?.baseURL || !provider?.apiKey) {
7
- throw new CliError("Not configured.", { hint: "Run: min-agent setup" });
8
- }
9
- console.log(`Fetching models (${provider.name ?? "default"})...`);
10
- const models = await fetchModels(provider.baseURL, provider.apiKey);
11
- if (models.length === 0) {
12
- console.log("No models found or unable to fetch model list.");
13
- }
14
- else {
15
- console.log(`\nAvailable models (${models.length}):`);
16
- for (const m of models) {
17
- const marker = m === provider.defaultModel ? " ← default" : "";
18
- console.log(` ${m}${marker}`);
19
- }
20
- }
21
- }
@@ -1,12 +0,0 @@
1
- import { runPermissionCli } from "../../permission-cli.js";
2
- export async function runPermissionCommand(args, opts, parentOpts) {
3
- const scope = opts.project ? "project" : opts.global ? "global" : undefined;
4
- const result = runPermissionCli({
5
- positionals: args,
6
- flagMode: parentOpts.permission,
7
- scope,
8
- });
9
- console.log(result.lines.join("\n"));
10
- if (!result.ok)
11
- process.exitCode = 1;
12
- }
@@ -1,33 +0,0 @@
1
- import { existsSync, writeFileSync, mkdirSync } from "fs";
2
- import { getConfigDir, getRulesFile } from "../../config.js";
3
- export async function runRulesShow() {
4
- const { loadInstructions } = await import("../../instructions.js");
5
- const instructions = await loadInstructions();
6
- if (instructions.length === 0) {
7
- console.log("No instruction rules loaded.");
8
- console.log("");
9
- console.log("Add rules by creating:");
10
- console.log(` Global: ${getRulesFile()}`);
11
- console.log(" Project: ./AGENTS.md or ./RULES.md");
12
- console.log("");
13
- console.log("Or add paths/URLs in ~/.min-agent/config.json:");
14
- console.log(' { "instructions": ["./docs/rules.md", "https://..."] }');
15
- }
16
- else {
17
- console.log(`Loaded ${instructions.length} instruction source(s):\n`);
18
- for (const inst of instructions) {
19
- const firstLine = inst.split("\n")[0];
20
- console.log(` ${firstLine}`);
21
- }
22
- }
23
- }
24
- export async function runRulesEdit() {
25
- const rulesFile = getRulesFile();
26
- if (!existsSync(rulesFile)) {
27
- mkdirSync(getConfigDir(), { recursive: true });
28
- writeFileSync(rulesFile, `# Global Agent Rules\n\n<!-- Add your custom instructions here. They will be included in every conversation. -->\n`, "utf-8");
29
- }
30
- const editor = process.env.EDITOR || "vi";
31
- const { execSync } = await import("child_process");
32
- execSync(`${editor} "${rulesFile}"`, { stdio: "inherit" });
33
- }
@@ -1,13 +0,0 @@
1
- import { runSandboxCli } from "../../sandbox-cli.js";
2
- export async function runSandboxCommand(args, opts, parentOpts) {
3
- const scope = opts.project ? "project" : opts.global ? "global" : undefined;
4
- const result = runSandboxCli({
5
- positionals: args,
6
- flagMode: parentOpts.sandbox,
7
- flagNetwork: parentOpts.network ?? opts.network,
8
- scope,
9
- });
10
- console.log(result.lines.join("\n"));
11
- if (!result.ok)
12
- process.exitCode = 1;
13
- }
@@ -1,9 +0,0 @@
1
- import { isConfigured } from "../../config.js";
2
- import { CliError } from "../errors.js";
3
- export async function runServeCommand(opts) {
4
- if (!isConfigured()) {
5
- throw new CliError("Not configured.", { hint: "Run: min-agent setup" });
6
- }
7
- const { runServe } = await import("../../serve.js");
8
- await runServe({ port: opts.port, host: opts.host });
9
- }
@@ -1,56 +0,0 @@
1
- import path from "path";
2
- import { Option } from "commander";
3
- import { fetchModelsLive, getConfigDir, loadConfig, saveConfig } from "../../config.js";
4
- import { parsePositiveIntArg } from "../option-helpers.js";
5
- import { parseProviderType } from "../setup/flags.js";
6
- import { runSetup } from "../setup/flow.js";
7
- export function registerSetupCommand(program, rootOpts) {
8
- program
9
- .command("setup")
10
- .description("Configure providers (interactively, or with flags)")
11
- .addOption(new Option("--type <type>", "openai-compatible, openai, or ollama").argParser(parseProviderType))
12
- .option("--url <url>", "API base URL")
13
- .option("--api-key <key>", "API key")
14
- .option("--name <name>", "Provider name")
15
- .option("--default-model <id>", "Default model to save")
16
- .addOption(new Option("--context-window <n>", "Context window in tokens").argParser(parsePositiveIntArg("--context-window")))
17
- .option("--switch <name>", "Set the active provider")
18
- .option("--remove <name>", "Remove a provider")
19
- .option("-y, --yes", "Skip overwrite and delete confirmation")
20
- .action(async (opts) => {
21
- await runSetupCommand(opts, { yes: Boolean(opts.yes || rootOpts().yes) });
22
- });
23
- }
24
- function createSetupDeps() {
25
- return {
26
- isTty: Boolean(process.stdin.isTTY && process.stdout.isTTY),
27
- load: loadConfig,
28
- save: saveConfig,
29
- fetchLive: fetchModelsLive,
30
- log: (message) => {
31
- console.log(message);
32
- },
33
- configPath: () => path.join(getConfigDir(), "config.json"),
34
- runWizard: async (wizardMode) => {
35
- const { renderSetupWizard } = await import("../setup/ui.js");
36
- return renderSetupWizard(wizardMode);
37
- },
38
- };
39
- }
40
- export async function offerInteractiveSetup(mode) {
41
- await runSetup({}, { ...createSetupDeps(), isTty: true }, mode);
42
- }
43
- export async function runSetupCommand(opts, session) {
44
- const flags = {
45
- type: opts.type,
46
- url: opts.url,
47
- apiKey: opts.apiKey,
48
- name: opts.name,
49
- defaultModel: opts.defaultModel,
50
- contextWindow: opts.contextWindow,
51
- switch: opts.switch,
52
- remove: opts.remove,
53
- yes: Boolean(session.yes || opts.yes),
54
- };
55
- await runSetup(flags, createSetupDeps());
56
- }
@@ -1,25 +0,0 @@
1
- import { isConfigured } from "../../config.js";
2
- import { CliError } from "../errors.js";
3
- import { shouldOfferSetupWizard } from "../setup/flow.js";
4
- export async function startTuiSession(input) {
5
- if (!isConfigured()) {
6
- const tty = Boolean(process.stdin.isTTY && process.stdout.isTTY);
7
- if (!shouldOfferSetupWizard(false, tty)) {
8
- throw new CliError("Not configured.", { hint: "Run: min-agent setup" });
9
- }
10
- const { offerInteractiveSetup } = await import("./setup.js");
11
- await offerInteractiveSetup("session-gate");
12
- if (!isConfigured()) {
13
- throw new CliError("Not configured.", { hint: "Run: min-agent setup" });
14
- }
15
- }
16
- const { runTui } = await import("../../tui-chat.js");
17
- const prompt = input.positionals.join(" ").trim();
18
- await runTui({
19
- modelId: input.model,
20
- providerName: input.provider,
21
- resumeSessionId: input.resume,
22
- images: input.images,
23
- initialPrompt: prompt || undefined,
24
- });
25
- }
@@ -1,119 +0,0 @@
1
- import { discoverSkills } from "../../skills.js";
2
- import { existsSync, writeFileSync, mkdirSync } from "fs";
3
- import path from "path";
4
- import os from "os";
5
- import { CliError } from "../errors.js";
6
- /** One-line, length-capped text for list output. */
7
- function truncate(text, max) {
8
- const flat = text.replace(/\s+/g, " ").trim();
9
- return flat.length <= max ? flat : `${flat.slice(0, max - 1)}…`;
10
- }
11
- export async function runSkillsList(json) {
12
- discoverSkills({ silent: true });
13
- const { getAllSkills, getStaleDisabledSkills } = await import("../../skills.js");
14
- const all = getAllSkills().sort((a, b) => a.name.localeCompare(b.name));
15
- const stale = getStaleDisabledSkills();
16
- if (json) {
17
- console.log(JSON.stringify({
18
- count: all.length,
19
- enabled_count: all.filter((s) => s.enabled).length,
20
- stale_disabled: stale,
21
- skills: all.map((s) => ({
22
- name: s.name,
23
- description: s.description,
24
- location: s.location,
25
- enabled: s.enabled,
26
- ...(s.disabledScope ? { disabled_scope: s.disabledScope } : {}),
27
- ...(s.version ? { version: s.version } : {}),
28
- ...(s.allowedTools.length ? { allowed_tools: s.allowedTools } : {}),
29
- ...(s.requiredBins.length ? { requires_bins: s.requiredBins } : {}),
30
- ...(s.builtin ? { builtin: true } : {}),
31
- ...(s.alwaysLoad ? { always_load: true } : {}),
32
- })),
33
- }, null, 2));
34
- return;
35
- }
36
- if (all.length === 0 && stale.length === 0) {
37
- console.log("No skills found. Add SKILL.md files in .min-agent/skills/<name>/");
38
- return;
39
- }
40
- console.log(`Skills (${all.filter((s) => s.enabled).length} enabled, ${all.filter((s) => !s.enabled).length} disabled):`);
41
- for (const skill of all) {
42
- const status = skill.enabled
43
- ? "\x1b[32menabled \x1b[0m"
44
- : `\x1b[90mdisabled(${skill.disabledScope === "project" ? "proj" : "glob"})\x1b[0m`;
45
- const origin = skill.builtin ? " \x1b[90mbuiltin\x1b[0m" : "";
46
- console.log(` ${skill.name} ${status}${origin} \x1b[90m${truncate(skill.description, 60)}\x1b[0m`);
47
- console.log(` \x1b[90m${skill.location}\x1b[0m`);
48
- }
49
- if (stale.length > 0) {
50
- console.log(`\n\x1b[33m⚠ disabledSkills/enabledSkills entries matching no skill: ${stale.join(", ")}\x1b[0m`);
51
- console.log(`\x1b[33m Remove them with: min-agent skills enable ${stale.join(" ")} (add --project if the entry is project-scoped)\x1b[0m`);
52
- }
53
- console.log("\nUse: min-agent skills info <name> for details");
54
- }
55
- export async function runSkillsInfo(name, json) {
56
- discoverSkills({ silent: true });
57
- const { getSkill, getAllSkills } = await import("../../skills.js");
58
- const skill = getSkill(name);
59
- if (!skill) {
60
- const names = getAllSkills().map((s) => s.name);
61
- throw new CliError(`Skill "${name}" not found.${names.length ? ` Available: ${names.join(", ")}` : " No skills discovered."}`);
62
- }
63
- if (json) {
64
- console.log(JSON.stringify(skill, null, 2));
65
- return;
66
- }
67
- console.log(`Name: ${skill.name}`);
68
- console.log(`Status: ${skill.enabled ? "enabled" : `disabled (${skill.disabledScope} scope)`}`);
69
- if (skill.builtin)
70
- console.log("Source: builtin");
71
- if (skill.version)
72
- console.log(`Version: ${skill.version}`);
73
- console.log(`Description: ${skill.description}`);
74
- console.log(`Location: ${skill.location}`);
75
- if (skill.allowedTools.length > 0)
76
- console.log(`Tools: ${skill.allowedTools.join(", ")}`);
77
- if (skill.requiredBins.length > 0)
78
- console.log(`Requires: ${skill.requiredBins.join(", ")}`);
79
- if (skill.content.trim()) {
80
- console.log("\n--- Content ---\n");
81
- console.log(skill.content.trim());
82
- }
83
- }
84
- export async function runSkillsToggle(names, enabled, scope) {
85
- const verb = enabled ? "enable" : "disable";
86
- if (names.length === 0)
87
- throw new CliError(`Usage: min-agent skills ${verb} <name...> [--project]`);
88
- discoverSkills({ silent: true });
89
- const { getAllSkills, setSkillEnabled, getStaleDisabledSkills } = await import("../../skills.js");
90
- const known = new Set(getAllSkills().map((s) => s.name));
91
- const stale = new Set(getStaleDisabledSkills());
92
- // `enable` must accept stale names so they can be cleaned up from config;
93
- // `disable` on an unknown name is always an error.
94
- const unknown = names.filter((n) => !known.has(n) && !(enabled && stale.has(n)));
95
- if (unknown.length > 0) {
96
- throw new CliError(`Skill${unknown.length > 1 ? "s" : ""} not found: ${unknown.join(", ")}`, {
97
- hint: known.size ? `Available: ${[...known].join(", ")}` : "No skills discovered.",
98
- });
99
- }
100
- for (const result of setSkillEnabled(names, enabled, scope)) {
101
- console.log(`✓ Skill "${result.name}" ${verb}d (${scope} scope)`);
102
- if (result.blockedBy) {
103
- console.log(`\x1b[33m ⚠ still ${result.enabled ? "enabled" : "disabled"} — overridden by ${result.blockedBy} scope\x1b[0m`);
104
- }
105
- }
106
- }
107
- export async function runSkillsNew(name, global) {
108
- if (!/^[\w-]+$/.test(name)) {
109
- throw new CliError("Invalid skill name", { hint: "use letters, digits, _ or -" });
110
- }
111
- const root = global ? path.join(os.homedir(), ".agents", "skills") : path.join(process.cwd(), ".min-agent", "skills");
112
- const dir = path.join(root, name);
113
- if (existsSync(path.join(dir, "SKILL.md"))) {
114
- throw new CliError(`Skill "${name}" already exists at ${dir}`);
115
- }
116
- mkdirSync(dir, { recursive: true });
117
- writeFileSync(path.join(dir, "SKILL.md"), `---\nname: ${name}\ndescription: What this skill does\n# version: 1.0.0\n# allowed-tools: [read, grep]\n# metadata:\n# requires:\n# bins: ["some-cli"]\n---\n\n# ${name}\n\nWrite the skill instructions here.\n`, "utf-8");
118
- console.log(`✓ Created skill "${name}" at ${path.join(dir, "SKILL.md")}`);
119
- }
@@ -1,12 +0,0 @@
1
- import { runThinkCli } from "../../think-cli.js";
2
- export async function runThinkCommand(args, opts, parentOpts) {
3
- const scope = opts.project ? "project" : opts.global ? "global" : undefined;
4
- const result = runThinkCli({
5
- positionals: args,
6
- flagEffort: parentOpts.think,
7
- scope,
8
- });
9
- console.log(result.lines.join("\n"));
10
- if (!result.ok)
11
- process.exitCode = 1;
12
- }
@@ -1,7 +0,0 @@
1
- import { runUpdate } from "../../updater.js";
2
- export async function runUpdateCommand() {
3
- const result = await runUpdate();
4
- if (result.status === "check-failed" || result.status === "install-failed") {
5
- process.exitCode = 1;
6
- }
7
- }
@@ -1,52 +0,0 @@
1
- import { runSandboxCli } from "../../sandbox-cli.js";
2
- import { runPermissionCli } from "../../permission-cli.js";
3
- import { runThinkCli } from "../../think-cli.js";
4
- import { runMemoryCli } from "../../memory-cli.js";
5
- export async function runWriteConfig(input) {
6
- const lines = [];
7
- let ok = true;
8
- if (input.sandbox !== undefined || input.network !== undefined) {
9
- const result = runSandboxCli({
10
- positionals: [],
11
- flagMode: input.sandbox,
12
- flagNetwork: input.network,
13
- scope: input.scope,
14
- });
15
- lines.push(...result.lines);
16
- if (!result.ok)
17
- ok = false;
18
- }
19
- if (input.permission !== undefined) {
20
- const result = runPermissionCli({
21
- positionals: [],
22
- flagMode: input.permission,
23
- scope: input.scope,
24
- });
25
- lines.push(...result.lines);
26
- if (!result.ok)
27
- ok = false;
28
- }
29
- if (input.think !== undefined) {
30
- const result = runThinkCli({
31
- positionals: [],
32
- flagEffort: input.think,
33
- scope: input.scope,
34
- });
35
- lines.push(...result.lines);
36
- if (!result.ok)
37
- ok = false;
38
- }
39
- if (input.memory !== undefined) {
40
- const result = runMemoryCli({
41
- positionals: [],
42
- flagMode: input.memory,
43
- scope: input.scope,
44
- });
45
- lines.push(...result.lines);
46
- if (!result.ok)
47
- ok = false;
48
- }
49
- console.log(lines.join("\n"));
50
- if (!ok)
51
- process.exitCode = 1;
52
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * Unified CLI error contract.
3
- *
4
- * Exit code convention:
5
- * 1 - user error (bad arguments, missing input, not found, validation failure)
6
- * 2 - runtime error (network failure, subprocess failure, unexpected exception)
7
- */
8
- export class CliError extends Error {
9
- exitCode;
10
- hint;
11
- constructor(message, options) {
12
- super(message);
13
- this.name = "CliError";
14
- this.exitCode = options?.exitCode ?? 1;
15
- this.hint = options?.hint;
16
- }
17
- }
18
- export function userError(message, hint) {
19
- return new CliError(message, { exitCode: 1, hint });
20
- }
21
- export function runtimeError(message, hint) {
22
- return new CliError(message, { exitCode: 2, hint });
23
- }
24
- /** Render a CliError (or any error) as the standard `✖ message` block on stderr. */
25
- export function formatCliError(err) {
26
- if (err instanceof CliError) {
27
- return err.hint ? `✖ ${err.message}\n → ${err.hint}` : `✖ ${err.message}`;
28
- }
29
- const message = err instanceof Error ? err.message : String(err);
30
- return `✖ ${message}`;
31
- }
32
- export function exitCodeFor(err) {
33
- if (err instanceof CliError)
34
- return err.exitCode;
35
- return 2;
36
- }