@agentprojectcontext/apx 1.33.0 → 1.34.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 (172) hide show
  1. package/package.json +1 -1
  2. package/skills/apc-context/SKILL.md +2 -5
  3. package/skills/apx/SKILL.md +49 -61
  4. package/src/core/agent/a2a/reply.js +48 -0
  5. package/src/core/agent/build-agent-system.js +4 -3
  6. package/src/core/agent/channels/voice-context.js +98 -0
  7. package/src/core/agent/memory.js +2 -1
  8. package/src/core/agent/prompt-builder.js +2 -1
  9. package/src/core/agent/prompts/modes/code-build.md +1 -0
  10. package/src/core/agent/prompts/modes/code-plan.md +1 -0
  11. package/src/core/agent/prompts/modes/index.js +28 -0
  12. package/src/core/agent/skills/loader.js +22 -18
  13. package/src/core/agent/stream/turn-accumulator.js +73 -0
  14. package/src/core/agent/suggestions.js +37 -0
  15. package/src/core/agent/tools/handlers/add-project.js +5 -2
  16. package/src/core/agent/tools/handlers/call-runtime.js +3 -2
  17. package/src/core/agent/tools/handlers/transcribe-audio.js +1 -1
  18. package/src/core/agent/tools/helpers.js +2 -2
  19. package/src/core/agent/tools/names.js +138 -0
  20. package/src/core/agent/tools/registry-bridge.js +6 -14
  21. package/src/core/agent/tools/registry.js +68 -65
  22. package/src/core/apc/context-copy.js +27 -0
  23. package/src/core/apc/notes.js +19 -0
  24. package/src/core/apc/parser.js +13 -6
  25. package/src/core/apc/paths.js +87 -0
  26. package/src/core/apc/scaffold.js +82 -74
  27. package/src/core/apc/skill-sync.js +13 -1
  28. package/src/core/channels/telegram/dispatch.js +595 -0
  29. package/src/core/channels/telegram/helpers.js +130 -0
  30. package/src/core/config/index.js +3 -2
  31. package/src/core/config/redact.js +95 -0
  32. package/src/core/constants/channels.js +2 -0
  33. package/src/core/constants/code-modes.js +10 -0
  34. package/src/core/constants/index.js +1 -0
  35. package/src/core/deck/manifest.js +186 -0
  36. package/src/core/engines/catalog.js +83 -0
  37. package/src/core/engines/gemini.js +28 -11
  38. package/src/core/engines/index.js +11 -1
  39. package/src/core/{tools → http-tools}/browser.js +0 -1
  40. package/src/core/{tools → http-tools}/fetch.js +0 -1
  41. package/src/core/{tools → http-tools}/glob.js +0 -1
  42. package/src/core/{tools → http-tools}/grep.js +0 -1
  43. package/src/core/{tools → http-tools}/registry.js +0 -1
  44. package/src/core/{tools → http-tools}/search.js +0 -1
  45. package/src/core/i18n/en.js +9 -0
  46. package/src/core/i18n/es.js +12 -0
  47. package/src/core/i18n/index.js +54 -0
  48. package/src/core/i18n/pt.js +9 -0
  49. package/src/core/identity/telegram.js +2 -1
  50. package/src/core/mcp/runner.js +272 -14
  51. package/src/core/mcp/sources.js +3 -2
  52. package/src/core/routines/index.js +16 -0
  53. package/src/{host/daemon/routines.js → core/routines/runner.js} +36 -103
  54. package/src/core/runtime-skills/apc-context/SKILL.md +159 -0
  55. package/src/core/runtime-skills/apx/SKILL.md +95 -0
  56. package/src/core/runtime-skills/apx-mcp/SKILL.md +116 -0
  57. package/src/core/runtime-skills/{claude-code.md → claude-code/SKILL.md} +1 -0
  58. package/src/core/runtime-skills/{codex-cli.md → codex-cli/SKILL.md} +1 -0
  59. package/src/core/runtime-skills/{opencode-cli.md → opencode-cli/SKILL.md} +1 -0
  60. package/src/core/runtime-skills/{openrouter.md → openrouter/SKILL.md} +1 -0
  61. package/src/{host/daemon/env-detect.js → core/runtimes/detect.js} +1 -1
  62. package/src/core/stores/code-sessions.js +50 -2
  63. package/src/core/stores/routine-memory.js +1 -1
  64. package/src/core/stores/sessions-search.js +121 -0
  65. package/src/core/stores/sessions.js +38 -0
  66. package/src/core/vars/index.js +14 -0
  67. package/src/core/vars/interpolate.js +86 -0
  68. package/src/core/vars/sources.js +151 -0
  69. package/src/core/voice/audio-decode.js +38 -0
  70. package/src/core/voice/transcription.js +225 -0
  71. package/src/host/daemon/api/admin-config.js +5 -82
  72. package/src/host/daemon/api/agents.js +5 -5
  73. package/src/host/daemon/api/code.js +17 -169
  74. package/src/host/daemon/api/config.js +3 -4
  75. package/src/host/daemon/api/conversations.js +8 -29
  76. package/src/host/daemon/api/deck.js +37 -404
  77. package/src/host/daemon/api/engines.js +1 -50
  78. package/src/host/daemon/api/exec.js +1 -1
  79. package/src/host/daemon/api/mcps.js +32 -0
  80. package/src/host/daemon/api/routines.js +1 -1
  81. package/src/host/daemon/api/runtimes.js +4 -3
  82. package/src/host/daemon/api/sessions-search.js +24 -140
  83. package/src/host/daemon/api/sessions.js +12 -30
  84. package/src/host/daemon/api/shared.js +2 -1
  85. package/src/host/daemon/api/telegram.js +1 -11
  86. package/src/host/daemon/api/tools.js +6 -6
  87. package/src/host/daemon/api/transcribe.js +2 -2
  88. package/src/host/daemon/api/vars.js +137 -0
  89. package/src/host/daemon/api/voice.js +13 -290
  90. package/src/host/daemon/api.js +2 -0
  91. package/src/host/daemon/db.js +6 -6
  92. package/src/host/daemon/deck-exec.js +148 -0
  93. package/src/host/daemon/index.js +3 -3
  94. package/src/host/daemon/plugins/telegram/index.js +24 -687
  95. package/src/host/daemon/routines-scheduler.js +64 -0
  96. package/src/host/daemon/smoke.js +3 -2
  97. package/src/host/daemon/whisper-server.js +225 -0
  98. package/src/interfaces/cli/commands/agent.js +3 -2
  99. package/src/interfaces/cli/commands/command.js +2 -3
  100. package/src/interfaces/cli/commands/messages.js +6 -2
  101. package/src/interfaces/cli/commands/pair.js +5 -4
  102. package/src/interfaces/cli/commands/search.js +1 -1
  103. package/src/interfaces/cli/commands/sessions.js +3 -2
  104. package/src/interfaces/cli/commands/skills.js +36 -55
  105. package/src/interfaces/web/dist/assets/index-DdmSRtsz.css +1 -0
  106. package/src/interfaces/web/dist/assets/index-M4FspaCH.js +613 -0
  107. package/src/interfaces/web/dist/assets/index-M4FspaCH.js.map +1 -0
  108. package/src/interfaces/web/dist/index.html +2 -2
  109. package/src/interfaces/web/package-lock.json +182 -182
  110. package/src/interfaces/web/src/components/ModelCombobox.tsx +44 -8
  111. package/src/interfaces/web/src/components/TelegramChannelDialog.tsx +1 -1
  112. package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +76 -0
  113. package/src/interfaces/web/src/components/chat/MessageBubble.tsx +16 -3
  114. package/src/interfaces/web/src/components/chat/MessageList.tsx +23 -1
  115. package/src/interfaces/web/src/components/chat/ModelPicker.tsx +3 -1
  116. package/src/interfaces/web/src/components/code/CodeArtifactsTab.tsx +4 -4
  117. package/src/interfaces/web/src/components/code/CodeChangesTab.tsx +1 -1
  118. package/src/interfaces/web/src/components/code/CodeFileTree.tsx +3 -2
  119. package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +3 -2
  120. package/src/interfaces/web/src/components/code/CodeTerminal.tsx +3 -2
  121. package/src/interfaces/web/src/components/config/GlobalConfigEditor.tsx +2 -1
  122. package/src/interfaces/web/src/components/deck/WidgetRow.tsx +2 -1
  123. package/src/interfaces/web/src/components/inputs/KeyValueList.tsx +93 -0
  124. package/src/interfaces/web/src/components/inputs/VarTokenInput.tsx +449 -0
  125. package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +2 -1
  126. package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +2 -2
  127. package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +5 -4
  128. package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +3 -2
  129. package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +3 -2
  130. package/src/interfaces/web/src/components/ui/chat-input.tsx +5 -4
  131. package/src/interfaces/web/src/components/ui/sidebar.tsx +3 -2
  132. package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +2 -1
  133. package/src/interfaces/web/src/constants/index.ts +1 -1
  134. package/src/interfaces/web/src/i18n/en.ts +174 -7
  135. package/src/interfaces/web/src/i18n/es.ts +179 -15
  136. package/src/interfaces/web/src/lib/api/mcps.ts +25 -0
  137. package/src/interfaces/web/src/lib/api/vars.ts +38 -0
  138. package/src/interfaces/web/src/lib/api.ts +1 -0
  139. package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -31
  140. package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +1 -1
  141. package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +4 -3
  142. package/src/interfaces/web/src/screens/modules/DesktopScreen.tsx +7 -6
  143. package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +4 -3
  144. package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +1 -1
  145. package/src/interfaces/web/src/screens/project/ConfigTab.tsx +132 -1
  146. package/src/interfaces/web/src/screens/project/McpsTab.tsx +549 -104
  147. package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +1 -1
  148. package/src/interfaces/web/src/screens/project/VarsTab.tsx +300 -0
  149. package/src/interfaces/web/src/types/daemon.ts +5 -0
  150. package/src/host/daemon/transcription.js +0 -538
  151. package/src/host/daemon/whisper-transcribe.py +0 -73
  152. package/src/interfaces/web/dist/assets/index-7dVT2O1S.css +0 -1
  153. package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js +0 -602
  154. package/src/interfaces/web/dist/assets/index-DWsE_8Nz.js.map +0 -1
  155. /package/src/{host/daemon → core/apc}/projects-helpers.js +0 -0
  156. /package/src/{host/daemon/plugins → core/channels}/telegram/ask.js +0 -0
  157. /package/src/{host/daemon/plugins → core/channels}/telegram/media.js +0 -0
  158. /package/src/core/{tools → http-tools}/index.js +0 -0
  159. /package/{skills → src/core/runtime-skills}/apx-agency-agents/SKILL.md +0 -0
  160. /package/{skills → src/core/runtime-skills}/apx-agent/SKILL.md +0 -0
  161. /package/{skills → src/core/runtime-skills}/apx-mcp-builder/SKILL.md +0 -0
  162. /package/{skills → src/core/runtime-skills}/apx-project/SKILL.md +0 -0
  163. /package/{skills → src/core/runtime-skills}/apx-routine/SKILL.md +0 -0
  164. /package/{skills → src/core/runtime-skills}/apx-runtime/SKILL.md +0 -0
  165. /package/{skills → src/core/runtime-skills}/apx-sessions/SKILL.md +0 -0
  166. /package/{skills → src/core/runtime-skills}/apx-skill-builder/SKILL.md +0 -0
  167. /package/{skills → src/core/runtime-skills}/apx-task/SKILL.md +0 -0
  168. /package/{skills → src/core/runtime-skills}/apx-telegram/SKILL.md +0 -0
  169. /package/{skills → src/core/runtime-skills}/apx-voice/SKILL.md +0 -0
  170. /package/src/{host/daemon/compact.js → core/stores/conversations-compactor.js} +0 -0
  171. /package/src/{host/daemon → core/stores}/conversations.js +0 -0
  172. /package/src/{host/daemon → core/util}/thinking.js +0 -0
