claudeup 4.29.0 → 4.31.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/README.md +98 -92
- package/package.json +4 -4
- package/src/__tests__/plugin-setup.test.ts +502 -6
- package/src/__tests__/profile-materializer.test.ts +87 -0
- package/src/cli/install.ts +36 -5
- package/src/cli/router.ts +17 -9
- package/src/services/plugin-setup.ts +413 -59
- package/src/services/profile-materializer.ts +55 -4
package/src/cli/install.ts
CHANGED
|
@@ -126,7 +126,16 @@ async function runCheck(
|
|
|
126
126
|
// ── install steps ───────────────────────────────────────────────────────────
|
|
127
127
|
|
|
128
128
|
async function ensureToolchains(closure: ResolvedClosure, yes: boolean): Promise<void> {
|
|
129
|
-
|
|
129
|
+
// Only the binaries actually missing can need a toolchain. Checking all of
|
|
130
|
+
// them warns "pip isn't installed" on a machine whose pip-provided binaries
|
|
131
|
+
// are already on PATH — an alarming message about work that will not happen.
|
|
132
|
+
const missing: ResolvedBin[] = [];
|
|
133
|
+
for (const bin of closure.bins) {
|
|
134
|
+
if (!(await resolveExecutable(bin.name))) missing.push(bin);
|
|
135
|
+
}
|
|
136
|
+
if (missing.length === 0) return;
|
|
137
|
+
|
|
138
|
+
const toolchains = await detectToolchains(missing);
|
|
130
139
|
for (const tc of toolchains) {
|
|
131
140
|
if (tc.present) continue;
|
|
132
141
|
const bootstrap = TOOLCHAIN_BOOTSTRAP[tc.name];
|
|
@@ -160,11 +169,25 @@ async function registerMarketplaces(closure: ResolvedClosure): Promise<void> {
|
|
|
160
169
|
}
|
|
161
170
|
}
|
|
162
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Install the closure's plugins at PROJECT scope.
|
|
174
|
+
*
|
|
175
|
+
* A profile is a property of one repo, so its plugins must be too. At user
|
|
176
|
+
* scope, adopting profiles in a single repo would enable that repo's plugins in
|
|
177
|
+
* every other project on the machine — and since Claude Code resolves
|
|
178
|
+
* enabledPlugins per id with fall-through, those would stay on everywhere.
|
|
179
|
+
* Project scope keeps the blast radius to this repo. The plugin *cache* is
|
|
180
|
+
* global either way, so `profile switch` stays offline.
|
|
181
|
+
*
|
|
182
|
+
* Whatever the CLI writes into .claude/settings.json here is transient:
|
|
183
|
+
* materialization rewrites that file from the manifest, and activation replaces
|
|
184
|
+
* it with a symlink. The manifest stays authoritative.
|
|
185
|
+
*/
|
|
163
186
|
async function installPlugins(closure: ResolvedClosure): Promise<void> {
|
|
164
187
|
for (const pluginId of Object.keys(closure.plugins)) {
|
|
165
188
|
try {
|
|
166
189
|
console.log(`+ plugin ${pluginId}`);
|
|
167
|
-
await installPlugin(pluginId, "
|
|
190
|
+
await installPlugin(pluginId, "project");
|
|
168
191
|
} catch (e) {
|
|
169
192
|
console.warn(`⚠ plugin ${pluginId}: ${(e as Error).message}`);
|
|
170
193
|
}
|
|
@@ -317,10 +340,18 @@ export async function runInstallCommand(
|
|
|
317
340
|
|
|
318
341
|
// Materialize every profile (so `profile switch` needs no reinstall), then
|
|
319
342
|
// activate the target (or the sole/first profile).
|
|
320
|
-
|
|
321
|
-
|
|
343
|
+
//
|
|
344
|
+
// Every profile is materialized even when one was named: a profile arg scopes
|
|
345
|
+
// what gets *installed* and which becomes active, not which settings files
|
|
346
|
+
// exist. It also keeps the union below consistent across all of them — a
|
|
347
|
+
// profile left holding an older union would stop disabling plugins added
|
|
348
|
+
// since, silently making `switch` additive again.
|
|
349
|
+
const unionPluginIds = Object.keys(
|
|
350
|
+
(flags.profile ? await resolveAllProfiles(manifest) : closure).plugins,
|
|
351
|
+
);
|
|
352
|
+
for (const id of profileIds) {
|
|
322
353
|
const profileClosure = await resolveProfile(manifest, id);
|
|
323
|
-
await materializeProfile(id, profileClosure, projectPath);
|
|
354
|
+
await materializeProfile(id, profileClosure, projectPath, unionPluginIds);
|
|
324
355
|
}
|
|
325
356
|
|
|
326
357
|
// Keep the generated dir + active-profile symlinks out of git before
|
package/src/cli/router.ts
CHANGED
|
@@ -73,25 +73,33 @@ function printHelp(version: string): void {
|
|
|
73
73
|
|
|
74
74
|
TUI tool for managing Claude Code plugins, MCPs, and configuration.
|
|
75
75
|
|
|
76
|
-
Usage: claudeup
|
|
77
|
-
claudeup
|
|
78
|
-
claudeup update Update claudeup to latest version
|
|
76
|
+
Usage: claudeup Open the interactive TUI
|
|
77
|
+
claudeup <command> [args]
|
|
79
78
|
|
|
80
79
|
Options:
|
|
81
80
|
-v, --version Show version and check for updates
|
|
82
81
|
-h, --help Show this help message
|
|
83
82
|
--no-refresh Skip auto-refresh of marketplaces on startup
|
|
84
83
|
|
|
85
|
-
|
|
84
|
+
Team profiles — reproduce this repo's Claude Code setup on any machine.
|
|
85
|
+
The manifest is .claude/profiles.json, committed. See docs/team-configuration.md.
|
|
86
|
+
install [profile] Install the profile's plugins, binaries, skills and env,
|
|
87
|
+
then activate it. No argument installs every profile.
|
|
88
|
+
--check Report drift only, write nothing (exits 1 in strict mode)
|
|
89
|
+
--yes, -y Skip the confirmation prompt
|
|
90
|
+
--force Discard unsynced local edits instead of refusing
|
|
91
|
+
profile list Show every profile; ● marks the active one
|
|
92
|
+
profile show <n> Print a profile's fully resolved closure
|
|
93
|
+
profile switch <n> Repoint the active profile — offline, no reinstall
|
|
94
|
+
profile sync Promote local edits back into .claude/profiles.json
|
|
95
|
+
doctor Check binary deps, profile symlinks, and conventions
|
|
96
|
+
--fix Apply the repairs it can make itself
|
|
97
|
+
|
|
98
|
+
Other commands:
|
|
86
99
|
claude [args...] Check for plugin updates (1h cache), then run claude
|
|
87
100
|
-f, --force Force update check (bypass 1h cache)
|
|
88
101
|
update Update claudeup itself to latest version
|
|
89
102
|
|
|
90
|
-
Experimental (in development):
|
|
91
|
-
install [profile] Install a team profile from .claude/profiles.json
|
|
92
|
-
profile <cmd> list | show | switch | sync team profiles
|
|
93
|
-
doctor Diagnose & repair plugin/marketplace/profile state
|
|
94
|
-
|
|
95
103
|
Navigation (TUI):
|
|
96
104
|
[1] Plugins [4] Settings [7] Git State
|
|
97
105
|
[2] Skills [5] Profiles [8] Alias
|