@agentprojectcontext/apx 1.33.1 → 1.35.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 (208) hide show
  1. package/package.json +1 -1
  2. package/skills/apx/SKILL.md +49 -61
  3. package/src/core/agent/a2a/reply.js +48 -0
  4. package/src/core/agent/build-agent-system.js +136 -59
  5. package/src/core/agent/channels/voice-context.js +98 -0
  6. package/src/core/agent/memory.js +2 -1
  7. package/src/core/agent/prompt-builder.js +178 -124
  8. package/src/core/agent/prompts/channels/code.md +12 -10
  9. package/src/core/agent/prompts/channels/desktop.md +5 -32
  10. package/src/core/agent/prompts/channels/telegram.md +4 -15
  11. package/src/core/agent/prompts/channels/web_code.md +11 -11
  12. package/src/core/agent/prompts/core/agent-base.md +24 -0
  13. package/src/core/agent/prompts/core/project-agent.md +11 -0
  14. package/src/core/agent/prompts/core/super-agent.md +21 -0
  15. package/src/core/agent/prompts/discipline/action.md +10 -0
  16. package/src/core/agent/prompts/discipline/single-segment.md +6 -0
  17. package/src/core/agent/prompts/discipline/two-segment.md +11 -0
  18. package/src/core/agent/prompts/modes/code-build.md +1 -0
  19. package/src/core/agent/prompts/modes/code-plan.md +1 -0
  20. package/src/core/agent/prompts/modes/index.js +28 -0
  21. package/src/core/agent/self-memory.js +43 -1
  22. package/src/core/agent/skills/index-store.js +307 -0
  23. package/src/core/agent/skills/index.js +15 -1
  24. package/src/core/agent/skills/inspector.js +317 -0
  25. package/src/core/agent/skills/loader.js +22 -18
  26. package/src/core/agent/stream/turn-accumulator.js +73 -0
  27. package/src/core/agent/suggestions.js +37 -0
  28. package/src/core/agent/super-agent.js +7 -1
  29. package/src/core/agent/tools/handlers/_git.js +50 -0
  30. package/src/core/agent/tools/handlers/add-project.js +5 -2
  31. package/src/core/agent/tools/handlers/call-runtime.js +3 -2
  32. package/src/core/agent/tools/handlers/git-diff.js +44 -0
  33. package/src/core/agent/tools/handlers/git-log.js +38 -0
  34. package/src/core/agent/tools/handlers/git-show.js +34 -0
  35. package/src/core/agent/tools/handlers/git-status.js +61 -0
  36. package/src/core/agent/tools/handlers/transcribe-audio.js +1 -1
  37. package/src/core/agent/tools/helpers.js +2 -2
  38. package/src/core/agent/tools/names.js +169 -0
  39. package/src/core/agent/tools/registry-bridge.js +6 -14
  40. package/src/core/agent/tools/registry.js +103 -69
  41. package/src/core/apc/context-copy.js +27 -0
  42. package/src/core/apc/notes.js +19 -0
  43. package/src/core/apc/parser.js +12 -5
  44. package/src/core/apc/paths.js +87 -0
  45. package/src/core/apc/scaffold.js +82 -76
  46. package/src/core/apc/skill-sync.js +10 -0
  47. package/src/{host/daemon/plugins → core/channels}/telegram/dispatch.js +38 -16
  48. package/src/core/config/index.js +24 -2
  49. package/src/core/config/redact.js +95 -0
  50. package/src/core/constants/channels.js +2 -0
  51. package/src/core/constants/code-modes.js +10 -0
  52. package/src/core/constants/index.js +1 -0
  53. package/src/core/deck/manifest.js +186 -0
  54. package/src/core/engines/catalog.js +83 -0
  55. package/src/core/{tools → http-tools}/browser.js +0 -1
  56. package/src/core/{tools → http-tools}/fetch.js +0 -1
  57. package/src/core/{tools → http-tools}/glob.js +0 -1
  58. package/src/core/{tools → http-tools}/grep.js +0 -1
  59. package/src/core/{tools → http-tools}/registry.js +0 -1
  60. package/src/core/{tools → http-tools}/search.js +0 -1
  61. package/src/core/i18n/en.js +9 -0
  62. package/src/core/i18n/es.js +12 -0
  63. package/src/core/i18n/index.js +54 -0
  64. package/src/core/i18n/pt.js +9 -0
  65. package/src/core/identity/telegram.js +2 -1
  66. package/src/core/mcp/runner.js +272 -14
  67. package/src/core/mcp/sources.js +3 -2
  68. package/src/core/routines/index.js +16 -0
  69. package/src/{host/daemon/routines.js → core/routines/runner.js} +36 -103
  70. package/src/core/runtime-skills/apc-context/SKILL.md +159 -0
  71. package/src/core/runtime-skills/apx/SKILL.md +83 -0
  72. package/src/core/runtime-skills/apx-agency-agents/SKILL.md +125 -0
  73. package/src/core/runtime-skills/apx-agent/SKILL.md +97 -0
  74. package/src/core/runtime-skills/apx-mcp/SKILL.md +111 -0
  75. package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +169 -0
  76. package/{skills → src/core/runtime-skills}/apx-project/SKILL.md +20 -29
  77. package/src/core/runtime-skills/apx-routine/SKILL.md +127 -0
  78. package/src/core/runtime-skills/apx-runtime/SKILL.md +99 -0
  79. package/src/core/runtime-skills/apx-sessions/SKILL.md +232 -0
  80. package/src/core/runtime-skills/apx-skill-builder/SKILL.md +129 -0
  81. package/{skills → src/core/runtime-skills}/apx-task/SKILL.md +18 -21
  82. package/src/core/runtime-skills/apx-telegram/SKILL.md +120 -0
  83. package/src/core/runtime-skills/apx-voice/SKILL.md +117 -0
  84. package/src/core/runtime-skills/{claude-code.md → claude-code/SKILL.md} +1 -0
  85. package/src/core/runtime-skills/{codex-cli.md → codex-cli/SKILL.md} +1 -0
  86. package/src/core/runtime-skills/{opencode-cli.md → opencode-cli/SKILL.md} +1 -0
  87. package/src/core/runtime-skills/{openrouter.md → openrouter/SKILL.md} +1 -0
  88. package/src/{host/daemon/env-detect.js → core/runtimes/detect.js} +1 -1
  89. package/src/core/stores/code-sessions.js +50 -2
  90. package/src/core/stores/routine-memory.js +1 -1
  91. package/src/core/stores/sessions-search.js +121 -0
  92. package/src/core/stores/sessions.js +38 -0
  93. package/src/core/vars/index.js +14 -0
  94. package/src/core/vars/interpolate.js +86 -0
  95. package/src/core/vars/sources.js +151 -0
  96. package/src/core/voice/audio-decode.js +38 -0
  97. package/src/core/voice/transcription.js +225 -0
  98. package/src/host/daemon/api/admin-config.js +5 -82
  99. package/src/host/daemon/api/agents.js +5 -5
  100. package/src/host/daemon/api/code.js +17 -169
  101. package/src/host/daemon/api/config.js +3 -4
  102. package/src/host/daemon/api/conversations.js +8 -29
  103. package/src/host/daemon/api/deck.js +37 -404
  104. package/src/host/daemon/api/engines.js +1 -80
  105. package/src/host/daemon/api/exec.js +1 -1
  106. package/src/host/daemon/api/mcps.js +32 -0
  107. package/src/host/daemon/api/routines.js +1 -1
  108. package/src/host/daemon/api/runtimes.js +4 -3
  109. package/src/host/daemon/api/sessions-search.js +24 -140
  110. package/src/host/daemon/api/sessions.js +12 -30
  111. package/src/host/daemon/api/shared.js +2 -1
  112. package/src/host/daemon/api/skills.js +140 -6
  113. package/src/host/daemon/api/super-agent.js +56 -1
  114. package/src/host/daemon/api/telegram.js +1 -11
  115. package/src/host/daemon/api/tools.js +6 -6
  116. package/src/host/daemon/api/transcribe.js +2 -2
  117. package/src/host/daemon/api/vars.js +137 -0
  118. package/src/host/daemon/api/voice.js +13 -290
  119. package/src/host/daemon/api.js +2 -0
  120. package/src/host/daemon/db.js +6 -6
  121. package/src/host/daemon/deck-exec.js +148 -0
  122. package/src/host/daemon/index.js +20 -3
  123. package/src/host/daemon/plugins/telegram/index.js +9 -9
  124. package/src/host/daemon/routines-scheduler.js +64 -0
  125. package/src/host/daemon/smoke.js +3 -2
  126. package/src/host/daemon/whisper-server.js +225 -0
  127. package/src/interfaces/cli/branding.js +53 -0
  128. package/src/interfaces/cli/commands/agent.js +3 -2
  129. package/src/interfaces/cli/commands/command.js +2 -3
  130. package/src/interfaces/cli/commands/messages.js +6 -2
  131. package/src/interfaces/cli/commands/pair.js +5 -4
  132. package/src/interfaces/cli/commands/search.js +1 -1
  133. package/src/interfaces/cli/commands/sessions.js +3 -2
  134. package/src/interfaces/cli/commands/skills.js +290 -55
  135. package/src/interfaces/cli/index.js +84 -2
  136. package/src/interfaces/web/dist/assets/index-C0fm31dY.js +618 -0
  137. package/src/interfaces/web/dist/assets/index-C0fm31dY.js.map +1 -0
  138. package/src/interfaces/web/dist/assets/index-UcAqlBO6.css +1 -0
  139. package/src/interfaces/web/dist/index.html +2 -2
  140. package/src/interfaces/web/package-lock.json +182 -182
  141. package/src/interfaces/web/src/components/ModelCombobox.tsx +2 -1
  142. package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +1 -1
  143. package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +76 -0
  144. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +37 -4
  145. package/src/interfaces/web/src/components/chat/MessageList.tsx +23 -1
  146. package/src/interfaces/web/src/components/chat/ModelPicker.tsx +3 -1
  147. package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +4 -4
  148. package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +1 -1
  149. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +3 -2
  150. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +3 -2
  151. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +3 -2
  152. package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +2 -1
  153. package/src/interfaces/web/src/components/deck/WidgetRow.tsx +2 -1
  154. package/src/interfaces/web/src/components/inputs/KeyValueList.tsx +93 -0
  155. package/src/interfaces/web/src/components/inputs/VarTokenInput.tsx +449 -0
  156. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +2 -1
  157. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +2 -2
  158. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +73 -4
  159. package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +222 -0
  160. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +3 -2
  161. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +3 -2
  162. package/src/interfaces/web/src/components/ui/chat-input.tsx +5 -4
  163. package/src/interfaces/web/src/components/ui/sidebar.tsx +3 -2
  164. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +2 -1
  165. package/src/interfaces/web/src/constants/index.ts +1 -1
  166. package/src/interfaces/web/src/hooks/useChat.ts +19 -0
  167. package/src/interfaces/web/src/i18n/en.ts +175 -7
  168. package/src/interfaces/web/src/i18n/es.ts +180 -15
  169. package/src/interfaces/web/src/lib/api/mcps.ts +25 -0
  170. package/src/interfaces/web/src/lib/api/skills.ts +70 -0
  171. package/src/interfaces/web/src/lib/api/vars.ts +38 -0
  172. package/src/interfaces/web/src/lib/api.ts +1 -0
  173. package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -31
  174. package/src/interfaces/web/src/screens/SettingsScreen.tsx +6 -2
  175. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
  176. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +4 -3
  177. package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +7 -6
  178. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +4 -3
  179. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +1 -1
  180. package/src/interfaces/web/src/screens/project/ConfigTab.tsx +132 -1
  181. package/src/interfaces/web/src/screens/project/McpsTab.tsx +549 -104
  182. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +1 -1
  183. package/src/interfaces/web/src/screens/project/VarsTab.tsx +300 -0
  184. package/src/interfaces/web/src/types/daemon.ts +15 -0
  185. package/skills/apx-agency-agents/SKILL.md +0 -141
  186. package/skills/apx-agent/SKILL.md +0 -100
  187. package/skills/apx-mcp-builder/SKILL.md +0 -183
  188. package/skills/apx-routine/SKILL.md +0 -140
  189. package/skills/apx-runtime/SKILL.md +0 -117
  190. package/skills/apx-sessions/SKILL.md +0 -281
  191. package/skills/apx-skill-builder/SKILL.md +0 -153
  192. package/skills/apx-telegram/SKILL.md +0 -131
  193. package/skills/apx-voice/SKILL.md +0 -137
  194. package/src/core/agent/prompts/action-discipline.md +0 -24
  195. package/src/core/agent/prompts/super-agent-base.md +0 -42
  196. package/src/host/daemon/transcription.js +0 -538
  197. package/src/host/daemon/whisper-transcribe.py +0 -73
  198. package/src/interfaces/web/dist/assets/index-Aaiw8BZN.css +0 -1
  199. package/src/interfaces/web/dist/assets/index-DPqtjDjh.js +0 -602
  200. package/src/interfaces/web/dist/assets/index-DPqtjDjh.js.map +0 -1
  201. /package/src/{host/daemon → core/apc}/projects-helpers.js +0 -0
  202. /package/src/{host/daemon/plugins → core/channels}/telegram/ask.js +0 -0
  203. /package/src/{host/daemon/plugins → core/channels}/telegram/helpers.js +0 -0
  204. /package/src/{host/daemon/plugins → core/channels}/telegram/media.js +0 -0
  205. /package/src/core/{tools → http-tools}/index.js +0 -0
  206. /package/src/{host/daemon/compact.js → core/stores/conversations-compactor.js} +0 -0
  207. /package/src/{host/daemon → core/stores}/conversations.js +0 -0
  208. /package/src/{host/daemon → core/util}/thinking.js +0 -0