@@ -1,19 +1,17 @@
1
- // Routines: scheduled tasks per project. State persists in .apc/routines.json.
1
+ // Routine execution the domain logic any caller can invoke (daemon
2
+ // scheduler, CLI `apx routine run`, HTTP `/projects/:pid/routines/:name/run`,
3
+ // MCP server, future scripts). The runner orchestrates a 3-phase pipeline:
4
+ // 1. pre_commands (shell)
5
+ // 2. handler (heartbeat / exec_agent / super_agent / telegram / shell)
6
+ // 3. post_commands (shell)
2
7
  //
3
- // Schedule formats:
4
- // every:60s | every:5m | every:1h | once:<iso-8601>
5
- //
6
- // Kinds:
7
- // heartbeat — log a heartbeat message. spec: { channel?, message? }
8
- // exec_agent — call an agent engine. spec: { agent: slug, prompt }
9
- // super_agent — call the APX super-agent. spec: { prompt }
10
- // telegram — send a Telegram message. spec: { channel?, chat_id?, text }
11
- // shell — run a shell command. spec: { command, timeout_ms? }
12
-
8
+ // `runRoutineNow(ctx, routine)` is the single entry point. Pass a ctx with at
9
+ // least { project, projects, plugins, registries, globalConfig }. The runner
10
+ // is process-state free — the daemon's RoutineScheduler is a separate file
11
+ // (host/daemon/routines-scheduler.js) that just polls and calls this.
13
12
  import { spawn } from "node:child_process";
