@agentprojectcontext/apx 1.6.0 → 1.8.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 (41) hide show
  1. package/README.md +4 -0
  2. package/package.json +1 -1
  3. package/src/cli/commands/config.js +23 -0
  4. package/src/cli/commands/messages.js +45 -0
  5. package/src/cli/commands/routine.js +27 -2
  6. package/src/cli/commands/setup.js +2 -2
  7. package/src/cli/index.js +969 -3
  8. package/src/core/apc-context-skill.md +3 -0
  9. package/src/core/apx-skill.md +30 -0
  10. package/src/core/config.js +2 -0
  11. package/src/core/mascot.js +5 -7
  12. package/src/core/messages-store.js +94 -20
  13. package/src/core/routines-store.js +3 -1
  14. package/src/daemon/api.js +3 -3
  15. package/src/daemon/index.js +38 -2
  16. package/src/daemon/plugins/telegram.js +32 -2
  17. package/src/daemon/routines.js +64 -2
  18. package/src/daemon/super-agent-tools/helpers.js +120 -0
  19. package/src/daemon/super-agent-tools/index.js +56 -0
  20. package/src/daemon/super-agent-tools/tools/add-project.js +36 -0
  21. package/src/daemon/super-agent-tools/tools/call-agent.js +45 -0
  22. package/src/daemon/super-agent-tools/tools/call-mcp.js +30 -0
  23. package/src/daemon/super-agent-tools/tools/call-runtime.js +107 -0
  24. package/src/daemon/super-agent-tools/tools/edit-file.js +44 -0
  25. package/src/daemon/super-agent-tools/tools/import-agent.js +48 -0
  26. package/src/daemon/super-agent-tools/tools/list-agents.js +36 -0
  27. package/src/daemon/super-agent-tools/tools/list-files.js +38 -0
  28. package/src/daemon/super-agent-tools/tools/list-mcps.js +48 -0
  29. package/src/daemon/super-agent-tools/tools/list-projects.js +20 -0
  30. package/src/daemon/super-agent-tools/tools/list-vault-agents.js +18 -0
  31. package/src/daemon/super-agent-tools/tools/read-agent-memory.js +28 -0
  32. package/src/daemon/super-agent-tools/tools/read-file.js +33 -0
  33. package/src/daemon/super-agent-tools/tools/run-shell.js +86 -0
  34. package/src/daemon/super-agent-tools/tools/search-messages.js +34 -0
  35. package/src/daemon/super-agent-tools/tools/send-telegram.js +30 -0
  36. package/src/daemon/super-agent-tools/tools/set-identity.js +35 -0
  37. package/src/daemon/super-agent-tools/tools/set-permission-mode.js +32 -0
  38. package/src/daemon/super-agent-tools/tools/tail-messages.js +39 -0
  39. package/src/daemon/super-agent-tools/tools/write-file.js +33 -0
  40. package/src/daemon/super-agent-tools.js +1 -539
  41. package/src/daemon/super-agent.js +56 -7
package/src/cli/index.js CHANGED
@@ -53,7 +53,7 @@ import {
53
53
  cmdTelegramStatus,
54
54
  cmdTelegramSetup,
55
55
  } from "./commands/telegram.js";
56
- import { cmdMessagesTail, cmdMessagesSearch } from "./commands/messages.js";
56
+ import { cmdMessagesTail, cmdMessagesSearch, cmdMessagesChat } from "./commands/messages.js";
57
57
  import { cmdExec } from "./commands/exec.js";
