@axiomatic-labs/claudeflow 2.43.30 → 2.43.32
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/lib/install.js +75 -48
- package/package.json +1 -1
package/lib/install.js
CHANGED
|
@@ -102,66 +102,90 @@ function syncClaudeMd(cwd, snippetPath) {
|
|
|
102
102
|
// Place + merge the framework from an extracted payload dir into a project. Pure filesystem, no network —
|
|
103
103
|
// so it is testable on a throwaway dir.
|
|
104
104
|
function installFromPayload(src, cwd) {
|
|
105
|
-
const out = { playbooks: 0, scripts: 0, skills: 0, agents: 0, claudeMd: false };
|
|
105
|
+
const out = { playbooks: 0, scripts: 0, skills: 0, agents: 0, claudeMd: false, failed: [] };
|
|
106
|
+
// Each placement step is ISOLATED: a failure in one (a copy error, a permission hiccup, a weird file in the
|
|
107
|
+
// user's tree) must NOT abort the rest — above all it must not skip the settings/env + CLAUDE.md config, the
|
|
108
|
+
// two steps a user most needs (the env block wires agent-teams + the autocompact window, etc.). Before this,
|
|
109
|
+
// any throw in steps 1–4 silently left settings/CLAUDE.md unconfigured. Each step records its name on failure
|
|
110
|
+
// so `run()` can warn instead of reporting a clean success over a partial install.
|
|
111
|
+
const step = (name, fn) => { try { fn(); } catch { out.failed.push(name); } };
|
|
106
112
|
|
|
107
113
|
// 1) Playbooks — always refreshed (shared system).
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
step('playbooks', () => {
|
|
115
|
+
const srcPlaybooks = path.join(src, '.claudeflow', 'playbooks');
|
|
116
|
+
if (fs.existsSync(srcPlaybooks)) {
|
|
117
|
+
const dst = path.join(cwd, '.claudeflow', 'playbooks');
|
|
118
|
+
rmrf(dst); copyDir(srcPlaybooks, dst);
|
|
119
|
+
out.playbooks = countFiles(dst);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
114
122
|
|
|
115
123
|
// 2) Configs — per-project ones create-if-absent (never clobber a customized brand); shared refresh.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
step('configs', () => {
|
|
125
|
+
fs.mkdirSync(path.join(cwd, '.claudeflow'), { recursive: true });
|
|
126
|
+
for (const c of PER_PROJECT_CONFIGS) {
|
|
127
|
+
const s = path.join(src, '.claudeflow', c), d = path.join(cwd, '.claudeflow', c);
|
|
128
|
+
if (fs.existsSync(s) && !fs.existsSync(d)) fs.copyFileSync(s, d);
|
|
129
|
+
}
|
|
130
|
+
for (const c of SHARED_CONFIGS) {
|
|
131
|
+
const s = path.join(src, '.claudeflow', c);
|
|
132
|
+
if (fs.existsSync(s)) fs.copyFileSync(s, path.join(cwd, '.claudeflow', c));
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// 3) Scripts (hooks + scans + servers) — always refreshed. Per-file isolation so ONE bad file (a socket, a
|
|
137
|
+
// permission denial) can't abort the whole copy — let alone the later settings/CLAUDE.md steps.
|
|
138
|
+
step('scripts', () => {
|
|
139
|
+
const srcScripts = path.join(src, 'scripts', 'claudeflow');
|
|
140
|
+
if (fs.existsSync(srcScripts)) {
|
|
141
|
+
const dst = path.join(cwd, 'scripts', 'claudeflow');
|
|
142
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
143
|
+
for (const e of fs.readdirSync(srcScripts)) {
|
|
144
|
+
try { fs.copyFileSync(path.join(srcScripts, e), path.join(dst, e)); out.scripts++; } catch {}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
133
148
|
|
|
134
149
|
// 4) Skills — replace each shipped claudeflow-* skill; preserve the user's own skills.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
150
|
+
step('skills', () => {
|
|
151
|
+
const srcSkills = path.join(src, '.claude', 'skills');
|
|
152
|
+
if (fs.existsSync(srcSkills)) {
|
|
153
|
+
const dst = path.join(cwd, '.claude', 'skills');
|
|
154
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
155
|
+
for (const e of fs.readdirSync(srcSkills, { withFileTypes: true })) {
|
|
156
|
+
if (!e.isDirectory() || !e.name.startsWith('claudeflow-')) continue;
|
|
157
|
+
const d = path.join(dst, e.name);
|
|
158
|
+
try { rmrf(d); copyDir(path.join(srcSkills, e.name), d); out.skills++; } catch {}
|
|
159
|
+
}
|
|
143
160
|
}
|
|
144
|
-
}
|
|
161
|
+
});
|
|
145
162
|
|
|
146
163
|
// 4b) Agents — replace each shipped claudeflow-* agent; preserve the user's own agents.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
164
|
+
step('agents', () => {
|
|
165
|
+
const srcAgents = path.join(src, '.claude', 'agents');
|
|
166
|
+
if (fs.existsSync(srcAgents)) {
|
|
167
|
+
const dst = path.join(cwd, '.claude', 'agents');
|
|
168
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
169
|
+
for (const e of fs.readdirSync(srcAgents, { withFileTypes: true })) {
|
|
170
|
+
if (!e.isFile() || !e.name.startsWith('claudeflow-') || !e.name.endsWith('.md')) continue;
|
|
171
|
+
try { fs.copyFileSync(path.join(srcAgents, e.name), path.join(dst, e.name)); out.agents++; } catch {}
|
|
172
|
+
}
|
|
154
173
|
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// 5) settings.json
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// 5) settings.json — MERGE the shipped hooks + env (add-if-absent) into the user's settings (never clobber).
|
|
177
|
+
// ALWAYS runs (isolated above) — this is what wires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS et al.
|
|
178
|
+
step('settings', () => {
|
|
179
|
+
const srcSettings = path.join(src, '.claude', 'settings.json');
|
|
180
|
+
if (fs.existsSync(srcSettings)) {
|
|
181
|
+
mergeSettings(cwd, JSON.parse(fs.readFileSync(srcSettings, 'utf8')));
|
|
182
|
+
}
|
|
183
|
+
});
|
|
162
184
|
|
|
163
185
|
// 6) CLAUDE.md — upsert the managed guidance block between markers (idempotent; updates propagate on re-install).
|
|
164
|
-
|
|
186
|
+
step('claude-md', () => {
|
|
187
|
+
out.claudeMd = syncClaudeMd(cwd, path.join(src, 'assets', 'CLAUDE.snippet.md'));
|
|
188
|
+
});
|
|
165
189
|
|
|
166
190
|
return out;
|
|
167
191
|
}
|
|
@@ -200,6 +224,9 @@ async function run() {
|
|
|
200
224
|
ui.success(`claudeflow v${version} installed`);
|
|
201
225
|
ui.info(` ${summary.playbooks} playbooks · ${summary.scripts} scripts · ${summary.skills} skills`
|
|
202
226
|
+ (summary.claudeMd ? ' · CLAUDE.md guidance synced' : ''));
|
|
227
|
+
if (summary.failed && summary.failed.length) {
|
|
228
|
+
ui.warn(` some steps did not complete: ${summary.failed.join(', ')}. Re-run \`npx @axiomatic-labs/claudeflow@latest install\` (the @latest avoids a stale npx cache).`);
|
|
229
|
+
}
|
|
203
230
|
ui.done(`Describe a change and the ${ui.BOLD}claudeflow-implementer${ui.RESET} agent will build it.`);
|
|
204
231
|
}
|
|
205
232
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiomatic-labs/claudeflow",
|
|
3
|
-
"version": "2.43.
|
|
3
|
+
"version": "2.43.32",
|
|
4
4
|
"description": "Claudeflow — AI-powered development toolkit for Claude Code. Skills, agents, hooks, and quality gates that ship production apps.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"claudeflow": "./bin/cli.js"
|