14
- import { execFile } from "node:child_process";
15
- import os from "node:os";
16
13
  import fs from "node:fs";
14
+ import os from "node:os";
17
15
  import path from "node:path";
18
16
  import { callEngine } from "#core/engines/index.js";
19
17
  import { runSuperAgent } from "#core/agent/super-agent.js";
@@ -22,32 +20,18 @@ import { readAgents } from "#core/apc/parser.js";
22
20
  import { buildAgentSystem } from "#core/agent/build-agent-system.js";
23
21
  import { resolveAgentName, SUPERAGENT_ACTOR_ID } from "#core/identity/index.js";
24
22
  import { resolveArtifactRef, ARTIFACTS_SKIP_SIGNAL } from "#core/stores/artifacts.js";
25
- import { ensureRoutineMemory, readRoutineMemoryForPrompt, routineMemoryPath } from "#core/stores/routine-memory.js";
23
+ import {
24
+ ensureRoutineMemory,
25
+ readRoutineMemoryForPrompt,
26
+ routineMemoryPath,
27
+ } from "#core/stores/routine-memory.js";
26
28
  import { CHANNELS } from "#core/constants/channels.js";
27
29
  import {
28
- listRoutines,
29
- getRoutine,
30
- upsertRoutine,
31
- deleteRoutine,
32
- setEnabled,
33
30
  updateRunState,
34
- getDueRoutines,
35
31
  parseSchedule,
36
32
  computeNextRun,
37
33
  } from "#core/stores/routines.js";
38
-
39
- export {
40
- listRoutines,
41
- getRoutine,
42
- upsertRoutine,
43
- deleteRoutine,
44
- setEnabled,
45
- parseSchedule,
46
- computeNextRun,
47
- };
48
-
49
- const TICK_MS = 5_000;
50
- const nowIso = () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
34
+ import { nowIso } from "#core/util/time.js";
51
35
 
52
36
  // --------------------- handlers ---------------------------------------------
53
37
 