@@ -0,0 +1,169 @@
1
+ ---
2
+ name: apx-mcp-builder
3
+ scope: internal
4
+ description: Author a new MCP (Model Context Protocol) server and register it in APX. Covers JSON-RPC stdio protocol, FastMCP (Python) / TypeScript SDK shapes, tool design, secrets, debugging. Load when building a new MCP / exposing a new tool surface. To add an existing MCP, load `apx-mcp` instead.
5
+ ---
6
+
7
+ # apx-mcp-builder
8
+
9
+ An MCP server is a tiny stdio JSON-RPC process. APX spawns it (via `apx mcp add`), discovers tools (`tools/list`), and lets the super-agent call them by name.
10
+
11
+ ## Minimum surface
12
+
13
+ | Method | Purpose | Returns |
14
+ |---|---|---|
15
+ | `initialize` | Handshake (protocol version + capabilities). | Server capabilities. |
16
+ | `tools/list` | Enumerate tools. | `{ tools: [{name, description, inputSchema}] }` |
17
+ | `tools/call` | Run one tool with `{ name, arguments }`. | `{ content: [...], isError? }` |
18
+ | `notifications/initialized` | One-way init-done from APX. | — |
19
+
20
+ JSON-RPC 2.0 over stdio, framed `Content-Length: N\r\n\r\n<JSON>`. The `@modelcontextprotocol/sdk` (TS) and `fastmcp` / `mcp` (Python) packages handle framing.
21
+
22
+ ## Pick a stack
23
+
24
+ | Stack | When |
25
+ |---|---|
26
+ | **Python + FastMCP** | Fastest path; decorator-based; ideal for pip-wrapping tools. |
27
+ | **Node + @modelcontextprotocol/sdk** | Node-only libs, or zero install (`npx -y`). |
28
+ | Raw JSON-RPC | Only when exposing an existing daemon. Otherwise use the SDK. |
29
+
30
+ ## Python (FastMCP) — minimum viable server
31
+
32
+ ```python
33
+ # my_server.py
34
+ from mcp.server.fastmcp import FastMCP
35
+
36
+ mcp = FastMCP("my-server")
37
+
38
+ @mcp.tool()
39
+ def search_inventory(query: str, limit: int = 10) -> list[dict]:
40
+ """Search the inventory by free-text query. Returns matching SKUs."""
41
+ return [{"sku": "abc", "title": "..."}]
42
+
43
+ @mcp.tool()
44
+ def get_stock(sku: str) -> dict:
45
+ """Return the current stock count for a SKU."""
46
+ return {"sku": sku, "stock": 42}
47
+
48
+ if __name__ == "__main__":
49
+ mcp.run() # stdio transport
50
+ ```
51
+
52
+ ```bash
53
+ pip install fastmcp
54
+ # or: uv tool install fastmcp
55
+
56
+ apx mcp add my-server \
57
+ --command uv --project iacrmar \
58
+ -- run python /abs/path/my_server.py
59
+ ```
60
+
61
+ ## Node (TypeScript SDK) — minimum viable server
62
+
63
+ ```typescript
64
+ // my-server.ts
65
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
66
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
67
+ import {
68
+ ListToolsRequestSchema,
69
+ CallToolRequestSchema,
70
+ } from "@modelcontextprotocol/sdk/types.js";
71
+
72
+ const server = new Server(
73
+ { name: "my-server", version: "0.1.0" },
74
+ { capabilities: { tools: {} } }
75
+ );
76
+
77
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
78
+ tools: [
79
+ {
80
+ name: "search_inventory",
81
+ description: "Search the inventory by free-text query.",
82
+ inputSchema: {
83
+ type: "object",
84
+ properties: {
85
+ query: { type: "string" },
86
+ limit: { type: "number", default: 10 },
87
+ },
88
+ required: ["query"],
89
+ },
90
+ },
91
+ ],
92
+ }));
93
+
94
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
95
+ if (req.params.name === "search_inventory") {
96
+ const { query, limit = 10 } = req.params.arguments as any;
97
+ return {
98
+ content: [{ type: "text", text: JSON.stringify([{ sku: "abc" }]) }],
99
+ };
100
+ }
101
+ throw new Error(`unknown tool: ${req.params.name}`);
102
+ });
103
+
104
+ await server.connect(new StdioServerTransport());
105
+ ```
106
+
107
+ ```bash
108
+ apx mcp add my-server \
109
+ --command npx --project iacrmar \
110
+ -- -y my-server-package
111
+ ```
112
+
113
+ ## Tool design rules
114
+
115
+ 1. **Names are snake_case verbs**: `search_inventory`, not `inventorySearch`.
116
+ 2. **inputSchema is JSON Schema draft-07**. `required` matters — vague schemas → bad calls.
117
+ 3. **Descriptions read like a man-page**. Tool + param descriptions are surfaced to the model.
118
+ 4. **Return structured data**, not prose. Convention: JSON inside a text content block. Images use the `image` type.
119
+ 5. **Errors are errors**: `throw new Error(...)` propagates as `isError: true`. Empty result = "found nothing" — different signal.
120
+
121
+ ## Env vars and secrets
122
+
123
+ ```bash
124
+ apx mcp add github \
125
+ --scope runtime --project iacrmar \
126
+ --command npx \
127
+ --env GITHUB_TOKEN=ghp_xxx \
128
+ --env GITHUB_OWNER=manuel \
129
+ -- -y @modelcontextprotocol/server-github
130
+ ```
131
+
132
+ `--scope runtime` writes to `~/.apx/projects/<id>/mcps.json` (chmod 0600, never committed). NEVER `--scope shared` for tokens — that file lives in `.apc/` and gets committed.
133
+
134
+ ## Anti-examples
135
+
136
+ ```python
137
+ # DON'T expose every internal function. A server with 40 tools eats context.
138
+ # Pick 5-10 high-value tools per server; split into multiple servers if more.
139
+
140
+ # DON'T return giant blobs in `content`. The agent re-reads every turn.
141
+ # Paginate (`offset`, `limit`) and let the agent ask for more.
142
+
143
+ # DON'T mix stdio + HTTP transports in one process. APX spawns stdio;
144
+ # for HTTP use `url:` in mcps.json instead of `command:`.
145
+
146
+ # DON'T print to stdout outside JSON-RPC frames. Stray print() corrupts
147
+ # the protocol — use stderr for logs. (SDKs handle this; bare `print("debug")`
148
+ # in a tool body breaks everything.)
149
+ ```
150
+
151
+ ## Debugging
152
+
153
+ ```bash
154
+ # Smoke test (apx mcp tools is a v0.2 stub — don't rely on it)
155
+ apx mcp run my-server search_inventory '{"query":"shoes"}'
156
+
157
+ # Spawn errors / stderr
158
+ apx log -f
159
+
160
+ # Scopes / files / env APX sees
161
+ apx mcp check --project iacrmar
162
+ ```
163
+
164
+ ## Don't
165
+
166
+ - Don't reinvent SDK framing — bypass only with reason.
167
+ - Don't make interactive tools. MCP is one-shot per call; split flows into multiple tools.
168
+ - Don't ship without a README — future-you forgets which env vars matter.
169
+ - Don't expect APX to retry MCP errors. The agent sees the error and decides.
@@ -1,30 +1,30 @@
1
1
  ---
