claudeup 6.2.0 → 6.3.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 +22 -0
- package/bin/claudeup.js +6 -1
- package/package.json +6 -6
- package/src/__tests__/alias-adopt.test.ts +331 -329
- package/src/__tests__/alias-parser.test.ts +384 -376
- package/src/__tests__/alias-shell-writer.test.ts +638 -625
- package/src/__tests__/alias-store.test.ts +143 -143
- package/src/__tests__/catalog-cache-store.test.ts +265 -265
- package/src/__tests__/catalog-notice.test.ts +123 -123
- package/src/__tests__/cli-apply-seams.test.ts +12 -8
- package/src/__tests__/cli-router.test.ts +132 -3
- package/src/__tests__/cli-update-view.test.ts +27 -8
- package/src/__tests__/community-staleness.test.ts +0 -2
- package/src/__tests__/component-badge.test.ts +4 -4
- package/src/__tests__/content-drift.test.ts +5 -1
- package/src/__tests__/conventions-integration.test.ts +774 -689
- package/src/__tests__/conventions-manager.test.ts +1216 -1152
- package/src/__tests__/doctor-bins.test.ts +14 -6
- package/src/__tests__/doctor.test.ts +438 -425
- package/src/__tests__/dual-write-prevention.test.ts +277 -282
- package/src/__tests__/enabled-not-installed.test.ts +71 -63
- package/src/__tests__/file-locking.test.ts +196 -196
- package/src/__tests__/gap-fill-versions.test.ts +318 -311
- package/src/__tests__/github-budget.test.ts +170 -164
- package/src/__tests__/gitignore-detector.test.ts +160 -152
- package/src/__tests__/gitignore-fixer.test.ts +285 -247
- package/src/__tests__/gitignore-prerun.test.ts +57 -57
- package/src/__tests__/gitignore-resolver.test.ts +173 -146
- package/src/__tests__/gitignore-service.test.ts +121 -119
- package/src/__tests__/go-module.test.ts +43 -0
- package/src/__tests__/install-command.test.ts +3 -3
- package/src/__tests__/install-plan.test.ts +13 -7
- package/src/__tests__/manifest.test.ts +16 -5
- package/src/__tests__/markdown-renderer.test.ts +0 -1
- package/src/__tests__/marketplace-badge.test.ts +111 -90
- package/src/__tests__/marketplace-version.test.ts +64 -61
- package/src/__tests__/plugin-manager-fallback.test.ts +249 -239
- package/src/__tests__/plugin-requires.test.ts +55 -1
- package/src/__tests__/plugin-setup.test.ts +111 -9
- package/src/__tests__/profile-command.test.ts +1 -7
- package/src/__tests__/profile-materializer.test.ts +31 -8
- package/src/__tests__/profile-sync.test.ts +23 -5
- package/src/__tests__/registry-version-resolution.test.ts +61 -47
- package/src/__tests__/resolve-executable.test.ts +1 -1
- package/src/__tests__/resolver.test.ts +38 -13
- package/src/__tests__/scope-action.test.ts +52 -50
- package/src/__tests__/scope-squares.test.tsx +4 -5
- package/src/__tests__/skill-install-files.test.ts +111 -103
- package/src/__tests__/symlink-manager.test.ts +27 -10
- package/src/__tests__/theme-env.test.ts +281 -0
- package/src/__tests__/theme-resolve.test.ts +380 -0
- package/src/__tests__/update-apply.test.ts +1 -3
- package/src/__tests__/useGitignoreModal.test.ts +69 -61
- package/src/__tests__/version-snapshot.test.ts +183 -165
- package/src/cli/ansi.ts +23 -15
- package/src/cli/doctor.ts +10 -9
- package/src/cli/install.ts +3 -3
- package/src/cli/profile.ts +5 -4
- package/src/cli/prompt.ts +0 -1
- package/src/cli/router.ts +69 -2
- package/src/cli/update-view.ts +11 -6
- package/src/cli/update.ts +9 -4
- package/src/cli/upgrade.ts +6 -4
- package/src/data/alias-flags.ts +260 -260
- package/src/data/gitignore-defaults.ts +20 -20
- package/src/data/gitignore-reasons.ts +86 -92
- package/src/data/gitignore-templates.ts +14 -14
- package/src/data/predefined-profiles.ts +1 -2
- package/src/data/skill-repos.ts +43 -35
- package/src/main.tsx +29 -6
- package/src/opentui.d.ts +1 -3
- package/src/prerunner/index.ts +7 -8
- package/src/services/alias-settings.ts +20 -23
- package/src/services/alias-shell-writer.ts +800 -803
- package/src/services/alias-store.ts +77 -77
- package/src/services/claude-settings.ts +27 -18
- package/src/services/content-drift.ts +14 -4
- package/src/services/conventions-manager.ts +692 -617
- package/src/services/doctor.ts +464 -403
- package/src/services/gitignore-detector.ts +113 -103
- package/src/services/gitignore-fixer.ts +204 -189
- package/src/services/gitignore-prerun.ts +26 -26
- package/src/services/gitignore-resolver.ts +162 -144
- package/src/services/gitignore-service.ts +120 -117
- package/src/services/install-plan.ts +4 -4
- package/src/services/local-marketplace.ts +7 -5
- package/src/services/manifest.ts +1 -1
- package/src/services/marketplace-catalog-git.ts +5 -2
- package/src/services/marketplace-fetcher.ts +241 -235
- package/src/services/plugin-manager.ts +17 -20
- package/src/services/plugin-mcp-config.ts +2 -2
- package/src/services/plugin-requires.ts +16 -8
- package/src/services/plugin-setup.ts +32 -15
- package/src/services/plugin-version-check.ts +4 -4
- package/src/services/profile-materializer.ts +9 -5
- package/src/services/profile-sync.ts +12 -4
- package/src/services/profiles.ts +3 -3
- package/src/services/resolver.ts +10 -6
- package/src/services/settings-manager.ts +82 -46
- package/src/services/skills-manager.ts +11 -9
- package/src/services/symlink-manager.ts +2 -5
- package/src/services/toolchain.ts +3 -3
- package/src/services/update-cache.ts +1 -1
- package/src/services/update-engine.ts +4 -4
- package/src/services/update-plan.ts +9 -11
- package/src/services/version-snapshot.ts +88 -88
- package/src/types/gitignore.ts +28 -28
- package/src/ui/App.tsx +36 -36
- package/src/ui/adapters/settingsAdapter.ts +2 -2
- package/src/ui/components/CategoryHeader.tsx +1 -1
- package/src/ui/components/FlagDetailEditor.tsx +0 -0
- package/src/ui/components/ScopeIndicator.tsx +3 -1
- package/src/ui/components/ScrollableList.tsx +2 -1
- package/src/ui/components/StyledText.tsx +1 -1
- package/src/ui/components/layout/FooterHints.tsx +5 -3
- package/src/ui/components/layout/Panel.tsx +2 -2
- package/src/ui/components/layout/ScreenLayout.tsx +5 -4
- package/src/ui/components/modals/InputModal.tsx +7 -1
- package/src/ui/components/modals/ModalContainer.tsx +3 -3
- package/src/ui/components/modals/SelectModal.tsx +1 -1
- package/src/ui/components/primitives/DetailSection.tsx +1 -1
- package/src/ui/components/primitives/KeyValueLine.tsx +1 -1
- package/src/ui/components/primitives/ScopeSquares.tsx +2 -2
- package/src/ui/hooks/index.ts +0 -1
- package/src/ui/hooks/useGitignoreModal.ts +1 -5
- package/src/ui/hooks/useMismatchModal.ts +4 -10
- package/src/ui/renderers/cliToolRenderers.tsx +2 -2
- package/src/ui/renderers/gitignoreRenderers.tsx +2 -2
- package/src/ui/renderers/mcpRenderers.tsx +1 -1
- package/src/ui/renderers/pluginRenderers.tsx +3 -9
- package/src/ui/renderers/profileRenderers.tsx +9 -8
- package/src/ui/renderers/settingsRenderers.tsx +4 -4
- package/src/ui/renderers/skillRenderers.tsx +14 -14
- package/src/ui/screens/AliasScreen.tsx +31 -34
- package/src/ui/screens/CliToolsScreen.tsx +14 -13
- package/src/ui/screens/EnvVarsScreen.tsx +8 -8
- package/src/ui/screens/GitignoreScreen.tsx +15 -14
- package/src/ui/screens/McpRegistryScreen.tsx +10 -7
- package/src/ui/screens/McpScreen.tsx +10 -10
- package/src/ui/screens/PluginsScreen.tsx +17 -21
- package/src/ui/screens/ProfilesScreen.tsx +25 -24
- package/src/ui/screens/SkillsScreen.tsx +16 -14
- package/src/ui/state/AppContext.tsx +4 -8
- package/src/ui/state/DimensionsContext.tsx +3 -2
- package/src/ui/theme-mode.ts +20 -38
- package/src/ui/theme-resolve.ts +148 -0
- package/src/utils/clipboard.ts +5 -5
- package/src/utils/command-utils.ts +2 -2
- package/src/utils/config-dir.ts +1 -3
- package/src/utils/file-locking.ts +88 -86
- package/src/utils/go-module.ts +36 -0
- package/src/ui/hooks/useAsyncData.ts +0 -127
- package/src/ui/state/AnimationContext.tsx +0 -76
package/src/cli/doctor.ts
CHANGED
|
@@ -8,16 +8,13 @@
|
|
|
8
8
|
* 3. Convention compliance — .gitignore + CLAUDE.md blocks (ported engine).
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import fs from "fs-extra";
|
|
12
11
|
import path from "node:path";
|
|
13
|
-
import
|
|
14
|
-
import { resolveAllProfiles } from "../services/resolver.js";
|
|
12
|
+
import fs from "fs-extra";
|
|
15
13
|
import { checkBinaries, missingBinaries } from "../services/doctor-bins.js";
|
|
16
|
-
import {
|
|
17
|
-
activeProfile,
|
|
18
|
-
profileDir,
|
|
19
|
-
} from "../services/symlink-manager.js";
|
|
20
14
|
import { checkProject, fixDoctorIssues } from "../services/doctor.js";
|
|
15
|
+
import { readManifest } from "../services/manifest.js";
|
|
16
|
+
import { resolveAllProfiles } from "../services/resolver.js";
|
|
17
|
+
import { activeProfile, profileDir } from "../services/symlink-manager.js";
|
|
21
18
|
|
|
22
19
|
export async function runDoctorCommand(args: string[]): Promise<number> {
|
|
23
20
|
const fix = args.includes("--fix");
|
|
@@ -42,7 +39,9 @@ export async function runDoctorCommand(args: string[]): Promise<number> {
|
|
|
42
39
|
problems++;
|
|
43
40
|
}
|
|
44
41
|
} else {
|
|
45
|
-
console.log(
|
|
42
|
+
console.log(
|
|
43
|
+
`✓ All ${closure.bins.length} binary dependencies present.`,
|
|
44
|
+
);
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
}
|
|
@@ -70,7 +69,9 @@ export async function runDoctorCommand(args: string[]): Promise<number> {
|
|
|
70
69
|
if (actionable.length > 0) {
|
|
71
70
|
console.log("\nConventions:");
|
|
72
71
|
for (const check of actionable) {
|
|
73
|
-
console.log(
|
|
72
|
+
console.log(
|
|
73
|
+
` ${check.status === "fail" ? "✗" : "•"} ${check.message}`,
|
|
74
|
+
);
|
|
74
75
|
}
|
|
75
76
|
const fixable = actionable.filter((c) => c.fixable).length;
|
|
76
77
|
const failures = actionable.filter((c) => c.status === "fail").length;
|
package/src/cli/install.ts
CHANGED
|
@@ -48,9 +48,9 @@ import type {
|
|
|
48
48
|
SkillInfo,
|
|
49
49
|
} from "../types/index.js";
|
|
50
50
|
import { formatCommand, resolveExecutable } from "../utils/command-utils.js";
|
|
51
|
+
import { runCommand, runShellScript } from "../utils/run.js";
|
|
51
52
|
import { ensureManifest } from "./bootstrap.js";
|
|
52
53
|
import { confirm, promptValue } from "./prompt.js";
|
|
53
|
-
import { runCommand, runShellScript } from "../utils/run.js";
|
|
54
54
|
|
|
55
55
|
interface InstallFlags {
|
|
56
56
|
check: boolean;
|
|
@@ -292,8 +292,8 @@ export async function runInstallCommand(
|
|
|
292
292
|
);
|
|
293
293
|
for (const c of drift) console.error(` ${c.kind}: ${c.detail}`);
|
|
294
294
|
console.error(
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
"\nRun `claudeup profile sync` to promote them into .claude/profiles.json,\n" +
|
|
296
|
+
"or re-run with --force to discard them.",
|
|
297
297
|
);
|
|
298
298
|
return 1;
|
|
299
299
|
}
|
package/src/cli/profile.ts
CHANGED
|
@@ -66,7 +66,7 @@ export async function initProfile(
|
|
|
66
66
|
`${getManifestPath(projectPath)} already defines: ${Object.keys(existing.profiles).join(", ")}`,
|
|
67
67
|
);
|
|
68
68
|
console.error(
|
|
69
|
-
|
|
69
|
+
"Use `claudeup profile sync` to promote local edits into it.",
|
|
70
70
|
);
|
|
71
71
|
return 1;
|
|
72
72
|
}
|
|
@@ -85,7 +85,7 @@ export async function listProfiles(projectPath: string): Promise<number> {
|
|
|
85
85
|
const active = await activeProfile(projectPath);
|
|
86
86
|
console.log("Profiles:");
|
|
87
87
|
for (const id of ids) {
|
|
88
|
-
const entry = manifest.profiles[id]
|
|
88
|
+
const entry = manifest.profiles[id];
|
|
89
89
|
const marker = id === active ? "●" : " ";
|
|
90
90
|
const materialized = (await fs.pathExists(profileDir(id, projectPath)))
|
|
91
91
|
? ""
|
|
@@ -105,14 +105,15 @@ export async function showProfile(
|
|
|
105
105
|
return 1;
|
|
106
106
|
}
|
|
107
107
|
const manifest = await readManifest(projectPath);
|
|
108
|
-
|
|
108
|
+
const entry = manifest.profiles[name];
|
|
109
|
+
if (!entry) {
|
|
109
110
|
console.error(
|
|
110
111
|
`Profile "${name}" not found. Available: ${Object.keys(manifest.profiles).join(", ")}`,
|
|
111
112
|
);
|
|
112
113
|
return 1;
|
|
113
114
|
}
|
|
114
115
|
const closure = await resolveProfile(manifest, name);
|
|
115
|
-
console.log(`Profile: ${name} (${
|
|
116
|
+
console.log(`Profile: ${name} (${entry.name})`);
|
|
116
117
|
for (const line of summarizeClosure(closure)) console.log(` ${line}`);
|
|
117
118
|
return 0;
|
|
118
119
|
}
|
package/src/cli/prompt.ts
CHANGED
package/src/cli/router.ts
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
* to the interactive TUI, preserving claudeup's historical behavior.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import type { ThemeMode } from "@opentui/core";
|
|
9
10
|
import { checkForUpdates } from "../services/version-check.js";
|
|
11
|
+
import { parseThemeWord } from "../ui/theme-resolve.js";
|
|
10
12
|
import { runClaudeCommand } from "./claude.js";
|
|
11
13
|
import { runDoctorCommand } from "./doctor.js";
|
|
12
14
|
import { runInstallCommand } from "./install.js";
|
|
@@ -21,6 +23,58 @@ export interface RouteOutcome {
|
|
|
21
23
|
exitCode?: number;
|
|
22
24
|
/** No subcommand matched — the caller should launch the TUI. */
|
|
23
25
|
launchTui: boolean;
|
|
26
|
+
/** From --theme, validated. Only meaningful when launchTui is true. */
|
|
27
|
+
theme?: ThemeMode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type ThemeFlagParse =
|
|
31
|
+
| { ok: true; theme?: ThemeMode; rest: string[] }
|
|
32
|
+
| { ok: false; message: string };
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Pull `--theme light|dark` (or `--theme=…`) out of argv.
|
|
36
|
+
*
|
|
37
|
+
* Exact words only, the same rule every other theme source follows — so
|
|
38
|
+
* `--theme Dark` errors instead of silently differing from `TERM_THEME=Dark`.
|
|
39
|
+
* A flag is typed on purpose, so a bad value is an error rather than the "no
|
|
40
|
+
* opinion" an inherited variable gets. `--theme` as the last token, or followed
|
|
41
|
+
* by another `--flag`, is the same error.
|
|
42
|
+
*/
|
|
43
|
+
export function parseThemeFlag(argv: string[]): ThemeFlagParse {
|
|
44
|
+
const rest: string[] = [];
|
|
45
|
+
let theme: ThemeMode | undefined;
|
|
46
|
+
|
|
47
|
+
const invalid = (got: string | undefined): ThemeFlagParse => ({
|
|
48
|
+
ok: false,
|
|
49
|
+
message:
|
|
50
|
+
got === undefined
|
|
51
|
+
? 'claudeup: --theme must be "light" or "dark" (no value given)'
|
|
52
|
+
: `claudeup: --theme must be "light" or "dark" (got "${got}")`,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
56
|
+
const token = argv[i] as string;
|
|
57
|
+
let value: string | undefined;
|
|
58
|
+
|
|
59
|
+
if (token === "--theme") {
|
|
60
|
+
const next = argv[i + 1];
|
|
61
|
+
if (next === undefined || next.startsWith("--"))
|
|
62
|
+
return invalid(undefined);
|
|
63
|
+
value = next;
|
|
64
|
+
i += 1;
|
|
65
|
+
} else if (token.startsWith("--theme=")) {
|
|
66
|
+
value = token.slice("--theme=".length);
|
|
67
|
+
} else {
|
|
68
|
+
rest.push(token);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const parsed = parseThemeWord(value);
|
|
73
|
+
if (parsed === null) return invalid(value);
|
|
74
|
+
theme = parsed;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return theme === undefined ? { ok: true, rest } : { ok: true, theme, rest };
|
|
24
78
|
}
|
|
25
79
|
|
|
26
80
|
const HANDLED = (exitCode: number): RouteOutcome => ({
|
|
@@ -50,7 +104,15 @@ export async function route(
|
|
|
50
104
|
return HANDLED(0);
|
|
51
105
|
}
|
|
52
106
|
|
|
53
|
-
const
|
|
107
|
+
const themeFlag = parseThemeFlag(argv);
|
|
108
|
+
if (!themeFlag.ok) {
|
|
109
|
+
console.error(themeFlag.message);
|
|
110
|
+
return HANDLED(1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Dispatch on argv with the theme tokens removed, so `--theme dark update`
|
|
114
|
+
// still runs `update`. Subcommands ignore the flag; only the TUI carries it.
|
|
115
|
+
const [command, ...rest] = themeFlag.rest;
|
|
54
116
|
|
|
55
117
|
switch (command) {
|
|
56
118
|
case "claude":
|
|
@@ -67,7 +129,9 @@ export async function route(
|
|
|
67
129
|
return HANDLED(await runDoctorCommand(rest));
|
|
68
130
|
default:
|
|
69
131
|
// Bare `claudeup` or an unrecognized token → interactive TUI.
|
|
70
|
-
return
|
|
132
|
+
return themeFlag.theme === undefined
|
|
133
|
+
? LAUNCH_TUI
|
|
134
|
+
: { ...LAUNCH_TUI, theme: themeFlag.theme };
|
|
71
135
|
}
|
|
72
136
|
}
|
|
73
137
|
|
|
@@ -83,6 +147,9 @@ Options:
|
|
|
83
147
|
-v, --version Show version and check for updates
|
|
84
148
|
-h, --help Show this help message
|
|
85
149
|
--no-refresh Skip auto-refresh of marketplaces on startup
|
|
150
|
+
--theme light|dark Force the palette. Otherwise: CLAUDEUP_THEME, then
|
|
151
|
+
TERM_THEME, then a 250 ms terminal query, then COLORFGBG,
|
|
152
|
+
then dark. Only the exact words "light"/"dark" count.
|
|
86
153
|
|
|
87
154
|
Dependency management — keep this project's plugins, CLI tools and skills
|
|
88
155
|
installed and current. The manifest is .claude/profiles.json, committed; a repo
|
package/src/cli/update-view.ts
CHANGED
|
@@ -24,13 +24,13 @@
|
|
|
24
24
|
* own word, so the report survives NO_COLOR, a pipe, and colour blindness.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
+
import { binInstallCommand, binUpgradeCommand } from "../services/toolchain.js";
|
|
27
28
|
import type {
|
|
28
29
|
BinUpdateItem,
|
|
29
30
|
PluginUpdateItem,
|
|
30
31
|
SkillUpdateItem,
|
|
31
32
|
UpdatePlan,
|
|
32
33
|
} from "../services/update-plan.js";
|
|
33
|
-
import { binInstallCommand, binUpgradeCommand } from "../services/toolchain.js";
|
|
34
34
|
import { brand } from "../ui/theme.js";
|
|
35
35
|
import { formatCommand } from "../utils/command-utils.js";
|
|
36
36
|
import {
|
|
@@ -197,7 +197,9 @@ export function stepFrame(steps: Step[], tick: number, now: number): string[] {
|
|
|
197
197
|
? `${fg(brand.accent, `${step.progress.done}/${step.progress.total}`)} `
|
|
198
198
|
: "";
|
|
199
199
|
const detail =
|
|
200
|
-
step.state === "running"
|
|
200
|
+
step.state === "running"
|
|
201
|
+
? fg(brand.accent, step.detail)
|
|
202
|
+
: dim(step.detail);
|
|
201
203
|
return `${PAD}${stepMark(step, tick)} ${label} ${bar} ${time} ${count}${detail}`;
|
|
202
204
|
});
|
|
203
205
|
}
|
|
@@ -214,10 +216,10 @@ export function stepRecord(steps: Step[], now: number): string[] {
|
|
|
214
216
|
const times = steps.map((s) => stepDuration(s, now) ?? 0);
|
|
215
217
|
const slowest = Math.max(1, ...times);
|
|
216
218
|
return steps.map((step, i) => {
|
|
217
|
-
const share = (times[i]
|
|
219
|
+
const share = (times[i] / slowest) * 100;
|
|
218
220
|
const bar = meter(share, BAR, ramps.severity);
|
|
219
221
|
const label = padEnd(step.label, STEP_LABEL_WIDTH);
|
|
220
|
-
const time = dim(padStart(elapsed(times[i]
|
|
222
|
+
const time = dim(padStart(elapsed(times[i]), 6));
|
|
221
223
|
return `${PAD}${stepMark(step, 0)} ${label} ${bar} ${time} ${dim(
|
|
222
224
|
step.detail,
|
|
223
225
|
)}`;
|
|
@@ -275,7 +277,8 @@ function section(
|
|
|
275
277
|
): string[] {
|
|
276
278
|
if (rows.length === 0) return [];
|
|
277
279
|
const counts = new Map<ActionKey, number>();
|
|
278
|
-
for (const row of rows)
|
|
280
|
+
for (const row of rows)
|
|
281
|
+
counts.set(row.action, (counts.get(row.action) ?? 0) + 1);
|
|
279
282
|
const bar = stackedBar(
|
|
280
283
|
BAR,
|
|
281
284
|
[...counts].map(([action, value]) => ({
|
|
@@ -284,7 +287,9 @@ function section(
|
|
|
284
287
|
})),
|
|
285
288
|
);
|
|
286
289
|
const legend = [...counts]
|
|
287
|
-
.map(([action, n]) =>
|
|
290
|
+
.map(([action, n]) =>
|
|
291
|
+
fg(ACTIONS[action].color, `${n} ${ACTIONS[action].label.toLowerCase()}`),
|
|
292
|
+
)
|
|
288
293
|
.join(dim(" · "));
|
|
289
294
|
|
|
290
295
|
return [
|
package/src/cli/update.ts
CHANGED
|
@@ -108,7 +108,6 @@ export function parseArgs(args: string[]): UpdateFlags {
|
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
|
|
112
111
|
// -- phase runner ------------------------------------------------------------
|
|
113
112
|
|
|
114
113
|
/**
|
|
@@ -254,7 +253,9 @@ export async function runUpdateCommand(
|
|
|
254
253
|
// Only now is there a denominator; until `onStart` fires the step
|
|
255
254
|
// shows a sweep rather than a meter that would have to guess one.
|
|
256
255
|
steps.marketplaces.progress = { done: 0, total: names.length };
|
|
257
|
-
say(
|
|
256
|
+
say(
|
|
257
|
+
names.length === 0 ? "none eligible" : `pulling ${names.join(", ")}`,
|
|
258
|
+
);
|
|
258
259
|
},
|
|
259
260
|
onSettled: (name, status) => {
|
|
260
261
|
settled++;
|
|
@@ -285,7 +286,9 @@ export async function runUpdateCommand(
|
|
|
285
286
|
),
|
|
286
287
|
);
|
|
287
288
|
notices.push(
|
|
288
|
-
noteLine(
|
|
289
|
+
noteLine(
|
|
290
|
+
`claude plugin marketplace update ${name} # to refresh it once`,
|
|
291
|
+
),
|
|
289
292
|
);
|
|
290
293
|
}
|
|
291
294
|
for (const name of refresh.failed) {
|
|
@@ -439,7 +442,9 @@ export async function runUpdateCommand(
|
|
|
439
442
|
|
|
440
443
|
if (!(await isClaudeAvailable())) {
|
|
441
444
|
console.error(
|
|
442
|
-
failLine(
|
|
445
|
+
failLine(
|
|
446
|
+
"claude CLI not found on PATH — cannot install or update plugins.",
|
|
447
|
+
),
|
|
443
448
|
);
|
|
444
449
|
return 1;
|
|
445
450
|
}
|
package/src/cli/upgrade.ts
CHANGED
|
@@ -26,7 +26,8 @@ export async function runUpgradeCommand(): Promise<number> {
|
|
|
26
26
|
timeout: 5000,
|
|
27
27
|
}).trim();
|
|
28
28
|
const bunPath = `${bunGlobalBin}/claudeup`;
|
|
29
|
-
if (existsSync(bunPath))
|
|
29
|
+
if (existsSync(bunPath))
|
|
30
|
+
installations.push({ manager: "bun", path: bunPath });
|
|
30
31
|
} catch {
|
|
31
32
|
// bun not installed or no global claudeup
|
|
32
33
|
}
|
|
@@ -38,7 +39,8 @@ export async function runUpgradeCommand(): Promise<number> {
|
|
|
38
39
|
timeout: 5000,
|
|
39
40
|
}).trim();
|
|
40
41
|
const npmPath = `${npmPrefix}/bin/claudeup`;
|
|
41
|
-
if (existsSync(npmPath))
|
|
42
|
+
if (existsSync(npmPath))
|
|
43
|
+
installations.push({ manager: "npm", path: npmPath });
|
|
42
44
|
} catch {
|
|
43
45
|
// npm not installed or no global claudeup
|
|
44
46
|
}
|
|
@@ -50,12 +52,12 @@ export async function runUpgradeCommand(): Promise<number> {
|
|
|
50
52
|
timeout: 5000,
|
|
51
53
|
}).trim();
|
|
52
54
|
|
|
53
|
-
console.log(
|
|
55
|
+
console.log("⚠ claudeup is installed via multiple package managers:\n");
|
|
54
56
|
for (const inst of installations) {
|
|
55
57
|
const tag = inst.path === activePath ? " (active)" : " (shadowed)";
|
|
56
58
|
console.log(` ${inst.manager}: ${inst.path}${tag}`);
|
|
57
59
|
}
|
|
58
|
-
console.log(
|
|
60
|
+
console.log("\nTo fix, keep one and remove the other:");
|
|
59
61
|
for (const inst of installations) {
|
|
60
62
|
console.log(` ${inst.manager} uninstall -g claudeup`);
|
|
61
63
|
}
|