@@ -211,7 +195,7 @@ const HANDLERS = {
211
195
 
212
196
  // --------------------- pipeline: pre/post shell commands --------------------
213
197
 
214
- // Run a single shell command. Returns { exitCode, stdout, stderr }.
198
+ /** Run a single shell command. Returns { exitCode, stdout, stderr }. */
215
199
  function runShellCmd(cmd, env = {}, cwd = os.homedir()) {
216
200
  return new Promise((resolve) => {
217
201
  const child = spawn("sh", ["-c", cmd], {
@@ -228,13 +212,13 @@ function runShellCmd(cmd, env = {}, cwd = os.homedir()) {
228
212
  });
229
213
  }
230
214
 
231
- // Inject {{pre_output}} into a prompt string.
215
+ /** Inject {{pre_output}} into a prompt string. */
232
216
  function injectPreOutput(prompt, preOutput) {
233
217
  if (!prompt || typeof prompt !== "string") return prompt;
234
218
  return prompt.replace(/\{\{pre_output\}\}/g, preOutput || "");
235
219
  }
236
220
 
237
- // Determine whether to skip the LLM call based on skip_prompt_on + pre results.
221
+ /** Decide whether to skip the LLM call based on skip_prompt_on + pre results. */
238
222
  function shouldSkipPrompt(routine, preExitCode, preStdout) {
239
223
  const mode = routine.skip_prompt_on || "signal";
240
224
  if (mode === "always") return true;
@@ -245,10 +229,22 @@ function shouldSkipPrompt(routine, preExitCode, preStdout) {
245
229
  return false;
246
230
  }
247
231
 
248
- // --------------------- runtime: run one + loop ------------------------------
249
-
232
+ // --------------------- runtime: run one routine -----------------------------
233
+
234
+ /**
235
+ * Execute a single routine end-to-end (pre_commands → handler → post_commands)
236
+ * and persist last-run state. Pure with respect to process lifecycle — does NOT
237
+ * touch a timer, queue, or scheduler. Pure with respect to network — the
238
+ * super-agent / telegram handlers obviously go out, but the orchestration is
239
+ * sync from the caller's point of view via the returned promise.
240
+ *
241
+ * @param {object} ctx
242
+ * - project: ProjectManager entry (logMessage, path, storagePath)
243
+ * - projects, plugins, registries, globalConfig
244
+ * @param {object} routine The routine record from core/stores/routines.js
245
+ * @returns {object} { status, last_run_at, next_run_at, ...handler-result }
246
+ */
250
247
  export async function runRoutineNow(ctx, routine) {
251
- // Determine the working directory for shell commands.
252
248
  const cwd = ctx.project?.path || os.homedir();
253
249
  const storagePath = ctx.project?.storagePath || os.homedir();
254
250
 
@@ -263,31 +259,26 @@ export async function runRoutineNow(ctx, routine) {
263
259
  if (hasPreCmds) {
264
260
  const combinedOut = [];
265
261
  for (const rawCmd of routine.pre_commands) {
266
- // Resolve "artifact:<name>" shorthand to its absolute path.
267
262
  const cmd = resolveArtifactRef(rawCmd, storagePath);
268
263
  const { exitCode, stdout, stderr } = await runShellCmd(cmd, {}, cwd);
269
264
  combinedOut.push(stdout);
270
265
  if (stderr) combinedOut.push(stderr);
271
266
  preExitCode = exitCode;
272
267
  if (exitCode !== 0 && (routine.skip_prompt_on === "pre_failure" || routine.skip_prompt_on === "signal")) {
273
- // Stop running further pre_commands on failure when mode cares about exit code.
274
268
  break;
275
269
  }
276
270
  }
277
271
  preStdout = combinedOut.join("");
278
272
 
279
- // Write pre output to a temp file so post_commands can reference it via
280
- // $APX_PRE_OUTPUT_FILE even if the output is large.
281
273
  try {
282
274
  preOutputFile = path.join(os.tmpdir(), `apx-pre-${routine.name}-${Date.now()}.txt`);
283
275
  fs.writeFileSync(preOutputFile, preStdout);
284
276
  } catch { preOutputFile = null; }
285
277
  }
286
278
 
287
- // Env vars injected into post_commands and available in shell pre_commands output.
288
279
  const pipelineEnv = {
289
280
  APX_PRE_EXIT: String(preExitCode),
290
- APX_PRE_OUTPUT: preStdout.slice(0, 32_000), // guard against huge outputs
281
+ APX_PRE_OUTPUT: preStdout.slice(0, 32_000),
291
282
  APX_PRE_OUTPUT_FILE: preOutputFile || "",
292
283
  APX_ROUTINE: routine.name,
293
284
  };
@@ -300,7 +291,6 @@ export async function runRoutineNow(ctx, routine) {
300
291
  let errMsg = null;
301
292
 
302
293
  if (!skip) {
303
- // Inject {{pre_output}} into exec_agent and super_agent prompts.
304
294
  const enrichedRoutine = (hasPreCmds && preStdout)
305
295
  ? {
306
296
  ...routine,
@@ -344,11 +334,9 @@ export async function runRoutineNow(ctx, routine) {
344
334
  for (const rawCmd of routine.post_commands) {
345
335
  const cmd = resolveArtifactRef(rawCmd, storagePath);
346
336
  await runShellCmd(cmd, postEnv, cwd);
347
- // Post-command failures are logged but don't change routine status.
348
337
  }
349
338
  }
350
339
 
351
- // Cleanup temp file.
352
340
  if (preOutputFile) try { fs.unlinkSync(preOutputFile); } catch {}
353
341
 
354
342
  const lastRun = nowIso();
@@ -374,58 +362,3 @@ export async function runRoutineNow(ctx, routine) {
374
362
  });
375
363
  return { ...result, last_run_at: lastRun, next_run_at: next };
376
364
  }
377
-
378
- export class RoutineScheduler {
379
- constructor({ projects, plugins, registries, globalConfig, log }) {
380
- this.projects = projects;
381
- this.plugins = plugins;
382
- this.registries = registries;
383
- this.globalConfig = globalConfig;
384
- this.log = log || (() => {});
385
- this._timer = null;
386
- this._running = false;
387
- }
388
-
389
- start() {
390
- if (this._timer) return;
391
- this._timer = setInterval(
392
- () => this._tick().catch((e) => this.log(`routines tick error: ${e.message}`)),
393
- TICK_MS
394
- );
395
- this._timer.unref?.();
396
- }
397
-
398
- stop() {
399
- if (this._timer) {
400
- clearInterval(this._timer);
401
- this._timer = null;
402
- }
403
- }
404
-
405
- async _tick() {
406
- if (this._running) return;
407
- this._running = true;
408
- try {
409
- const nowStr = nowIso();
410
- for (const proj of this.projects.list().map((p) => this.projects.get(p.id))) {
411
- if (!proj) continue;
412
- const due = getDueRoutines(proj.storagePath, nowStr);
413
- for (const r of due) {
414
- this.log(`routine ${r.name} (${r.kind}) firing in project #${proj.id}`);
415
- await runRoutineNow(
416
- {
417
- project: proj,
418
- projects: this.projects,
419
- plugins: this.plugins,
420
- registries: this.registries,
421
- globalConfig: this.globalConfig,
422
- },
423
- r
424
- );
425
- }
426
- }
427
- } finally {
428
- this._running = false;
429
- }
430
- }
431
- }
@@ -0,0 +1,159 @@
1
+ ---
2
+ name: apc-context
3
+ description: "ALWAYS activate when the project has a .apc/ directory or AGENTS.md file. Do not wait to be asked. Read .apc/ before making any assumption about agents, memory, or project structure. Activate on: .apc/, AGENTS.md, 'which agents', 'list agents', 'agent context', 'who are the agents', any question about agents or memory in this project. IMPORTANT: if .apc/migrate.md exists, open the conversation with a migration offer before answering anything else. If the user declines, delete .apc/migrate.md immediately so it is not shown again."
4
+ homepage: https://github.com/agentprojectcontext/agentprojectcontext
5
+ ---
6
+
7
+ # Agent Project Context
8
+
9
+ This project uses APC. APC stores portable project context in `.apc/` and `AGENTS.md`.
10
+
11
+ APC does not store raw runtime sessions. Sessions, conversations, messages, caches, provider
12
+ threads, and private runtime memory stay in the IDE, CLI, daemon, or user-level store that created
13
+ them.
14
+
15
+ ## FIRST: check for pending migration
16
+
17
+ Before doing anything else, check if `.apc/migrate.md` exists:
18
+
19
+ ```bash
20
+ cat .apc/migrate.md 2>/dev/null
21
+ ```
22
+
23
+ If it exists, open with this offer before answering anything else:
24
+
25
+ > I see this project was initialized with Agent Project Context (APC).
26
+ >
27
+ > I found context files that may need migration:
28
+ > [list files from .apc/migrate.md]
29
+ >
30
+ > I can read them, separate durable project context from runtime/private state, and migrate only
31
+ > what belongs in APC.
32
+ >
33
+ > Want me to start?
34
+
35
+ If the user says no or later, delete `.apc/migrate.md` so the offer is not repeated.
36
+
37
+ ## Migration rule: think, do not copy
38
+
39
+ Read detected files first. Also read `AGENTS.md` if it exists.
40
+
41
+ Classify content:
42
+
43
+ | Content | Action |
44
+ |---|---|
45
+ | Agent definitions: name, model, description | Put in `.apc/agents/<name>.md` and/or `AGENTS.md` |
46
+ | Shared project rules, stack notes, commands, testing policy | Keep in `AGENTS.md` |
47
+ | Reusable instruction blocks | Move to `.apc/skills/<name>.md` |
48
+ | Durable safe facts useful to all contributors | Add to `.apc/agents/<name>/memory.md` only after curation |
49
+ | MCP expectations without secrets | Add to `.apc/mcps.json` |
50
+ | Raw sessions, transcripts, conversations, messages, tool logs | Do not move into `.apc/`; leave with source runtime |
51
+ | Secrets, tokens, credentials, private headers | Do not store in repository |
52
+ | IDE UI settings or personal aliases | Leave in IDE/user config |
53
+ | Instructions to store sessions under `.apc/` | Drop as obsolete |
54
+
55
+ After migration:
56
+
57
+ 1. Update `AGENTS.md` as the root project contract.
58
+ 2. Create or update `.apc/agents/`, `.apc/skills/`, `.apc/mcps.json` as needed.
59
+ 3. Do not create `.apc/**/sessions`, `.apc/messages`, or `.apc/conversations`.
60
+ 4. Delete obsolete source files only when their useful project context was migrated or intentionally dropped.
61
+ 5. Delete `.apc/migrate.md`.
62
+ 6. Summarize what moved, what stayed local, and what was dropped.
63
+
64
+ ## APC structure
65
+
66
+ ```text
67
+ AGENTS.md ← root project contract
68
+ .apc/
69
+ project.json ← project metadata
70
+ .gitignore ← safety guard
71
+ agents/<name>.md ← agent definition
72
+ agents/<name>/memory.md ← optional curated project memory
73
+ skills/<name>.md ← reusable project instructions
74
+ mcps.json ← MCP hints without secrets
75
+ ```
76
+
77
+ Do not store:
78
+
79
+ ```text
80
+ .apc/agents/<name>/sessions/
81
+ .apc/sessions/
82
+ .apc/conversations/
83
+ .apc/messages/
84
+ .apc/cache/
85
+ .apc/tmp/
86
+ .apc/private/
87
+ .apc/secrets/
88
+ ```
89
+
90
+ ## Visibility rules
91
+
92
+ | Data | Visibility | Commit? |
93
+ |---|---|---|
94
+ | Agent definitions, skills, project rules | `stable` / `project` | Yes |
95
+ | Curated safe `memory.md` | `project` | Yes, if team-safe |
96
+ | MCP hints without secrets | `project` | Yes |
97
+ | Sessions, conversations, messages | `local` | No; runtime-owned |
98
+ | Secrets, tokens, `*.secret.json`, `*.env` | `private` | Never |
99
+ | Caches, temp files, databases | `ephemeral` | No |
100
+
101
+ ## Operating rules
102
+
103
+ 1. Read `AGENTS.md` and relevant `.apc/` files before assuming project context.
104
+ 2. Read agent definitions from `.apc/agents/<name>.md` when present.
105
+ 3. Read curated project memory from `.apc/agents/<name>/memory.md` when present.
106
+ 4. Write only durable, safe, curated facts to APC memory.
107
+ 5. Never write raw sessions, transcripts, messages, conversations, or tool logs into `.apc/`.
108
+ 6. Keep secrets out of APC and out of git.
109
+ 7. Treat `.apc/mcps.json` as MCP configuration hints, not as an MCP implementation.
110
+
111
+ ## Normalization
112
+
113
+ If agent formats are broken or use legacy fields (role, skills in YAML), offer to normalize:
114
+
115
+ ```yaml
116
+ ---
117
+ name: agent-name
118
+ model: inherit
119
+ description: Semantic activation trigger
120
+ ---
121
+ ```
122
+
123
+ Identify and fix inconsistencies in `model` (use technical IDs or `inherit`) and ensure `description` is present for semantic activation.
124
+
125
+ ## Sessions
126
+
127
+ Sessions belong to the runtime that created them.
128
+
129
+ Examples:
130
+
131
+ ```text
132
+ Codex runtime storage
133
+ Claude Code runtime storage
134
+ OpenCode runtime storage
135
+ ~/.apx/projects/<project-id>/agents/<name>/sessions/
136
+ ```
137
+
138
+ At task end, provide the user a concise result. If project memory should be updated, write a short
139
+ sanitized fact to `.apc/agents/<name>/memory.md` only when useful and safe.
140
+
141
+ ## APX
142
+
143
+ Read `.apc/project.json` if present. It may contain an `apx` field:
144
+
145
+ - `"installed"`: APX is available; use `apx` commands when useful.
146
+ - `"declined"`: user chose not to install; do not suggest or run APX.
147
+ - missing or `null`: unknown; do not assume APX is available.
148
+
149
+ If APX is installed, it may manage runtime state outside the repository:
150
+
151
+ ```text
152
+ ~/.apx/projects/<project-id>/
153
+ ```
154
+
155
+ APX can provide a local daemon, MCP management, Telegram bridge, routines, and runtime dispatch
156
+ across Codex, Claude Code, OpenCode, Aider, or direct LLM engines. Those are APX runtime features,
157
+ not APC portable-core requirements.
158
+
159
+ Never use APX to write secrets or raw sessions into `.apc/`.
@@ -0,0 +1,95 @@
1
+ ---
2
+ name: apx
3
+ description: "APX CLI umbrella — which sub-skill handles each operation (sessions, MCPs, routines, tasks, telegram, projects, agents, runtimes). Activate when the user mentions `apx`, the APX daemon, or wants to coordinate/run/delegate agents. Not for `.apc/` alone (use apc-context). Triggers: 'apx', 'apx run', 'apx daemon', 'coordinate agents', 'apx help'."
4
+ homepage: https://github.com/agentprojectcontext/apx
5
+ ---
6
+
7
+ # APX — Agent Project Context Runtime
8
+
9
+ APX is a daemon (`127.0.0.1:7430`, auto-starts on first call) that turns external coding CLIs (Claude Code, Codex, OpenCode, Aider, …) and configurable agents into a unified orchestration surface.
10
+
11
+ It reads APC project context from `.apc/` (committed) but keeps runtime state outside the repo under `~/.apx/projects/<project-id>/`. The super-agent has a default workspace at `~/.apx/projects/default` for system-level work.
12
+
13
+ ---
14
+
15
+ ## When to use APX (vs. spawning a subagent natively)
16
+
17
+ If you can spawn a subagent natively in the IDE you're in (Claude Code, Cursor, …) — **do that**. No APX needed.
18
+
19
+ Use APX when:
20
+ - The user explicitly asks for a specific external runtime ("run this in Codex", "delegate to OpenCode").
21
+ - You need to run an agent in a runtime different from the one you're in.
22
+ - You're orchestrating from outside any IDE (a script, Telegram bot, CI, routine).
23
+
24
+ ---
25
+
26
+ ## Sub-skill index — open the one that matches the task
27
+
28
+ | Topic | Sub-skill | When |
29
+ |-------|-----------|------|
30
+ | Delegate to an external coding CLI | **apx-runtime** | `apx run <agent> --runtime claude-code\|codex\|...` |
31
+ | List / read / resume / summarise / continue sessions across engines | **apx-sessions** | `apx session resume`, `apx sessions list`, "import a codex session" |
32
+ | Use a registered MCP tool | **apx-mcp** | `apx mcp run`, "call MCP filesystem", "the MCP is failing" |
33
+ | Add / configure / use a project agent | **apx-agent** | "add an agent", "import from vault", per-agent model, agent memory |
34
+ | Register / list / configure a project | **apx-project** | "register this project", `apx project list`, per-project config |
35
+ | Per-project TODO list | **apx-task** | "add a task", "remind me to…", "what's pending" |
36
+ | Scheduled / recurring agents | **apx-routine** | `apx routine add`, every-5m, cron-like jobs |
37
+ | Telegram I/O | **apx-telegram** | configure bot, channels, send a message |
38
+ | Voice channel (TTS, speech) — *optional* | **apx-voice** | only if voice is being set up |
39
+ | Build a new MCP server — *internal/dev* | **apx-mcp-builder** | when developing a brand-new MCP from scratch |
40
+ | Author a new APX skill — *internal/dev* | **apx-skill-builder** | when adding to APX itself |
41
+
42
+ > Sub-skills marked *internal/dev* are not pushed to IDE skill dirs by default. They live in the APX repo and are loaded by APX itself; install one to your IDE with `apx skills add <slug> --global` if you want it there.
43
+
44
+ ---
45
+
46
+ ## Generic patterns (apply to every sub-skill)
47
+
48
+ ### Verify commands before recommending them
49
+
50
+ Do not invent APX subcommands. Confirm exact CLI form with `apx --help` or `apx <command> --help` before telling another runtime to invoke APX. Avoid guessed aliases (e.g. `apx send-telegram` is *not* a thing — see apx-telegram).
51
+
52
+ ### `APC_RESULT` contract — structured return values
53
+
54
+ When you want APX to capture a structured value from an agent (any runtime), instruct the agent to print on its last meaningful line:
55
+
56
+ ```
57
+ APC_RESULT: <one-line value>
58
+ ```
59
+
60
+ APX's `extractApfResult()` parses that and stores it as the session's `result` field. Useful for automation, routines, and CI.
61
+
62
+ ### Tool permissions
63
+
64
+ ```bash
65
+ apx permission show
66
+ apx permission set automatico # total | automatico | permiso
67
+ ```
68
+
69
+ `automatico` runs read/list/safe shell checks directly and asks before destructive shell, MCP, runtime, outbound, config, or filesystem mutation actions.
70
+
71
+ ### Memory
72
+
73
+ Write memory only for durable, safe project facts. Do not store raw transcripts or secrets.
74
+
75
+ ```bash
76
+ apx memory <slug> # read agent's memory.md
77
+ apx memory <slug> --append "<fact>" # append a durable note
78
+ apx memory <slug> --replace < file.md # replace entire memory from stdin
79
+ ```
80
+
81
+ ### Observe activity
82
+
83
+ ```bash
84
+ apx messages tail # last 50 messages, all channels
85
+ apx messages chat --channel telegram -n 20 # readable chat view
86
+ apx messages tail --channel runtime --agent <slug> -n 20
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Anti-patterns
92
+
93
+ - Don't activate APX-sessions inside a request that's purely about `apx run` orchestration — use apx-runtime.
94
+ - Don't activate apx-mcp-builder unless the user is actually authoring a new MCP server (it's a deep developer guide, not a usage guide).
95
+ - Don't push state to `.apc/` that belongs in `~/.apx/projects/<id>/` (sessions, conversations, runtime logs).
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: apx-mcp
3
+ description: How to register, list, debug, and scope MCP servers in APX. Use BEFORE adding any MCP — three scopes (shared/runtime/global) with different commit and secrecy semantics.
4
+ ---
5
+
6
+ # apx-mcp
7
+
8
+ APX exposes Model Context Protocol (MCP) servers to agents. Three scopes, each in a different file with different rules:
9
+
10
+ | Scope | File | Committed? | Secrets OK? | When |
11
+ |---|---|---|---|---|
12
+ | `shared` | `<repo>/.apc/mcps.json` | yes | **no** | Team-wide MCPs (filesystem, brave, github public) |
13
+ | `runtime` | `~/.apx/projects/<apxId>/mcps.json` (chmod 0600) | no | yes | Per-project local — tokens, machine-specific endpoints |
14
+ | `global` | `~/.apx/mcps.json` | n/a | yes | Machine-wide — not tied to any project |
15
+
16
+ Resolution priority when a name appears in more than one: **runtime > shared > global**. Conflicts surface in `apx mcp check`.
17
+
18
+ ## Concrete CLI calls
19
+
20
+ ```bash
21
+ # List (all scopes, this is the default)
22
+ apx mcp list --project iacrmar
23
+ apx mcp list --scope runtime --project iacrmar
24
+ apx mcp list --scope shared --project iacrmar
25
+ apx mcp list --scope global
26
+
27
+ # Inspect sources and conflicts
28
+ apx mcp check --project iacrmar
29
+
30
+ # Add — shared (commit to repo)
31
+ apx mcp add filesystem --command npx --project iacrmar \
32
+ -- -y @modelcontextprotocol/server-filesystem .
33
+
34
+ # Add — runtime (per-project, local, secrets safe)
35
+ apx mcp add github --scope runtime --project iacrmar \
36
+ --command npx --env GITHUB_TOKEN=ghp_xxx \
37
+ -- -y @modelcontextprotocol/server-github
38
+
39
+ # Add — global (machine-wide, not tied to a project)
40
+ apx mcp add brave --scope global \
41
+ --command npx --env BRAVE_API_KEY=BSAxxx \
42
+ -- -y @modelcontextprotocol/server-brave-search
43
+
44
+ # Remove (pass --scope when the MCP isn't in the default scope:
45
+ # shared inside an APC project, else global)
46
+ apx mcp remove filesystem --project iacrmar
47
+ apx mcp remove github --scope runtime --project iacrmar
48
+
49
+ # Toggle (defaults to the scope that owns the MCP)
50
+ apx mcp enable filesystem --project iacrmar
51
+ apx mcp disable filesystem --project iacrmar
52
+
53
+ # Call a tool through the daemon (useful for debugging)
54
+ apx mcp run filesystem read_file '{"path":"README.md"}'
55
+ ```
56
+
57
+ ## When the user asks for a new MCP
58
+
59
+ Decision tree:
60
+ 1. **Has secrets / tokens?** → `runtime` scope. Always.
61
+ 2. **Is part of the project's shared dev environment?** → `shared` (committed).
62
+ 3. **Used across all your projects?** → `global`.
63
+
64
+ Default if none is obvious: `shared` when inside an APC project, `global` outside.
65
+
66
+ ## Common command shapes by transport
67
+
68
+ ```bash
69
+ # stdio MCP (most common — npx, uvx, node, python)
70
+ apx mcp add <name> --command npx -- -y <package-or-flag-list>
71
+ apx mcp add <name> --command uvx -- <python-cli-name>
72
+ apx mcp add <name> --command python -- /abs/path/to/server.py
73
+
74
+ # Env vars (one --env per var)
75
+ apx mcp add <name> --command npx \
76
+ --env GITHUB_TOKEN=ghp_xxx \
77
+ --env GITHUB_OWNER=manuel \
78
+ -- -y @modelcontextprotocol/server-github
79
+ ```
80
+
81
+ Anything after `--` is forwarded verbatim as args to the command. Quote carefully.
82
+
83
+ ## Anti-examples
84
+
85
+ ```bash
86
+ # DON'T put tokens in shared scope. It commits.
87
+ apx mcp add github --scope shared --env GITHUB_TOKEN=ghp_xxx ...
88
+ # ↑ Token ends up in .apc/mcps.json in your repo. Use --scope runtime.
89
+
90
+ # DON'T remove an MCP from the wrong scope.
91
+ apx mcp remove github # if github lives in runtime, this errors with a hint
92
+ # ↑ Daemon returns 409 with the right scope to use.
93
+
94
+ # DON'T expect IDE-foreign configs (~/.cursor/mcps.json, ~/.claude/mcps.json) to be
95
+ # removable via apx mcp remove. APX reads them as advisory (source=cursor/claude/etc)
96
+ # but won't write them. Edit the IDE config directly.
97
+ ```
98
+
99
+ ## Debugging connection issues
100
+
101
+ ```bash
102
+ apx mcp check --project iacrmar # what scopes APX sees + which files exist
103
+ apx mcp run <name> <tool> '{...}' # spawn the server and call a tool for real
104
+ apx log -f # tail unified log for spawn errors
105
+ ```
106
+
107
+ A server that "doesn't show tools" usually means: the command failed to start (env vars missing, package not found), or the server crashed during initialize. The unified log has the stderr buffer.
108
+
109
+ > `apx mcp tools <name>` is a placeholder stub (prints a "coming in v0.2" notice, lists nothing). To verify a server actually spawns, call a tool with `apx mcp run`.
110
+
111
+ ## Don't
112
+
113
+ - Don't mix scopes for the same MCP name unless you actually want shadowing. The result is "the one with highest priority wins, others stay invisible."
114
+ - Don't edit `~/.apx/projects/<id>/mcps.json` by hand; use `apx mcp add --scope runtime`. The file is chmod 0600 — the CLI keeps it that way.
115
+ - Don't add tokens via `--env KEY=` inline if your shell history is public. Set them in your shell first, then `--env KEY=$KEY`.
116
+ - Don't forget to `apx daemon reload` after editing config — actually `apx mcp` does this for you, but if you hand-edited the JSON, it's manual.
@@ -1,4 +1,5 @@
1
1
  ---
2
+ scope: internal
2
3
  name: claude-code
3
4
  description: "Activate ONLY when the user explicitly mentions Claude Code, Claude CLI, claude command, Anthropic Claude Code, installing Claude Code, using Claude Code, or APX runtime claude-code. Do not activate for generic Claude model discussion."
4
5
  homepage: https://docs.anthropic.com/en/docs/claude-code
@@ -1,4 +1,5 @@
1
1
  ---
2
+ scope: internal
2
3
  name: codex-cli
3
4
  description: "Activate ONLY when the user explicitly mentions Codex CLI, OpenAI Codex, @openai/codex, codex command, codex exec, installing Codex, using Codex, ~/.codex, or APX runtime codex."
4
5
  homepage: https://developers.openai.com/codex
@@ -1,4 +1,5 @@
1
1
  ---
2
+ scope: internal
2
3
  name: opencode-cli
3
4
  description: "Activate ONLY when the user explicitly mentions OpenCode, opencode command, installing OpenCode, using OpenCode, OpenCode provider setup, or APX runtime opencode."
4
5
  homepage: https://opencode.ai/docs
@@ -1,4 +1,5 @@
1
1
  ---
2
+ scope: internal
2
3
  name: openrouter
3
4
  description: "Activate ONLY when the user explicitly mentions OpenRouter, OPENROUTER_API_KEY, OpenRouter models, installing OpenRouter provider config, or using OpenRouter with APX, OpenCode, LiteLLM, or an OpenAI-compatible client."
4
5
  homepage: https://openrouter.ai/docs
@@ -1,7 +1,7 @@
1
1
  // Best-effort detection of installed agent CLIs and LLM runners.
2
2
  // We just probe the binary with `--version` (or equivalent) and don't fail if
3
3
  // it isn't there — caller decides what to do with absence.
4
- import { runProcess } from "./runtimes/_spawn.js";
4
+ import { runProcess } from "#host/daemon/runtimes/_spawn.js";
5
5
 
6
6
  const PROBES = [
7
7
  // Coding-agent CLIs (runtimes/)