2
2
  name: apx-project
3
- description: How to register, list, configure, and manage APX projects. Use BEFORE asking the user "which project?" — registered projects are listable; per-project config (model override, etc) is set with dotted-key PATCH.
3
+ description: Register, list, configure, manage APX projects. Load BEFORE asking "which project?" — registered projects are listable; per-project config set via dotted-key PATCH. Triggers: 'register project', 'apx project', 'project config', 'list projects', 'what projects are registered'.
4
4
  ---
5
5
 
6
6
  # apx-project
7
7
 
8
- A project in APX is an APC-compliant folder on disk (`AGENTS.md` + `.apc/project.json`). Once registered, APX keeps runtime state (sessions, messages, routines, tasks, MCPs) under `~/.apx/projects/<apxId>/`.
8
+ A project in APX is an APC-compliant folder (`AGENTS.md` + `.apc/project.json`). Once registered, APX keeps runtime state (sessions, messages, routines, tasks, MCPs) under `~/.apx/projects/<apxId>/`.
9
9
 
10
- ## The two kinds of projects
10
+ ## Two kinds of projects
11
11
 
12
- - **`default`** (id=0): the super-agent's scratch workspace under `~/.apx/projects/default/`. Used when the user has no project named, has no project registered, or explicitly addresses "apx itself". Don't use it for real work — it's shared.
12
+ - **`default`** (id=0): super-agent's scratch workspace at `~/.apx/projects/default/`. Used when user has no project named, no project registered, or addresses "apx itself". Don't use for real work — shared.
13
13
  - **registered** (id=1+): real projects, each rooted at a path the user owns.
