agentpack-cli 0.1.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.
- package/LICENSE +21 -0
- package/README.md +174 -0
- package/SECURITY.md +44 -0
- package/assets/agentpack-logo.jpg +0 -0
- package/dist/src/agentpack.d.ts +2 -0
- package/dist/src/agentpack.js +8 -0
- package/dist/src/agentpack.js.map +1 -0
- package/dist/src/cli/index.d.ts +3 -0
- package/dist/src/cli/index.js +412 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/core/budget.d.ts +14 -0
- package/dist/src/core/budget.js +56 -0
- package/dist/src/core/budget.js.map +1 -0
- package/dist/src/core/checkpoints.d.ts +24 -0
- package/dist/src/core/checkpoints.js +93 -0
- package/dist/src/core/checkpoints.js.map +1 -0
- package/dist/src/core/doctor.d.ts +4 -0
- package/dist/src/core/doctor.js +304 -0
- package/dist/src/core/doctor.js.map +1 -0
- package/dist/src/core/git.d.ts +2 -0
- package/dist/src/core/git.js +34 -0
- package/dist/src/core/git.js.map +1 -0
- package/dist/src/core/hash.d.ts +5 -0
- package/dist/src/core/hash.js +29 -0
- package/dist/src/core/hash.js.map +1 -0
- package/dist/src/core/ids.d.ts +1 -0
- package/dist/src/core/ids.js +7 -0
- package/dist/src/core/ids.js.map +1 -0
- package/dist/src/core/presets.d.ts +12 -0
- package/dist/src/core/presets.js +24 -0
- package/dist/src/core/presets.js.map +1 -0
- package/dist/src/core/redaction.d.ts +4 -0
- package/dist/src/core/redaction.js +18 -0
- package/dist/src/core/redaction.js.map +1 -0
- package/dist/src/core/resume.d.ts +13 -0
- package/dist/src/core/resume.js +398 -0
- package/dist/src/core/resume.js.map +1 -0
- package/dist/src/core/store.d.ts +20 -0
- package/dist/src/core/store.js +240 -0
- package/dist/src/core/store.js.map +1 -0
- package/dist/src/core/types.d.ts +43 -0
- package/dist/src/core/types.js +2 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/integrations/install.d.ts +5 -0
- package/dist/src/integrations/install.js +361 -0
- package/dist/src/integrations/install.js.map +1 -0
- package/dist/src/mcp/server.d.ts +9 -0
- package/dist/src/mcp/server.js +347 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/operations.d.ts +29 -0
- package/dist/src/operations.js +199 -0
- package/dist/src/operations.js.map +1 -0
- package/docs/DOGFOOD.md +72 -0
- package/docs/INTEGRATIONS.md +183 -0
- package/docs/MCP.md +83 -0
- package/docs/MVP.md +97 -0
- package/docs/ROADMAP.md +129 -0
- package/docs/SETUP.md +56 -0
- package/docs/agentpack-flow.md +63 -0
- package/package.json +55 -0
- package/scripts/mcp-smoke.mjs +197 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createId } from "./ids.js";
|
|
4
|
+
export const PACK_DIR = ".agentpack";
|
|
5
|
+
export const SCHEMA_VERSION = 1;
|
|
6
|
+
export const AGENTPACK_IGNORE_PATTERNS = [
|
|
7
|
+
`${PACK_DIR}/`,
|
|
8
|
+
".codex",
|
|
9
|
+
".claude",
|
|
10
|
+
".mcp.json",
|
|
11
|
+
"AGENTS.md",
|
|
12
|
+
"CLAUDE.md"
|
|
13
|
+
];
|
|
14
|
+
const LOCK_TIMEOUT_MS = 10_000;
|
|
15
|
+
const STALE_LOCK_MS = 5 * 60_000;
|
|
16
|
+
const heldLocks = new Set();
|
|
17
|
+
const sleepBuffer = new SharedArrayBuffer(4);
|
|
18
|
+
const sleepArray = new Int32Array(sleepBuffer);
|
|
19
|
+
export function findPackRoot(startDir) {
|
|
20
|
+
let current = path.resolve(startDir);
|
|
21
|
+
while (true) {
|
|
22
|
+
if (existsSync(path.join(current, PACK_DIR))) {
|
|
23
|
+
return current;
|
|
24
|
+
}
|
|
25
|
+
const parent = path.dirname(current);
|
|
26
|
+
if (parent === current) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
current = parent;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function requirePackRoot(startDir) {
|
|
33
|
+
const root = findPackRoot(startDir);
|
|
34
|
+
if (!root) {
|
|
35
|
+
throw new Error("No .agentpack directory found. Run `agentpack init` first.");
|
|
36
|
+
}
|
|
37
|
+
return root;
|
|
38
|
+
}
|
|
39
|
+
export function initPack(root) {
|
|
40
|
+
const packPath = path.join(root, PACK_DIR);
|
|
41
|
+
const now = new Date().toISOString();
|
|
42
|
+
mkdirSync(packPath, { recursive: true });
|
|
43
|
+
for (const dir of ["checkpoints", "evidence", "instructions", "exports", "cache"]) {
|
|
44
|
+
mkdirSync(path.join(packPath, dir), { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
writeJsonIfMissing(path.join(packPath, "config.json"), {
|
|
47
|
+
schemaVersion: SCHEMA_VERSION,
|
|
48
|
+
projectName: path.basename(root),
|
|
49
|
+
redactions: [
|
|
50
|
+
"OPENAI_API_KEY",
|
|
51
|
+
"ANTHROPIC_API_KEY",
|
|
52
|
+
"GITHUB_TOKEN",
|
|
53
|
+
"NPM_TOKEN"
|
|
54
|
+
],
|
|
55
|
+
defaultBudget: 4000,
|
|
56
|
+
includeGitDiff: true
|
|
57
|
+
});
|
|
58
|
+
writeJsonIfMissing(path.join(packPath, "state.json"), {
|
|
59
|
+
schemaVersion: SCHEMA_VERSION,
|
|
60
|
+
goal: null,
|
|
61
|
+
currentStatus: "Initialized Agentpack.",
|
|
62
|
+
nextActions: [],
|
|
63
|
+
currentCheckpoint: null,
|
|
64
|
+
createdAt: now,
|
|
65
|
+
updatedAt: now
|
|
66
|
+
});
|
|
67
|
+
writeJsonIfMissing(path.join(packPath, "sources.json"), {
|
|
68
|
+
schemaVersion: SCHEMA_VERSION,
|
|
69
|
+
sources: []
|
|
70
|
+
});
|
|
71
|
+
if (!existsSync(path.join(packPath, "events.jsonl"))) {
|
|
72
|
+
writeFileSync(path.join(packPath, "events.jsonl"), "", "utf8");
|
|
73
|
+
}
|
|
74
|
+
ensurePackIgnored(root);
|
|
75
|
+
return packPath;
|
|
76
|
+
}
|
|
77
|
+
export function ensurePackIgnored(root) {
|
|
78
|
+
const gitignorePath = path.join(root, ".gitignore");
|
|
79
|
+
const existing = existsSync(gitignorePath) ? readFileSync(gitignorePath, "utf8") : "";
|
|
80
|
+
const lines = existing.split(/\r?\n/).map((line) => line.trim());
|
|
81
|
+
const missing = AGENTPACK_IGNORE_PATTERNS.filter((pattern) => !hasIgnorePattern(lines, pattern));
|
|
82
|
+
if (!missing.length) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const prefix = existing && !existing.endsWith("\n") ? "\n" : "";
|
|
86
|
+
writeFileSync(gitignorePath, `${existing}${prefix}${missing.join("\n")}\n`, "utf8");
|
|
87
|
+
}
|
|
88
|
+
function hasIgnorePattern(lines, pattern) {
|
|
89
|
+
const normalized = pattern.endsWith("/") ? pattern.slice(0, -1) : pattern;
|
|
90
|
+
return lines.some((line) => {
|
|
91
|
+
const normalizedLine = line.endsWith("/") ? line.slice(0, -1) : line;
|
|
92
|
+
return normalizedLine === normalized;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
export function getPackPath(root, ...parts) {
|
|
96
|
+
return path.join(root, PACK_DIR, ...parts);
|
|
97
|
+
}
|
|
98
|
+
export function readJson(filePath, fallback) {
|
|
99
|
+
if (!existsSync(filePath)) {
|
|
100
|
+
return fallback;
|
|
101
|
+
}
|
|
102
|
+
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
103
|
+
}
|
|
104
|
+
export function writeJson(filePath, value) {
|
|
105
|
+
writeTextFileAtomic(filePath, `${JSON.stringify(value, null, 2)}\n`);
|
|
106
|
+
}
|
|
107
|
+
export function writeJsonIfMissing(filePath, value) {
|
|
108
|
+
if (!existsSync(filePath)) {
|
|
109
|
+
writeJson(filePath, value);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export function readState(root) {
|
|
113
|
+
const state = readJson(getPackPath(root, "state.json"), null);
|
|
114
|
+
if (!state) {
|
|
115
|
+
throw new Error("Agentpack state.json is missing. Run `agentpack init` again.");
|
|
116
|
+
}
|
|
117
|
+
return state;
|
|
118
|
+
}
|
|
119
|
+
export function writeState(root, state) {
|
|
120
|
+
withPackWriteLock(root, () => {
|
|
121
|
+
writeJson(getPackPath(root, "state.json"), {
|
|
122
|
+
...state,
|
|
123
|
+
updatedAt: new Date().toISOString()
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
export function readSources(root) {
|
|
128
|
+
return readJson(getPackPath(root, "sources.json"), { schemaVersion: SCHEMA_VERSION, sources: [] });
|
|
129
|
+
}
|
|
130
|
+
export function writeSources(root, sources) {
|
|
131
|
+
withPackWriteLock(root, () => {
|
|
132
|
+
writeJson(getPackPath(root, "sources.json"), sources);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
export function appendEvent(root, type, payload = {}) {
|
|
136
|
+
const event = {
|
|
137
|
+
id: createId("evt"),
|
|
138
|
+
ts: new Date().toISOString(),
|
|
139
|
+
type,
|
|
140
|
+
...payload
|
|
141
|
+
};
|
|
142
|
+
withPackWriteLock(root, () => {
|
|
143
|
+
writeFileSync(getPackPath(root, "events.jsonl"), `${JSON.stringify(event)}\n`, {
|
|
144
|
+
encoding: "utf8",
|
|
145
|
+
flag: "a"
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
return event;
|
|
149
|
+
}
|
|
150
|
+
export function readEvents(root) {
|
|
151
|
+
const content = readFileSync(getPackPath(root, "events.jsonl"), "utf8");
|
|
152
|
+
return content
|
|
153
|
+
.split("\n")
|
|
154
|
+
.filter(Boolean)
|
|
155
|
+
.map((line) => JSON.parse(line));
|
|
156
|
+
}
|
|
157
|
+
export function listCheckpoints(root) {
|
|
158
|
+
const checkpointsPath = getPackPath(root, "checkpoints");
|
|
159
|
+
if (!existsSync(checkpointsPath)) {
|
|
160
|
+
return [];
|
|
161
|
+
}
|
|
162
|
+
return readdirSync(checkpointsPath, { withFileTypes: true })
|
|
163
|
+
.filter((entry) => entry.isDirectory())
|
|
164
|
+
.map((entry) => entry.name)
|
|
165
|
+
.sort();
|
|
166
|
+
}
|
|
167
|
+
export function withPackWriteLock(root, fn) {
|
|
168
|
+
const lockPath = getPackPath(root, ".lock");
|
|
169
|
+
if (heldLocks.has(lockPath)) {
|
|
170
|
+
return fn();
|
|
171
|
+
}
|
|
172
|
+
acquireLock(lockPath);
|
|
173
|
+
heldLocks.add(lockPath);
|
|
174
|
+
try {
|
|
175
|
+
return fn();
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
heldLocks.delete(lockPath);
|
|
179
|
+
releaseLock(lockPath);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function writeTextFileAtomic(filePath, content) {
|
|
183
|
+
const dir = path.dirname(filePath);
|
|
184
|
+
const tempPath = path.join(dir, `.${path.basename(filePath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
185
|
+
try {
|
|
186
|
+
writeFileSync(tempPath, content, "utf8");
|
|
187
|
+
renameSync(tempPath, filePath);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
try {
|
|
191
|
+
unlinkSync(tempPath);
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// Best effort cleanup; preserve the original write error.
|
|
195
|
+
}
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function acquireLock(lockPath) {
|
|
200
|
+
const startedAt = Date.now();
|
|
201
|
+
while (true) {
|
|
202
|
+
try {
|
|
203
|
+
mkdirSync(lockPath, { mode: 0o700 });
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
if (!isErrnoException(error) || error.code !== "EEXIST") {
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
210
|
+
removeStaleLock(lockPath);
|
|
211
|
+
if (Date.now() - startedAt > LOCK_TIMEOUT_MS) {
|
|
212
|
+
throw new Error(`Timed out waiting for Agentpack state lock: ${lockPath}`);
|
|
213
|
+
}
|
|
214
|
+
sleepSync(25);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function releaseLock(lockPath) {
|
|
219
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
220
|
+
}
|
|
221
|
+
function removeStaleLock(lockPath) {
|
|
222
|
+
try {
|
|
223
|
+
const ageMs = Date.now() - statSync(lockPath).mtimeMs;
|
|
224
|
+
if (ageMs > STALE_LOCK_MS) {
|
|
225
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
if (!isErrnoException(error) || error.code !== "ENOENT") {
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function sleepSync(ms) {
|
|
235
|
+
Atomics.wait(sleepArray, 0, 0, ms);
|
|
236
|
+
}
|
|
237
|
+
function isErrnoException(error) {
|
|
238
|
+
return error instanceof Error && "code" in error;
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/core/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface AgentpackConfig {
|
|
2
|
+
schemaVersion: number;
|
|
3
|
+
projectName: string;
|
|
4
|
+
redactions: string[];
|
|
5
|
+
defaultBudget: number;
|
|
6
|
+
includeGitDiff: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface AgentpackState {
|
|
9
|
+
schemaVersion: number;
|
|
10
|
+
goal: string | null;
|
|
11
|
+
currentStatus: string;
|
|
12
|
+
nextActions: string[];
|
|
13
|
+
currentCheckpoint: string | null;
|
|
14
|
+
createdAt: string;
|
|
15
|
+
updatedAt: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SourceRecord {
|
|
18
|
+
path: string;
|
|
19
|
+
hash: string;
|
|
20
|
+
size: number;
|
|
21
|
+
mtimeMs: number;
|
|
22
|
+
recordedAt: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
snippet: string;
|
|
25
|
+
}
|
|
26
|
+
export interface SourcesFile {
|
|
27
|
+
schemaVersion: number;
|
|
28
|
+
sources: SourceRecord[];
|
|
29
|
+
}
|
|
30
|
+
export interface AgentpackEvent {
|
|
31
|
+
id: string;
|
|
32
|
+
ts: string;
|
|
33
|
+
type: string;
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
export interface GitInfo {
|
|
37
|
+
available: boolean;
|
|
38
|
+
topLevel?: string;
|
|
39
|
+
branch: string | null;
|
|
40
|
+
head: string | null;
|
|
41
|
+
status: string;
|
|
42
|
+
diff: string;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { getPackPath, readJson } from "../core/store.js";
|
|
4
|
+
const INSTALL_TARGETS = ["codex", "claude", "claude-desktop", "cursor"];
|
|
5
|
+
const INSTRUCTIONS = `# Agentpack
|
|
6
|
+
|
|
7
|
+
Use Agentpack as the task-state ledger for this repo.
|
|
8
|
+
Agentpack is not an activity logger; do not record every thought, file read, or edit.
|
|
9
|
+
|
|
10
|
+
At the start of a task:
|
|
11
|
+
- call \`load_context\` with a small preset first
|
|
12
|
+
- call \`source_status\` before re-reading previously inspected files
|
|
13
|
+
|
|
14
|
+
During work:
|
|
15
|
+
- call \`record_source\` after inspecting an important file, with a concise conclusion
|
|
16
|
+
- call \`record_decision\` for durable technical/product decisions
|
|
17
|
+
- call \`record_dead_end\` when an approach failed and should not be repeated
|
|
18
|
+
- call \`attach_evidence\` for useful test output, command output, or verification notes
|
|
19
|
+
|
|
20
|
+
Default cadence:
|
|
21
|
+
- start with Agentpack context
|
|
22
|
+
- work locally without recording every micro-step
|
|
23
|
+
- record durable findings and evidence before a checkpoint
|
|
24
|
+
- use full safe mode for risky or release-like changes
|
|
25
|
+
|
|
26
|
+
Before re-reading an unchanged source file, prefer the recorded source conclusion unless the task requires fresh inspection.
|
|
27
|
+
|
|
28
|
+
After meaningful progress, call \`checkpoint\` with:
|
|
29
|
+
- summary
|
|
30
|
+
- current status
|
|
31
|
+
- next actions
|
|
32
|
+
`;
|
|
33
|
+
export function installIntegration(root, targetValue, options = {}) {
|
|
34
|
+
const target = parseTarget(targetValue);
|
|
35
|
+
const dryRun = options.dryRun !== false;
|
|
36
|
+
const plan = buildInstallPlan(root, target);
|
|
37
|
+
const statuses = plan.files.map((file) => ({
|
|
38
|
+
file,
|
|
39
|
+
status: fileStatus(file.filePath, file.content)
|
|
40
|
+
}));
|
|
41
|
+
if (!dryRun) {
|
|
42
|
+
applyPlan(plan);
|
|
43
|
+
}
|
|
44
|
+
return formatInstallResult(root, plan, statuses, dryRun);
|
|
45
|
+
}
|
|
46
|
+
function buildInstallPlan(root, target) {
|
|
47
|
+
mkdirSync(getPackPath(root, "instructions"), { recursive: true });
|
|
48
|
+
const serverName = mcpServerName(root);
|
|
49
|
+
if (target === "codex") {
|
|
50
|
+
const codexSnippetPath = getPackPath(root, "instructions", "codex-mcp.example.toml");
|
|
51
|
+
return {
|
|
52
|
+
target,
|
|
53
|
+
files: [
|
|
54
|
+
writeFilePlan(root, ".agentpack/instructions/codex.md", "Write Codex-specific Agentpack workflow instructions.", INSTRUCTIONS),
|
|
55
|
+
managedBlockPlan(root, "AGENTS.md", "Add or update the Agentpack block in AGENTS.md.", INSTRUCTIONS),
|
|
56
|
+
tomlTablePlan(root, ".codex/config.toml", "Add the Agentpack MCP server to project-local Codex config.", `mcp_servers.${serverName}`, codexMcpTomlTable(serverName), "mcp_servers.agentpack"),
|
|
57
|
+
writeFilePlan(root, ".agentpack/instructions/codex-mcp.example.toml", "Write a Codex MCP config snippet for manual review.", codexTomlSnippet(serverName))
|
|
58
|
+
],
|
|
59
|
+
notes: [
|
|
60
|
+
"No global Codex config is modified.",
|
|
61
|
+
`Codex should use the project-local .codex/config.toml entry named ${serverName} for this repo.`,
|
|
62
|
+
"Remove any old ~/.codex/config.toml agentpack server that hard-codes --root or cwd to another project.",
|
|
63
|
+
`For manual review, see ${relativePath(root, codexSnippetPath)}.`
|
|
64
|
+
]
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (target === "claude") {
|
|
68
|
+
return {
|
|
69
|
+
target,
|
|
70
|
+
files: [
|
|
71
|
+
writeFilePlan(root, ".agentpack/instructions/claude.md", "Write Claude-specific Agentpack workflow instructions.", INSTRUCTIONS),
|
|
72
|
+
managedBlockPlan(root, "CLAUDE.md", "Add or update the Agentpack block in CLAUDE.md.", INSTRUCTIONS),
|
|
73
|
+
jsonMergePlan(root, ".mcp.json", "Add the Agentpack MCP server to project .mcp.json.", serverName, claudeMcpServer())
|
|
74
|
+
],
|
|
75
|
+
notes: [
|
|
76
|
+
"Only project-local files are modified.",
|
|
77
|
+
`The Claude Code MCP server key is ${serverName} to avoid cross-repo name collisions.`,
|
|
78
|
+
"Claude Code prompts before using project-scoped MCP servers from .mcp.json."
|
|
79
|
+
]
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (target === "claude-desktop") {
|
|
83
|
+
const desktopSnippetPath = getPackPath(root, "instructions", "claude-desktop-mcp.example.json");
|
|
84
|
+
return {
|
|
85
|
+
target,
|
|
86
|
+
files: [
|
|
87
|
+
writeFilePlan(root, ".agentpack/instructions/claude-desktop.md", "Write Claude Desktop-specific Agentpack setup notes.", claudeDesktopInstructions(root, desktopSnippetPath)),
|
|
88
|
+
writeFilePlan(root, ".agentpack/instructions/claude-desktop-mcp.example.json", "Write a Claude Desktop MCP config snippet for manual review.", claudeDesktopJsonSnippet(root, serverName))
|
|
89
|
+
],
|
|
90
|
+
notes: [
|
|
91
|
+
"No Claude Desktop global config is modified.",
|
|
92
|
+
"Claude Desktop does not read project .mcp.json or CLAUDE.md.",
|
|
93
|
+
`To enable local MCP in Claude Desktop manually, review ${relativePath(root, desktopSnippetPath)} and merge it into ~/Library/Application Support/Claude/claude_desktop_config.json on macOS.`
|
|
94
|
+
]
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
target,
|
|
99
|
+
files: [
|
|
100
|
+
writeFilePlan(root, ".agentpack/instructions/cursor.md", "Write Cursor-specific Agentpack workflow instructions.", INSTRUCTIONS),
|
|
101
|
+
writeFilePlan(root, ".cursor/rules/agentpack.mdc", "Write a Cursor project rule for Agentpack.", INSTRUCTIONS),
|
|
102
|
+
jsonMergePlan(root, ".cursor/mcp.json", "Add the Agentpack MCP server to Cursor project MCP config.", serverName, cursorMcpServer())
|
|
103
|
+
],
|
|
104
|
+
notes: [
|
|
105
|
+
"Only project-local files are modified.",
|
|
106
|
+
"Cursor reads project-specific MCP servers from .cursor/mcp.json."
|
|
107
|
+
]
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function applyPlan(plan) {
|
|
111
|
+
for (const file of plan.files) {
|
|
112
|
+
mkdirSync(path.dirname(file.filePath), { recursive: true });
|
|
113
|
+
if (existsSync(file.filePath) && readFileSync(file.filePath, "utf8") === file.content) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
writeFileSync(file.filePath, file.content, "utf8");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function formatInstallResult(root, plan, statuses, dryRun) {
|
|
120
|
+
const lines = [
|
|
121
|
+
dryRun
|
|
122
|
+
? `Agentpack ${plan.target} install plan (dry run)`
|
|
123
|
+
: `Installed Agentpack ${plan.target} integration`,
|
|
124
|
+
dryRun ? "No files were changed." : "Files written:",
|
|
125
|
+
"",
|
|
126
|
+
...statuses.map(({ file, status }) => `- ${status.toUpperCase()} ${relativePath(root, file.filePath)}: ${file.description}`),
|
|
127
|
+
"",
|
|
128
|
+
"Notes:",
|
|
129
|
+
...plan.notes.map((note) => `- ${note}`)
|
|
130
|
+
];
|
|
131
|
+
if (dryRun) {
|
|
132
|
+
lines.push("", "To apply:", ` agentpack install ${plan.target} --write`);
|
|
133
|
+
}
|
|
134
|
+
return lines.join("\n");
|
|
135
|
+
}
|
|
136
|
+
function writeFilePlan(root, relativeFilePath, description, content) {
|
|
137
|
+
return {
|
|
138
|
+
filePath: path.join(root, relativeFilePath),
|
|
139
|
+
description,
|
|
140
|
+
content: ensureTrailingNewline(content)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function managedBlockPlan(root, relativeFilePath, description, block) {
|
|
144
|
+
const filePath = path.join(root, relativeFilePath);
|
|
145
|
+
const existing = existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
|
|
146
|
+
return {
|
|
147
|
+
filePath,
|
|
148
|
+
description,
|
|
149
|
+
content: upsertManagedBlock(existing, block)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function jsonMergePlan(root, relativeFilePath, description, serverName, server) {
|
|
153
|
+
const filePath = path.join(root, relativeFilePath);
|
|
154
|
+
const existing = readJson(filePath, {});
|
|
155
|
+
const mcpServers = isRecord(existing.mcpServers) ? existing.mcpServers : {};
|
|
156
|
+
const nextMcpServers = {
|
|
157
|
+
...mcpServers,
|
|
158
|
+
[serverName]: server
|
|
159
|
+
};
|
|
160
|
+
if (serverName !== "agentpack" && JSON.stringify(mcpServers.agentpack) === JSON.stringify(server)) {
|
|
161
|
+
delete nextMcpServers.agentpack;
|
|
162
|
+
}
|
|
163
|
+
const next = {
|
|
164
|
+
...existing,
|
|
165
|
+
mcpServers: nextMcpServers
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
filePath,
|
|
169
|
+
description,
|
|
170
|
+
content: `${JSON.stringify(next, null, 2)}\n`
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function tomlTablePlan(root, relativeFilePath, description, tableName, tableBody, legacyTableName) {
|
|
174
|
+
const filePath = path.join(root, relativeFilePath);
|
|
175
|
+
const existing = existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
|
|
176
|
+
const withoutLegacy = legacyTableName && legacyTableName !== tableName
|
|
177
|
+
? removeTomlTable(existing, legacyTableName)
|
|
178
|
+
: existing;
|
|
179
|
+
return {
|
|
180
|
+
filePath,
|
|
181
|
+
description,
|
|
182
|
+
content: upsertTomlTable(withoutLegacy, tableName, tableBody)
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function upsertManagedBlock(existing, block) {
|
|
186
|
+
const marker = "<!-- agentpack:start -->";
|
|
187
|
+
const endMarker = "<!-- agentpack:end -->";
|
|
188
|
+
const wrapped = `${marker}\n${block.trim()}\n${endMarker}\n`;
|
|
189
|
+
if (existing.includes(marker)) {
|
|
190
|
+
return existing.replace(new RegExp(`${escapeRegExp(marker)}[\\s\\S]*?${escapeRegExp(endMarker)}\\n?`), wrapped);
|
|
191
|
+
}
|
|
192
|
+
return `${existing.trimEnd()}\n\n${wrapped}`.trimStart();
|
|
193
|
+
}
|
|
194
|
+
function upsertTomlTable(existing, tableName, tableBody) {
|
|
195
|
+
const tableHeader = `[${tableName}]`;
|
|
196
|
+
const lines = existing.split(/\r?\n/);
|
|
197
|
+
const start = lines.findIndex((line) => line.trim() === tableHeader);
|
|
198
|
+
const bodyLines = tableBody.trimEnd().split("\n");
|
|
199
|
+
if (start === -1) {
|
|
200
|
+
const prefix = existing.trimEnd();
|
|
201
|
+
return ensureTrailingNewline(prefix ? `${prefix}\n\n${tableBody}` : tableBody);
|
|
202
|
+
}
|
|
203
|
+
let end = start + 1;
|
|
204
|
+
const nestedPrefix = `[${tableName}.`;
|
|
205
|
+
while (end < lines.length) {
|
|
206
|
+
const trimmed = (lines[end] || "").trim();
|
|
207
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]") && !trimmed.startsWith(nestedPrefix)) {
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
end += 1;
|
|
211
|
+
}
|
|
212
|
+
lines.splice(start, end - start, ...bodyLines);
|
|
213
|
+
return ensureTrailingNewline(lines.join("\n").trimEnd());
|
|
214
|
+
}
|
|
215
|
+
function removeTomlTable(existing, tableName) {
|
|
216
|
+
const tableHeader = `[${tableName}]`;
|
|
217
|
+
const lines = existing.split(/\r?\n/);
|
|
218
|
+
const start = lines.findIndex((line) => line.trim() === tableHeader);
|
|
219
|
+
if (start === -1) {
|
|
220
|
+
return existing;
|
|
221
|
+
}
|
|
222
|
+
let end = start + 1;
|
|
223
|
+
const nestedPrefix = `[${tableName}.`;
|
|
224
|
+
while (end < lines.length) {
|
|
225
|
+
const trimmed = (lines[end] || "").trim();
|
|
226
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]") && !trimmed.startsWith(nestedPrefix)) {
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
end += 1;
|
|
230
|
+
}
|
|
231
|
+
lines.splice(start, end - start);
|
|
232
|
+
return ensureTrailingNewline(lines.join("\n").trimEnd());
|
|
233
|
+
}
|
|
234
|
+
function codexTomlSnippet(serverName) {
|
|
235
|
+
return [
|
|
236
|
+
"# Add this to the repo's .codex/config.toml after reviewing it.",
|
|
237
|
+
"# Do not put a project-specific --root or cwd in ~/.codex/config.toml.",
|
|
238
|
+
"# A hard-coded global root makes Agentpack read the wrong repo.",
|
|
239
|
+
codexMcpTomlTable(serverName),
|
|
240
|
+
""
|
|
241
|
+
].join("\n");
|
|
242
|
+
}
|
|
243
|
+
function codexMcpTomlTable(serverName) {
|
|
244
|
+
return [
|
|
245
|
+
`[mcp_servers.${serverName}]`,
|
|
246
|
+
"command = \"agentpack\"",
|
|
247
|
+
"args = [\"mcp\"]",
|
|
248
|
+
"startup_timeout_sec = 10",
|
|
249
|
+
"tool_timeout_sec = 60",
|
|
250
|
+
""
|
|
251
|
+
].join("\n");
|
|
252
|
+
}
|
|
253
|
+
function claudeMcpServer() {
|
|
254
|
+
return {
|
|
255
|
+
type: "stdio",
|
|
256
|
+
command: "agentpack",
|
|
257
|
+
args: ["mcp"]
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
function claudeDesktopMcpServer(root) {
|
|
261
|
+
return {
|
|
262
|
+
command: "agentpack",
|
|
263
|
+
args: ["mcp", "--root", root],
|
|
264
|
+
env: {
|
|
265
|
+
AGENTPACK_ROOT: root
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
function claudeDesktopJsonSnippet(root, serverName) {
|
|
270
|
+
return JSON.stringify({
|
|
271
|
+
mcpServers: {
|
|
272
|
+
[serverName]: claudeDesktopMcpServer(root)
|
|
273
|
+
}
|
|
274
|
+
}, null, 2);
|
|
275
|
+
}
|
|
276
|
+
function claudeDesktopInstructions(root, snippetPath) {
|
|
277
|
+
return [
|
|
278
|
+
"# Agentpack for Claude Desktop",
|
|
279
|
+
"",
|
|
280
|
+
"Claude Desktop does not read project-local `.mcp.json` or `CLAUDE.md`.",
|
|
281
|
+
"Use Claude Code's `.mcp.json` for Claude Code only.",
|
|
282
|
+
"",
|
|
283
|
+
"For Claude Desktop local MCP, prefer Desktop Extensions/MCP bundles when Agentpack ships one.",
|
|
284
|
+
"Until then, review the generated JSON snippet and merge it into your Claude Desktop config manually.",
|
|
285
|
+
"Do not copy the generated snippet over the Desktop config file; that can delete existing MCP servers.",
|
|
286
|
+
"",
|
|
287
|
+
"macOS config path:",
|
|
288
|
+
"",
|
|
289
|
+
"```text",
|
|
290
|
+
"~/Library/Application Support/Claude/claude_desktop_config.json",
|
|
291
|
+
"```",
|
|
292
|
+
"",
|
|
293
|
+
"Generated snippet:",
|
|
294
|
+
"",
|
|
295
|
+
"```text",
|
|
296
|
+
relativePath(root, snippetPath),
|
|
297
|
+
"```",
|
|
298
|
+
"",
|
|
299
|
+
"Safe manual flow:",
|
|
300
|
+
"",
|
|
301
|
+
"```bash",
|
|
302
|
+
"agentpack install claude-desktop --write",
|
|
303
|
+
"cat .agentpack/instructions/claude-desktop-mcp.example.json",
|
|
304
|
+
"mkdir -p \"$HOME/Library/Application Support/Claude\"",
|
|
305
|
+
"open -e \"$HOME/Library/Application Support/Claude/claude_desktop_config.json\"",
|
|
306
|
+
"```",
|
|
307
|
+
"",
|
|
308
|
+
"If the config file does not exist yet, create it with the generated snippet content.",
|
|
309
|
+
"If it already exists, merge only the `mcpServers.agentpack` entry into the existing JSON.",
|
|
310
|
+
"",
|
|
311
|
+
"After editing the Claude Desktop config, restart Claude Desktop.",
|
|
312
|
+
"",
|
|
313
|
+
"If Claude Desktop cannot find `agentpack`, replace the `command` value with an absolute executable path.",
|
|
314
|
+
"Keep both the `--root` argument and `AGENTPACK_ROOT` env value pointed at the project whose `.agentpack/` state you want Claude Desktop to use.",
|
|
315
|
+
"When switching Claude Desktop to another repo, update both the global `mcpServers.agentpack.args` `--root` value and `mcpServers.agentpack.env.AGENTPACK_ROOT`, then restart Claude Desktop."
|
|
316
|
+
].join("\n");
|
|
317
|
+
}
|
|
318
|
+
function cursorMcpServer() {
|
|
319
|
+
return {
|
|
320
|
+
type: "stdio",
|
|
321
|
+
command: "agentpack",
|
|
322
|
+
args: ["mcp", "--root", "${workspaceFolder}"]
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function mcpServerName(root) {
|
|
326
|
+
const projectName = path.basename(root);
|
|
327
|
+
const slug = projectName
|
|
328
|
+
.toLowerCase()
|
|
329
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
330
|
+
.replace(/^-+|-+$/g, "")
|
|
331
|
+
.replace(/-{2,}/g, "-");
|
|
332
|
+
if (!slug || slug === "agentpack") {
|
|
333
|
+
return "agentpack";
|
|
334
|
+
}
|
|
335
|
+
return `agentpack-${slug}`;
|
|
336
|
+
}
|
|
337
|
+
function parseTarget(target) {
|
|
338
|
+
if (INSTALL_TARGETS.includes(target)) {
|
|
339
|
+
return target;
|
|
340
|
+
}
|
|
341
|
+
throw new Error(`Unknown install target: ${target}`);
|
|
342
|
+
}
|
|
343
|
+
function fileStatus(filePath, content) {
|
|
344
|
+
if (!existsSync(filePath)) {
|
|
345
|
+
return "create";
|
|
346
|
+
}
|
|
347
|
+
return readFileSync(filePath, "utf8") === content ? "unchanged" : "update";
|
|
348
|
+
}
|
|
349
|
+
function relativePath(root, filePath) {
|
|
350
|
+
return path.relative(root, filePath) || ".";
|
|
351
|
+
}
|
|
352
|
+
function ensureTrailingNewline(value) {
|
|
353
|
+
return value.endsWith("\n") ? value : `${value}\n`;
|
|
354
|
+
}
|
|
355
|
+
function isRecord(value) {
|
|
356
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
357
|
+
}
|
|
358
|
+
function escapeRegExp(value) {
|
|
359
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
360
|
+
}
|
|
361
|
+
//# sourceMappingURL=install.js.map
|