claudeup 6.2.1 → 6.3.2
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__/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 +18 -4
- package/src/__tests__/plugin-setup.test.ts +12 -12
- 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 +40 -15
- 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 +181 -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 +8 -9
- 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 +13 -3
- 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/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 +9 -6
- package/src/services/plugin-setup.ts +7 -9
- 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/ui/hooks/useAsyncData.ts +0 -127
- package/src/ui/state/AnimationContext.tsx +0 -76
|
@@ -1,168 +1,176 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
4
|
import { tmpdir } from "node:os";
|
|
4
5
|
import { join } from "node:path";
|
|
5
|
-
import { spawnSync } from "node:child_process";
|
|
6
6
|
import { detectViolations } from "../services/gitignore-detector";
|
|
7
7
|
import type { ResolvedManifest } from "../types/gitignore";
|
|
8
8
|
|
|
9
9
|
function git(cwd: string, ...args: string[]): string {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
10
|
+
// core.excludesFile=/dev/null bypasses the developer's global gitignore
|
|
11
|
+
// so the test environment doesn't leak into the result.
|
|
12
|
+
//
|
|
13
|
+
// commit.gpgsign=false is the same isolation, one step further: a developer
|
|
14
|
+
// with signed commits makes every `git commit` here call their signer. With
|
|
15
|
+
// 1Password's SSH agent that means a prompt or an agent error, so these tests
|
|
16
|
+
// failed or timed out locally for reasons that have nothing to do with the
|
|
17
|
+
// code under test. CI has no signing config, so it only ever broke locally.
|
|
18
|
+
const r = spawnSync(
|
|
19
|
+
"git",
|
|
20
|
+
[
|
|
21
|
+
"-c",
|
|
22
|
+
"core.excludesFile=/dev/null",
|
|
23
|
+
"-c",
|
|
24
|
+
"commit.gpgsign=false",
|
|
25
|
+
...args,
|
|
26
|
+
],
|
|
27
|
+
{
|
|
28
|
+
cwd,
|
|
29
|
+
encoding: "utf8",
|
|
30
|
+
},
|
|
31
|
+
);
|
|
32
|
+
if (r.status !== 0) {
|
|
33
|
+
throw new Error(`git ${args.join(" ")} failed: ${r.stderr}`);
|
|
34
|
+
}
|
|
35
|
+
return r.stdout;
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
async function makeRepo(): Promise<string> {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
const dir = await mkdtemp(join(tmpdir(), "gitig-det-"));
|
|
40
|
+
git(dir, "init", "-q");
|
|
41
|
+
git(dir, "config", "user.email", "test@test");
|
|
42
|
+
git(dir, "config", "user.name", "test");
|
|
43
|
+
return dir;
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
function manifest(rules: ResolvedManifest["rules"]): ResolvedManifest {
|
|
43
|
-
|
|
47
|
+
return { rules, conflicts: [] };
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
describe("detectViolations", () => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
51
|
+
let repo: string;
|
|
52
|
+
|
|
53
|
+
beforeEach(async () => {
|
|
54
|
+
repo = await makeRepo();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
afterEach(async () => {
|
|
58
|
+
await rm(repo, { recursive: true, force: true });
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("returns empty for non-git directory", async () => {
|
|
62
|
+
const tmp = await mkdtemp(join(tmpdir(), "gitig-nogit-"));
|
|
63
|
+
try {
|
|
64
|
+
const r = await detectViolations(
|
|
65
|
+
tmp,
|
|
66
|
+
manifest([{ pattern: ".env", action: "ignore", source: "builtin" }]),
|
|
67
|
+
);
|
|
68
|
+
expect(r).toEqual([]);
|
|
69
|
+
} finally {
|
|
70
|
+
await rm(tmp, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("flags tracked-but-should-ignore for a tracked file", async () => {
|
|
75
|
+
await writeFile(join(repo, "secret.txt"), "x");
|
|
76
|
+
git(repo, "add", "secret.txt");
|
|
77
|
+
git(repo, "commit", "-q", "-m", "add secret");
|
|
78
|
+
|
|
79
|
+
const r = await detectViolations(
|
|
80
|
+
repo,
|
|
81
|
+
manifest([
|
|
82
|
+
{ pattern: "secret.txt", action: "ignore", source: "project" },
|
|
83
|
+
]),
|
|
84
|
+
);
|
|
85
|
+
expect(r.length).toBe(1);
|
|
86
|
+
expect(r[0].kind).toBe("tracked-but-should-ignore");
|
|
87
|
+
expect(r[0].severity).toBe("destructive");
|
|
88
|
+
expect(r[0].path).toBe("secret.txt");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("flags missing-from-gitignore when path neither tracked nor in .gitignore", async () => {
|
|
92
|
+
const r = await detectViolations(
|
|
93
|
+
repo,
|
|
94
|
+
manifest([{ pattern: ".env", action: "ignore", source: "builtin" }]),
|
|
95
|
+
);
|
|
96
|
+
expect(r.length).toBe(1);
|
|
97
|
+
expect(r[0].kind).toBe("missing-from-gitignore");
|
|
98
|
+
expect(r[0].severity).toBe("safe");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("does NOT flag missing-from-gitignore when .gitignore already covers the path", async () => {
|
|
102
|
+
await writeFile(join(repo, ".gitignore"), ".env\n");
|
|
103
|
+
const r = await detectViolations(
|
|
104
|
+
repo,
|
|
105
|
+
manifest([{ pattern: ".env", action: "ignore", source: "builtin" }]),
|
|
106
|
+
);
|
|
107
|
+
expect(r).toEqual([]);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("flags ignored-but-should-track when track rule is excluded by .gitignore", async () => {
|
|
111
|
+
await writeFile(join(repo, ".gitignore"), ".mcp.json\n");
|
|
112
|
+
await writeFile(join(repo, ".mcp.json"), "{}");
|
|
113
|
+
const r = await detectViolations(
|
|
114
|
+
repo,
|
|
115
|
+
manifest([{ pattern: ".mcp.json", action: "track", source: "builtin" }]),
|
|
116
|
+
);
|
|
117
|
+
expect(r.length).toBe(1);
|
|
118
|
+
expect(r[0].kind).toBe("ignored-but-should-track");
|
|
119
|
+
expect(r[0].severity).toBe("destructive");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("flags untracked-and-should-track when path exists but isn't tracked", async () => {
|
|
123
|
+
await writeFile(join(repo, ".mcp.json"), "{}");
|
|
124
|
+
const r = await detectViolations(
|
|
125
|
+
repo,
|
|
126
|
+
manifest([{ pattern: ".mcp.json", action: "track", source: "builtin" }]),
|
|
127
|
+
);
|
|
128
|
+
expect(r.length).toBe(1);
|
|
129
|
+
expect(r[0].kind).toBe("untracked-and-should-track");
|
|
130
|
+
expect(r[0].severity).toBe("destructive");
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("does NOT flag track rule when path is already tracked", async () => {
|
|
134
|
+
await writeFile(join(repo, ".mcp.json"), "{}");
|
|
135
|
+
git(repo, "add", ".mcp.json");
|
|
136
|
+
git(repo, "commit", "-q", "-m", "add mcp");
|
|
137
|
+
const r = await detectViolations(
|
|
138
|
+
repo,
|
|
139
|
+
manifest([{ pattern: ".mcp.json", action: "track", source: "builtin" }]),
|
|
140
|
+
);
|
|
141
|
+
expect(r).toEqual([]);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("matches directory patterns against tracked subpaths", async () => {
|
|
145
|
+
await mkdir(join(repo, "ai-docs", "sessions"), { recursive: true });
|
|
146
|
+
await writeFile(join(repo, "ai-docs", "sessions", "leak.md"), "x");
|
|
147
|
+
git(repo, "add", "ai-docs/sessions/leak.md");
|
|
148
|
+
git(repo, "commit", "-q", "-m", "leak");
|
|
149
|
+
|
|
150
|
+
const r = await detectViolations(
|
|
151
|
+
repo,
|
|
152
|
+
manifest([
|
|
153
|
+
{ pattern: "ai-docs/sessions/", action: "ignore", source: "builtin" },
|
|
154
|
+
]),
|
|
155
|
+
);
|
|
156
|
+
expect(r.length).toBeGreaterThan(0);
|
|
157
|
+
expect(r[0].kind).toBe("tracked-but-should-ignore");
|
|
158
|
+
expect(r[0].path).toBe("ai-docs/sessions/leak.md");
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it("returns no violations when manifest is satisfied", async () => {
|
|
162
|
+
await writeFile(join(repo, ".gitignore"), ".env\n");
|
|
163
|
+
await writeFile(join(repo, ".mcp.json"), "{}");
|
|
164
|
+
git(repo, "add", ".gitignore", ".mcp.json");
|
|
165
|
+
git(repo, "commit", "-q", "-m", "init");
|
|
166
|
+
|
|
167
|
+
const r = await detectViolations(
|
|
168
|
+
repo,
|
|
169
|
+
manifest([
|
|
170
|
+
{ pattern: ".env", action: "ignore", source: "builtin" },
|
|
171
|
+
{ pattern: ".mcp.json", action: "track", source: "builtin" },
|
|
172
|
+
]),
|
|
173
|
+
);
|
|
174
|
+
expect(r).toEqual([]);
|
|
175
|
+
});
|
|
168
176
|
});
|