14
14
 
15
15
  ## Concrete CLI calls
16
16
 
17
17
  ```bash
18
18
  # Register
19
- apx project add /path/to/repo # registers; reads AGENTS.md + .apc/project.json
19
+ apx project add /path/to/repo # reads AGENTS.md + .apc/project.json
20
20
  apx project add . # current dir
21
21
 
22
22
  # Inspect
23
23
  apx project list # id, name, agents count, path
24
24
 
25
- # Remove / rebuild (id or exact path only — these do NOT resolve by name)
25
+ # Remove / rebuild (id or exact path only — no name resolution here)
26
26
  apx project remove <id|path>
27
- apx project rebuild <id|path> # force re-scan of .apc/ on disk
27
+ apx project rebuild <id|path> # force re-scan of .apc/
28
28
 
29
29
  # Per-project config — dotted keys, lives in <repo>/.apc/config.json
30
30
  apx project config show <project> # effective + project_only
@@ -36,17 +36,11 @@ apx project config unset <project> super_agent.model # back to glo
36
36
  apx project config edit <project> # opens $EDITOR on project_only JSON
37
37
  ```
38
38
 
39
- Every write to `project config` triggers `POST /admin/reload` so the daemon picks up the change without restart.
39
+ Every `project config` write triggers `POST /admin/reload` so the daemon picks up changes without restart.
40
40
 
