@codecademy/gamut 68.6.1-alpha.e6c390.0 → 68.6.1-alpha.f6b2ce.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/agent-tools/.cursor-plugin/plugin.json +1 -1
- package/agent-tools/DESIGN.Codecademy.md +239 -191
- package/agent-tools/DESIGN.LXStudio.md +236 -184
- package/agent-tools/DESIGN.Percipio.md +232 -182
- package/agent-tools/DESIGN.md +1 -1
- package/agent-tools/commands/gamut-review.md +176 -87
- package/agent-tools/guidelines/components/animations.md +74 -0
- package/agent-tools/guidelines/components/buttons.md +74 -23
- package/agent-tools/guidelines/components/card.md +19 -0
- package/agent-tools/guidelines/components/coachmark.md +21 -0
- package/agent-tools/guidelines/components/data-table.md +79 -0
- package/agent-tools/guidelines/components/forms.md +106 -0
- package/agent-tools/guidelines/components/loading-states.md +17 -0
- package/agent-tools/guidelines/components/menu.md +58 -0
- package/agent-tools/guidelines/components/overview.md +97 -17
- package/agent-tools/guidelines/components/radial-progress.md +13 -0
- package/agent-tools/guidelines/components/select.md +23 -0
- package/agent-tools/guidelines/components/tooltips.md +22 -0
- package/agent-tools/guidelines/components/video.md +29 -0
- package/agent-tools/guidelines/foundations/color.md +140 -58
- package/agent-tools/guidelines/foundations/modes.md +39 -17
- package/agent-tools/guidelines/foundations/spacing.md +78 -37
- package/agent-tools/guidelines/foundations/typography.md +69 -37
- package/agent-tools/guidelines/overview-icons.md +19 -0
- package/agent-tools/guidelines/overview-illustrations.md +7 -0
- package/agent-tools/guidelines/overview-patterns.md +7 -0
- package/agent-tools/guidelines/overview.md +69 -23
- package/agent-tools/guidelines/setup.md +59 -18
- package/agent-tools/rules/accessibility.mdc +22 -13
- package/agent-tools/skills/gamut-accessibility/SKILL.md +97 -112
- package/agent-tools/skills/gamut-color-mode/SKILL.md +79 -29
- package/agent-tools/skills/gamut-components/SKILL.md +46 -0
- package/agent-tools/skills/gamut-forms/SKILL.md +101 -0
- package/agent-tools/skills/gamut-style-utilities/SKILL.md +111 -0
- package/agent-tools/skills/gamut-system-props/SKILL.md +70 -26
- package/agent-tools/skills/gamut-testing/SKILL.md +106 -62
- package/agent-tools/skills/gamut-theming/SKILL.md +34 -86
- package/agent-tools/skills/gamut-typography/SKILL.md +36 -80
- package/bin/commands/plugin/install.mjs +96 -56
- package/bin/commands/plugin/list.mjs +11 -43
- package/bin/commands/plugin/remove.mjs +30 -38
- package/bin/commands/plugin/update.mjs +15 -5
- package/bin/gamut.mjs +17 -13
- package/bin/lib/design.mjs +71 -0
- package/bin/lib/io.mjs +14 -0
- package/package.json +6 -6
- package/bin/lib/figma.mjs +0 -49
|
@@ -1,39 +1,46 @@
|
|
|
1
1
|
import { cp, mkdir, readdir, rm, symlink } from 'node:fs/promises';
|
|
2
|
-
import {
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
3
|
|
|
4
4
|
import { claudePluginSpec, marketplaceName } from '../../lib/claude.mjs';
|
|
5
5
|
import { cursorDestPath } from '../../lib/cursor.mjs';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
installDesignMd,
|
|
8
|
+
listCanonicalThemes,
|
|
9
|
+
resolveTheme,
|
|
10
|
+
} from '../../lib/design.mjs';
|
|
11
|
+
import { log, warn } from '../../lib/io.mjs';
|
|
7
12
|
import { getFlag, resolvePluginDir } from '../../lib/resolve-plugin-dir.mjs';
|
|
8
13
|
import { runCommand } from '../../lib/run-command.mjs';
|
|
9
14
|
|
|
10
|
-
export const TARGETS = ['cursor', 'claude'
|
|
15
|
+
export const TARGETS = ['cursor', 'claude'];
|
|
11
16
|
export const SCOPES = ['all', 'skills', 'rules', 'commands', 'agents'];
|
|
12
17
|
|
|
13
18
|
export function help() {
|
|
14
|
-
|
|
19
|
+
log(`
|
|
15
20
|
Usage:
|
|
16
21
|
gamut plugin install [target] [options]
|
|
17
22
|
|
|
18
|
-
Install the Gamut plugin into an AI
|
|
23
|
+
Install the Gamut plugin into an AI tool.
|
|
19
24
|
|
|
20
25
|
Arguments:
|
|
21
26
|
target Tool to install into (default: cursor)
|
|
22
|
-
cursor | claude
|
|
27
|
+
cursor | claude
|
|
23
28
|
|
|
24
29
|
Options:
|
|
25
30
|
--scope <scope> Content to install (default: all)
|
|
26
31
|
all | skills | rules | commands | agents
|
|
27
|
-
--
|
|
28
|
-
|
|
32
|
+
--theme <theme> Copy DESIGN.*.md to ./DESIGN.md in the current directory
|
|
33
|
+
core | admin | platform | percipio | lxstudio
|
|
34
|
+
(admin/platform use Codecademy DESIGN; aliases: codecademy, cc, lx-studio)
|
|
35
|
+
--force Overwrite existing DESIGN.md when using --theme
|
|
29
36
|
--plugin-dir <path> Override the bundled agent-tools directory
|
|
30
37
|
-h, --help Show this help message
|
|
31
38
|
|
|
32
39
|
Examples:
|
|
33
40
|
gamut plugin install
|
|
34
41
|
gamut plugin install claude
|
|
35
|
-
gamut plugin install
|
|
36
|
-
gamut plugin install
|
|
42
|
+
gamut plugin install cursor --theme core
|
|
43
|
+
gamut plugin install cursor --theme percipio --force
|
|
37
44
|
gamut plugin install cursor --scope skills
|
|
38
45
|
gamut plugin install cursor --plugin-dir ./my-agent-tools
|
|
39
46
|
`);
|
|
@@ -44,7 +51,6 @@ Examples:
|
|
|
44
51
|
/** Directories in the plugin source that should not be installed to Cursor. */
|
|
45
52
|
const CURSOR_IGNORE = new Set([
|
|
46
53
|
'.claude-plugin', // Claude Code manifest — not a Cursor concept
|
|
47
|
-
'guidelines', // Figma Make only
|
|
48
54
|
]);
|
|
49
55
|
|
|
50
56
|
/** @param {string} sourceRoot @param {string} scope */
|
|
@@ -55,7 +61,7 @@ async function installCursor(sourceRoot, scope) {
|
|
|
55
61
|
// Symlink the whole plugin dir (dev convenience)
|
|
56
62
|
await rm(dest, { recursive: true, force: true });
|
|
57
63
|
await symlink(resolve(sourceRoot), dest, 'dir');
|
|
58
|
-
|
|
64
|
+
log(`Cursor: symlinked to ${dest}`);
|
|
59
65
|
return;
|
|
60
66
|
}
|
|
61
67
|
|
|
@@ -63,31 +69,42 @@ async function installCursor(sourceRoot, scope) {
|
|
|
63
69
|
await rm(dest, { recursive: true, force: true });
|
|
64
70
|
await mkdir(dest, { recursive: true });
|
|
65
71
|
|
|
66
|
-
await cp(`${sourceRoot}/.cursor-plugin`, `${dest}/.cursor-plugin`, {
|
|
72
|
+
await cp(`${sourceRoot}/.cursor-plugin`, `${dest}/.cursor-plugin`, {
|
|
73
|
+
recursive: true,
|
|
74
|
+
});
|
|
67
75
|
|
|
68
76
|
let dirs;
|
|
69
77
|
if (scope === 'all') {
|
|
70
78
|
const entries = await readdir(sourceRoot, { withFileTypes: true });
|
|
71
79
|
dirs = entries
|
|
72
|
-
.filter(
|
|
80
|
+
.filter(
|
|
81
|
+
(e) =>
|
|
82
|
+
e.isDirectory() &&
|
|
83
|
+
!e.name.startsWith('.') &&
|
|
84
|
+
!CURSOR_IGNORE.has(e.name)
|
|
85
|
+
)
|
|
73
86
|
.map((e) => e.name);
|
|
74
87
|
} else {
|
|
75
88
|
dirs = [scope];
|
|
76
89
|
}
|
|
77
90
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
await Promise.all(
|
|
92
|
+
dirs.map((dir) =>
|
|
93
|
+
cp(`${sourceRoot}/${dir}`, `${dest}/${dir}`, { recursive: true }).catch(
|
|
94
|
+
() => {
|
|
95
|
+
// directory may be empty/missing — not an error
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
);
|
|
83
100
|
|
|
84
101
|
const scopeLabel = scope === 'all' ? 'all content' : scope;
|
|
85
|
-
|
|
102
|
+
log(`Cursor: installed (${scopeLabel}) → ${dest}`);
|
|
86
103
|
}
|
|
87
104
|
|
|
88
105
|
// Claude Code only loads from recognized plugin directories: skills/, commands/, agents/.
|
|
89
|
-
// rules/ is Cursor-specific (.mdc format)
|
|
90
|
-
//
|
|
106
|
+
// rules/ is Cursor-specific (.mdc format). guidelines/ is installed to Cursor and is
|
|
107
|
+
// also source for the Figma Make kit; Claude marketplace registers the full sourceRoot.
|
|
91
108
|
|
|
92
109
|
/** @param {string} sourceRoot */
|
|
93
110
|
async function installClaude(sourceRoot) {
|
|
@@ -95,56 +112,58 @@ async function installClaude(sourceRoot) {
|
|
|
95
112
|
const mpName = marketplaceName(spec);
|
|
96
113
|
const root = resolve(sourceRoot);
|
|
97
114
|
|
|
98
|
-
let code = await runCommand('claude', [
|
|
115
|
+
let code = await runCommand('claude', [
|
|
116
|
+
'plugin',
|
|
117
|
+
'marketplace',
|
|
118
|
+
'add',
|
|
119
|
+
root,
|
|
120
|
+
'--scope',
|
|
121
|
+
'user',
|
|
122
|
+
]);
|
|
99
123
|
if (code !== 0) {
|
|
100
|
-
|
|
124
|
+
warn(
|
|
101
125
|
`warning: "claude plugin marketplace add" exited ${code} — ` +
|
|
102
|
-
`if it's already registered this is safe to ignore
|
|
126
|
+
`if it's already registered this is safe to ignore.`
|
|
103
127
|
);
|
|
104
|
-
code = await runCommand('claude', [
|
|
128
|
+
code = await runCommand('claude', [
|
|
129
|
+
'plugin',
|
|
130
|
+
'marketplace',
|
|
131
|
+
'update',
|
|
132
|
+
mpName,
|
|
133
|
+
]);
|
|
105
134
|
if (code !== 0) {
|
|
106
135
|
throw new Error(
|
|
107
136
|
`claude plugin marketplace add/update failed (exit ${code}).\n` +
|
|
108
|
-
`Try manually: claude plugin marketplace add ${root}
|
|
137
|
+
`Try manually: claude plugin marketplace add ${root}`
|
|
109
138
|
);
|
|
110
139
|
}
|
|
111
140
|
}
|
|
112
141
|
|
|
113
|
-
code = await runCommand('claude', [
|
|
142
|
+
code = await runCommand('claude', [
|
|
143
|
+
'plugin',
|
|
144
|
+
'install',
|
|
145
|
+
spec,
|
|
146
|
+
'--scope',
|
|
147
|
+
'user',
|
|
148
|
+
]);
|
|
114
149
|
if (code !== 0) {
|
|
115
150
|
throw new Error(
|
|
116
151
|
`claude plugin install failed (exit ${code}).\n` +
|
|
117
|
-
`Try manually: claude plugin install ${spec} --scope user
|
|
152
|
+
`Try manually: claude plugin install ${spec} --scope user`
|
|
118
153
|
);
|
|
119
154
|
}
|
|
120
155
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* @param {string} sourceRoot
|
|
128
|
-
* @param {string | undefined} outputArg
|
|
129
|
-
*/
|
|
130
|
-
async function installFigma(sourceRoot, outputArg) {
|
|
131
|
-
const src = join(sourceRoot, 'guidelines');
|
|
132
|
-
const { path: dest, discovered } = await resolveFigmaOutput(outputArg);
|
|
133
|
-
|
|
134
|
-
if (discovered) {
|
|
135
|
-
console.log(`Figma: found figma.config.json — installing to ${dest}`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
await rm(dest, { recursive: true, force: true });
|
|
139
|
-
await cp(src, dest, { recursive: true });
|
|
140
|
-
console.log(`Figma: installed guidelines/ → ${dest}`);
|
|
141
|
-
console.log(` In Figma Make, point your kit at this guidelines/ directory for design system context.`);
|
|
156
|
+
log(`Claude Code: installed ${spec} (user scope)`);
|
|
157
|
+
log(
|
|
158
|
+
` Tip: run /reload-plugins in Claude Code if skills don't appear immediately.`
|
|
159
|
+
);
|
|
160
|
+
log(` One-off without install: claude --plugin-dir ${root}`);
|
|
142
161
|
}
|
|
143
162
|
|
|
144
163
|
// ---------------------------------------------------------------------------
|
|
145
164
|
|
|
146
165
|
/**
|
|
147
|
-
* gamut plugin install [cursor|claude
|
|
166
|
+
* gamut plugin install [cursor|claude] [--scope all|skills|rules|commands|agents]
|
|
148
167
|
* [--plugin-dir <path>]
|
|
149
168
|
*
|
|
150
169
|
* @param {string[]} args
|
|
@@ -154,20 +173,41 @@ export default async function install(args) {
|
|
|
154
173
|
const scope = getFlag(args, '--scope', 'all') ?? 'all';
|
|
155
174
|
|
|
156
175
|
if (!TARGETS.includes(target)) {
|
|
157
|
-
throw new Error(
|
|
176
|
+
throw new Error(
|
|
177
|
+
`Unknown target: "${target}". Choose from: ${TARGETS.join(', ')}`
|
|
178
|
+
);
|
|
158
179
|
}
|
|
159
180
|
if (!SCOPES.includes(scope)) {
|
|
160
|
-
throw new Error(
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Unknown scope: "${scope}". Choose from: ${SCOPES.join(', ')}`
|
|
183
|
+
);
|
|
161
184
|
}
|
|
162
185
|
|
|
163
186
|
const pluginDir = await resolvePluginDir(args);
|
|
187
|
+
const theme = getFlag(args, '--theme');
|
|
188
|
+
const force = args.includes('--force');
|
|
189
|
+
|
|
190
|
+
if (theme) {
|
|
191
|
+
resolveTheme(theme);
|
|
192
|
+
}
|
|
164
193
|
|
|
165
194
|
if (target === 'cursor') {
|
|
166
195
|
await installCursor(pluginDir, scope);
|
|
167
196
|
} else if (target === 'claude') {
|
|
168
197
|
await installClaude(pluginDir);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (theme) {
|
|
201
|
+
const { dest, label } = await installDesignMd(
|
|
202
|
+
pluginDir,
|
|
203
|
+
process.cwd(),
|
|
204
|
+
theme,
|
|
205
|
+
{
|
|
206
|
+
force,
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
log(`DESIGN.md: installed (${label}) → ${dest}`);
|
|
172
210
|
}
|
|
173
211
|
}
|
|
212
|
+
|
|
213
|
+
export { listCanonicalThemes };
|
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
import { stat } from 'node:fs/promises';
|
|
2
2
|
|
|
3
3
|
import { cursorDestPath } from '../../lib/cursor.mjs';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { log } from '../../lib/io.mjs';
|
|
5
|
+
import { resolvePluginDir } from '../../lib/resolve-plugin-dir.mjs';
|
|
6
6
|
|
|
7
7
|
export function help() {
|
|
8
|
-
|
|
8
|
+
log(`
|
|
9
9
|
Usage:
|
|
10
10
|
gamut plugin list [options]
|
|
11
11
|
|
|
12
12
|
Show installation status for all supported targets.
|
|
13
13
|
|
|
14
14
|
Options:
|
|
15
|
-
--output <path> [figma] Explicit path to DESIGN.md.
|
|
16
|
-
If omitted, walks up from cwd to find figma.config.json.
|
|
17
15
|
--plugin-dir <path> Override the bundled agent-tools directory
|
|
18
16
|
-h, --help Show this help message
|
|
19
17
|
|
|
20
18
|
Examples:
|
|
21
19
|
gamut plugin list
|
|
22
|
-
gamut plugin list --output ./docs/DESIGN.md
|
|
23
20
|
`);
|
|
24
21
|
}
|
|
25
22
|
|
|
@@ -45,32 +42,6 @@ async function claudeStatus() {
|
|
|
45
42
|
};
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
/** @param {string | undefined} outputArg */
|
|
49
|
-
async function figmaStatus(outputArg) {
|
|
50
|
-
let dest;
|
|
51
|
-
if (outputArg) {
|
|
52
|
-
dest = outputArg;
|
|
53
|
-
} else {
|
|
54
|
-
const dir = await findFigmaConfigDir(process.cwd());
|
|
55
|
-
dest = dir ? `${dir}/DESIGN.md` : null;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (!dest) {
|
|
59
|
-
return {
|
|
60
|
-
target: 'figma',
|
|
61
|
-
status: '? unknown',
|
|
62
|
-
notes: 'figma.config.json not found — run from your project root or use --output',
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const installed = !!(await stat(dest).catch(() => null));
|
|
67
|
-
return {
|
|
68
|
-
target: 'figma',
|
|
69
|
-
status: installed ? '✓ installed' : '✗ not installed',
|
|
70
|
-
notes: installed ? dest : `run: gamut plugin install figma`,
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
45
|
// ---------------------------------------------------------------------------
|
|
75
46
|
|
|
76
47
|
/**
|
|
@@ -82,24 +53,21 @@ async function figmaStatus(outputArg) {
|
|
|
82
53
|
*/
|
|
83
54
|
export default async function list(args) {
|
|
84
55
|
const pluginDir = await resolvePluginDir(args);
|
|
85
|
-
const output = getFlag(args, '--output', undefined);
|
|
86
56
|
|
|
87
|
-
const rows = await Promise.all([
|
|
88
|
-
cursorStatus(pluginDir),
|
|
89
|
-
claudeStatus(),
|
|
90
|
-
figmaStatus(output),
|
|
91
|
-
]);
|
|
57
|
+
const rows = await Promise.all([cursorStatus(pluginDir), claudeStatus()]);
|
|
92
58
|
|
|
93
59
|
const col0 = Math.max(...rows.map((r) => r.target.length));
|
|
94
60
|
const col1 = Math.max(...rows.map((r) => r.status.length));
|
|
95
61
|
|
|
96
|
-
const header = `${'Target'.padEnd(col0)} ${'Status'.padEnd(
|
|
62
|
+
const header = `${'Target'.padEnd(col0)} ${'Status'.padEnd(
|
|
63
|
+
col1
|
|
64
|
+
)} Path / Notes`;
|
|
97
65
|
const rule = '─'.repeat(header.length);
|
|
98
66
|
|
|
99
|
-
|
|
100
|
-
|
|
67
|
+
log(`\n${header}`);
|
|
68
|
+
log(rule);
|
|
101
69
|
for (const row of rows) {
|
|
102
|
-
|
|
70
|
+
log(`${row.target.padEnd(col0)} ${row.status.padEnd(col1)} ${row.notes}`);
|
|
103
71
|
}
|
|
104
|
-
|
|
72
|
+
log('');
|
|
105
73
|
}
|
|
@@ -2,33 +2,29 @@ import { rm, stat } from 'node:fs/promises';
|
|
|
2
2
|
|
|
3
3
|
import { claudePluginSpec, marketplaceName } from '../../lib/claude.mjs';
|
|
4
4
|
import { cursorDestPath } from '../../lib/cursor.mjs';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { log, warn } from '../../lib/io.mjs';
|
|
6
|
+
import { resolvePluginDir } from '../../lib/resolve-plugin-dir.mjs';
|
|
7
7
|
import { runCommand } from '../../lib/run-command.mjs';
|
|
8
8
|
import { TARGETS } from './install.mjs';
|
|
9
9
|
|
|
10
10
|
export function help() {
|
|
11
|
-
|
|
11
|
+
log(`
|
|
12
12
|
Usage:
|
|
13
13
|
gamut plugin remove [target] [options]
|
|
14
14
|
|
|
15
|
-
Remove the installed Gamut plugin from an AI
|
|
15
|
+
Remove the installed Gamut plugin from an AI tool.
|
|
16
16
|
|
|
17
17
|
Arguments:
|
|
18
18
|
target Tool to remove from (default: cursor)
|
|
19
|
-
cursor | claude
|
|
19
|
+
cursor | claude
|
|
20
20
|
|
|
21
21
|
Options:
|
|
22
|
-
--output <path> [figma] Path to the DESIGN.md that was installed.
|
|
23
|
-
If omitted, walks up from cwd to find figma.config.json.
|
|
24
22
|
--plugin-dir <path> Override the bundled agent-tools directory
|
|
25
23
|
-h, --help Show this help message
|
|
26
24
|
|
|
27
25
|
Examples:
|
|
28
26
|
gamut plugin remove
|
|
29
27
|
gamut plugin remove claude
|
|
30
|
-
gamut plugin remove figma
|
|
31
|
-
gamut plugin remove figma --output ./docs/DESIGN.md
|
|
32
28
|
`);
|
|
33
29
|
}
|
|
34
30
|
|
|
@@ -40,12 +36,12 @@ async function removeCursor(sourceRoot) {
|
|
|
40
36
|
const st = await stat(dest).catch(() => null);
|
|
41
37
|
|
|
42
38
|
if (!st) {
|
|
43
|
-
|
|
39
|
+
log(`Cursor: nothing to remove — ${dest} does not exist.`);
|
|
44
40
|
return;
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
await rm(dest, { recursive: true, force: true });
|
|
48
|
-
|
|
44
|
+
log(`Cursor: removed ${dest}`);
|
|
49
45
|
}
|
|
50
46
|
|
|
51
47
|
/** @param {string} sourceRoot */
|
|
@@ -54,45 +50,42 @@ async function removeClaude(sourceRoot) {
|
|
|
54
50
|
const mpName = marketplaceName(spec);
|
|
55
51
|
const pluginName = spec.split('@')[0];
|
|
56
52
|
|
|
57
|
-
let code = await runCommand('claude', [
|
|
53
|
+
let code = await runCommand('claude', [
|
|
54
|
+
'plugin',
|
|
55
|
+
'remove',
|
|
56
|
+
pluginName,
|
|
57
|
+
'--scope',
|
|
58
|
+
'user',
|
|
59
|
+
]);
|
|
58
60
|
if (code !== 0) {
|
|
59
|
-
|
|
60
|
-
`warning: "claude plugin remove" exited ${code} — the plugin may not have been installed
|
|
61
|
+
warn(
|
|
62
|
+
`warning: "claude plugin remove" exited ${code} — the plugin may not have been installed.`
|
|
61
63
|
);
|
|
62
64
|
} else {
|
|
63
|
-
|
|
65
|
+
log(`Claude Code: removed plugin "${pluginName}"`);
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
code = await runCommand('claude', [
|
|
68
|
+
code = await runCommand('claude', [
|
|
69
|
+
'plugin',
|
|
70
|
+
'marketplace',
|
|
71
|
+
'remove',
|
|
72
|
+
mpName,
|
|
73
|
+
]);
|
|
67
74
|
if (code !== 0) {
|
|
68
|
-
|
|
75
|
+
warn(
|
|
69
76
|
`warning: "claude plugin marketplace remove" exited ${code} — ` +
|
|
70
77
|
`the marketplace entry may not exist or the command syntax may differ. ` +
|
|
71
|
-
`Run "claude plugin marketplace list" to check
|
|
78
|
+
`Run "claude plugin marketplace list" to check.`
|
|
72
79
|
);
|
|
73
80
|
} else {
|
|
74
|
-
|
|
81
|
+
log(`Claude Code: removed marketplace "${mpName}"`);
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
|
|
78
|
-
/** @param {string | undefined} outputArg */
|
|
79
|
-
async function removeFigma(outputArg) {
|
|
80
|
-
const { path: dest } = await resolveFigmaOutput(outputArg);
|
|
81
|
-
const st = await stat(dest).catch(() => null);
|
|
82
|
-
|
|
83
|
-
if (!st) {
|
|
84
|
-
console.log(`Figma: nothing to remove — ${dest} does not exist.`);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
await rm(dest, { force: true });
|
|
89
|
-
console.log(`Figma: removed ${dest}`);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
85
|
// ---------------------------------------------------------------------------
|
|
93
86
|
|
|
94
87
|
/**
|
|
95
|
-
* gamut plugin remove [cursor|claude
|
|
88
|
+
* gamut plugin remove [cursor|claude] [--plugin-dir <path>]
|
|
96
89
|
*
|
|
97
90
|
* @param {string[]} args
|
|
98
91
|
*/
|
|
@@ -100,7 +93,9 @@ export default async function remove(args) {
|
|
|
100
93
|
const target = args.find((a) => !a.startsWith('-')) ?? 'cursor';
|
|
101
94
|
|
|
102
95
|
if (!TARGETS.includes(target)) {
|
|
103
|
-
throw new Error(
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Unknown target: "${target}". Choose from: ${TARGETS.join(', ')}`
|
|
98
|
+
);
|
|
104
99
|
}
|
|
105
100
|
|
|
106
101
|
const pluginDir = await resolvePluginDir(args);
|
|
@@ -109,8 +104,5 @@ export default async function remove(args) {
|
|
|
109
104
|
await removeCursor(pluginDir);
|
|
110
105
|
} else if (target === 'claude') {
|
|
111
106
|
await removeClaude(pluginDir);
|
|
112
|
-
} else if (target === 'figma') {
|
|
113
|
-
const output = getFlag(args, '--output', undefined);
|
|
114
|
-
await removeFigma(output);
|
|
115
107
|
}
|
|
116
108
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { log } from '../../lib/io.mjs';
|
|
1
2
|
import { getFlag } from '../../lib/resolve-plugin-dir.mjs';
|
|
2
3
|
import install, { TARGETS } from './install.mjs';
|
|
3
4
|
|
|
4
5
|
export function help() {
|
|
5
|
-
|
|
6
|
+
log(`
|
|
6
7
|
Usage:
|
|
7
8
|
gamut plugin update [target] [options]
|
|
8
9
|
|
|
@@ -11,23 +12,26 @@ Equivalent to re-running install — replaces the existing installation in place
|
|
|
11
12
|
|
|
12
13
|
Arguments:
|
|
13
14
|
target Tool to update (default: cursor)
|
|
14
|
-
cursor | claude
|
|
15
|
+
cursor | claude
|
|
15
16
|
|
|
16
17
|
Options:
|
|
17
18
|
--scope <scope> Content to update (default: all)
|
|
18
19
|
all | skills | rules | commands | agents
|
|
20
|
+
--theme <theme> Refresh ./DESIGN.md (same themes as install)
|
|
21
|
+
--force Overwrite existing DESIGN.md when using --theme
|
|
19
22
|
--plugin-dir <path> Override the bundled agent-tools directory
|
|
20
23
|
-h, --help Show this help message
|
|
21
24
|
|
|
22
25
|
Examples:
|
|
23
26
|
gamut plugin update
|
|
24
27
|
gamut plugin update claude
|
|
28
|
+
gamut plugin update cursor --theme core --force
|
|
25
29
|
gamut plugin update cursor --scope skills
|
|
26
30
|
`);
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
/**
|
|
30
|
-
* gamut plugin update [cursor|claude
|
|
34
|
+
* gamut plugin update [cursor|claude] [--scope all|skills|rules|commands|agents]
|
|
31
35
|
* [--plugin-dir <path>]
|
|
32
36
|
*
|
|
33
37
|
* Re-runs install with the same arguments. For Cursor this does an in-place
|
|
@@ -41,9 +45,15 @@ export default async function update(args) {
|
|
|
41
45
|
const scope = getFlag(args, '--scope', 'all') ?? 'all';
|
|
42
46
|
|
|
43
47
|
if (!TARGETS.includes(target)) {
|
|
44
|
-
throw new Error(
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Unknown target: "${target}". Choose from: ${TARGETS.join(', ')}`
|
|
50
|
+
);
|
|
45
51
|
}
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
log(
|
|
54
|
+
`Updating Gamut plugin for ${target}${
|
|
55
|
+
scope !== 'all' ? ` (scope: ${scope})` : ''
|
|
56
|
+
}…`
|
|
57
|
+
);
|
|
48
58
|
await install(args);
|
|
49
59
|
}
|
package/bin/gamut.mjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { error, log } from './lib/io.mjs';
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Gamut CLI
|
|
5
7
|
*
|
|
6
8
|
* Usage:
|
|
7
|
-
* gamut plugin install [cursor|claude
|
|
8
|
-
* gamut plugin remove [cursor|claude
|
|
9
|
-
* gamut plugin update [cursor|claude
|
|
9
|
+
* gamut plugin install [cursor|claude] [--scope all|skills|rules|commands|agents]
|
|
10
|
+
* gamut plugin remove [cursor|claude]
|
|
11
|
+
* gamut plugin update [cursor|claude] [--scope all|skills|rules|commands|agents]
|
|
10
12
|
* gamut plugin list
|
|
11
13
|
*/
|
|
12
14
|
|
|
@@ -19,7 +21,7 @@ if (!noun || noun === '--help' || noun === '-h') {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
if (noun !== 'plugin') {
|
|
22
|
-
|
|
24
|
+
error(`Unknown command: "${noun}"`);
|
|
23
25
|
printHelp();
|
|
24
26
|
process.exit(1);
|
|
25
27
|
}
|
|
@@ -33,7 +35,7 @@ let cmd;
|
|
|
33
35
|
try {
|
|
34
36
|
cmd = await import(`./commands/plugin/${verb}.mjs`);
|
|
35
37
|
} catch {
|
|
36
|
-
|
|
38
|
+
error(`Unknown plugin subcommand: "${verb}"`);
|
|
37
39
|
printPluginHelp();
|
|
38
40
|
process.exit(1);
|
|
39
41
|
}
|
|
@@ -46,7 +48,7 @@ if (rest.includes('--help') || rest.includes('-h')) {
|
|
|
46
48
|
try {
|
|
47
49
|
await cmd.default(rest);
|
|
48
50
|
} catch (/** @type {any} */ err) {
|
|
49
|
-
|
|
51
|
+
error(`Error: ${err.message}`);
|
|
50
52
|
process.exit(1);
|
|
51
53
|
}
|
|
52
54
|
|
|
@@ -55,7 +57,7 @@ try {
|
|
|
55
57
|
// ---------------------------------------------------------------------------
|
|
56
58
|
|
|
57
59
|
function printHelp() {
|
|
58
|
-
|
|
60
|
+
log(`
|
|
59
61
|
gamut — Gamut design system CLI
|
|
60
62
|
|
|
61
63
|
Usage:
|
|
@@ -69,21 +71,23 @@ Run "gamut plugin --help" for plugin subcommands.
|
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
function printPluginHelp() {
|
|
72
|
-
|
|
74
|
+
log(`
|
|
73
75
|
gamut plugin — Manage the Gamut plugin
|
|
74
76
|
|
|
75
77
|
Subcommands:
|
|
76
|
-
install [target] [--scope <scope>]
|
|
77
|
-
remove [target]
|
|
78
|
-
update [target] [--scope <scope>]
|
|
79
|
-
list
|
|
78
|
+
install [target] [--scope <scope>] [--theme <theme>] Install the plugin (+ optional DESIGN.md)
|
|
79
|
+
remove [target] Remove an installed plugin
|
|
80
|
+
update [target] [--scope <scope>] [--theme <theme>] Update an installed plugin
|
|
81
|
+
list Show installation status for all targets
|
|
80
82
|
|
|
81
|
-
Targets: cursor (default) | claude
|
|
83
|
+
Targets: cursor (default) | claude
|
|
82
84
|
Scopes: all (default) | skills | rules | commands | agents
|
|
85
|
+
Themes: core | admin | platform | percipio | lxstudio (--theme copies DESIGN.md to repo root)
|
|
83
86
|
|
|
84
87
|
Examples:
|
|
85
88
|
gamut plugin install
|
|
86
89
|
gamut plugin install claude
|
|
90
|
+
gamut plugin install cursor --theme percipio
|
|
87
91
|
gamut plugin install cursor --scope skills
|
|
88
92
|
gamut plugin remove claude
|
|
89
93
|
gamut plugin update
|