claudeup 6.2.1 → 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__/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 +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 +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
|
@@ -25,66 +25,66 @@ import { join } from "node:path";
|
|
|
25
25
|
import type { ResolvedManifest, Violation } from "../types/gitignore.js";
|
|
26
26
|
|
|
27
27
|
export async function detectViolations(
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
cwd: string,
|
|
29
|
+
resolved: ResolvedManifest,
|
|
30
30
|
): Promise<Violation[]> {
|
|
31
|
-
|
|
31
|
+
if (!(await isGitRepo(cwd))) return [];
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
const violations: Violation[] = [];
|
|
34
|
+
const trackedFiles = await listTrackedFiles(cwd);
|
|
35
|
+
const trackedSet = new Set(trackedFiles);
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
37
|
+
for (const rule of resolved.rules) {
|
|
38
|
+
if (rule.action === "ignore") {
|
|
39
|
+
const tracked = matchesTrackedFile(rule.pattern, trackedSet);
|
|
40
|
+
if (tracked.length > 0) {
|
|
41
|
+
for (const path of tracked) {
|
|
42
|
+
violations.push({
|
|
43
|
+
kind: "tracked-but-should-ignore",
|
|
44
|
+
path,
|
|
45
|
+
source: rule.source,
|
|
46
|
+
severity: "destructive",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
} else {
|
|
50
|
+
// Not tracked — check if .gitignore covers it. If not, suggest
|
|
51
|
+
// a safe additive fix (append to .gitignore).
|
|
52
|
+
const ignored = await pathIsIgnored(cwd, rule.pattern);
|
|
53
|
+
if (!ignored) {
|
|
54
|
+
violations.push({
|
|
55
|
+
kind: "missing-from-gitignore",
|
|
56
|
+
path: rule.pattern,
|
|
57
|
+
source: rule.source,
|
|
58
|
+
severity: "safe",
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
// action === "track"
|
|
64
|
+
const ignored = await pathIsIgnored(cwd, rule.pattern);
|
|
65
|
+
if (ignored) {
|
|
66
|
+
violations.push({
|
|
67
|
+
kind: "ignored-but-should-track",
|
|
68
|
+
path: rule.pattern,
|
|
69
|
+
source: rule.source,
|
|
70
|
+
severity: "destructive",
|
|
71
|
+
});
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const isTracked = trackedSet.has(rule.pattern);
|
|
75
|
+
const existsOnDisk = existsSync(join(cwd, rule.pattern));
|
|
76
|
+
if (existsOnDisk && !isTracked) {
|
|
77
|
+
violations.push({
|
|
78
|
+
kind: "untracked-and-should-track",
|
|
79
|
+
path: rule.pattern,
|
|
80
|
+
source: rule.source,
|
|
81
|
+
severity: "destructive",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
return violations;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/**
|
|
@@ -92,66 +92,76 @@ export async function detectViolations(
|
|
|
92
92
|
* (trailing "/") match every tracked path under that prefix.
|
|
93
93
|
*/
|
|
94
94
|
function matchesTrackedFile(pattern: string, tracked: Set<string>): string[] {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
95
|
+
if (pattern.endsWith("/")) {
|
|
96
|
+
const prefix = pattern;
|
|
97
|
+
return Array.from(tracked).filter((p) => p.startsWith(prefix));
|
|
98
|
+
}
|
|
99
|
+
if (pattern.includes("*")) {
|
|
100
|
+
// Very limited literal-prefix glob handling. Full expansion is git's job.
|
|
101
|
+
const star = pattern.indexOf("*");
|
|
102
|
+
const prefix = pattern.slice(0, star);
|
|
103
|
+
return Array.from(tracked).filter((p) => p.startsWith(prefix));
|
|
104
|
+
}
|
|
105
|
+
return tracked.has(pattern) ? [pattern] : [];
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
async function isGitRepo(cwd: string): Promise<boolean> {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
try {
|
|
110
|
+
await runGit(["rev-parse", "--is-inside-work-tree"], cwd);
|
|
111
|
+
return true;
|
|
112
|
+
} catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
async function listTrackedFiles(cwd: string): Promise<string[]> {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
try {
|
|
119
|
+
const out = await runGit(["ls-files"], cwd);
|
|
120
|
+
return out
|
|
121
|
+
.split("\n")
|
|
122
|
+
.map((l) => l.trim())
|
|
123
|
+
.filter(Boolean);
|
|
124
|
+
} catch {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
async function pathIsIgnored(cwd: string, path: string): Promise<boolean> {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
130
|
+
try {
|
|
131
|
+
// git check-ignore exits 0 when path IS ignored, 1 when NOT, >1 on error.
|
|
132
|
+
await runGit(["check-ignore", "--quiet", "--", path], cwd);
|
|
133
|
+
return true;
|
|
134
|
+
} catch (err) {
|
|
135
|
+
// exit code 1 = not ignored (expected), anything else swallowed.
|
|
136
|
+
if (err instanceof GitError && err.code === 1) return false;
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
class GitError extends Error {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
constructor(
|
|
143
|
+
public code: number,
|
|
144
|
+
public stderr: string,
|
|
145
|
+
) {
|
|
146
|
+
super(`git exited ${code}: ${stderr}`);
|
|
147
|
+
}
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
function runGit(args: string[], cwd: string): Promise<string> {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
const proc = spawn("git", args, { cwd });
|
|
153
|
+
let stdout = "";
|
|
154
|
+
let stderr = "";
|
|
155
|
+
proc.stdout.on("data", (b) => {
|
|
156
|
+
stdout += b.toString();
|
|
157
|
+
});
|
|
158
|
+
proc.stderr.on("data", (b) => {
|
|
159
|
+
stderr += b.toString();
|
|
160
|
+
});
|
|
161
|
+
proc.on("error", reject);
|
|
162
|
+
proc.on("close", (code) => {
|
|
163
|
+
if (code === 0) resolve(stdout);
|
|
164
|
+
else reject(new GitError(code ?? -1, stderr));
|
|
165
|
+
});
|
|
166
|
+
});
|
|
157
167
|
}
|