41
- ## Resolution of `<project>` argument
41
+ ## `<project>` argument resolution
42
42
 
43
- Accepted forms:
44
- - numeric id: `1`
45
- - exact name from `.apc/project.json`: `iacrmar`
46
- - absolute path: `/Volumes/SSDT7Shield/trabajos_proyectos/iacrmar`
47
- - relative path (from cwd) — resolved before matching.
48
-
49
- The CLI calls `resolveProjectId()` which does fuzzy id-or-name-or-path matching. If you got "project not found", `apx project list` first.
43
+ Accepted: numeric id (`1`), exact name from `.apc/project.json` (`iacrmar`), absolute path, relative path (resolved from cwd). The CLI's `resolveProjectId()` does fuzzy id/name/path matching. If "project not found", run `apx project list` first.
50
44
 
51
45
  ## What lives where
52
46
 
@@ -59,7 +53,7 @@ The CLI calls `resolveProjectId()` which does fuzzy id-or-name-or-path matching.
59
53
  ├── skills/<slug>.md or <slug>/SKILL.md
60
54
  ├── mcps.json ← shared MCPs (committed)
61
55
  ├── commands/ ← custom slash-commands
62
- └── config.json ← project-only overrides (this is what `project config` edits)
56
+ └── config.json ← project-only overrides (edited by `project config`)
63
57
 