58
58
  import {
59
59
  cmdChat,
@@ -66,6 +66,7 @@ import {
66
66
  cmdConfigShow,
67
67
  cmdConfigSet,
68
68
  cmdConfigUnset,
69
+ cmdPermission,
69
70
  } from "./commands/config.js";
70
71
  import { cmdPluginsList, cmdPluginStatus } from "./commands/plugins.js";
71
72
  import { cmdSkillsAdd, cmdSkillsList, cmdSkillsStatus } from "./commands/skills.js";
@@ -84,6 +85,7 @@ import {
84
85
  cmdRoutineEnable,
85
86
  cmdRoutineDisable,
86
87
  cmdRoutineRun,
88
+ cmdRoutineHistory,
87
89
  } from "./commands/routine.js";
88
90
 
89
91
  const __filename = fileURLToPath(import.meta.url);
@@ -108,6 +110,887 @@ const hCmd = (cmd, pad, desc) => ` ${H.WH}${cmd.padEnd(pad)}${H.R} ${H.DI}${d
108
110
  const hSub = (sub, pad, desc) => ` ${H.CY}${sub.padEnd(pad)}${H.R} ${H.DI}${desc}${H.R}`;
109
111
  const hFlag = (f, pad, desc) => ` ${H.YE}${f.padEnd(pad)}${H.R} ${H.DI}${desc}${H.R}`;
110
112
 
113
+ const topic = ({ title, summary, usage = [], commands = [], options = [], examples = [] }) => ({
114
+ title,
115
+ summary,
116
+ usage,
117
+ commands,
118
+ options,
119
+ examples,
120
+ });
121
+
122
+ const HELP_TOPICS = new Map(Object.entries({
123
+ init: topic({
124
+ title: "apx init",
125
+ summary: "Initialize APC project files in the current directory or a target path.",
126
+ usage: ["apx init [path] [--name <name>]"],
127
+ options: [
128
+ ["--name <name>", "Project display name written to .apc/project.json."],
129
+ ],
130
+ examples: ["apx init", "apx init ./my-project --name \"My Project\""],
131
+ }),
132
+ setup: topic({
133
+ title: "apx setup",
134
+ summary: "Run the interactive APX setup wizard.",
135
+ usage: ["apx setup", "apx install"],
136
+ examples: ["apx setup"],
137
+ }),
138
+ install: topic({
139
+ title: "apx install",
140
+ summary: "Alias for apx setup.",
141
+ usage: ["apx install"],
142
+ examples: ["apx install"],
143
+ }),
144
+ status: topic({
145
+ title: "apx status",
146
+ summary: "Print daemon, super-agent, engine, Telegram, and project status.",
147
+ usage: ["apx status"],
148
+ examples: ["apx status"],
149
+ }),
150
+ update: topic({
151
+ title: "apx update",
152
+ summary: "Check for a published APX update and upgrade the global install.",
153
+ usage: ["apx update", "apx upgrade"],
154
+ examples: ["apx update"],
155
+ }),
156
+ upgrade: topic({
157
+ title: "apx upgrade",
158
+ summary: "Alias for apx update.",
159
+ usage: ["apx upgrade"],
160
+ examples: ["apx upgrade"],
161
+ }),
162
+ project: topic({
163
+ title: "apx project",
164
+ summary: "Register, list, remove, and rebuild daemon project entries.",
165
+ usage: ["apx project <subcommand> [args] [--flags]"],
166
+ commands: [
167
+ ["add [path]", "Register a project path with the daemon."],
168
+ ["list | ls", "List known daemon projects."],
169
+ ["remove | rm <id>", "Remove a daemon project entry."],
170
+ ["rebuild [id]", "Rebuild daemon index from project files."],
171
+ ["<name|id> <command>", "Run another APX command pinned to that project."],
172
+ ],
173
+ options: [["--project <name|id|path>", "Pin command to a specific project where supported."]],
174
+ examples: ["apx project add .", "apx project list", "apx project testing mcp list"],
175
+ }),
176
+ "project add": topic({
177
+ title: "apx project add",
178
+ summary: "Register a project with the APX daemon.",
179
+ usage: ["apx project add [path]"],
180
+ examples: ["apx project add .", "apx add project ../repo"],
181
+ }),
182
+ "project list": topic({
183
+ title: "apx project list",
184
+ summary: "List projects known by the daemon.",
185
+ usage: ["apx project list", "apx project ls"],
186
+ examples: ["apx project list"],
187
+ }),
188
+ "project remove": topic({
189
+ title: "apx project remove",
190
+ summary: "Remove a project entry from daemon storage.",
191
+ usage: ["apx project remove <id>", "apx project rm <id>"],
192
+ examples: ["apx project remove default"],
193
+ }),
194
+ "project rebuild": topic({
195
+ title: "apx project rebuild",
196
+ summary: "Rebuild a daemon project index from filesystem context.",
197
+ usage: ["apx project rebuild [id]"],
198
+ examples: ["apx project rebuild", "apx project rebuild default"],
199
+ }),
200
+ add: topic({
201
+ title: "apx add",
202
+ summary: "Friendly alias namespace for add operations.",
203
+ usage: ["apx add project [path]"],
204
+ commands: [["project [path]", "Alias for apx project add [path]."]],
205
+ examples: ["apx add project ."],
206
+ }),
207
+ "add project": topic({
208
+ title: "apx add project",
209
+ summary: "Alias for apx project add.",
210
+ usage: ["apx add project [path]"],
211
+ examples: ["apx add project ."],
212
+ }),
213
+ agent: topic({
214
+ title: "apx agent",
215
+ summary: "Create, inspect, import, and vault agent definitions.",
216
+ usage: ["apx agent <subcommand> [args] [--flags]"],
217
+ commands: [
218
+ ["add <slug>", "Create a project-local agent."],
219
+ ["list | ls", "List project agents."],
220
+ ["get | show <slug>", "Print one agent definition."],
221
+ ["import <slug>", "Import an agent template from ~/.apx/agents."],
222
+ ["vault list | ls", "List reusable global agent templates."],
223
+ ["vault add <slug>", "Create or copy a reusable global agent template."],
224
+ ],
225
+ examples: ["apx agent add reviewer --role Reviewer --model gpt-5.2", "apx agent list"],
226
+ }),
227
+ "agent add": topic({
228
+ title: "apx agent add",
229
+ summary: "Create a project-local agent definition.",
230
+ usage: ["apx agent add <slug> [--role <role>] [--model <model>] [--skills a,b] [--language <tag>] [--description <text>] [--tools a,b]"],
231
+ options: [
232
+ ["--role <role>", "Human-readable role."],
233
+ ["--model <model>", "Preferred model id."],
234
+ ["--skills a,b", "Comma-separated skill names."],
235
+ ["--language <tag>", "Default response language, for example en-US or es-AR."],
236
+ ["--description <text>", "Short agent description."],
237
+ ["--tools a,b", "Comma-separated tool hints."],
238
+ ],
239
+ examples: ["apx agent add reviewer --role Reviewer --model gpt-5.2 --skills review,test"],
240
+ }),
241
+ "agent list": topic({
242
+ title: "apx agent list",
243
+ summary: "List agents available in the current APC project.",
244
+ usage: ["apx agent list", "apx agent ls"],
245
+ examples: ["apx agent list"],
246
+ }),
247
+ "agent get": topic({
248
+ title: "apx agent get",
249
+ summary: "Print one project agent definition.",
250
+ usage: ["apx agent get <slug>", "apx agent show <slug>"],
251
+ examples: ["apx agent get reviewer"],
252
+ }),
253
+ "agent import": topic({
254
+ title: "apx agent import",
255
+ summary: "Import a reusable agent template from the APX vault into the current project.",
256
+ usage: ["apx agent import <slug> [--copy] [--force]"],
257
+ options: [
258
+ ["--copy", "Copy the vault markdown file into the project instead of linking it."],
259
+ ["--force", "Overwrite an existing project-local definition when used with --copy."],
260
+ ],
261
+ examples: ["apx agent import reviewer", "apx agent import reviewer --copy --force"],
262
+ }),
263
+ "agent vault": topic({
264
+ title: "apx agent vault",
265
+ summary: "Manage reusable global agent templates under ~/.apx/agents.",
266
+ usage: ["apx agent vault <subcommand> [args] [--flags]"],
267
+ commands: [
268
+ ["list | ls", "List vault templates."],
269
+ ["add <slug>", "Create a vault template or copy a local project agent into the vault."],
270
+ ],
271
+ examples: ["apx agent vault list", "apx agent vault add reviewer"],
272
+ }),
273
+ "agent vault list": topic({
274
+ title: "apx agent vault list",
275
+ summary: "List reusable global agent templates.",
276
+ usage: ["apx agent vault list", "apx agent vault ls"],
277
+ examples: ["apx agent vault list"],
278
+ }),
279
+ "agent vault add": topic({
280
+ title: "apx agent vault add",
281
+ summary: "Create a reusable global agent template.",
282
+ usage: ["apx agent vault add <slug> [--role <role>] [--model <model>] [--skills a,b] [--language <tag>] [--description <text>]"],
283
+ options: [
284
+ ["--role <role>", "Human-readable role."],
285
+ ["--model <model>", "Preferred model id."],
286
+ ["--skills a,b", "Comma-separated skill names."],
287
+ ["--language <tag>", "Default response language."],
288
+ ["--description <text>", "Short agent description."],
289
+ ],
290
+ examples: ["apx agent vault add reviewer --role Reviewer --model gpt-5.2"],
291
+ }),
292
+ identity: topic({
293
+ title: "apx identity",
294
+ summary: "Read or edit daemon identity fields.",
295
+ usage: ["apx identity <show|set|wizard> [args]"],
296
+ commands: [
297
+ ["show", "Print current identity."],
298
+ ["set <key> <value>", "Set one identity field."],
299
+ ["wizard", "Run interactive identity setup."],
300
+ ],
301
+ examples: ["apx identity show", "apx identity set agent_name Ada"],
302
+ }),
303
+ "identity show": topic({
304
+ title: "apx identity show",
305
+ summary: "Print current daemon identity.",
306
+ usage: ["apx identity show"],
307
+ examples: ["apx identity show"],
308
+ }),
309
+ "identity set": topic({
310
+ title: "apx identity set",
311
+ summary: "Set one daemon identity field.",
312
+ usage: ["apx identity set <key> <value>"],
313
+ examples: ["apx identity set agent_name Ada", "apx identity set owner_name Sam"],
314
+ }),
315
+ "identity wizard": topic({
316
+ title: "apx identity wizard",
317
+ summary: "Run interactive identity setup.",
318
+ usage: ["apx identity wizard"],
319
+ examples: ["apx identity wizard"],
320
+ }),
321
+ config: topic({
322
+ title: "apx config",
323
+ summary: "Read and edit project configuration in .apc/config.json.",
324
+ usage: ["apx config [show] [--effective] [--only-overrides]", "apx config set <key.path> <value>", "apx config unset <key.path>"],
325
+ commands: [
326
+ ["show | ls", "Print config."],
327
+ ["set <key> <value>", "Set a JSON-aware value."],
328
+ ["unset | rm <key>", "Remove a key."],
329
+ ],
330
+ options: [
331
+ ["--effective", "Show merged effective config."],
332
+ ["--only-overrides", "Show only project overrides."],
333
+ ],
334
+ examples: ["apx config show --effective", "apx config set engines.openai.model gpt-5.2"],
335
+ }),
336
+ "config show": topic({
337
+ title: "apx config show",
338
+ summary: "Print project config.",
339
+ usage: ["apx config show [--effective] [--only-overrides]", "apx config ls"],
340
+ options: [
341
+ ["--effective", "Show merged effective config."],
342
+ ["--only-overrides", "Show only project overrides."],
343
+ ],
344
+ examples: ["apx config show", "apx config show --effective"],
345
+ }),
346
+ "config set": topic({
347
+ title: "apx config set",
348
+ summary: "Set a JSON-aware value in .apc/config.json.",
349
+ usage: ["apx config set <key.path> <value>"],
350
+ examples: ["apx config set super_agent.enabled true", "apx config set engines.openai.model gpt-5.2"],
351
+ }),
352
+ "config unset": topic({
353
+ title: "apx config unset",
354
+ summary: "Remove a key from .apc/config.json.",
355
+ usage: ["apx config unset <key.path>", "apx config rm <key.path>"],
356
+ examples: ["apx config unset engines.openai.model"],
357
+ }),
358
+ permission: topic({
359
+ title: "apx permission",
360
+ summary: "Show or set super-agent permission mode.",
361
+ usage: ["apx permission show", "apx permission set <total|automatico|permiso>"],
362
+ commands: [
363
+ ["show", "Print current permission mode."],
364
+ ["set <mode>", "Set permission mode."],
365
+ ],
366
+ examples: ["apx permission show", "apx permission set automatico"],
367
+ }),
368
+ "permission show": topic({
369
+ title: "apx permission show",
370
+ summary: "Print current super-agent permission mode.",
371
+ usage: ["apx permission show"],
372
+ examples: ["apx permission show"],
373
+ }),
374
+ "permission set": topic({
375
+ title: "apx permission set",
376
+ summary: "Set super-agent permission mode.",
377
+ usage: ["apx permission set <total|automatico|permiso>"],
378
+ examples: ["apx permission set permiso"],
379
+ }),
380
+ memory: topic({
381
+ title: "apx memory",
382
+ summary: "Read, append, or replace an agent memory.md file.",
383
+ usage: ["apx memory <slug>", "apx memory <slug> --append \"<note>\"", "apx memory <slug> --replace < memory.md"],
384
+ options: [
385
+ ["--append <note>", "Append a durable note under Recent context."],
386
+ ["--replace", "Replace memory from stdin."],
387
+ ],
388
+ examples: ["apx memory reviewer", "apx memory reviewer --append \"Prefers short PR summaries\""],
389
+ }),
390
+ session: topic({
391
+ title: "apx session",
392
+ summary: "Manage local runtime sessions stored under ~/.apx/projects/<project-id>.",
393
+ usage: ["apx session <subcommand> [args] [--flags]"],
394
+ commands: [
395
+ ["new <slug>", "Create a session file."],
396
+ ["list | ls [slug]", "List sessions."],
397
+ ["get | show <id>", "Print session metadata or body."],
398
+ ["update <id>", "Update session frontmatter."],
399
+ ["close <id>", "Mark a session complete."],
400
+ ["check", "Exit non-zero if an active session exists."],
401
+ ["close-stale", "Auto-close stale active sessions."],
402
+ ["resume <id>", "Show APC session and optional external transcript summary."],
403
+ ["compact <slug>", "Compact latest or selected conversation into summary."],
404
+ ],
405
+ examples: ["apx session list reviewer --last 5", "apx session close 2026-05-09-01 --result \"Done\""],
406
+ }),
407
+ "session new": topic({
408
+ title: "apx session new",
409
+ summary: "Create a local runtime session file for an agent.",
410
+ usage: ["apx session new <slug> --title \"<title>\" [--task-ref <ref>] [--body -|\"text\"]"],
411
+ options: [
412
+ ["--title <title>", "Required session title."],
413
+ ["--task-ref <ref>", "External task id or URL."],
414
+ ["--body -|text", "Initial session body from stdin or inline text."],
415
+ ],
416
+ examples: ["apx session new reviewer --title \"Review PR\" --body -"],
417
+ }),
418
+ "session list": topic({
419
+ title: "apx session list",
420
+ summary: "List local runtime sessions.",
421
+ usage: ["apx session list [slug] [--last N]", "apx session ls [slug]"],
422
+ options: [["--last N", "Limit output to the most recent N sessions."]],
423
+ examples: ["apx session list", "apx session list reviewer --last 5"],
424
+ }),
425
+ "session get": topic({
426
+ title: "apx session get",
427
+ summary: "Print one session metadata record or full markdown body.",
428
+ usage: ["apx session get <id> [--body]", "apx session show <id> [--body]"],
429
+ options: [["--body", "Print the full session markdown file."]],
430
+ examples: ["apx session get 2026-05-09-01", "apx session get 2026-05-09-01 --body"],
431
+ }),
432
+ "session update": topic({
433
+ title: "apx session update",
434
+ summary: "Update session frontmatter fields.",
435
+ usage: ["apx session update <id> [--status <s>] [--result <r>] [--title <t>] [--task_ref <ref>] [--completed <iso>]"],
436
+ options: [
437
+ ["--status <s>", "Set status."],
438
+ ["--result <r>", "Set result summary."],
439
+ ["--title <t>", "Set title."],
440
+ ["--task_ref <ref>", "Set task reference."],
441
+ ["--completed <iso>", "Set completion timestamp."],
442
+ ],
443
+ examples: ["apx session update 2026-05-09-01 --status \"in progress\""],
444
+ }),
445
+ "session close": topic({
446
+ title: "apx session close",
447
+ summary: "Mark a session complete and optionally store a result.",
448
+ usage: ["apx session close <id> [--result \"<text>\"]"],
449
+ options: [["--result <text>", "One-line completion result."]],
450
+ examples: ["apx session close 2026-05-09-01 --result \"Tests passing\""],
451
+ }),
452
+ "session check": topic({
453
+ title: "apx session check",
454
+ summary: "Detect active sessions to avoid agent collision.",
455
+ usage: ["apx session check"],
456
+ examples: ["apx session check"],
457
+ }),
458
+ "session close-stale": topic({
459
+ title: "apx session close-stale",
460
+ summary: "Auto-close active sessions older than the stale threshold.",
461
+ usage: ["apx session close-stale"],
462
+ examples: ["apx session close-stale"],
463
+ }),
464
+ "session resume": topic({
465
+ title: "apx session resume",
466
+ summary: "Show APC session metadata and optional external transcript summary.",
467
+ usage: ["apx session resume <id> [--summary] [--full] [--project <name|id|path>]"],
468
+ options: [
469
+ ["--summary", "Ask the super-agent to summarize when available."],
470
+ ["--full", "Print the full available transcript tail."],
471
+ ["--project <name|id|path>", "Resolve session in a specific daemon project."],
472
+ ],
473
+ examples: ["apx session resume 2026-05-09-01 --summary"],
474
+ }),
475
+ "session compact": topic({
476
+ title: "apx session compact",
477
+ summary: "Compact an agent conversation into a durable summary.",
478
+ usage: ["apx session compact <slug> [--conversation <id>] [--model <model>] [--project <name|id|path>]"],
479
+ options: [
480
+ ["--conversation <id>", "Compact a specific conversation instead of latest."],
481
+ ["--model <model>", "Override summarizer model."],
482
+ ["--project <name|id|path>", "Pin to a specific daemon project."],
483
+ ],
484
+ examples: ["apx session compact reviewer --conversation abc123"],
485
+ }),
486
+ mcp: topic({
487
+ title: "apx mcp",
488
+ summary: "Manage and call MCP servers merged from APC and supported IDE configs.",
489
+ usage: ["apx mcp <subcommand> [args] [--flags]"],
490
+ commands: [
491
+ ["list | ls", "List MCP servers for a project."],
492
+ ["add <name>", "Add a project-owned MCP server."],
493
+ ["remove | rm <name>", "Remove a project-owned MCP server."],
494
+ ["enable <name>", "Enable a project-owned MCP server."],
495
+ ["disable <name>", "Disable a project-owned MCP server."],
496
+ ["run <name> <tool>", "Call one MCP tool."],
497
+ ["tools <name>", "Show tool-list hint."],
498
+ ["check", "Audit source files, merge order, and conflicts."],
499
+ ],
500
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
501
+ examples: ["apx mcp list", "apx mcp run filesystem read_file '{\"path\":\"README.md\"}'"],
502
+ }),
503
+ "mcp list": topic({
504
+ title: "apx mcp list",
505
+ summary: "List MCP servers available to a project.",
506
+ usage: ["apx mcp list [--project <name|id|path>]", "apx mcp ls [--project <name|id|path>]"],
507
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
508
+ examples: ["apx mcp list", "apx mcp list --project default"],
509
+ }),
510
+ "mcp add": topic({
511
+ title: "apx mcp add",
512
+ summary: "Add a project-owned MCP server.",
513
+ usage: ["apx mcp add <name> --command <cmd> [--env KEY=VAL ...] [--project <name|id|path>] [-- <arg> ...]"],
514
+ options: [
515
+ ["--command <cmd>", "Executable command for stdio MCP server."],
516
+ ["--env KEY=VAL", "Environment variable. Repeatable."],
517
+ ["--project <name|id|path>", "Pin command to a specific project."],
518
+ ["-- <arg> ...", "Arguments passed to the MCP command."],
519
+ ],
520
+ examples: ["apx mcp add filesystem --command npx -- -y @modelcontextprotocol/server-filesystem ."],
521
+ }),
522
+ "mcp remove": topic({
523
+ title: "apx mcp remove",
524
+ summary: "Remove a project-owned MCP server.",
525
+ usage: ["apx mcp remove <name> [--project <name|id|path>]", "apx mcp rm <name> [--project <name|id|path>]"],
526
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
527
+ examples: ["apx mcp remove filesystem"],
528
+ }),
529
+ "mcp enable": topic({
530
+ title: "apx mcp enable",
531
+ summary: "Enable a project-owned MCP server.",
532
+ usage: ["apx mcp enable <name> [--project <name|id|path>]"],
533
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
534
+ examples: ["apx mcp enable filesystem"],
535
+ }),
536
+ "mcp disable": topic({
537
+ title: "apx mcp disable",
538
+ summary: "Disable a project-owned MCP server.",
539
+ usage: ["apx mcp disable <name> [--project <name|id|path>]"],
540
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
541
+ examples: ["apx mcp disable filesystem"],
542
+ }),
543
+ "mcp run": topic({
544
+ title: "apx mcp run",
545
+ summary: "Call a tool on an MCP server through the daemon.",
546
+ usage: ["apx mcp run <name> <tool> ['<json-args>'] [--project <name|id|path>]"],
547
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
548
+ examples: ["apx mcp run filesystem read_file '{\"path\":\"README.md\"}'"],
549
+ }),
550
+ "mcp tools": topic({
551
+ title: "apx mcp tools",
552
+ summary: "Show MCP tool-list guidance for a server.",
553
+ usage: ["apx mcp tools <name> [--project <name|id|path>]"],
554
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
555
+ examples: ["apx mcp tools filesystem"],
556
+ }),
557
+ "mcp check": topic({
558
+ title: "apx mcp check",
559
+ summary: "Audit MCP source files, active entries, and merge conflicts.",
560
+ usage: ["apx mcp check [--project <name|id|path>]"],
561
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
562
+ examples: ["apx mcp check"],
563
+ }),
564
+ daemon: topic({
565
+ title: "apx daemon",
566
+ summary: "Start, stop, inspect, and read logs from the local APX daemon.",
567
+ usage: ["apx daemon <start|stop|status|logs> [--flags]"],
568
+ commands: [
569
+ ["start", "Start daemon."],
570
+ ["stop", "Stop daemon."],
571
+ ["status", "Show daemon health."],
572
+ ["logs", "Print daemon log tail."],
573
+ ],
574
+ examples: ["apx daemon status", "apx daemon logs --tail 100"],
575
+ }),
576
+ "daemon start": topic({
577
+ title: "apx daemon start",
578
+ summary: "Start the local APX daemon.",
579
+ usage: ["apx daemon start"],
580
+ examples: ["apx daemon start"],
581
+ }),
582
+ "daemon stop": topic({
583
+ title: "apx daemon stop",
584
+ summary: "Stop the local APX daemon.",
585
+ usage: ["apx daemon stop"],
586
+ examples: ["apx daemon stop"],
587
+ }),
588
+ "daemon status": topic({
589
+ title: "apx daemon status",
590
+ summary: "Show local APX daemon status.",
591
+ usage: ["apx daemon status"],
592
+ examples: ["apx daemon status"],
593
+ }),
594
+ "daemon logs": topic({
595
+ title: "apx daemon logs",
596
+ summary: "Print daemon logs.",
597
+ usage: ["apx daemon logs [--tail N]"],
598
+ options: [["--tail N", "Number of lines to print."]],
599
+ examples: ["apx daemon logs --tail 100"],
600
+ }),
601
+ telegram: topic({
602
+ title: "apx telegram",
603
+ summary: "Configure, inspect, and send through the Telegram bridge.",
604
+ usage: ["apx telegram <send|status|setup> [args] [--flags]"],
605
+ commands: [
606
+ ["send \"text\"", "Send a Telegram message."],
607
+ ["status", "Show Telegram plugin status."],
608
+ ["setup", "Print setup guidance."],
609
+ ],
610
+ examples: ["apx telegram status", "apx telegram send \"hello\" --chat 123456"],
611
+ }),
612
+ "telegram send": topic({
613
+ title: "apx telegram send",
614
+ summary: "Send a Telegram message through the configured bridge.",
615
+ usage: ["apx telegram send \"<text>\" [--chat <id>]"],
616
+ options: [["--chat <id>", "Override configured chat id."]],
617
+ examples: ["apx telegram send \"Deploy finished\" --chat 123456"],
618
+ }),
619
+ "telegram status": topic({
620
+ title: "apx telegram status",
621
+ summary: "Show Telegram bridge status.",
622
+ usage: ["apx telegram status"],
623
+ examples: ["apx telegram status"],
624
+ }),
625
+ "telegram setup": topic({
626
+ title: "apx telegram setup",
627
+ summary: "Print Telegram setup guidance.",
628
+ usage: ["apx telegram setup"],
629
+ examples: ["apx telegram setup"],
630
+ }),
631
+ messages: topic({
632
+ title: "apx messages",
633
+ summary: "Read APX message logs.",
634
+ usage: ["apx messages <tail|chat|search> [args] [--flags]"],
635
+ commands: [
636
+ ["tail", "Print recent messages."],
637
+ ["chat", "Print recent messages as a chat transcript with actor types."],
638
+ ["search \"query\"", "Search message logs."],
639
+ ],
640
+ examples: ["apx messages chat --channel telegram -n 20", "apx messages search \"deploy\""],
641
+ }),
642
+ "messages tail": topic({
643
+ title: "apx messages tail",
644
+ summary: "Print recent APX messages.",
645
+ usage: ["apx messages tail [--agent <slug>] [--channel <name>] [-n N] [--global] [--project <name|id|path>]"],
646
+ options: [
647
+ ["--agent <slug>", "Filter by agent."],
648
+ ["--channel <name>", "Filter by channel, for example runtime, telegram, exec."],
649
+ ["-n N", "Number of messages to print."],
650
+ ["--global", "Read global message store where supported."],
651
+ ["--project <name|id|path>", "Pin command to a specific project."],
652
+ ],
653
+ examples: ["apx messages tail", "apx messages tail --channel runtime -n 20"],
654
+ }),
655
+ "messages search": topic({
656
+ title: "apx messages search",
657
+ summary: "Search APX message logs.",
658
+ usage: ["apx messages search \"<query>\" [--project <name|id|path>]"],
659
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
660
+ examples: ["apx messages search \"deploy\""],
661
+ }),
662
+ "messages chat": topic({
663
+ title: "apx messages chat",
664
+ summary: "Print APX messages as a chat transcript with user, agent, tool, or system type.",
665
+ usage: ["apx messages chat [--channel <name>] [-n N] [--global] [--agent <slug>] [--project <name|id|path>]"],
666
+ options: [
667
+ ["--channel <name>", "Filter by channel; telegram defaults to global message store."],
668
+ ["-n N", "Number of messages to print."],
669
+ ["--global", "Read global message store."],
670
+ ["--agent <slug>", "Filter project messages by agent."],
671
+ ["--project <name|id|path>", "Pin command to a specific project."],
672
+ ],
673
+ examples: ["apx messages chat --channel telegram -n 20", "apx messages chat --channel a2a --project default"],
674
+ }),
675
+ exec: topic({
676
+ title: "apx exec",
677
+ summary: "Run a quick one-shot LLM call as an agent.",
678
+ usage: ["apx exec <agent> \"<prompt>\" [--model <id>] [--max-tokens N] [--temperature T] [--project <name|id|path>]"],
679
+ options: [
680
+ ["--model <id>", "Override configured model."],
681
+ ["--max-tokens N", "Output token limit."],
682
+ ["--temperature T", "Sampling temperature."],
683
+ ["--project <name|id|path>", "Pin command to a specific project."],
684
+ ],
685
+ examples: ["apx exec reviewer \"Summarize your role\" --model gpt-5.2"],
686
+ }),
687
+ chat: topic({
688
+ title: "apx chat",
689
+ summary: "Start an interactive agent chat REPL.",
690
+ usage: ["apx chat <agent> [--conversation <id>] [--model <id>] [--project <name|id|path>]"],
691
+ options: [
692
+ ["--conversation <id>", "Continue an existing conversation."],
693
+ ["--model <id>", "Override configured model."],
694
+ ["--project <name|id|path>", "Pin command to a specific project."],
695
+ ],
696
+ examples: ["apx chat reviewer", "apx chat reviewer --conversation abc123"],
697
+ }),
698
+ conversations: topic({
699
+ title: "apx conversations",
700
+ summary: "List or read stored agent conversations.",
701
+ usage: ["apx conversations <list|get> <agent> [id] [--project <name|id|path>]", "apx conv <list|get> <agent> [id]"],
702
+ commands: [
703
+ ["list | ls <agent>", "List conversations for an agent."],
704
+ ["get | show <agent> <id>", "Print one conversation."],
705
+ ],
706
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
707
+ examples: ["apx conversations list reviewer", "apx conversations get reviewer abc123"],
708
+ }),
709
+ "conversations list": topic({
710
+ title: "apx conversations list",
711
+ summary: "List stored conversations for an agent.",
712
+ usage: ["apx conversations list <agent> [--project <name|id|path>]", "apx conv ls <agent>"],
713
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
714
+ examples: ["apx conversations list reviewer"],
715
+ }),
716
+ "conversations get": topic({
717
+ title: "apx conversations get",
718
+ summary: "Print one stored conversation.",
719
+ usage: ["apx conversations get <agent> <id> [--project <name|id|path>]", "apx conv show <agent> <id>"],
720
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
721
+ examples: ["apx conversations get reviewer abc123"],
722
+ }),
723
+ conv: topic({
724
+ title: "apx conv",
725
+ summary: "Alias for apx conversations.",
726
+ usage: ["apx conv <list|get> <agent> [id]"],
727
+ examples: ["apx conv list reviewer"],
728
+ }),
729
+ run: topic({
730
+ title: "apx run",
731
+ summary: "Launch a full external runtime session for an agent.",
732
+ usage: ["apx run <agent> --runtime <claude-code|codex|opencode|aider> \"<prompt>\" [--timeout <seconds>] [--project <name|id|path>]"],
733
+ options: [
734
+ ["--runtime <id>", "Runtime CLI to launch: claude-code, codex, opencode, aider."],
735
+ ["--timeout <seconds>", "Runtime timeout."],
736
+ ["--project <name|id|path>", "Pin command to a specific project."],
737
+ ],
738
+ examples: ["apx run reviewer --runtime codex \"Review this repo\" --timeout 600"],
739
+ }),
740
+ env: topic({
741
+ title: "apx env",
742
+ summary: "Inspect local agent runtime environment.",
743
+ usage: ["apx env detect", "apx env list"],
744
+ commands: [["detect | list", "Show which supported runtime CLIs are installed."]],
745
+ examples: ["apx env detect"],
746
+ }),
747
+ "env detect": topic({
748
+ title: "apx env detect",
749
+ summary: "Show which supported runtime CLIs are installed.",
750
+ usage: ["apx env detect", "apx env list"],
751
+ examples: ["apx env detect"],
752
+ }),
753
+ send: topic({
754
+ title: "apx send",
755
+ summary: "Log an agent-to-agent message, optionally delivering it through the target engine.",
756
+ usage: ["apx send <from> <to> \"<message>\" [--deliver] [--project <name|id|path>]"],
757
+ options: [
758
+ ["--deliver", "Run the target engine after logging the message."],
759
+ ["--project <name|id|path>", "Pin command to a specific project."],
760
+ ],
761
+ examples: ["apx send planner reviewer \"Please review this plan\" --deliver"],
762
+ }),
763
+ connections: topic({
764
+ title: "apx connections",
765
+ summary: "Show an agent communication map.",
766
+ usage: ["apx connections <agent> [--project <name|id|path>]", "apx graph <agent> [--project <name|id|path>]"],
767
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
768
+ examples: ["apx connections reviewer"],
769
+ }),
770
+ graph: topic({
771
+ title: "apx graph",
772
+ summary: "Alias for apx connections.",
773
+ usage: ["apx graph <agent> [--project <name|id|path>]"],
774
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
775
+ examples: ["apx graph reviewer"],
776
+ }),
777
+ routine: topic({
778
+ title: "apx routine",
779
+ summary: "Manage scheduled APX routines.",
780
+ usage: ["apx routine <subcommand> [args] [--flags]"],
781
+ commands: [
782
+ ["list | ls", "List routines with next and last run."],
783
+ ["add | new <name>", "Create a routine."],
784
+ ["get | show <name>", "Print routine definition."],
785
+ ["history | hist <name>", "Show execution history."],
786
+ ["run <name>", "Trigger manually."],
787
+ ["enable <name>", "Enable routine."],
788
+ ["disable <name>", "Disable routine."],
789
+ ["remove | rm <name>", "Remove routine."],
790
+ ],
791
+ examples: ["apx routine list", "apx routine add heartbeat --kind heartbeat --schedule every:5m"],
792
+ }),
793
+ routines: topic({
794
+ title: "apx routines",
795
+ summary: "Alias for apx routine.",
796
+ usage: ["apx routines <subcommand> [args] [--flags]"],
797
+ examples: ["apx routines list"],
798
+ }),
799
+ "routine list": topic({
800
+ title: "apx routine list",
801
+ summary: "List routines with next and last run details.",
802
+ usage: ["apx routine list [--project <name|id|path>]", "apx routine ls [--project <name|id|path>]"],
803
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
804
+ examples: ["apx routine list"],
805
+ }),
806
+ "routine add": topic({
807
+ title: "apx routine add",
808
+ summary: "Create a scheduled routine.",
809
+ usage: ["apx routine add <name> --kind <kind> --schedule <schedule> [--spec '<json>'] [--permission-mode <mode>] [--allowed-tools a,b] [--project <name|id|path>]"],
810
+ options: [
811
+ ["--kind <kind>", "heartbeat, exec_agent, super_agent, telegram, or shell."],
812
+ ["--schedule <schedule>", "every:60s, every:5m, every:1h, or once:<iso>."],
813
+ ["--spec '<json>'", "Routine-specific JSON config."],
814
+ ["--permission-mode <mode>", "total, automatico, or permiso."],
815
+ ["--allowed-tools a,b", "Comma-separated allowed tool names."],
816
+ ["--project <name|id|path>", "Pin command to a specific project."],
817
+ ],
818
+ examples: ["apx routine add check --kind shell --schedule every:1h --spec '{\"cmd\":\"npm test\"}'"],
819
+ }),
820
+ "routine get": topic({
821
+ title: "apx routine get",
822
+ summary: "Print one routine definition.",
823
+ usage: ["apx routine get <name> [--project <name|id|path>]", "apx routine show <name> [--project <name|id|path>]"],
824
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
825
+ examples: ["apx routine get check"],
826
+ }),
827
+ "routine history": topic({
828
+ title: "apx routine history",
829
+ summary: "Show execution history for one routine.",
830
+ usage: ["apx routine history <name> [--project <name|id|path>]", "apx routine hist <name> [--project <name|id|path>]"],
831
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
832
+ examples: ["apx routine history check"],
833
+ }),
834
+ "routine run": topic({
835
+ title: "apx routine run",
836
+ summary: "Trigger a routine manually, ignoring schedule.",
837
+ usage: ["apx routine run <name> [--project <name|id|path>]"],
838
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
839
+ examples: ["apx routine run check"],
840
+ }),
841
+ "routine enable": topic({
842
+ title: "apx routine enable",
843
+ summary: "Enable one routine.",
844
+ usage: ["apx routine enable <name> [--project <name|id|path>]"],
845
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
846
+ examples: ["apx routine enable check"],
847
+ }),
848
+ "routine disable": topic({
849
+ title: "apx routine disable",
850
+ summary: "Disable one routine.",
851
+ usage: ["apx routine disable <name> [--project <name|id|path>]"],
852
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
853
+ examples: ["apx routine disable check"],
854
+ }),
855
+ "routine remove": topic({
856
+ title: "apx routine remove",
857
+ summary: "Remove one routine.",
858
+ usage: ["apx routine remove <name> [--project <name|id|path>]", "apx routine rm <name> [--project <name|id|path>]"],
859
+ options: [["--project <name|id|path>", "Pin command to a specific project."]],
860
+ examples: ["apx routine remove check"],
861
+ }),
862
+ command: topic({
863
+ title: "apx command",
864
+ summary: "List or show workflow commands from .apc/commands/.",
865
+ usage: ["apx command [list]", "apx command show <name>"],
866
+ commands: [
867
+ ["list | ls", "List workflow commands."],
868
+ ["show | get <name>", "Print one command file."],
869
+ ],
870
+ examples: ["apx command list", "apx command show release"],
871
+ }),
872
+ commands: topic({
873
+ title: "apx commands",
874
+ summary: "Alias for apx command.",
875
+ usage: ["apx commands [list]", "apx commands show <name>"],
876
+ examples: ["apx commands list"],
877
+ }),
878
+ "command list": topic({
879
+ title: "apx command list",
880
+ summary: "List workflow commands in .apc/commands/.",
881
+ usage: ["apx command list", "apx command ls"],
882
+ examples: ["apx command list"],
883
+ }),
884
+ "command show": topic({
885
+ title: "apx command show",
886
+ summary: "Print one workflow command file.",
887
+ usage: ["apx command show <name>", "apx command get <name>"],
888
+ examples: ["apx command show release"],
889
+ }),
890
+ skills: topic({
891
+ title: "apx skills",
892
+ summary: "Install and inspect APX skill files for IDEs and agent tools.",
893
+ usage: ["apx skills [add] [targets] [--global]", "apx skills list", "apx skills status"],
894
+ commands: [
895
+ ["add [targets]", "Install APX skills into selected targets."],
896
+ ["list | ls", "List known skill targets."],
897
+ ["status", "Show installed target status."],
898
+ ],
899
+ examples: ["apx skills add claude-code cursor", "apx skills add --global"],
900
+ }),
901
+ "skills add": topic({
902
+ title: "apx skills add",
903
+ summary: "Install APX skill files into local or global agent-tool targets.",
904
+ usage: ["apx skills add [targets] [--global]"],
905
+ options: [["--global", "Install to global user-level skill targets."]],
906
+ examples: ["apx skills add claude-code cursor", "apx skills add --global"],
907
+ }),
908
+ "skills list": topic({
909
+ title: "apx skills list",
910
+ summary: "List known APX skill targets.",
911
+ usage: ["apx skills list", "apx skills ls"],
912
+ examples: ["apx skills list"],
913
+ }),
914
+ "skills status": topic({
915
+ title: "apx skills status",
916
+ summary: "Show which APX skill targets are installed.",
917
+ usage: ["apx skills status"],
918
+ examples: ["apx skills status"],
919
+ }),
920
+ plugins: topic({
921
+ title: "apx plugins",
922
+ summary: "Inspect loaded APX daemon plugins.",
923
+ usage: ["apx plugins [list]", "apx plugins status <id>"],
924
+ commands: [
925
+ ["list | ls", "Show loaded plugins and status."],
926
+ ["status <id>", "Print detailed status for one plugin."],
927
+ ],
928
+ examples: ["apx plugins list", "apx plugins status telegram"],
929
+ }),
930
+ plugin: topic({
931
+ title: "apx plugin",
932
+ summary: "Alias for apx plugins.",
933
+ usage: ["apx plugin [list]", "apx plugin status <id>"],
934
+ examples: ["apx plugin list"],
935
+ }),
936
+ "plugins list": topic({
937
+ title: "apx plugins list",
938
+ summary: "Show loaded plugins and their status.",
939
+ usage: ["apx plugins list", "apx plugins ls"],
940
+ examples: ["apx plugins list"],
941
+ }),
942
+ "plugins status": topic({
943
+ title: "apx plugins status",
944
+ summary: "Show detailed status for one plugin.",
945
+ usage: ["apx plugins status <id>"],
946
+ examples: ["apx plugins status telegram"],
947
+ }),
948
+ }));
949
+
950
+ const HELP_ALIASES = new Map(Object.entries({
951
+ "project ls": "project list",
952
+ "project rm": "project remove",
953
+ "agent ls": "agent list",
954
+ "agent show": "agent get",
955
+ "agent vault ls": "agent vault list",
956
+ "session ls": "session list",
957
+ "session show": "session get",
958
+ "mcp ls": "mcp list",
959
+ "mcp rm": "mcp remove",
960
+ "conv list": "conversations list",
961
+ "conv ls": "conversations list",
962
+ "conv get": "conversations get",
963
+ "conv show": "conversations get",
964
+ "env list": "env detect",
965
+ "routines list": "routine list",
966
+ "routines ls": "routine list",
967
+ "routines add": "routine add",
968
+ "routines new": "routine add",
969
+ "routine new": "routine add",
970
+ "routines get": "routine get",
971
+ "routines show": "routine get",
972
+ "routine show": "routine get",
973
+ "routines history": "routine history",
974
+ "routines hist": "routine history",
975
+ "routine hist": "routine history",
976
+ "routines run": "routine run",
977
+ "routines enable": "routine enable",
978
+ "routines disable": "routine disable",
979
+ "routines remove": "routine remove",
980
+ "routines rm": "routine remove",
981
+ "routine rm": "routine remove",
982
+ "commands list": "command list",
983
+ "commands ls": "command list",
984
+ "command ls": "command list",
985
+ "commands show": "command show",
986
+ "commands get": "command show",
987
+ "command get": "command show",
988
+ "skills ls": "skills list",
989
+ "plugin list": "plugins list",
990
+ "plugin ls": "plugins list",
991
+ "plugin status": "plugins status",
992
+ }));
993
+
111
994
  function buildHelp(version) {
112
995
  return [
113
996
  "",
@@ -142,6 +1025,8 @@ function buildHelp(version) {
142
1025
  hCmd("apx identity wizard", 36, "interactive identity setup"),
143
1026
  hCmd("apx config show", 36, "--effective --only-overrides"),
144
1027
  hCmd("apx config set <key> <val>", 36, "set key in .apc/config.json (JSON-aware)"),
1028
+ hCmd("apx permission show", 36, "show super-agent permission mode"),
1029
+ hCmd("apx permission set <mode>", 36, "mode: total | automatico | permiso"),
145
1030
  hCmd("apx config unset <key>", 36, "remove key from .apc/config.json"),
146
1031
 
147
1032
  hSec("Memory"),
@@ -182,6 +1067,7 @@ function buildHelp(version) {
182
1067
 
183
1068
  hSec("Messages"),
184
1069
  hCmd("apx messages tail", 36, "--agent <slug> --channel <ch> -n 50 --global"),
1070
+ hCmd("apx messages chat", 36, "--channel telegram -n 50"),
185
1071
  hCmd("apx messages search \"q\"", 36, ""),
186
1072
 
187
1073
  hSec("LLM / Chat"),
@@ -203,9 +1089,11 @@ function buildHelp(version) {
203
1089
  hSec("Routines"),
204
1090
  hCmd("apx routine list", 36, "list routines + next/last run"),
205
1091
  hCmd("apx routine add <name>", 36, "--kind K --schedule S [--spec '{...}']"),
206
- ` ${H.DI}kinds: heartbeat | exec_agent | telegram | shell${H.R}`,
1092
+ ` ${H.DI}kinds: heartbeat | exec_agent | super_agent | telegram | shell${H.R}`,
1093
+ ` ${H.DI}flags: --permission-mode total|automatico|permiso --allowed-tools a,b${H.R}`,
207
1094
  ` ${H.DI}schedule: every:60s | every:5m | every:1h | once:<iso>${H.R}`,
208
1095
  hCmd("apx routine get <name>", 36, ""),
1096
+ hCmd("apx routine history <name>", 36, "show routine execution history"),
209
1097
  hCmd("apx routine run <name>", 36, "manual trigger (ignores schedule)"),
210
1098
  hCmd("apx routine enable <name>", 36, ""),
211
1099
  hCmd("apx routine disable <name>", 36, ""),
@@ -231,6 +1119,72 @@ function buildHelp(version) {
231
1119
  ].join("\n") + "\n";
232
1120
  }
233
1121
 
1122
+ function buildTopicHelp(t) {
1123
+ const lines = [
1124
+ "",
1125
+ ` ${H.B}${H.WH}${t.title}${H.R}`,
1126
+ ` ${H.DI}${t.summary}${H.R}`,
1127
+ "",
1128
+ ];
1129
+ if (t.usage.length) {
1130
+ lines.push(hSec("Usage"));
1131
+ for (const u of t.usage) lines.push(` ${H.WH}${u}${H.R}`);
1132
+ }
1133
+ if (t.commands.length) {
1134
+ lines.push(hSec("Commands"));
1135
+ for (const [name, desc] of t.commands) lines.push(hSub(name, 28, desc));
1136
+ }
1137
+ if (t.options.length) {
1138
+ lines.push(hSec("Options"));
1139
+ for (const [flag, desc] of t.options) lines.push(hFlag(flag, 28, desc));
1140
+ }
1141
+ if (t.examples.length) {
1142
+ lines.push(hSec("Examples"));
1143
+ for (const ex of t.examples) lines.push(` ${H.WH}${ex}${H.R}`);
1144
+ }
1145
+ lines.push(
1146
+ hSec("Global Flags"),
1147
+ hFlag("--help", 28, "show this help"),
1148
+ hFlag("--version", 28, "print version"),
1149
+ "",
1150
+ );
1151
+ return lines.join("\n") + "\n";
1152
+ }
1153
+
1154
+ function normalizeHelpKey(key) {
1155
+ return HELP_ALIASES.get(key) || key;
1156
+ }
1157
+
1158
+ function findHelpTopic(argv) {
1159
+ const hasHelpFlag = argv.some((a) => a === "--help" || a === "-h");
1160
+ const hasHelpCommand = argv[0] === "help" || argv[1] === "help";
1161
+ const wantsHelp = hasHelpFlag || hasHelpCommand;
1162
+ if (!wantsHelp) return null;
1163
+
1164
+ const withoutFlags = argv.filter((a) => a !== "--help" && a !== "-h");
1165
+ const tokens = withoutFlags[0] === "help"
1166
+ ? withoutFlags.slice(1)
1167
+ : withoutFlags[1] === "help"
1168
+ ? [withoutFlags[0], ...withoutFlags.slice(2)]
1169
+ : withoutFlags;
1170
+ if (tokens.length === 0) return { global: true };
1171
+
1172
+ const projectSubcommands = new Set(["add", "list", "ls", "remove", "rm", "rebuild"]);
1173
+ if (tokens[0] === "project" && tokens.length >= 3 && !projectSubcommands.has(tokens[1])) {
1174
+ for (let n = tokens.length - 2; n > 0; n--) {
1175
+ const key = normalizeHelpKey(tokens.slice(2, 2 + n).join(" "));
1176
+ if (HELP_TOPICS.has(key)) return { topic: HELP_TOPICS.get(key) };
1177
+ }
1178
+ }
1179
+
1180
+ for (let n = tokens.length; n > 0; n--) {
1181
+ const key = normalizeHelpKey(tokens.slice(0, n).join(" "));
1182
+ if (HELP_TOPICS.has(key)) return { topic: HELP_TOPICS.get(key) };
1183
+ }
1184
+
1185
+ return { global: true };
1186
+ }
1187
+
234
1188
  function parseArgs(argv) {
235
1189
  const args = { _: [], flags: {} };
236
1190
  for (let i = 0; i < argv.length; i++) {
@@ -283,10 +1237,15 @@ process.on("unhandledRejection", (reason) => {
283
1237
  die(reason instanceof Error ? reason.message : String(reason));
284
1238
  });
285
1239
 
286
- if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h" || argv[0] === "help") {
1240
+ const helpRequest = findHelpTopic(argv);
1241
+ if (argv.length === 0 || helpRequest?.global) {
287
1242
  process.stdout.write(buildHelp(VERSION));
288
1243
  process.exit(0);
289
1244
  }
1245
+ if (helpRequest?.topic) {
1246
+ process.stdout.write(buildTopicHelp(helpRequest.topic));
1247
+ process.exit(0);
1248
+ }
290
1249
 
291
1250
  if (argv[0] === "--version" || argv[0] === "-v") {
292
1251
  console.log(VERSION);
@@ -401,6 +1360,7 @@ async function dispatch(cmd, rest) {
401
1360
  const sub = rest[0];
402
1361
  const a = parseArgs(rest.slice(1));
403
1362
  if (sub === "tail") await cmdMessagesTail(a);
1363
+ else if (sub === "chat") await cmdMessagesChat(a);
404
1364
  else if (sub === "search") await cmdMessagesSearch(a);
405
1365
  else die(`unknown messages subcommand: ${sub || "(none)"}`);
406
1366
  break;
@@ -454,6 +1414,11 @@ async function dispatch(cmd, rest) {
454
1414
  break;
455
1415
  }
456
1416
 
1417
+ case "permission": {
1418
+ await cmdPermission(parseArgs(rest));
1419
+ break;
1420
+ }
1421
+
457
1422
  case "plugins":
458
1423
  case "plugin": {
459
1424
  const sub = rest[0];
@@ -475,6 +1440,7 @@ async function dispatch(cmd, rest) {
475
1440
  else if (sub === "enable") await cmdRoutineEnable(a);
476
1441
  else if (sub === "disable") await cmdRoutineDisable(a);
477
1442
  else if (sub === "run") await cmdRoutineRun(a);
1443
+ else if (sub === "history" || sub === "hist") await cmdRoutineHistory(a);
478
1444
  else die(`unknown routine subcommand: ${sub}`);
479
1445
  break;
480
1446
  }