@agentprojectcontext/apx 1.0.3
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.
- package/LICENSE +21 -0
- package/README.md +142 -0
- package/package.json +52 -0
- package/skills/apx/SKILL.md +77 -0
- package/src/cli/commands/a2a.js +66 -0
- package/src/cli/commands/agent.js +181 -0
- package/src/cli/commands/chat.js +84 -0
- package/src/cli/commands/command.js +42 -0
- package/src/cli/commands/config.js +56 -0
- package/src/cli/commands/daemon.js +148 -0
- package/src/cli/commands/exec.js +56 -0
- package/src/cli/commands/identity.js +146 -0
- package/src/cli/commands/init.js +23 -0
- package/src/cli/commands/mcp.js +147 -0
- package/src/cli/commands/memory.js +69 -0
- package/src/cli/commands/messages.js +61 -0
- package/src/cli/commands/plugins.js +23 -0
- package/src/cli/commands/project.js +124 -0
- package/src/cli/commands/routine.js +99 -0
- package/src/cli/commands/runtime.js +64 -0
- package/src/cli/commands/session.js +387 -0
- package/src/cli/commands/skills.js +153 -0
- package/src/cli/commands/telegram.js +48 -0
- package/src/cli/http.js +102 -0
- package/src/cli/index.js +481 -0
- package/src/cli/postinstall.js +25 -0
- package/src/core/apc-context-skill.md +150 -0
- package/src/core/apx-skill.md +78 -0
- package/src/core/config.js +129 -0
- package/src/core/identity.js +23 -0
- package/src/core/messages-store.js +421 -0
- package/src/core/parser.js +217 -0
- package/src/core/routines-store.js +144 -0
- package/src/core/scaffold.js +417 -0
- package/src/core/session-store.js +36 -0
- package/src/daemon/apc-runtime-context.js +123 -0
- package/src/daemon/api.js +946 -0
- package/src/daemon/compact.js +140 -0
- package/src/daemon/conversations.js +108 -0
- package/src/daemon/db.js +81 -0
- package/src/daemon/engines/anthropic.js +58 -0
- package/src/daemon/engines/gemini.js +55 -0
- package/src/daemon/engines/index.js +65 -0
- package/src/daemon/engines/mock.js +18 -0
- package/src/daemon/engines/ollama.js +66 -0
- package/src/daemon/engines/openai.js +58 -0
- package/src/daemon/env-detect.js +69 -0
- package/src/daemon/index.js +156 -0
- package/src/daemon/mcp-runner.js +218 -0
- package/src/daemon/mcp-sources.js +114 -0
- package/src/daemon/plugins/index.js +91 -0
- package/src/daemon/plugins/telegram.js +549 -0
- package/src/daemon/project-config.js +98 -0
- package/src/daemon/routines.js +211 -0
- package/src/daemon/runtimes/_spawn.js +44 -0
- package/src/daemon/runtimes/aider.js +32 -0
- package/src/daemon/runtimes/claude-code.js +60 -0
- package/src/daemon/runtimes/codex.js +30 -0
- package/src/daemon/runtimes/index.js +39 -0
- package/src/daemon/runtimes/opencode.js +28 -0
- package/src/daemon/smoke.js +54 -0
- package/src/daemon/super-agent-tools.js +539 -0
- package/src/daemon/super-agent.js +188 -0
- package/src/daemon/thinking.js +45 -0
- package/src/daemon/tool-call-parser.js +116 -0
- package/src/daemon/wakeup.js +92 -0
- package/src/mcp/index.js +220 -0
package/src/cli/index.js
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// apx — unified CLI for APC (Agent Project Framework).
|
|
3
|
+
// ESM, Node >= 18.
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
|
|
8
|
+
import { cmdInit } from "./commands/init.js";
|
|
9
|
+
import {
|
|
10
|
+
cmdProjectAdd,
|
|
11
|
+
cmdProjectList,
|
|
12
|
+
cmdProjectRemove,
|
|
13
|
+
cmdProjectRebuild,
|
|
14
|
+
} from "./commands/project.js";
|
|
15
|
+
import {
|
|
16
|
+
cmdAgentAdd,
|
|
17
|
+
cmdAgentList,
|
|
18
|
+
cmdAgentGet,
|
|
19
|
+
cmdAgentImport,
|
|
20
|
+
cmdAgentVaultList,
|
|
21
|
+
cmdAgentVaultAdd,
|
|
22
|
+
} from "./commands/agent.js";
|
|
23
|
+
import { cmdMemory } from "./commands/memory.js";
|
|
24
|
+
import {
|
|
25
|
+
cmdSessionNew,
|
|
26
|
+
cmdSessionList,
|
|
27
|
+
cmdSessionGet,
|
|
28
|
+
cmdSessionUpdate,
|
|
29
|
+
cmdSessionClose,
|
|
30
|
+
cmdSessionCheck,
|
|
31
|
+
cmdSessionCloseStale,
|
|
32
|
+
cmdSessionResume,
|
|
33
|
+
cmdSessionCompact,
|
|
34
|
+
} from "./commands/session.js";
|
|
35
|
+
import {
|
|
36
|
+
cmdMcpList,
|
|
37
|
+
cmdMcpAdd,
|
|
38
|
+
cmdMcpRemove,
|
|
39
|
+
cmdMcpEnable,
|
|
40
|
+
cmdMcpDisable,
|
|
41
|
+
cmdMcpRun,
|
|
42
|
+
cmdMcpTools,
|
|
43
|
+
cmdMcpCheck,
|
|
44
|
+
} from "./commands/mcp.js";
|
|
45
|
+
import {
|
|
46
|
+
cmdDaemonStart,
|
|
47
|
+
cmdDaemonStop,
|
|
48
|
+
cmdDaemonStatus,
|
|
49
|
+
cmdDaemonLogs,
|
|
50
|
+
} from "./commands/daemon.js";
|
|
51
|
+
import {
|
|
52
|
+
cmdTelegramSend,
|
|
53
|
+
cmdTelegramStatus,
|
|
54
|
+
cmdTelegramSetup,
|
|
55
|
+
} from "./commands/telegram.js";
|
|
56
|
+
import { cmdMessagesTail, cmdMessagesSearch } from "./commands/messages.js";
|
|
57
|
+
import { cmdExec } from "./commands/exec.js";
|
|
58
|
+
import {
|
|
59
|
+
cmdChat,
|
|
60
|
+
cmdConversationsList,
|
|
61
|
+
cmdConversationsGet,
|
|
62
|
+
} from "./commands/chat.js";
|
|
63
|
+
import { cmdRun, cmdEnvDetect } from "./commands/runtime.js";
|
|
64
|
+
import { cmdSend, cmdConnections } from "./commands/a2a.js";
|
|
65
|
+
import {
|
|
66
|
+
cmdConfigShow,
|
|
67
|
+
cmdConfigSet,
|
|
68
|
+
cmdConfigUnset,
|
|
69
|
+
} from "./commands/config.js";
|
|
70
|
+
import { cmdPluginsList, cmdPluginStatus } from "./commands/plugins.js";
|
|
71
|
+
import { cmdSkillsAdd, cmdSkillsList, cmdSkillsStatus } from "./commands/skills.js";
|
|
72
|
+
import { cmdIdentity } from "./commands/identity.js";
|
|
73
|
+
import { cmdCommandList, cmdCommandShow } from "./commands/command.js";
|
|
74
|
+
import {
|
|
75
|
+
cmdRoutineList,
|
|
76
|
+
cmdRoutineGet,
|
|
77
|
+
cmdRoutineAdd,
|
|
78
|
+
cmdRoutineRemove,
|
|
79
|
+
cmdRoutineEnable,
|
|
80
|
+
cmdRoutineDisable,
|
|
81
|
+
cmdRoutineRun,
|
|
82
|
+
} from "./commands/routine.js";
|
|
83
|
+
|
|
84
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
85
|
+
const __dirname = path.dirname(__filename);
|
|
86
|
+
const VERSION = JSON.parse(
|
|
87
|
+
fs.readFileSync(path.join(__dirname, "..", "..", "package.json"), "utf8")
|
|
88
|
+
).version;
|
|
89
|
+
|
|
90
|
+
const HELP = `apx — Agent Project Framework
|
|
91
|
+
|
|
92
|
+
Usage:
|
|
93
|
+
apx <command> [<subcommand>] [args] [--flags]
|
|
94
|
+
|
|
95
|
+
Bootstrap:
|
|
96
|
+
apx init [path] [--name "<name>"] initialize an APC project
|
|
97
|
+
apx project add <path> register a project with the daemon
|
|
98
|
+
apx project list
|
|
99
|
+
apx project remove <path|id>
|
|
100
|
+
apx project rebuild [<path|id>] rebuild SQLite cache from filesystem
|
|
101
|
+
|
|
102
|
+
Agents:
|
|
103
|
+
apx agent add <slug> [--role R] [--model M] [--skills a,b] [--language es-AR] [--description D]
|
|
104
|
+
apx agent list
|
|
105
|
+
apx agent get <slug>
|
|
106
|
+
|
|
107
|
+
Memory:
|
|
108
|
+
apx memory <slug> print memory.md
|
|
109
|
+
apx memory <slug> --append "<note>" append under "## Recent context"
|
|
110
|
+
apx memory <slug> --replace replace from stdin
|
|
111
|
+
|
|
112
|
+
Sessions:
|
|
113
|
+
apx session new <slug> --title "<title>" [--task-ref REF] [--body - | --body "<text>"]
|
|
114
|
+
apx session list [<slug>] [--last N]
|
|
115
|
+
apx session get <id> [--body]
|
|
116
|
+
apx session update <id> [--status S] [--result R] [--title T] [--task-ref REF]
|
|
117
|
+
apx session close <id> [--result "<text>"]
|
|
118
|
+
apx session check anti-collision: exit 1 if active session
|
|
119
|
+
apx session close-stale auto-close sessions older than 1h
|
|
120
|
+
apx session resume <id> [--summary] [--full] read APC session + external transcript (Claude Code, etc.)
|
|
121
|
+
apx session compact <agent> [--conversation <id>] collapse conversation history into a dense summary
|
|
122
|
+
|
|
123
|
+
MCPs:
|
|
124
|
+
apx mcp list
|
|
125
|
+
apx mcp add <name> --command <cmd> [args...] [--env KEY=VAL]
|
|
126
|
+
apx mcp remove <name>
|
|
127
|
+
apx mcp enable <name>
|
|
128
|
+
apx mcp disable <name>
|
|
129
|
+
apx mcp run <name> <tool> [<json-args>] call a tool through the daemon
|
|
130
|
+
apx mcp tools <name> list tools (v0.2)
|
|
131
|
+
apx mcp check audit multi-source merge (v0.2)
|
|
132
|
+
|
|
133
|
+
Daemon:
|
|
134
|
+
apx daemon start
|
|
135
|
+
apx daemon stop
|
|
136
|
+
apx daemon status
|
|
137
|
+
apx daemon logs [--tail N]
|
|
138
|
+
|
|
139
|
+
Telegram:
|
|
140
|
+
apx telegram send "<text>" [--chat <id>]
|
|
141
|
+
apx telegram status
|
|
142
|
+
apx telegram setup
|
|
143
|
+
|
|
144
|
+
Messages:
|
|
145
|
+
apx messages tail [--agent <slug>] [--channel <ch>] [-n 50] [--global]
|
|
146
|
+
global channels (telegram, direct, whatsapp) → ~/.apx/messages/<ch>/
|
|
147
|
+
project channels (runtime, a2a, exec) → <project>/.apc/messages/
|
|
148
|
+
apx messages search "<query>"
|
|
149
|
+
|
|
150
|
+
LLM engines (v0.2):
|
|
151
|
+
apx exec <agent> "<prompt>" [--model <id>] [--max-tokens N] [--temperature T]
|
|
152
|
+
one-shot LLM call (Anthropic/OpenAI/Ollama/Gemini/mock)
|
|
153
|
+
apx chat <agent> [--conversation <id>] [--model <id>] interactive REPL
|
|
154
|
+
apx conversations list <agent>
|
|
155
|
+
apx conversations get <agent> <id>
|
|
156
|
+
|
|
157
|
+
External agent runtimes (v0.3):
|
|
158
|
+
apx run <agent> --runtime <id> "<prompt>" [--timeout <s>]
|
|
159
|
+
claude-code | codex | opencode | aider
|
|
160
|
+
apx env detect which agent CLIs are installed
|
|
161
|
+
|
|
162
|
+
Agent-to-agent (v0.4):
|
|
163
|
+
apx send <from> <to> "<body>" [--deliver] log a2a message; --deliver runs target's engine
|
|
164
|
+
apx connections <agent> mental map: who/how/when this agent talked
|
|
165
|
+
|
|
166
|
+
Project config (.apc/config.json):
|
|
167
|
+
apx config show [--effective | --only-overrides] show project overrides + effective config
|
|
168
|
+
apx config set <key.path> <value> set a key in .apc/config.json (JSON-aware)
|
|
169
|
+
apx config unset <key.path> remove a key from .apc/config.json
|
|
170
|
+
|
|
171
|
+
Global flags:
|
|
172
|
+
--project <name|id|path> pin commands to a specific project
|
|
173
|
+
(or use sugar: apx project <name|id> <subcommand...>)
|
|
174
|
+
|
|
175
|
+
Plugins:
|
|
176
|
+
apx plugins list show loaded plugins and their status
|
|
177
|
+
apx plugins status <id> detailed status of one plugin (e.g. telegram)
|
|
178
|
+
|
|
179
|
+
Routines (per-project scheduled tasks):
|
|
180
|
+
apx routine list list routines + next/last run
|
|
181
|
+
apx routine add <name> --kind <K> --schedule <S> [--spec '<json>' | --K=V...]
|
|
182
|
+
kinds: heartbeat | exec_agent | telegram | shell
|
|
183
|
+
schedule: every:60s | every:5m | every:1h | once:<iso>
|
|
184
|
+
apx routine get <name>
|
|
185
|
+
apx routine run <name> run now (manual trigger, ignores schedule)
|
|
186
|
+
apx routine enable <name> | apx routine disable <name>
|
|
187
|
+
apx routine remove <name>
|
|
188
|
+
|
|
189
|
+
Commands (.apc/commands/):
|
|
190
|
+
apx command list list workflow commands
|
|
191
|
+
apx command show <name> print command content
|
|
192
|
+
|
|
193
|
+
Skills (IDE integration):
|
|
194
|
+
apx skills add [<target>...] install APX skill into project IDE rule files
|
|
195
|
+
targets: claude-code cursor windsurf copilot trae
|
|
196
|
+
(omit targets to install all)
|
|
197
|
+
apx skills add --global install to ~/.claude/skills/ ~/.cursor/skills/ ~/.agents/skills/
|
|
198
|
+
picked up by Claude Code, Cursor, Codex, Antigravity globally
|
|
199
|
+
apx skills list list skills in .apc/skills/
|
|
200
|
+
apx skills status show which IDE targets are installed (project + global)
|
|
201
|
+
|
|
202
|
+
Other:
|
|
203
|
+
apx --help
|
|
204
|
+
apx --version
|
|
205
|
+
|
|
206
|
+
Docs: https://agentprojectcontext.com
|
|
207
|
+
`;
|
|
208
|
+
|
|
209
|
+
function parseArgs(argv) {
|
|
210
|
+
const args = { _: [], flags: {} };
|
|
211
|
+
for (let i = 0; i < argv.length; i++) {
|
|
212
|
+
const a = argv[i];
|
|
213
|
+
if (a === "--") {
|
|
214
|
+
// everything after `--` is positional
|
|
215
|
+
args._.push(...argv.slice(i + 1));
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
if (a.startsWith("--")) {
|
|
219
|
+
const key = a.slice(2);
|
|
220
|
+
const next = argv[i + 1];
|
|
221
|
+
if (next === undefined || next.startsWith("--")) {
|
|
222
|
+
args.flags[key] = true;
|
|
223
|
+
} else {
|
|
224
|
+
// support repeated flags (e.g. --env A=1 --env B=2)
|
|
225
|
+
if (Object.prototype.hasOwnProperty.call(args.flags, key)) {
|
|
226
|
+
if (Array.isArray(args.flags[key])) args.flags[key].push(next);
|
|
227
|
+
else args.flags[key] = [args.flags[key], next];
|
|
228
|
+
} else {
|
|
229
|
+
args.flags[key] = next;
|
|
230
|
+
}
|
|
231
|
+
i++;
|
|
232
|
+
}
|
|
233
|
+
} else if (a === "-n") {
|
|
234
|
+
args.flags.n = argv[++i];
|
|
235
|
+
} else {
|
|
236
|
+
args._.push(a);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return args;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function die(msg, code = 1) {
|
|
243
|
+
process.stderr.write(`apx: ${msg}\n`);
|
|
244
|
+
process.exit(code);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const argv = process.argv.slice(2);
|
|
248
|
+
|
|
249
|
+
if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h" || argv[0] === "help") {
|
|
250
|
+
process.stdout.write(HELP);
|
|
251
|
+
process.exit(0);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (argv[0] === "--version" || argv[0] === "-v") {
|
|
255
|
+
console.log(VERSION);
|
|
256
|
+
process.exit(0);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async function dispatch(cmd, rest) {
|
|
260
|
+
switch (cmd) {
|
|
261
|
+
case "init":
|
|
262
|
+
cmdInit(parseArgs(rest));
|
|
263
|
+
break;
|
|
264
|
+
|
|
265
|
+
case "project": {
|
|
266
|
+
const sub = rest[0];
|
|
267
|
+
const a = parseArgs(rest.slice(1));
|
|
268
|
+
const PROJECT_SUBCOMMANDS = new Set([
|
|
269
|
+
"add", "list", "ls", "remove", "rm", "rebuild",
|
|
270
|
+
]);
|
|
271
|
+
if (sub === "add") await cmdProjectAdd(a);
|
|
272
|
+
else if (sub === "list" || sub === "ls") await cmdProjectList();
|
|
273
|
+
else if (sub === "remove" || sub === "rm") await cmdProjectRemove(a);
|
|
274
|
+
else if (sub === "rebuild") await cmdProjectRebuild(a);
|
|
275
|
+
else if (sub && !PROJECT_SUBCOMMANDS.has(sub)) {
|
|
276
|
+
// Sugar: `apx project <name|id> <subcommand...>` runs the inner
|
|
277
|
+
// subcommand with --project=<name|id> appended.
|
|
278
|
+
// apx project testing mcp list → apx mcp list --project testing
|
|
279
|
+
// apx project 2 routine list → apx routine list --project 2
|
|
280
|
+
const innerCmd = rest[1];
|
|
281
|
+
if (!innerCmd) die(`apx project ${sub}: missing subcommand`);
|
|
282
|
+
const innerRest = [...rest.slice(2), "--project", sub];
|
|
283
|
+
await dispatch(innerCmd, innerRest);
|
|
284
|
+
}
|
|
285
|
+
else die(`unknown project subcommand: ${sub || "(none)"}`);
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
case "agent": {
|
|
290
|
+
const sub = rest[0];
|
|
291
|
+
const a = parseArgs(rest.slice(1));
|
|
292
|
+
if (sub === "add") await cmdAgentAdd(a);
|
|
293
|
+
else if (sub === "list" || sub === "ls") cmdAgentList();
|
|
294
|
+
else if (sub === "get" || sub === "show") cmdAgentGet(a);
|
|
295
|
+
else if (sub === "import") await cmdAgentImport(a);
|
|
296
|
+
else if (sub === "vault") {
|
|
297
|
+
const vsub = a._[0];
|
|
298
|
+
const va = { ...a, _: a._.slice(1) };
|
|
299
|
+
if (vsub === "list" || vsub === "ls") cmdAgentVaultList();
|
|
300
|
+
else if (vsub === "add") await cmdAgentVaultAdd(va);
|
|
301
|
+
else die(`unknown vault subcommand: ${vsub || "(none)"} — try: list, add`);
|
|
302
|
+
}
|
|
303
|
+
else die(`unknown agent subcommand: ${sub || "(none)"}`);
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
case "memory":
|
|
308
|
+
cmdMemory(parseArgs(rest));
|
|
309
|
+
break;
|
|
310
|
+
|
|
311
|
+
case "session": {
|
|
312
|
+
const sub = rest[0];
|
|
313
|
+
const a = parseArgs(rest.slice(1));
|
|
314
|
+
if (sub === "new") cmdSessionNew(a);
|
|
315
|
+
else if (sub === "list" || sub === "ls") cmdSessionList(a);
|
|
316
|
+
else if (sub === "get" || sub === "show") cmdSessionGet(a);
|
|
317
|
+
else if (sub === "update") cmdSessionUpdate(a);
|
|
318
|
+
else if (sub === "close") cmdSessionClose(a);
|
|
319
|
+
else if (sub === "check") cmdSessionCheck();
|
|
320
|
+
else if (sub === "close-stale") cmdSessionCloseStale();
|
|
321
|
+
else if (sub === "resume") await cmdSessionResume(a);
|
|
322
|
+
else if (sub === "compact") await cmdSessionCompact(a);
|
|
323
|
+
else die(`unknown session subcommand: ${sub || "(none)"}`);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
case "mcp": {
|
|
328
|
+
const sub = rest[0];
|
|
329
|
+
const a = parseArgs(rest.slice(1));
|
|
330
|
+
if (sub === "list" || sub === "ls") await cmdMcpList(a);
|
|
331
|
+
else if (sub === "add") await cmdMcpAdd(a);
|
|
332
|
+
else if (sub === "remove" || sub === "rm") await cmdMcpRemove(a);
|
|
333
|
+
else if (sub === "enable") await cmdMcpEnable(a);
|
|
334
|
+
else if (sub === "disable") await cmdMcpDisable(a);
|
|
335
|
+
else if (sub === "run") await cmdMcpRun(a);
|
|
336
|
+
else if (sub === "tools") await cmdMcpTools(a);
|
|
337
|
+
else if (sub === "check") await cmdMcpCheck(a);
|
|
338
|
+
else die(`unknown mcp subcommand: ${sub || "(none)"}`);
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
case "daemon": {
|
|
343
|
+
const sub = rest[0];
|
|
344
|
+
const a = parseArgs(rest.slice(1));
|
|
345
|
+
if (sub === "start") await cmdDaemonStart(a);
|
|
346
|
+
else if (sub === "stop") await cmdDaemonStop(a);
|
|
347
|
+
else if (sub === "status") await cmdDaemonStatus(a);
|
|
348
|
+
else if (sub === "logs") cmdDaemonLogs(a);
|
|
349
|
+
else die(`unknown daemon subcommand: ${sub || "(none)"}`);
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
case "telegram": {
|
|
354
|
+
const sub = rest[0];
|
|
355
|
+
const a = parseArgs(rest.slice(1));
|
|
356
|
+
if (sub === "send") await cmdTelegramSend(a);
|
|
357
|
+
else if (sub === "status") await cmdTelegramStatus();
|
|
358
|
+
else if (sub === "setup") cmdTelegramSetup();
|
|
359
|
+
else die(`unknown telegram subcommand: ${sub || "(none)"}`);
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
case "messages": {
|
|
364
|
+
const sub = rest[0];
|
|
365
|
+
const a = parseArgs(rest.slice(1));
|
|
366
|
+
if (sub === "tail") await cmdMessagesTail(a);
|
|
367
|
+
else if (sub === "search") await cmdMessagesSearch(a);
|
|
368
|
+
else die(`unknown messages subcommand: ${sub || "(none)"}`);
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
case "exec":
|
|
373
|
+
await cmdExec(parseArgs(rest));
|
|
374
|
+
break;
|
|
375
|
+
|
|
376
|
+
case "chat":
|
|
377
|
+
await cmdChat(parseArgs(rest));
|
|
378
|
+
break;
|
|
379
|
+
|
|
380
|
+
case "conversations":
|
|
381
|
+
case "conv": {
|
|
382
|
+
const sub = rest[0];
|
|
383
|
+
const a = parseArgs(rest.slice(1));
|
|
384
|
+
if (sub === "list" || sub === "ls") await cmdConversationsList(a);
|
|
385
|
+
else if (sub === "get" || sub === "show") await cmdConversationsGet(a);
|
|
386
|
+
else die(`unknown conversations subcommand: ${sub || "(none)"}`);
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
case "run":
|
|
391
|
+
await cmdRun(parseArgs(rest));
|
|
392
|
+
break;
|
|
393
|
+
|
|
394
|
+
case "env": {
|
|
395
|
+
const sub = rest[0];
|
|
396
|
+
if (sub === "detect" || sub === "list") await cmdEnvDetect();
|
|
397
|
+
else die(`unknown env subcommand: ${sub || "(none)"}`);
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
case "send":
|
|
402
|
+
await cmdSend(parseArgs(rest));
|
|
403
|
+
break;
|
|
404
|
+
|
|
405
|
+
case "connections":
|
|
406
|
+
case "graph":
|
|
407
|
+
await cmdConnections(parseArgs(rest));
|
|
408
|
+
break;
|
|
409
|
+
|
|
410
|
+
case "config": {
|
|
411
|
+
const sub = rest[0];
|
|
412
|
+
const a = parseArgs(rest.slice(1));
|
|
413
|
+
if (sub === "show" || sub === "ls" || sub === undefined) await cmdConfigShow(a);
|
|
414
|
+
else if (sub === "set") await cmdConfigSet(a);
|
|
415
|
+
else if (sub === "unset" || sub === "rm") await cmdConfigUnset(a);
|
|
416
|
+
else die(`unknown config subcommand: ${sub}`);
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
case "plugins":
|
|
421
|
+
case "plugin": {
|
|
422
|
+
const sub = rest[0];
|
|
423
|
+
const a = parseArgs(rest.slice(1));
|
|
424
|
+
if (sub === "list" || sub === "ls" || sub === undefined) await cmdPluginsList();
|
|
425
|
+
else if (sub === "status") await cmdPluginStatus(a);
|
|
426
|
+
else die(`unknown plugins subcommand: ${sub}`);
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
case "routine":
|
|
431
|
+
case "routines": {
|
|
432
|
+
const sub = rest[0];
|
|
433
|
+
const a = parseArgs(rest.slice(1));
|
|
434
|
+
if (sub === "list" || sub === "ls" || sub === undefined) await cmdRoutineList(a);
|
|
435
|
+
else if (sub === "get" || sub === "show") await cmdRoutineGet(a);
|
|
436
|
+
else if (sub === "add" || sub === "new") await cmdRoutineAdd(a);
|
|
437
|
+
else if (sub === "remove" || sub === "rm") await cmdRoutineRemove(a);
|
|
438
|
+
else if (sub === "enable") await cmdRoutineEnable(a);
|
|
439
|
+
else if (sub === "disable") await cmdRoutineDisable(a);
|
|
440
|
+
else if (sub === "run") await cmdRoutineRun(a);
|
|
441
|
+
else die(`unknown routine subcommand: ${sub}`);
|
|
442
|
+
break;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
case "command":
|
|
446
|
+
case "commands": {
|
|
447
|
+
const sub = rest[0];
|
|
448
|
+
const a = parseArgs(rest.slice(1));
|
|
449
|
+
if (!sub || sub === "list" || sub === "ls") cmdCommandList();
|
|
450
|
+
else if (sub === "show" || sub === "get") cmdCommandShow(a);
|
|
451
|
+
else die(`unknown command subcommand: ${sub}`);
|
|
452
|
+
break;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
case "skills": {
|
|
456
|
+
const sub = rest[0];
|
|
457
|
+
const a = parseArgs(rest.slice(1));
|
|
458
|
+
if (!sub || sub === "add") await cmdSkillsAdd(a);
|
|
459
|
+
else if (sub === "list" || sub === "ls") await cmdSkillsList(a);
|
|
460
|
+
else if (sub === "status") await cmdSkillsStatus();
|
|
461
|
+
else die(`unknown skills subcommand: ${sub}`);
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
case "identity":
|
|
466
|
+
await cmdIdentity(parseArgs(rest));
|
|
467
|
+
break;
|
|
468
|
+
|
|
469
|
+
default:
|
|
470
|
+
die(`unknown command: ${cmd}\nRun \`apx --help\` for usage.`);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const [topCmd, ...topRest] = argv;
|
|
475
|
+
(async () => {
|
|
476
|
+
try {
|
|
477
|
+
await dispatch(topCmd, topRest);
|
|
478
|
+
} catch (err) {
|
|
479
|
+
die(err && err.message ? err.message : String(err));
|
|
480
|
+
}
|
|
481
|
+
})();
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Runs automatically after `npm install -g apx`.
|
|
3
|
+
// Installs APX + APC context skills to all global skill directories.
|
|
4
|
+
import { installGlobalSkills } from "../core/scaffold.js";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
|
|
7
|
+
try {
|
|
8
|
+
const results = installGlobalSkills();
|
|
9
|
+
if (results.length === 0) process.exit(0);
|
|
10
|
+
|
|
11
|
+
const home = os.homedir();
|
|
12
|
+
const bySkill = {};
|
|
13
|
+
for (const r of results) {
|
|
14
|
+
if (!bySkill[r.skill]) bySkill[r.skill] = [];
|
|
15
|
+
bySkill[r.skill].push(r.dir.replace(home, "~"));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
console.log("\napx: skills installed globally");
|
|
19
|
+
for (const [skill, dirs] of Object.entries(bySkill)) {
|
|
20
|
+
console.log(` ${skill.padEnd(14)} → ${dirs.join(", ")}`);
|
|
21
|
+
}
|
|
22
|
+
console.log("");
|
|
23
|
+
} catch {
|
|
24
|
+
// Non-fatal — don't break the install
|
|
25
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
|
|
2
|
+
# Agent Project Context
|
|
3
|
+
|
|
4
|
+
This project uses APC. All agent context lives in `.apc/` — not in `.claude/`, `.cursor/`, `.windsurf/`, or any other IDE folder.
|
|
5
|
+
|
|
6
|
+
## FIRST: check for pending migration
|
|
7
|
+
|
|
8
|
+
**Before doing anything else**, check if `.apc/migrate.md` exists:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
cat .apc/migrate.md 2>/dev/null
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
If it exists, open the conversation with this message — do not answer any other question first:
|
|
15
|
+
|
|
16
|
+
> I see this project was just initialized with **Agent Project Context (APC)**.
|
|
17
|
+
>
|
|
18
|
+
> I found context files that haven't been migrated yet:
|
|
19
|
+
> [list files from .apc/migrate.md]
|
|
20
|
+
>
|
|
21
|
+
> I'll read them, understand what's in them, and migrate intelligently — keeping only what APC doesn't already handle.
|
|
22
|
+
>
|
|
23
|
+
> **Want me to start?**
|
|
24
|
+
|
|
25
|
+
### How to migrate — think, don't copy
|
|
26
|
+
|
|
27
|
+
**Step 1 — Read everything first.** Read all detected context files in full. Also read `AGENTS.md` if it exists. Understand the full project structure, conventions, and any referenced directories (e.g. `works/`, `docs/`, `notes/`).
|
|
28
|
+
|
|
29
|
+
**Step 2 — Classify each piece of content:**
|
|
30
|
+
|
|
31
|
+
| What it says | What to do |
|
|
32
|
+
|---|---|
|
|
33
|
+
| Agent definitions (role, model, skills) | Create `.apc/agents/<slug>.md` |
|
|
34
|
+
| Any instruction about writing sessions to a custom path (`works/sessions/`, `notes/`, etc.) | **Drop it** — APC handles sessions natively in `.apc/agents/<slug>/sessions/` |
|
|
35
|
+
| Any instruction about writing memory to a custom path (`works/memory.md`, etc.) | **Drop it** — APC handles memory natively in `.apc/agents/<slug>/memory.md` |
|
|
36
|
+
| "List agents in `AGENTS.md`" or any auto-generation rule for `AGENTS.md` | **Drop it** — APC handles this natively |
|
|
37
|
+
| Project-specific directories not covered by APC (e.g. `works/specs/`, `works/tasks/`) | **Keep in `AGENTS.md`** — document the convention there |
|
|
38
|
+
| Project rules, testing policy, stack notes, URLs, credentials | **Keep in `AGENTS.md`** — project context that APC doesn't define |
|
|
39
|
+
| IDE-specific shortcuts or instructions (e.g. "run `npm run dev` in Claude terminal") | **Keep in `AGENTS.md`** — still useful to all agents |
|
|
40
|
+
|
|
41
|
+
**Step 3 — Write `AGENTS.md`.** Start from what already exists in `AGENTS.md`, add what you kept from the classified content. Remove anything that duplicates APC native behavior. Keep it agent-neutral — no IDE-specific framing.
|
|
42
|
+
|
|
43
|
+
**Step 4 — Delete the original files** (`CLAUDE.md`, `.cursorrules`, etc.). Do not leave stubs. The content either moved to `AGENTS.md` / `.apc/agents/` or was intentionally dropped because APC covers it.
|
|
44
|
+
|
|
45
|
+
**Step 5 — Delete `.apc/migrate.md`** to mark migration complete.
|
|
46
|
+
|
|
47
|
+
**Step 6 — Summarize** what was created, what was kept, and what was dropped (and why).
|
|
48
|
+
|
|
49
|
+
If the user says no or later: delete `.apc/migrate.md` immediately so this offer is not shown again in future sessions.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Structure
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
AGENTS.md ← project context: rules, stack, conventions (commit)
|
|
57
|
+
.apc/
|
|
58
|
+
project.json ← metadata + apx field (commit)
|
|
59
|
+
.gitignore ← safe defaults, created by apx init (commit)
|
|
60
|
+
agents/<slug>.md ← agent definition (commit)
|
|
61
|
+
agents/<slug>/
|
|
62
|
+
memory.md ← curated memory (commit)
|
|
63
|
+
sessions/ ← raw session logs (local-only, gitignored)
|
|
64
|
+
skills/ ← reusable prompt fragments (commit)
|
|
65
|
+
mcps.json ← MCP declarations without secrets (commit)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Visibility rules
|
|
69
|
+
|
|
70
|
+
| What | Visibility | Commit? |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| Agent definitions, skills, rules | `stable` / `project` | Yes |
|
|
73
|
+
| `memory.md` | `project` | Yes |
|
|
74
|
+
| `sessions/` | `local` | No — gitignored |
|
|
75
|
+
| `secrets/`, `*.secret.json`, `*.env` | `private` | Never |
|
|
76
|
+
| `cache/`, `tmp/` | `ephemeral` | No — gitignored |
|
|
77
|
+
| `migrate.md` | `ephemeral` | No — gitignored |
|
|
78
|
+
|
|
79
|
+
**Write sessions to `.apc/agents/<slug>/sessions/`** — they stay local. Extract meaningful decisions into `memory.md` — that travels with the repo.
|
|
80
|
+
|
|
81
|
+
## Rules
|
|
82
|
+
|
|
83
|
+
1. Read your definition and memory from `.apc/agents/<your-slug>/`
|
|
84
|
+
2. Write memory to `.apc/agents/<your-slug>/memory.md` — never to IDE-specific folders
|
|
85
|
+
3. Write raw session logs to `.apc/agents/<your-slug>/sessions/` — they are gitignored
|
|
86
|
+
4. `AGENTS.md` is the neutral project context file — edit it directly, it is not auto-generated
|
|
87
|
+
5. To list agents: read `AGENTS.md` or list `.apc/agents/*.md`
|
|
88
|
+
|
|
89
|
+
## Sessions — write one at the end of every task
|
|
90
|
+
|
|
91
|
+
Sessions are the record of what was done, for future agents and for the team.
|
|
92
|
+
|
|
93
|
+
**Where to write:**
|
|
94
|
+
- APC standard path: `.apc/agents/<slug>/sessions/<date>-<slug>.md` (gitignored)
|
|
95
|
+
- Project-specific path: check `AGENTS.md` — some projects use `works/sessions/` or similar
|
|
96
|
+
|
|
97
|
+
**Format — always use this frontmatter:**
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+
---
|
|
101
|
+
title: Short title of what was done
|
|
102
|
+
description: One-line summary for the index
|
|
103
|
+
date: YYYY-MM-DD
|
|
104
|
+
status: open | completed | in-progress | abandoned
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Goal
|
|
108
|
+
What was the task or request.
|
|
109
|
+
|
|
110
|
+
## Done
|
|
111
|
+
What was completed. Be specific — file paths, decisions, changes.
|
|
112
|
+
|
|
113
|
+
## Pending
|
|
114
|
+
Anything left unfinished or deferred.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**How to create:**
|
|
118
|
+
- If APX is installed (`apx` field in `project.json` is `"installed"`):
|
|
119
|
+
```bash
|
|
120
|
+
apx session new <slug> --title "Short title"
|
|
121
|
+
```
|
|
122
|
+
Then fill in `description`, update `status` to `completed` when done.
|
|
123
|
+
- If APX is not available: create the file manually following the format above.
|
|
124
|
+
|
|
125
|
+
**When to write:** at the end of every task session, before closing. Not optional.
|
|
126
|
+
|
|
127
|
+
## APX — check once, remember forever
|
|
128
|
+
|
|
129
|
+
Read `.apc/project.json`. It has an `apx` field:
|
|
130
|
+
|
|
131
|
+
- **`"installed"`** — APX is available. Use `apx` commands freely when useful.
|
|
132
|
+
- **`"declined"`** — user chose not to install. Never suggest or run `apx` commands.
|
|
133
|
+
- **`null` or missing** — unknown. Do the one-time check below, then write the result and never ask again.
|
|
134
|
+
|
|
135
|
+
### One-time APX detection (only when `apx` is null or missing)
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
apx --version 2>/dev/null && echo "FOUND" || echo "NOT_FOUND"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- If `FOUND`: write `"apx": "installed"` to `.apc/project.json`. Use APX normally.
|
|
142
|
+
- If `NOT_FOUND`: tell the user once:
|
|
143
|
+
|
|
144
|
+
> APX is not installed. It adds agent coordination, MCP server management, and memory commands to this project.
|
|
145
|
+
> Want me to install it? (`npm install -g apx`)
|
|
146
|
+
|
|
147
|
+
- If yes: run `npm install -g apx`, then write `"apx": "installed"`.
|
|
148
|
+
- If no: write `"apx": "declined"`. Never mention APX again in this project.
|
|
149
|
+
|
|
150
|
+
**Never run `apx` commands if the field is `null`, `"declined"`, or unconfirmed.**
|