64
58
  ~/.apx/projects/<apxId>/ ← runtime state (never committed)
65
59
  ├── messages/YYYY-MM-DD.jsonl
@@ -70,29 +64,26 @@ The CLI calls `resolveProjectId()` which does fuzzy id-or-name-or-path matching.
70
64
  └── mcps.json ← per-project runtime MCPs (local, may hold tokens)
71
65
  ```
72
66
 
73
- ## Anti-example
67
+ ## Anti-examples
74
68
 
75
69
  ```bash
76
70
  # DON'T hand-write AGENTS.md + .apc/project.json with shell tools.
77
71
  echo "Hello" > /path/repo/AGENTS.md
78
- mkdir -p /path/repo/.apc
79
- echo "{...}" > /path/repo/.apc/project.json
80
- ```
72
+ mkdir -p /path/repo/.apc && echo "{...}" > /path/repo/.apc/project.json
73
+ # No scaffold validation; project appears registered but breaks on `apx project rebuild`.
74
+ # Use `apx init <path>` then `apx project add <path>`.
81
75
 
82
- There's no scaffold validation, the project will appear registered but break on the first `apx project rebuild`. Use `apx init <path>` (project scaffold) and then `apx project add <path>`.
83
-
84
- ```bash
85
- # DON'T set super_agent.model to a model that's not in the engine you have keys for.
76
+ # DON'T set super_agent.model to a model lacking an engine key.
86
77
  apx project config set iacrmar super_agent.model gemini:gemini-1.5-pro
