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,131 +0,0 @@
1
- /**
2
- * Split "thinking" fragments (inline XML-style blocks some models leak into text)
3
- * from displayable assistant text. Thinking is emitted to stderr; display goes to Markdown.
4
- */
5
- const BT = String.fromCharCode(96); // backtick — some models wrap thinking in `think` / `redacted_thinking`
6
- const THINKING_BLOCKS = [
7
- { open: "<think>", close: "</think>" },
8
- { open: "<thinking>", close: "</thinking>" },
9
- { open: `<${BT}think${BT}>`, close: `<${BT}/think${BT}>` },
10
- { open: `<${BT}redacted_thinking${BT}>`, close: `<${BT}/redacted_thinking${BT}>` },
11
- ];
12
- /** Max tail to keep when looking for a partial opening tag. */
13
- const PARTIAL_TAG_HOLD = 72;
14
- /**
15
- * If an opening tag never gets closed (truncated / misbehaving model), the
16
- * buffer would grow without bound. Beyond this size, treat the remainder as
17
- * thinking text and move on.
18
- */
19
- const UNCLOSED_THINK_MAX = 16 * 1024;
20
- function lower(s) {
21
- return s.toLowerCase();
22
- }
23
- function findFirstOpen(buf) {
24
- const l = lower(buf);
25
- let best = null;
26
- for (const tag of THINKING_BLOCKS) {
27
- const i = l.indexOf(tag.open);
28
- if (i >= 0 && (!best || i < best.index))
29
- best = { index: i, tag };
30
- }
31
- return best;
32
- }
33
- /**
34
- * Incremental filter: feed raw model text deltas; get display text (for stdout / history)
35
- * and thinking text (for stderr). Handles tags split across chunks.
36
- */
37
- export class ThinkingBodySplitter {
38
- buf = "";
39
- feed(chunk) {
40
- this.buf += chunk;
41
- return this.drain(false);
42
- }
43
- /** End of stream: flush remainder; incomplete thinking block → stderr only. */
44
- flush() {
45
- return this.drain(true);
46
- }
47
- drain(isFinal) {
48
- let display = "";
49
- let thinking = "";
50
- let hadThinking = false;
51
- while (this.buf.length > 0) {
52
- const open = findFirstOpen(this.buf);
53
- if (!open) {
54
- if (isFinal) {
55
- display += this.buf;
56
- this.buf = "";
57
- }
58
- else {
59
- const holdFrom = lastPotentialPartialOpen(this.buf);
60
- if (holdFrom >= 0) {
61
- display += this.buf.slice(0, holdFrom);
62
- this.buf = this.buf.slice(holdFrom);
63
- }
64
- else {
65
- display += this.buf;
66
- this.buf = "";
67
- }
68
- }
69
- break;
70
- }
71
- if (open.index > 0) {
72
- // Strip trailing newlines before thinking block
73
- let pre = this.buf.slice(0, open.index);
74
- pre = pre.replace(/\n+$/, "");
75
- if (pre)
76
- display += pre;
77
- this.buf = this.buf.slice(open.index);
78
- }
79
- const low = lower(this.buf);
80
- const afterOpen = open.tag.open.length;
81
- const closeRel = low.indexOf(open.tag.close, afterOpen);
82
- if (closeRel < 0) {
83
- if (isFinal) {
84
- thinking += this.buf.slice(afterOpen);
85
- this.buf = "";
86
- }
87
- else if (this.buf.length - afterOpen > UNCLOSED_THINK_MAX) {
88
- thinking += this.buf.slice(afterOpen);
89
- this.buf = "";
90
- hadThinking = true;
91
- }
92
- break;
93
- }
94
- const inner = this.buf.slice(afterOpen, closeRel);
95
- thinking += inner;
96
- hadThinking = true;
97
- this.buf = this.buf.slice(closeRel + open.tag.close.length);
98
- }
99
- // Strip leading newlines from display that follow a thinking block
100
- if (hadThinking) {
101
- display = display.replace(/^\n+/, "");
102
- }
103
- return { display, thinking };
104
- }
105
- }
106
- /** If `buf` ends with `<...` that could still become a thinking open tag, return index of `<` to hold from; else -1. */
107
- function lastPotentialPartialOpen(buf) {
108
- const start = Math.max(0, buf.length - PARTIAL_TAG_HOLD);
109
- const tail = buf.slice(start);
110
- const lt = tail.lastIndexOf("<");
111
- if (lt < 0)
112
- return -1;
113
- const globalLt = start + lt;
114
- const cand = buf.slice(globalLt).toLowerCase();
115
- if (cand.length > 64)
116
- return -1;
117
- for (const tag of THINKING_BLOCKS) {
118
- if (tag.open.startsWith(cand))
119
- return globalLt;
120
- }
121
- return -1;
122
- }
123
- /** Final strip for assistant message (complete tags only). */
124
- export function stripThinkingFromAssistantText(text) {
125
- let s = text;
126
- for (const { open, close } of THINKING_BLOCKS) {
127
- const re = new RegExp(open.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "[\\s\\S]*?" + close.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi");
128
- s = s.replace(re, "");
129
- }
130
- return s;
131
- }
@@ -1,13 +0,0 @@
1
- import { startTuiSession } from "./shared.js";
2
- import { applySessionOverrides, applySessionRuntimeOverrides } from "../program.js";
3
- export async function runChat(promptTokens, opts) {
4
- applySessionOverrides(opts);
5
- await applySessionRuntimeOverrides(opts);
6
- await startTuiSession({
7
- model: opts.model,
8
- provider: opts.provider,
9
- resume: opts.resume,
10
- images: opts.image,
11
- positionals: promptTokens,
12
- });
13
- }
@@ -1,7 +0,0 @@
1
- import { runCtxCli } from "../../ctx-cli.js";
2
- export async function runCtxCommand(args) {
3
- const result = runCtxCli({ positionals: args });
4
- console.log(result.lines.join("\n"));
5
- if (!result.ok)
6
- process.exitCode = 1;
7
- }
@@ -1,35 +0,0 @@
1
- import { runAgent } from "../../agent.js";
2
- import { isConfigured } from "../../config.js";
3
- import { resolveExecPrompt } from "../exec-prompt.js";
4
- import { CliError } from "../errors.js";
5
- import { applySessionOverrides, applySessionRuntimeOverrides } from "../program.js";
6
- export async function runExec(messageTokens, opts) {
7
- if (!isConfigured()) {
8
- throw new CliError("Not configured.", { hint: "Run: min-agent setup" });
9
- }
10
- applySessionOverrides(opts);
11
- await applySessionRuntimeOverrides(opts);
12
- const stdinIsTty = Boolean(process.stdin.isTTY);
13
- const joined = messageTokens.join(" ");
14
- const shouldReadStdin = joined === "-" || !stdinIsTty;
15
- let stdinText = "";
16
- if (shouldReadStdin) {
17
- try {
18
- const chunks = [];
19
- for await (const chunk of process.stdin) {
20
- chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
21
- }
22
- stdinText = Buffer.concat(chunks).toString("utf-8");
23
- }
24
- catch {
25
- throw new CliError("Failed to read stdin");
26
- }
27
- }
28
- const resolved = resolveExecPrompt(messageTokens, stdinText, stdinIsTty);
29
- if (!resolved.ok) {
30
- throw new CliError(resolved.error);
31
- }
32
- const failed = await runAgent(resolved.prompt, opts.model, opts.image.length > 0 ? opts.image : undefined, opts.provider, opts.resume);
33
- if (failed)
34
- process.exitCode = 1;
35
- }
@@ -1,58 +0,0 @@
1
- import { writeFileSync } from "fs";
2
- import { CliError } from "../errors.js";
3
- export async function runHistoryList() {
4
- const { listSessions } = await import("../../sessions.js");
5
- const sessions = listSessions();
6
- if (sessions.length === 0) {
7
- console.log("No saved sessions.");
8
- console.log("Sessions are auto-saved when you exit interactive chat.");
9
- }
10
- else {
11
- console.log(`Sessions (${sessions.length}):`);
12
- for (const s of sessions.slice(0, 20)) {
13
- const date = s.updated.split("T")[0];
14
- console.log(` ${s.id} ${date} ${s.title} (${s.messageCount} msgs)`);
15
- }
16
- console.log("\nResume with: min-agent --resume <id>");
17
- }
18
- }
19
- export async function runHistoryDelete(id) {
20
- const { deleteSession } = await import("../../sessions.js");
21
- if (deleteSession(id)) {
22
- console.log(`✓ Session ${id} deleted`);
23
- }
24
- else {
25
- throw new CliError(`Session ${id} not found`);
26
- }
27
- }
28
- export async function runHistoryRename(id, titleTokens) {
29
- const title = titleTokens.join(" ");
30
- if (!title)
31
- throw new CliError("Usage: min-agent history rename <id> <title>");
32
- const { renameSession } = await import("../../sessions.js");
33
- if (renameSession(id, title)) {
34
- console.log(`✓ Session ${id} renamed to: ${title}`);
35
- }
36
- else {
37
- throw new CliError(`Session ${id} not found`);
38
- }
39
- }
40
- export async function runHistoryExport(id, opts) {
41
- const { loadSession } = await import("../../sessions.js");
42
- const session = loadSession(id);
43
- if (!session)
44
- throw new CliError(`Session ${id} not found`);
45
- const json = JSON.stringify(session, null, 2);
46
- if (opts.output) {
47
- try {
48
- writeFileSync(opts.output, json, "utf-8");
49
- console.log(`✓ Session ${id} exported to ${opts.output}`);
50
- }
51
- catch (err) {
52
- throw new CliError(`Export failed: ${err.message}`, { exitCode: 2 });
53
- }
54
- }
55
- else {
56
- console.log(json);
57
- }
58
- }
@@ -1,249 +0,0 @@
1
- import { Option } from "commander";
2
- import { resolveScope, parsePositiveIntArg } from "../option-helpers.js";
3
- import { registerSetupCommand } from "./setup.js";
4
- import { runModelsCommand } from "./models.js";
5
- import { runChat } from "./chat.js";
6
- import { runExec } from "./exec.js";
7
- import { runServeCommand } from "./serve.js";
8
- import { runSandboxCommand } from "./sandbox.js";
9
- import { runPermissionCommand } from "./permission.js";
10
- import { runThinkCommand } from "./think.js";
11
- import { runCtxCommand } from "./ctx.js";
12
- import { runInitCommand } from "./init.js";
13
- import { runRulesShow, runRulesEdit } from "./rules.js";
14
- import { runUpdateCommand } from "./update.js";
15
- import { runHistoryList, runHistoryDelete, runHistoryRename, runHistoryExport } from "./history.js";
16
- import { runMemoryList, runMemoryAdd, runMemorySearch, runMemoryDelete, runMemoryMode } from "./memory.js";
17
- import { runMcpAdd, runMcpRemove, runMcpList, runMcpInfo, runMcpCheck, runMcpToggle, } from "./mcp.js";
18
- import { runSkillsList, runSkillsInfo, runSkillsToggle, runSkillsNew } from "./skills.js";
19
- /**
20
- * All `--project`/`--global`/`--model`/`--provider`/`--resume`/`--image`/`--sandbox`/
21
- * `--network`/`--permission`/`--think`/`--memory` flags live on the root `program` (see addSessionOptions),
22
- * so they can appear before or after a subcommand name. Subcommands read them via
23
- * `program.opts<SessionOptions>()` instead of re-declaring the same options — commander
24
- * resolves options against the first command in the chain that declares them, so a
25
- * subcommand-local redeclaration would silently shadow the root option instead of merging.
26
- */
27
- export function registerCommands(program) {
28
- const rootOpts = () => program.opts();
29
- // --- Session aliases -----------------------------------------------------
30
- for (const alias of ["chat", "code"]) {
31
- program
32
- .command(alias)
33
- .description("Same as interactive session (compat)")
34
- .argument("[prompt...]", "Prompt to send")
35
- .allowUnknownOption()
36
- .action(async (prompt) => {
37
- await runChat(prompt, rootOpts());
38
- });
39
- }
40
- program
41
- .command("exec")
42
- .description("Run one message non-interactively")
43
- .argument("[message...]", 'Message to send (use "-" to read from stdin)')
44
- .allowUnknownOption()
45
- .action(async (message) => {
46
- await runExec(message, rootOpts());
47
- });
48
- // --- Setup & config ----------------------------------------------------
49
- registerSetupCommand(program, rootOpts);
50
- program.command("init").description("Initialize .min-agent/ in current directory").action(runInitCommand);
51
- program
52
- .command("models")
53
- .description("List available models")
54
- .action(async () => {
55
- await runModelsCommand(rootOpts());
56
- });
57
- const rules = program.command("rules").description("Show or edit instruction rules");
58
- rules.action(runRulesShow);
59
- rules.command("edit").description("Edit the global rules file").action(runRulesEdit);
60
- const memory = program.command("memory").description("Show or set memory, and manage saved memories");
61
- memory.argument("[state]", "on or off");
62
- memory.action(async (state) => {
63
- const opts = rootOpts();
64
- const scope = opts.project ? "project" : opts.global ? "global" : undefined;
65
- if (await runMemoryMode(state, scope, opts.memory))
66
- return;
67
- if (state && state !== "list") {
68
- const { CliError } = await import("../errors.js");
69
- throw new CliError("Usage: min-agent memory [on|off|list|add|search|delete] [--project|--global]");
70
- }
71
- await runMemoryList(scope);
72
- });
73
- memory
74
- .command("add")
75
- .argument("<text...>")
76
- .description("Add a memory")
77
- .action(async (text) => {
78
- const opts = rootOpts();
79
- await runMemoryAdd(text, opts.project ? "project" : opts.global ? "global" : undefined);
80
- });
81
- memory
82
- .command("search")
83
- .argument("<query...>")
84
- .description("Search memories")
85
- .action(async (query) => {
86
- const opts = rootOpts();
87
- await runMemorySearch(query, opts.project ? "project" : opts.global ? "global" : undefined);
88
- });
89
- memory
90
- .command("delete")
91
- .argument("<index>")
92
- .description("Delete a memory by index")
93
- .action(async (index) => {
94
- const opts = rootOpts();
95
- await runMemoryDelete(index, opts.project ? "project" : opts.global ? "global" : undefined);
96
- });
97
- const sandbox = program
98
- .command("sandbox")
99
- .description("Show or set isolation mode (uses --project/--global)")
100
- .argument("[mode]", "off, workspace, or strict");
101
- sandbox.action(async (mode) => {
102
- const opts = rootOpts();
103
- await runSandboxCommand(mode ? [mode] : [], opts, opts);
104
- });
105
- sandbox
106
- .command("network")
107
- .description("Show or set network policy")
108
- .argument("[policy]", "allow or deny")
109
- .action(async (policy) => {
110
- const opts = rootOpts();
111
- await runSandboxCommand(["network", ...(policy ? [policy] : [])], opts, opts);
112
- });
113
- program
114
- .command("permission")
115
- .description("Show or set confirmation mode (uses --project/--global)")
116
- .argument("[mode]", "ask, accept-edits, or allow-all")
117
- .action(async (mode) => {
118
- const opts = rootOpts();
119
- await runPermissionCommand(mode ? [mode] : [], opts, opts);
120
- });
121
- program
122
- .command("think")
123
- .description("Show or set thinking intensity (uses --project/--global)")
124
- .argument("[level]", "off, low, medium, high, or max")
125
- .action(async (level) => {
126
- const opts = rootOpts();
127
- await runThinkCommand(level ? [level] : [], opts, opts);
128
- });
129
- program
130
- .command("ctx")
131
- .description("Show or set the Ollama context window level")
132
- .argument("[level]", "2k, 4k, 8k, 12k, 16k, 32k, 64k, 128k, 256k, or auto")
133
- .action(async (level) => {
134
- await runCtxCommand(level ? [level] : []);
135
- });
136
- // --- Integrations --------------------------------------------------------
137
- const mcp = program.command("mcp").description("Manage MCP servers");
138
- mcp
139
- .command("add")
140
- .description("Add a new MCP server (stdio or remote)")
141
- .usage("[options] <name> [command...]")
142
- .argument("<name>")
143
- .argument("[cmd...]", "Command to launch a stdio server (npx, node, ...)")
144
- .option("--url <url>", "Remote server URL")
145
- .option("--sse", "Use SSE transport for the remote server")
146
- .option("--streamable-http", "Use streamable-http transport for the remote server")
147
- .option("--token <token>", "Bearer token for remote servers")
148
- .option("--env <KEY=VALUE>", "Extra env for stdio servers (repeatable)", (v, prev) => [...prev, v], [])
149
- .addOption(new Option("--timeout <ms>", "Connection/call timeout").argParser(parsePositiveIntArg("--timeout")))
150
- .option("--skip-check", "Skip validation before saving")
151
- .addHelpText("after", "\nAll options above must come before <name>. Everything after <name> (including flags meant for the\n" +
152
- "launched command, like `npx -y`) is passed through as-is.\n" +
153
- "Scope: pass --project on `min-agent` before `mcp add` to write to .min-agent/mcp.json.")
154
- .allowUnknownOption()
155
- .passThroughOptions()
156
- .action(async (name, cmd, opts) => {
157
- await runMcpAdd(name, cmd, { ...opts, project: rootOpts().project });
158
- });
159
- mcp
160
- .command("remove")
161
- .argument("<name>")
162
- .description("Remove a server")
163
- .action(async (name) => {
164
- await runMcpRemove(name, { project: rootOpts().project });
165
- });
166
- mcp.command("list").description("List configured MCP servers").action(runMcpList);
167
- mcp.command("info").argument("<name>").description("Show details of a server").action(runMcpInfo);
168
- mcp.command("check").description("Test connectivity of all servers").action(runMcpCheck);
169
- mcp
170
- .command("enable")
171
- .argument("<names...>")
172
- .description("Enable disabled servers (use --project to target project scope)")
173
- .action(async (names) => {
174
- await runMcpToggle(names, true, { project: rootOpts().project });
175
- });
176
- mcp
177
- .command("disable")
178
- .argument("<names...>")
179
- .description("Disable servers (use --project to target project scope)")
180
- .action(async (names) => {
181
- await runMcpToggle(names, false, { project: rootOpts().project });
182
- });
183
- const skills = program.command("skills").description("Manage skills");
184
- skills
185
- .command("list")
186
- .option("--json", "Machine-readable JSON output")
187
- .description("List skills")
188
- .action(async (opts) => {
189
- await runSkillsList(Boolean(opts.json));
190
- });
191
- skills
192
- .command("info")
193
- .argument("<name>")
194
- .option("--json", "Machine-readable JSON output")
195
- .description("Show details of a skill")
196
- .action(async (name, opts) => {
197
- await runSkillsInfo(name, Boolean(opts.json));
198
- });
199
- skills
200
- .command("new")
201
- .argument("<name>")
202
- .description("Create a new skill scaffold (use --global on `min-agent` for ~/.agents/skills/)")
203
- .action(async (name) => {
204
- await runSkillsNew(name, Boolean(rootOpts().global));
205
- });
206
- skills
207
- .command("enable")
208
- .argument("<names...>")
209
- .description("Enable disabled skills (use --project to target this project only)")
210
- .action(async (names) => {
211
- await runSkillsToggle(names, true, resolveScope(rootOpts()));
212
- });
213
- skills
214
- .command("disable")
215
- .argument("<names...>")
216
- .description("Disable skills (use --project to target this project only)")
217
- .action(async (names) => {
218
- await runSkillsToggle(names, false, resolveScope(rootOpts()));
219
- });
220
- // --- Operations -----------------------------------------------------------
221
- program
222
- .command("serve")
223
- .description("Start the HTTP API (see docs/API.md)")
224
- .option("--host <host>", "Bind host")
225
- .addOption(new Option("--port <port>", "Bind port").argParser(parsePositiveIntArg("--port")))
226
- .action(async (opts) => {
227
- await runServeCommand(opts);
228
- });
229
- const history = program.command("history").description("Manage saved sessions");
230
- history.action(runHistoryList);
231
- history.command("delete").argument("<id>").description("Delete a saved session").action(runHistoryDelete);
232
- history
233
- .command("rename")
234
- .argument("<id>")
235
- .argument("<title...>")
236
- .description("Rename a saved session")
237
- .action(async (id, title) => {
238
- await runHistoryRename(id, title);
239
- });
240
- history
241
- .command("export")
242
- .argument("<id>")
243
- .option("-o, --output <file>", "Write to a file instead of stdout")
244
- .description("Export a session as JSON")
245
- .action(async (id, opts) => {
246
- await runHistoryExport(id, opts);
247
- });
248
- program.command("update").description("Upgrade to the latest npm release").action(runUpdateCommand);
249
- }
@@ -1,18 +0,0 @@
1
- import { existsSync, writeFileSync, mkdirSync } from "fs";
2
- import path from "path";
3
- function ensureProjectDefaults() {
4
- const projectConfigDir = path.join(process.cwd(), ".min-agent");
5
- const projectSkillsDir = path.join(projectConfigDir, "skills");
6
- const projectMcpFile = path.join(projectConfigDir, "mcp.json");
7
- if (!existsSync(projectSkillsDir)) {
8
- mkdirSync(projectSkillsDir, { recursive: true });
9
- }
10
- if (!existsSync(projectMcpFile)) {
11
- mkdirSync(projectConfigDir, { recursive: true });
12
- writeFileSync(projectMcpFile, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
13
- }
14
- }
15
- export async function runInitCommand() {
16
- ensureProjectDefaults();
17
- console.log(`✓ Initialized .min-agent/ in ${process.cwd()}`);
18
- }