87
- # ↑ Will fail at first call unless engines.gemini.api_key is set.
78
+ # ↑ Fails at first call unless engines.gemini.api_key is set.
88
79
  ```
89
80
 
90
81
  ## When asked "what projects are there?"
91
82
 
92
- Don't ask. Call `list_projects` (tool) or `apx project list`. Same for "which agents does X have?" → `list_agents` / `apx agent list --project X`.
83
+ Don't ask call `list_projects` tool or `apx project list`. Same for "which agents does X have?" → `list_agents` / `apx agent list --project X`.
93
84
 
94
85
  ## Don't
95
86
 
96
- - Don't operate on the default project (id=0) as if it were the user's main work. It's a scratch space for super-agent state.
87
+ - Don't operate on the default project (id=0) as if it were the user's main work. Scratch space for super-agent state.
97
88
  - Don't put secrets in `.apc/config.json` — it's committed. Put them in `~/.apx/config.json` (machine-local) under `engines.*` or `voice.tts.*`.
98
- - Don't move a project's `.apc/` folder without re-running `apx project rebuild` afterwards. The `apxId` will be stale.
89
+ - Don't move a project's `.apc/` folder without re-running `apx project rebuild` `apxId` will be stale.
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: apx-routine
3
+ description: Create, edit, run, debug APX routines (scheduled tasks). Load BEFORE `apx routine add` — schedule grammar, kind selection, pre/post hooks, double-reply gotcha.
4
+ ---
5
+
6
+ # apx-routine
7
+
8
+ A scheduled APX task. Scheduler ticks every 5s. Each routine has a `kind`, `schedule`, optional `spec`, and optional `pre_commands` / `post_commands` shell hooks.
9
+
10
+ ## Picking `kind`
11
+
12
+ | Kind | Tools? | Description |
13
+ |---|---|---|
14
+ | `heartbeat` | no | "Still alive" marker. No LLM. |
15
+ | `shell` | no | Pure shell. Stdout captured. |
16
+ | `exec_agent` | **no** | Loads agent prompt, sends `spec.prompt`, returns text. Single LLM call. |
17
+ | `super_agent` | **all** | Default agent with full tool registry. Multi-iteration loop. |
18
+ | `telegram` | n/a | Sends hardcoded text via Telegram plugin. |
19
+
20
+ Rule: text from model → `exec_agent`; orchestration (MCPs, files, multi-agent) → `super_agent`; pure shell → `shell`; fixed Telegram poke → `telegram`.
21
+
22
+ ## Schedule grammar
23
+
24
+ - `every:<N><unit>` — `every:30s`, `every:5m`, `every:24h`, `every:7d`. **Most common.**
25
+ - `once:<iso-8601>` — `once:2026-12-01T08:00:00Z`. Fires once, then disabled.
26
+ - Cron — `*/5 * * * *`, `0 8 * * *`. Standard 5-field.
27
+
28
+ ## Anatomy
29
+
30
+ ```json
31
+ {
32
+ "name": "weather-bariloche",
33
+ "kind": "exec_agent",
34
+ "schedule": "every:24h",
35
+ "spec": { "agent": "default", "prompt": "Write a short greeting..." },
36
+ "pre_commands": ["curl -s 'https://wttr.in/Bariloche?format=...'"],
37
+ "post_commands": ["apx telegram send \"$APX_LLM_OUTPUT\""],
38
+ "enabled": true,
39
+ "skip_prompt_on": "signal"
40
+ }
41
+ ```
42
+
43
+ Pipeline: `pre_commands` run sequentially → combined stdout becomes `{{pre_output}}` in `spec.prompt` and `$APX_PRE_OUTPUT` (plus `$APX_PRE_OUTPUT_FILE` for big payloads) → handler runs, result becomes `$APX_LLM_OUTPUT` → `post_commands` run.
44
+
45
+ ## Anti-example: double-reply
46
+
47
+ ```json
48
+ {
49
+ "kind": "super_agent", ← DON'T
50
+ "spec": { "prompt": "The weather is {{pre_output}}. Send it via Telegram." },
51
+ "post_commands": ["apx telegram send \"$APX_LLM_OUTPUT\""]
52
+ }
53
+ ```
54
+
55
+ Sends **two** messages: one from agent's `send_telegram` tool, one from `post_commands`. The runner auto-suppresses `send_telegram` when post contains `apx telegram send`, but the clean fix is `exec_agent`:
56
+
57
+ ```json
58
+ {
59
+ "kind": "exec_agent",
60
+ "spec": { "agent": "default", "prompt": "The weather is {{pre_output}}. One friendly sentence." },
61
+ "post_commands": ["apx telegram send \"$APX_LLM_OUTPUT\""]
62
+ }
63
+ ```
64
+
65
+ ## Concrete CLI calls
66
+
67
+ ```bash
68
+ # Always pin --project; never use default for real ones
69
+ apx routine list --project iacrmar
70
+ apx routine get weather-bariloche --project iacrmar
71
+
72
+ # Create — exec_agent + shell delivery
73
+ apx routine add weather-bariloche \
74
+ --project iacrmar \
75
+ --kind exec_agent \
76
+ --schedule "every:24h" \
77
+ --spec '{"agent":"default","prompt":"The weather is {{pre_output}}. One friendly sentence."}' \
78
+ --pre-commands "curl -s 'https://wttr.in/Bariloche?format=%t+%C+viento+%w'" \
79
+ --post-commands 'apx telegram send "$APX_LLM_OUTPUT"'
80
+
81
+ # Create — super-agent with tools
82
+ apx routine add daily-status \
83
+ --project iacrmar \
84
+ --kind super_agent \
85
+ --schedule "0 9 * * *" \
86
+ --spec '{"prompt":"List projects with pending tasks and send me a short summary via Telegram."}' \
87
+ --permission-mode automatico
88
+
89
+ # Toggle / run / remove
90
+ apx routine enable weather-bariloche --project iacrmar
91
+ apx routine disable weather-bariloche --project iacrmar
92
+ apx routine run weather-bariloche --project iacrmar # force-trigger now
93
+ apx routine remove weather-bariloche --project iacrmar
94
+ ```
95
+
96
+ ## `--project` is non-negotiable
97
+
98
+ Routines live in `~/.apx/projects/<apxId>/routines.json`. Without `--project`, they go to default (id=0, super-agent scratch) — **not** a user project. Always pass `--project <name|id|path>`.
99
+
100
+ ## `skip_prompt_on`
101
+
102
+ Gates the LLM call based on `pre_commands` (`shouldSkipPrompt` in `host/daemon/routines.js`). Post-commands always run.
103
+
104
+ | Value | Skips LLM when… |
105
+ |---|---|
106
+ | `signal` (default) | pre_command prints literal `APX_SKIP`. Non-zero exit alone does NOT skip. |
107
+ | `pre_failure` | any pre_command exits non-zero. |
108
+ | `pre_success` | pre_commands exit 0 (LLM only on pre failure). |
109
+ | `always` | unconditionally — pure pre→post, no LLM. |
110
+ | `never` | LLM always runs, even if pre crashes. |
111
+
112
+ ## Debugging
113
+
114
+ ```bash
115
+ apx routine history weather-bariloche --project iacrmar # last runs
116
+ apx log -f # tail unified log
117
+ apx messages tail --channel routine -n 20 # routine-channel messages
118
+ ```
119
+
120
+ "Sends nothing" usually means: `enabled: false`, `next_run_at` in the future, or empty LLM text (check `apx messages` or `result.text`).
121
+
122
+ ## Don't
123
+
124
+ - Use `super_agent` when `exec_agent` would do — it loops, calls tools, costs more.
125
+ - Write `apx telegram send` inside a `super_agent` prompt — agent calls `send_telegram` AND post_commands fire. Pick one.
126
+ - Hardcode model names in `spec` without reason — routines inherit `super_agent.model` (with router fallback).
127
+ - Put credentials in `spec`. Use `~/.apx/config.json` engines and reference by provider.
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: apx-runtime
3
+ description: Delegate a task to an external coding CLI (claude-code, codex, opencode, aider, cursor-agent, gemini-cli, qwen-code) via `apx run`. APX builds the system prompt, spawns the CLI, captures the result. Load when delegating to another AI tool.
4
+ ---
5
+
6
+ # apx-runtime
7
+
8
+ A "runtime" is an external AI coding CLI that APX invokes headlessly. APX builds the agent's system prompt, spawns the CLI with the right flags, captures stdout (and the external session id when available), and stores run metadata as a session file under `~/.apx/projects/<apxId>/agents/<slug>/sessions/` (never committed). Some flows link to the engine's own transcript path.
9
+
10
+ ## Supported runtimes
11
+
12
+ | id | binary | Headless flag |
13
+ |---|---|---|
14
+ | `claude-code` | `claude` | `-p "<prompt>" --append-system-prompt "<sys>" --output-format json` |
15
+ | `codex` | `codex` | `exec "<prompt>"` (works outside git repos) |
16
+ | `opencode` | `opencode` | non-interactive mode |
17
+ | `aider` | `aider` | `--message "<prompt>" --no-stream` |
18
+ | `cursor-agent` | `cursor-agent` | headless print mode |
19
+ | `gemini-cli` | `gemini` | headless prompt mode |
20
+ | `qwen-code` | `qwen-code` | system prompt passed separately |
21
+
22
+ `apx env detect` reports which are installed and reachable.
23
+
24
+ ## Concrete CLI calls
25
+
26
+ ```bash
27
+ apx env detect # which runtimes are installed
28
+ apx env list # alias
29
+
30
+ apx run reviewer --runtime claude-code "Review the diff in src/host/daemon/api/ for memory leaks"
31
+ apx run scratch --runtime codex "Refactor parseAgentsMd to use a state machine"
32
+ apx run scratch --runtime opencode "<prompt>"
33
+ apx run scratch --runtime codex --timeout 300 "<prompt>" # cap (seconds)
34
+ apx run scratch --runtime codex - # prompt from stdin (large prompts)
35
+ ```
36
+
37
+ Behavior:
38
+ 1. APX picks project from `--project` or cwd.
39
+ 2. Reads agent's `AGENT.md` + memory + skills; builds system prompt with `buildAgentSystem({ invocation: "runtime", runtime: "<id>" })`.
40
+ 3. Spawns CLI with the right flags; cwd = project path.
41
+ 4. Captures stdout. If runtime printed `APC_RESULT: <value>`, that's the structured result; else first 200 chars of stdout.
42
+ 5. Writes `~/.apx/projects/<apxId>/agents/<slug>/sessions/<YYYY-MM-DD>-<id>.md` with frontmatter linking back to the external transcript when available.
43
+
44
+ ## Resuming an external session
45
+
46
+ The session file references the external transcript:
47
+
48
+ ```yaml
49
+ # ~/.apx/projects/<apxId>/agents/reviewer/sessions/2026-05-27-claude-code-abc123.md
50
+ ---
51
+ external_session_path: /Users/.../.claude/projects/<...>/abc123.jsonl
52
+ runtime: claude-code
53
+ session_id: abc123
54
+ ---
55
+ ```
56
+
57
+ Full resume/get/continue/summarise lives in the **`apx-sessions`** skill. Quick paths:
58
+
59
+ ```bash
60
+ apx sessions list --engine claude --project iacrmar
61
+ apx session resume <id> # auto-detects engine
62
+ apx session resume <id> --continue # spawn native CLI to keep going
63
+ apx session resume <id> --summary # super-agent summary
64
+ apx session resume <id> --into apx:<slug> # seed new APX session
65
+ apx session get <id> --any --full # or --engine claude --tail 16k
66
+ ```
67
+
68
+ See `apx-sessions` for full flag reference, collision handling, and daemon-vs-no-daemon matrix.
69
+
70
+ ## APC_RESULT contract
71
+
72
+ To capture a structured value from the external runtime, instruct it via the prompt to print on its last line:
73
+
74
+ ```
75
+ APC_RESULT: <one-line value>
76
+ ```
77
+
78
+ `extractApfResult()` parses that into the session's `result` field. Useful for automation return values.
79
+
80
+ ## Anti-examples
81
+
82
+ - DON'T expect `apx run` to be interactive — it's headless. For interactive, invoke the CLI directly (e.g. `claude`).
83
+ - DON'T pass huge prompts via command line (shell arg limits). For >~10KB, use stdin (`-`) or a temp file.
84
+ - DON'T expect APX to impose a model on the external CLI. APX passes system + user prompt only; the external CLI's own config wins.
85
+
86
+ ## When to use which
87
+
88
+ | You want | Pick |
89
+ |---|---|
90
+ | Pair-program with file edits + shell | `claude-code` if installed, else `codex` |
91
+ | Lightweight LLM run, no tools | `apx exec <agent> "<prompt>"` (no runtime needed) |
92
+ | Super-agent to call other agents | `call_agent` tool (in-process, no spawn) |
93
+ | Persisted state across days | `apx run` with `claude-code` or `codex` (their sessions persist) |
94
+
95
+ ## Don't
96
+
97
+ - Run untrusted prompts in a `--runtime` CLI with broad tool permissions — the CLI may take file/shell actions.
98
+ - Expect APX to track tool calls inside the external transcript. APX captures stdout + external session path only; inspect the external transcript for tool-level audit.
99
+ - Pick a runtime the user doesn't have installed; `apx env detect` first.