@maccesar/aiskills 1.16.0 → 1.17.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 +25 -16
- package/commands/release.md +417 -0
- package/lib/claude-plugin.js +105 -0
- package/lib/commands/doctor.js +50 -3
- package/lib/commands/skills.js +19 -4
- package/lib/commands/update.js +4 -0
- package/lib/config.js +11 -0
- package/lib/installer.js +18 -0
- package/lib/symlink.js +5 -10
- package/package.json +3 -2
- package/skills/humaniza/SKILL.md +1 -1
- package/skills/refactoring-ui/SKILL.md +32 -34
- package/skills/session-log/SKILL.md +9 -37
- package/skills/session-log/references/file-layout.md +48 -0
- package/skills/stitch-showcase/SKILL.md +7 -3
- package/skills/vscode-extension-dev/SKILL.md +51 -43
- package/skills/vscode-extension-dev/references/architecture.md +13 -0
- package/skills/vscode-extension-dev/references/package-json-schema.md +12 -0
package/lib/commands/doctor.js
CHANGED
|
@@ -16,6 +16,11 @@ import {
|
|
|
16
16
|
} from '../config.js';
|
|
17
17
|
import { hasHook } from '../hooks.js';
|
|
18
18
|
import { readLastCheck } from '../cache.js';
|
|
19
|
+
import {
|
|
20
|
+
isClaudePluginEnabled,
|
|
21
|
+
hasClaudePluginCache,
|
|
22
|
+
pluginProvidesSkill,
|
|
23
|
+
} from '../claude-plugin.js';
|
|
19
24
|
|
|
20
25
|
const CHECK = chalk.green('✓');
|
|
21
26
|
const CROSS = chalk.red('✗');
|
|
@@ -79,8 +84,18 @@ export async function doctorCommand() {
|
|
|
79
84
|
for (const platform of platforms) {
|
|
80
85
|
const missing = [];
|
|
81
86
|
const broken = [];
|
|
87
|
+
const servedByPlugin = [];
|
|
82
88
|
|
|
83
89
|
for (const skill of SKILLS) {
|
|
90
|
+
// A skill the marketplace plugin provides is *supposed* to have no mirror
|
|
91
|
+
// here — the CLI removes it on purpose to avoid a duplicate entry. Counting
|
|
92
|
+
// it as missing turns a healthy marketplace install into a wall of errors
|
|
93
|
+
// telling the user to run a command that will correctly do nothing.
|
|
94
|
+
if (platform.name === 'claude' && pluginProvidesSkill(skill, homeDir)) {
|
|
95
|
+
servedByPlugin.push(skill);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
84
99
|
const linkPath = join(platform.skillsDir, skill);
|
|
85
100
|
try {
|
|
86
101
|
const stat = lstatSync(linkPath);
|
|
@@ -96,15 +111,26 @@ export async function doctorCommand() {
|
|
|
96
111
|
}
|
|
97
112
|
}
|
|
98
113
|
|
|
99
|
-
const
|
|
114
|
+
const expected = SKILLS.length - servedByPlugin.length;
|
|
115
|
+
const linkedCount = expected - missing.length - broken.length;
|
|
116
|
+
const pluginNote =
|
|
117
|
+
servedByPlugin.length > 0
|
|
118
|
+
? chalk.dim(` (+${servedByPlugin.length} served by the marketplace plugin)`)
|
|
119
|
+
: '';
|
|
100
120
|
|
|
101
121
|
if (missing.length === 0 && broken.length === 0) {
|
|
102
|
-
|
|
122
|
+
const summary =
|
|
123
|
+
expected === 0
|
|
124
|
+
? `all ${servedByPlugin.length} skills served by the marketplace plugin`
|
|
125
|
+
: `${linkedCount}/${expected} skills linked${pluginNote}`;
|
|
126
|
+
console.log(` ${CHECK} ${platform.displayName}: ${summary}`);
|
|
103
127
|
} else {
|
|
104
128
|
const problems = [];
|
|
105
129
|
if (missing.length > 0) problems.push(`missing: ${missing.join(', ')}`);
|
|
106
130
|
if (broken.length > 0) problems.push(`broken: ${broken.join(', ')}`);
|
|
107
|
-
console.log(
|
|
131
|
+
console.log(
|
|
132
|
+
` ${CROSS} ${platform.displayName}: ${linkedCount}/${expected} skills linked${pluginNote} (${problems.join('; ')})`
|
|
133
|
+
);
|
|
108
134
|
issues += missing.length + broken.length;
|
|
109
135
|
|
|
110
136
|
// Collect symlink issues for detailed report
|
|
@@ -117,6 +143,27 @@ export async function doctorCommand() {
|
|
|
117
143
|
}
|
|
118
144
|
}
|
|
119
145
|
|
|
146
|
+
// Marketplace plugin
|
|
147
|
+
//
|
|
148
|
+
// Worth its own section because the two channels look identical from the
|
|
149
|
+
// outside and produce opposite expectations: with the plugin enabled, absent
|
|
150
|
+
// mirrors are correct; without it, absent mirrors mean no skills at all.
|
|
151
|
+
console.log('');
|
|
152
|
+
console.log(' Marketplace plugin:');
|
|
153
|
+
const pluginEnabled = isClaudePluginEnabled(homeDir);
|
|
154
|
+
const pluginCached = hasClaudePluginCache(homeDir);
|
|
155
|
+
|
|
156
|
+
if (pluginEnabled) {
|
|
157
|
+
console.log(` ${CHECK} Enabled — Claude Code is served by the plugin, mirrors intentionally absent`);
|
|
158
|
+
} else if (pluginCached) {
|
|
159
|
+
console.log(` ${WARN} Not enabled, but a cache directory remains from a previous install`);
|
|
160
|
+
console.log(` ${chalk.dim('Harmless on this version. On aiskills < 1.16.1 it made install skip')}`);
|
|
161
|
+
console.log(` ${chalk.dim('every symlink, leaving Claude Code with no skills. Remove it with:')}`);
|
|
162
|
+
console.log(` ${chalk.cyan('rm -rf ~/.claude/plugins/cache/maccesar-aiskills')}`);
|
|
163
|
+
} else {
|
|
164
|
+
console.log(` ${CHECK} Not installed — skills reach Claude Code through npm mirrors`);
|
|
165
|
+
}
|
|
166
|
+
|
|
120
167
|
// Symlink issues detail
|
|
121
168
|
if (symlinkIssues.length > 0) {
|
|
122
169
|
console.log('');
|
package/lib/commands/skills.js
CHANGED
|
@@ -79,10 +79,12 @@ export async function skillsCommand(options) {
|
|
|
79
79
|
chalk.dim('(agentskills.io standard)')
|
|
80
80
|
);
|
|
81
81
|
console.log(
|
|
82
|
-
' ' + chalk.
|
|
82
|
+
' ' + chalk.green('✓'),
|
|
83
|
+
chalk.dim('Gemini, Codex, Cursor, Cline, Amp, GitHub Copilot +more read it directly —')
|
|
83
84
|
);
|
|
85
|
+
console.log(' ' + chalk.dim('nothing else to configure for them.'));
|
|
84
86
|
console.log(
|
|
85
|
-
' ' + chalk.dim('
|
|
87
|
+
' ' + chalk.dim('Claude Code needs symlink mirrors, created below.')
|
|
86
88
|
);
|
|
87
89
|
console.log('');
|
|
88
90
|
|
|
@@ -112,10 +114,19 @@ export async function skillsCommand(options) {
|
|
|
112
114
|
process.exit(1);
|
|
113
115
|
}
|
|
114
116
|
|
|
115
|
-
// Show detected platforms
|
|
117
|
+
// Show detected platforms.
|
|
118
|
+
//
|
|
119
|
+
// Only assistants that need aiskills-managed mirrors appear here, so a bare
|
|
120
|
+
// "Claude Code detected" reads as if the other assistants were not found at
|
|
121
|
+
// all. They were never looked for: Gemini, Codex and the rest read
|
|
122
|
+
// ~/.agents/skills/ directly and are already served by the install itself.
|
|
116
123
|
if (detectedPlatforms.length > 0) {
|
|
117
124
|
for (const platform of detectedPlatforms) {
|
|
118
|
-
console.log(
|
|
125
|
+
console.log(
|
|
126
|
+
chalk.green('✓'),
|
|
127
|
+
`${platform.displayName} detected`,
|
|
128
|
+
chalk.dim('— needs mirrors, linked below')
|
|
129
|
+
);
|
|
119
130
|
}
|
|
120
131
|
console.log('');
|
|
121
132
|
} else if (isLocal) {
|
|
@@ -269,6 +280,10 @@ export async function skillsCommand(options) {
|
|
|
269
280
|
spinner.succeed(
|
|
270
281
|
`${commandsResult.installed.length} slash command${commandsResult.installed.length !== 1 ? 's' : ''} installed`
|
|
271
282
|
);
|
|
283
|
+
} else if (commandsResult.skipped.length > 0) {
|
|
284
|
+
spinner.info(
|
|
285
|
+
`${commandsResult.skipped.length} slash command${commandsResult.skipped.length !== 1 ? 's' : ''} already provided by the marketplace plugin`
|
|
286
|
+
);
|
|
272
287
|
} else {
|
|
273
288
|
spinner.info('No slash commands to install');
|
|
274
289
|
}
|
package/lib/commands/update.js
CHANGED
|
@@ -67,6 +67,10 @@ async function performUpdate(baseDir, repoDir, spinner) {
|
|
|
67
67
|
spinner.succeed(
|
|
68
68
|
`${commandsResult.installed.length} slash command${commandsResult.installed.length !== 1 ? 's' : ''} synced`
|
|
69
69
|
);
|
|
70
|
+
} else if (commandsResult.skipped.length > 0) {
|
|
71
|
+
spinner.info(
|
|
72
|
+
`${commandsResult.skipped.length} slash command${commandsResult.skipped.length !== 1 ? 's' : ''} already provided by the marketplace plugin`
|
|
73
|
+
);
|
|
70
74
|
} else {
|
|
71
75
|
spinner.info('No slash commands to sync');
|
|
72
76
|
}
|
package/lib/config.js
CHANGED
|
@@ -64,6 +64,17 @@ export const CLAUDE_PLUGIN_NAME = 'aiskills';
|
|
|
64
64
|
export const getClaudePluginSkillsPath = (baseDir = os.homedir()) =>
|
|
65
65
|
path.join(baseDir, '.claude', 'plugins', 'cache', CLAUDE_PLUGIN_MARKETPLACE, CLAUDE_PLUGIN_NAME);
|
|
66
66
|
|
|
67
|
+
// The key Claude Code writes under "enabledPlugins" when the plugin is installed.
|
|
68
|
+
export const CLAUDE_PLUGIN_KEY = `${CLAUDE_PLUGIN_NAME}@${CLAUDE_PLUGIN_MARKETPLACE}`;
|
|
69
|
+
|
|
70
|
+
// Where Claude Code records which plugins are enabled. Both files are consulted
|
|
71
|
+
// because the local variant overrides the shared one, and either may carry the
|
|
72
|
+
// entry depending on how the plugin was installed.
|
|
73
|
+
export const getClaudeSettingsPaths = (baseDir = os.homedir()) => [
|
|
74
|
+
path.join(baseDir, '.claude', 'settings.json'),
|
|
75
|
+
path.join(baseDir, '.claude', 'settings.local.json'),
|
|
76
|
+
];
|
|
77
|
+
|
|
67
78
|
// AI platform detection
|
|
68
79
|
//
|
|
69
80
|
// Only platforms that need aiskills-managed symlinks appear here.
|
package/lib/installer.js
CHANGED
|
@@ -135,6 +135,7 @@ export async function installCommands(repoDir, baseDir = os.homedir()) {
|
|
|
135
135
|
installed: [],
|
|
136
136
|
failed: [],
|
|
137
137
|
removed: [],
|
|
138
|
+
skipped: [],
|
|
138
139
|
};
|
|
139
140
|
|
|
140
141
|
const legacyLocal = removeCommands(baseDir, { legacyOnly: true });
|
|
@@ -147,7 +148,24 @@ export async function installCommands(repoDir, baseDir = os.homedir()) {
|
|
|
147
148
|
results.failed.push(...legacyGlobal.failed);
|
|
148
149
|
}
|
|
149
150
|
|
|
151
|
+
const { pluginProvidesCommand } = await import('./claude-plugin.js');
|
|
152
|
+
const commandsDir = getClaudeCommandsDir(baseDir);
|
|
153
|
+
|
|
150
154
|
for (const cmd of COMMANDS) {
|
|
155
|
+
// Same rule the symlink step applies to skills: when the marketplace plugin
|
|
156
|
+
// already provides the command, installing our own copy makes it show up
|
|
157
|
+
// twice in the autocomplete. Clean up any copy left from before the plugin
|
|
158
|
+
// was installed.
|
|
159
|
+
if (pluginProvidesCommand(cmd, baseDir)) {
|
|
160
|
+
const stalePath = join(commandsDir, `${cmd}.md`);
|
|
161
|
+
if (existsSync(stalePath)) {
|
|
162
|
+
await remove(stalePath);
|
|
163
|
+
results.removed.push(cmd);
|
|
164
|
+
}
|
|
165
|
+
results.skipped.push(cmd);
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
|
|
151
169
|
if (await installCommand(repoDir, cmd, baseDir)) {
|
|
152
170
|
results.installed.push(cmd);
|
|
153
171
|
} else {
|
package/lib/symlink.js
CHANGED
|
@@ -75,21 +75,16 @@ async function removePath(path) {
|
|
|
75
75
|
* and an additional symlink at ~/.claude/skills/<skill> produces a duplicate
|
|
76
76
|
* entry in the slash-command autocomplete. This helper lets the symlink step
|
|
77
77
|
* skip Claude when the plugin already covers it.
|
|
78
|
+
*
|
|
79
|
+
* Requires the plugin to be *enabled*, not merely cached — see `claude-plugin.js`
|
|
80
|
+
* for why the distinction matters.
|
|
78
81
|
* @param {string} skillName - Skill name (e.g. 'stitch-showcase')
|
|
79
82
|
* @param {string} baseDir - Optional base directory (defaults to homedir via config)
|
|
80
83
|
* @returns {Promise<boolean>} True if the plugin provides this skill
|
|
81
84
|
*/
|
|
82
85
|
export async function isClaudePluginSkillInstalled(skillName, baseDir) {
|
|
83
|
-
const {
|
|
84
|
-
|
|
85
|
-
const pluginBase = getClaudePluginSkillsPath(baseDir);
|
|
86
|
-
if (!existsSync(pluginBase)) return false;
|
|
87
|
-
try {
|
|
88
|
-
const versions = await readdir(pluginBase);
|
|
89
|
-
return versions.some((v) => existsSync(join(pluginBase, v, 'skills', skillName)));
|
|
90
|
-
} catch {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
86
|
+
const { pluginProvidesSkill } = await import('./claude-plugin.js');
|
|
87
|
+
return pluginProvidesSkill(skillName, baseDir);
|
|
93
88
|
}
|
|
94
89
|
|
|
95
90
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maccesar/aiskills",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "AI coding assistant skills for Claude Code, Gemini CLI, and Codex CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
"files": [
|
|
54
54
|
"bin/",
|
|
55
55
|
"lib/",
|
|
56
|
-
"skills/"
|
|
56
|
+
"skills/",
|
|
57
|
+
"commands/"
|
|
57
58
|
],
|
|
58
59
|
"publishConfig": {
|
|
59
60
|
"access": "public"
|
package/skills/humaniza/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: humaniza
|
|
3
|
-
description: '
|
|
3
|
+
description: 'Editor de estilo para textos en español (especialmente es-MX): quita los tics de escritura de IA y devuelve prosa natural, concreta y directa, sin cambiar el contenido. Úsalo siempre que alguien quiera revisar, pulir o reescribir un texto en español —emails, documentación, marketing, soporte, posts, textos técnicos— aunque nunca diga "humanizar": "esto suena a ChatGPT", "quítale lo robótico", "hazlo más natural", "que no parezca IA", "sonó muy acartonado", "límale el tono", "revísame este correo antes de mandarlo". También cuando el texto mismo trae las señales: rayas por todas partes, "no es X, sino Y", "cabe destacar", listas de tres, abridores como "la verdad es que". No es para: traducir, corregir solo ortografía o gramática, escribir un texto desde cero, ni editar textos en inglés.'
|
|
4
4
|
allowed-tools: Read, Write, Edit, Grep, Glob, Bash, AskUserQuestion
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: refactoring-ui
|
|
3
|
-
description: '
|
|
3
|
+
description: 'Design advice grounded in the principles of "Refactoring UI" by Adam Wathan & Steve Schoger. Use this whenever someone is trying to make an interface look better, or asks about visual hierarchy, color palettes and greys, type scales, spacing systems, shadows and depth, images, empty states, borders, dark mode, motion and hover states, or the layout of a modal, form or table — including when they never say "design" and just paste a component asking why it looks off, or say it "feels cramped", "looks generic", "needs polish", "how do I make this look better?". Applies to any stack: Tailwind, plain CSS, React, Blade, mobile. Not for: writing the copy itself, logo or brand identity work, user research, or debugging CSS that renders wrong.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Refactoring UI Skill
|
|
@@ -17,13 +17,13 @@ SKILL.md is not enough.**
|
|
|
17
17
|
|
|
18
18
|
| Task involves | Required reading |
|
|
19
19
|
|---|---|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
| Color
|
|
23
|
-
| Empty states, borders, accents, finishing touches | [references/04-polish.md](references/04-polish.md) |
|
|
24
|
-
| Motion, microinteractions, transitions, hover/press states, loading | [references/05-motion.md](references/05-motion.md) |
|
|
25
|
-
| Dark mode, multi-theme color tokens, theme toggle, contrast strategy | [references/06-dark-mode.md](references/06-dark-mode.md) |
|
|
26
|
-
| Modals, forms, tables —
|
|
20
|
+
| Project mindset: feature-first work, scope discipline, defining systems, picking a voice | [references/01-foundations.md](references/01-foundations.md) |
|
|
21
|
+
| Visual hierarchy, layout, white space, spacing scales, typography | [references/02-page-mechanics.md](references/02-page-mechanics.md) |
|
|
22
|
+
| Color systems (HSL, shades, greys, contrast), depth and shadows, image handling | [references/03-visual-treatment.md](references/03-visual-treatment.md) |
|
|
23
|
+
| Empty states, borders, accents, decorative defaults, finishing touches | [references/04-polish.md](references/04-polish.md) |
|
|
24
|
+
| Motion, microinteractions, transitions, hover/press states, loading, `prefers-reduced-motion` — *complementary, not from the book* | [references/05-motion.md](references/05-motion.md) |
|
|
25
|
+
| Dark mode, multi-theme color tokens, theme toggle, contrast strategy — *complementary, extrapolates the book's HSL principles* | [references/06-dark-mode.md](references/06-dark-mode.md) |
|
|
26
|
+
| Modals (focus, layout), forms (labels, validation), tables (density, alignment) — *complementary, extends the book's principles* | [references/07-component-patterns.md](references/07-component-patterns.md) |
|
|
27
27
|
|
|
28
28
|
### Step 2 — Output contract
|
|
29
29
|
|
|
@@ -41,38 +41,17 @@ prepend `FROM_MEMORY (unverified):` to that claim. Do not hide it.
|
|
|
41
41
|
|
|
42
42
|
### Banned behaviors
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
- ❌ Reproducing the book's prose, illustrations, or examples verbatim — paraphrase only
|
|
46
|
-
- ❌ Mixing in advice from unrelated design systems (Material, HIG, Tailwind defaults) as if it were *Refactoring UI* doctrine
|
|
47
|
-
- ❌ Marking the answer complete without listing which reference files you read
|
|
44
|
+
These four are where advice like this usually goes wrong, so they're worth naming:
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
- User asks about visual hierarchy or emphasis
|
|
54
|
-
- User is designing a UI component, page, or layout
|
|
55
|
-
- User wants a design review or critique
|
|
56
|
-
- User asks about shadows, depth, or layering
|
|
57
|
-
- User asks about handling images in UI
|
|
58
|
-
- User asks about empty states, borders, or decorative elements
|
|
46
|
+
- Inventing ratios, scale values, contrast numbers, or rules not in the references. A made-up number is indistinguishable from a real one once it's in someone's stylesheet.
|
|
47
|
+
- Reproducing the book's prose, illustrations, or examples verbatim. The references paraphrase on purpose — the original material belongs to its authors and is worth buying.
|
|
48
|
+
- Presenting advice from unrelated design systems (Material, HIG, Tailwind defaults) as *Refactoring UI* doctrine. Those systems are fine; attributing them here makes the citation meaningless.
|
|
49
|
+
- Marking the answer complete without listing which reference files you read. The list is what lets the reader tell a grounded answer from a plausible one.
|
|
59
50
|
|
|
60
51
|
## Source
|
|
61
52
|
|
|
62
53
|
Inspired by 'Refactoring UI' by Adam Wathan & Steve Schoger — refactoringui.com
|
|
63
54
|
|
|
64
|
-
## Reference Files
|
|
65
|
-
|
|
66
|
-
| File | Topics |
|
|
67
|
-
| ----------------------------------- | --------------------------------------------------------------------------------------- |
|
|
68
|
-
| `references/01-foundations.md` | Project mindset: feature-first work, scope discipline, defining systems, picking a voice |
|
|
69
|
-
| `references/02-page-mechanics.md` | Visual hierarchy, layout, white space, spacing scales, typography |
|
|
70
|
-
| `references/03-visual-treatment.md` | Color systems (HSL, shades, greys, contrast), depth and shadows, image handling |
|
|
71
|
-
| `references/04-polish.md` | Finishing touches: borders, accents, empty states, decorative defaults, design intuition |
|
|
72
|
-
| `references/05-motion.md` | Motion system (durations, easings), hover/press states, loading patterns, prefers-reduced-motion — **complementary** (not from RUI) |
|
|
73
|
-
| `references/06-dark-mode.md` | Dark mode color tokens, text contrast, shadow handling, images, theme toggle — **complementary** (extrapolates RUI's HSL principles) |
|
|
74
|
-
| `references/07-component-patterns.md` | Modals (focus, layout), forms (labels, validation), tables (density, alignment) — **complementary** (extends RUI principles to specific components) |
|
|
75
|
-
|
|
76
55
|
## Anti-Patterns to Watch For
|
|
77
56
|
|
|
78
57
|
- Designing layouts/navs/shells before designing real features [source: references/01-foundations.md]
|
|
@@ -84,6 +63,25 @@ Inspired by 'Refactoring UI' by Adam Wathan & Steve Schoger — refactoringui.co
|
|
|
84
63
|
- Designing with placeholder images instead of real content [source: references/03-visual-treatment.md]
|
|
85
64
|
- Shrinking a logo down to use as a favicon [source: references/03-visual-treatment.md]
|
|
86
65
|
- Using preprocessor `lighten()` / `darken()` to derive shades [source: references/03-visual-treatment.md]
|
|
66
|
+
- Leaving an empty state as a bare "No data" rectangle — it's often the first thing a new user sees [source: references/04-polish.md]
|
|
67
|
+
- Rendering tabs, filters or pagination that have nothing to operate on (reads as broken) [source: references/04-polish.md]
|
|
68
|
+
- Reaching for a border when a shadow, a second background color, or more space separates better [source: references/04-polish.md]
|
|
69
|
+
- Shipping browser-default bullets, checkboxes and radios [source: references/04-polish.md]
|
|
70
|
+
- Animating layout properties (`width`, `top`, `margin`) instead of `transform` / `opacity` [source: references/05-motion.md]
|
|
71
|
+
- Inventing a duration per component instead of picking from a fixed motion scale [source: references/05-motion.md]
|
|
72
|
+
- Scaling a whole element up on hover (1.05×), or animating font size [source: references/05-motion.md]
|
|
73
|
+
- Showing a spinner before ~150ms of waiting [source: references/05-motion.md]
|
|
74
|
+
- Ignoring `prefers-reduced-motion` [source: references/05-motion.md]
|
|
75
|
+
- Pure `#000` for the canvas, or pure white for text [source: references/06-dark-mode.md]
|
|
76
|
+
- Producing dark mode with `filter: invert(1)` [source: references/06-dark-mode.md]
|
|
77
|
+
- Reusing the light-mode brand color in dark mode without rechecking contrast [source: references/06-dark-mode.md]
|
|
78
|
+
- Applying the theme after first paint (flash of the wrong theme on every load) [source: references/06-dark-mode.md]
|
|
79
|
+
- Keeping every light-mode shadow unchanged on a dark canvas, where it's invisible [source: references/06-dark-mode.md]
|
|
80
|
+
- Using a placeholder as the only label [source: references/07-component-patterns.md]
|
|
81
|
+
- Validating a field on every keystroke instead of on blur [source: references/07-component-patterns.md]
|
|
82
|
+
- A modal with no focus trap, or centered vertically instead of anchored near the top [source: references/07-component-patterns.md]
|
|
83
|
+
- Left-aligning numeric columns, which hides magnitude [source: references/07-component-patterns.md]
|
|
84
|
+
- A translucent sticky table header, with rows showing through it [source: references/07-component-patterns.md]
|
|
87
85
|
|
|
88
86
|
## Attribution
|
|
89
87
|
|
|
@@ -93,53 +93,25 @@ repositories. Very often it's also **one working session**: someone adds an
|
|
|
93
93
|
endpoint on the API side and, without switching context, wires the app that
|
|
94
94
|
consumes it. The work is a single thought; only the folders are separate.
|
|
95
95
|
|
|
96
|
-
**Install from inside each repo, separately
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
servers connect, and its stack-specific skills detect themselves. Installing a
|
|
96
|
+
**Install from inside each repo, separately**, and let each keep its own
|
|
97
|
+
`status.md` — two repos have two branches, two deploy states and two histories, so
|
|
98
|
+
one shared file goes stale on whichever side isn't being edited. Installing a
|
|
100
99
|
repo's notes from its sibling means describing a project you're looking at from
|
|
101
|
-
outside
|
|
102
|
-
useful is exactly what you don't see from across the fence.
|
|
103
|
-
|
|
104
|
-
Each keeps its own `status.md` — two repos have two branches, two deploy states
|
|
105
|
-
and two histories, and one shared file would go stale on whichever side isn't
|
|
106
|
-
being edited.
|
|
107
|
-
|
|
108
|
-
Put the sibling's **path** in the header, not just its name, so whoever reads it
|
|
109
|
-
next can actually go there:
|
|
110
|
-
|
|
111
|
-
```markdown
|
|
112
|
-
**Sibling:** `../../Apps/EM Industrial` (Titanium client) — waiting on
|
|
113
|
-
`/work-orders/{id}/progress`, not built here yet.
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**Once both are installed, updating them from one session is fine** — that's the
|
|
117
|
-
day-to-day case, and it's different from installing. The files already exist and
|
|
118
|
-
carry the project's own vocabulary; you're appending what changed, not inventing
|
|
119
|
-
a description of a repo you can't see.
|
|
100
|
+
outside, and the result reads like it.
|
|
120
101
|
|
|
121
102
|
**When a session touched both, close both.** This is the part that gets skipped,
|
|
122
103
|
and it's where the two halves drift into separate realities: the mobile notes say
|
|
123
104
|
"waiting on the API" for three weeks while the backend's notes never mention that
|
|
124
|
-
anything is waiting.
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
Even then, write the sibling's status from what you did to it, not from what you
|
|
128
|
-
assume about it. "Added the client call for `/work-orders/{id}/progress`" is
|
|
129
|
-
something you know. "The app is now feature-complete for E5" is something the app
|
|
130
|
-
would have to tell you.
|
|
131
|
-
|
|
132
|
-
If the sibling isn't reachable from where you're working, say so in the handoff
|
|
133
|
-
rather than guessing at its state. "Endpoint added here; the app side needs its
|
|
134
|
-
status updated, I couldn't reach that repo" is honest and actionable. A confident
|
|
135
|
-
claim about a repo you didn't open is neither.
|
|
105
|
+
anything is waiting. Write each side from what you did to it, not from what you
|
|
106
|
+
assume about it — and if you couldn't reach the sibling, say that in the handoff
|
|
107
|
+
instead of guessing at its state.
|
|
136
108
|
|
|
137
109
|
A **monorepo** is the opposite case and takes the opposite answer — one
|
|
138
110
|
`docs/project/` at the root, packages as headings — because one repo has one branch,
|
|
139
111
|
one deploy and one history to describe. And `status.md` being rewritten whole every
|
|
140
112
|
session makes it **conflict-prone the moment a second person or branch touches it**.
|
|
141
|
-
|
|
142
|
-
person and one branch, which is most of them.
|
|
113
|
+
All three cases, with the sibling header format, are in `references/file-layout.md`;
|
|
114
|
+
none comes up on a project with one person and one branch, which is most of them.
|
|
143
115
|
|
|
144
116
|
### Why status.md is not loaded at startup
|
|
145
117
|
|
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
Read this when installing the convention in a project or migrating one that keeps
|
|
4
4
|
its notes somewhere else.
|
|
5
5
|
|
|
6
|
+
<!-- TOC-START -->
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Layout](#layout)
|
|
10
|
+
- [The pointer block](#the-pointer-block)
|
|
11
|
+
- [Two variants](#two-variants)
|
|
12
|
+
- [Repos that come in pairs](#repos-that-come-in-pairs)
|
|
13
|
+
- [Templates](#templates)
|
|
14
|
+
- [Migrating an existing project](#migrating-an-existing-project)
|
|
15
|
+
- [Sizing](#sizing)
|
|
16
|
+
|
|
17
|
+
<!-- TOC-END -->
|
|
18
|
+
|
|
6
19
|
## Layout
|
|
7
20
|
|
|
8
21
|
```
|
|
@@ -87,6 +100,41 @@ Resolve conflicts by **keeping both sides and merging by section** — two peopl
|
|
|
87
100
|
nobody gets back. If the friction is constant rather than occasional, the team wants
|
|
88
101
|
a heading per workstream inside the file. Still one file.
|
|
89
102
|
|
|
103
|
+
## Repos that come in pairs
|
|
104
|
+
|
|
105
|
+
A web backend and the mobile client that consumes it. The mechanics of installing
|
|
106
|
+
and closing both are in the skill; what follows is the detail that didn't need to
|
|
107
|
+
load every session.
|
|
108
|
+
|
|
109
|
+
**Install from inside each repo, separately.** Open the backend, install; open the
|
|
110
|
+
app, install. It's a one-time act per repo and it's worth doing from the right
|
|
111
|
+
place: sitting inside the project means its own context file loads, its own MCP
|
|
112
|
+
servers connect, and its stack-specific skills detect themselves. Installing a
|
|
113
|
+
repo's notes from its sibling means describing a project you're looking at from
|
|
114
|
+
outside — and the result reads like it, because the detail that makes `context.md`
|
|
115
|
+
useful is exactly what you don't see from across the fence.
|
|
116
|
+
|
|
117
|
+
Put the sibling's **path** in the header of `status.md`, not just its name, so
|
|
118
|
+
whoever reads it next can actually go there:
|
|
119
|
+
|
|
120
|
+
```markdown
|
|
121
|
+
**Sibling:** `../../Apps/EM Industrial` (Titanium client) — waiting on
|
|
122
|
+
`/work-orders/{id}/progress`, not built here yet.
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Once both are installed, updating them from one session is fine** — that's the
|
|
126
|
+
day-to-day case, and it's different from installing. The files already exist and
|
|
127
|
+
carry the project's own vocabulary; you're appending what changed, not inventing a
|
|
128
|
+
description of a repo you can't see.
|
|
129
|
+
|
|
130
|
+
Write the sibling's status from what you did to it, not from what you assume about
|
|
131
|
+
it. "Added the client call for `/work-orders/{id}/progress`" is something you know.
|
|
132
|
+
"The app is now feature-complete for E5" is something the app would have to tell
|
|
133
|
+
you. And if the sibling isn't reachable from where you're working, say so in the
|
|
134
|
+
handoff rather than guessing: "endpoint added here; the app side needs its status
|
|
135
|
+
updated, I couldn't reach that repo" is honest and actionable. A confident claim
|
|
136
|
+
about a repo you didn't open is neither.
|
|
137
|
+
|
|
90
138
|
## Templates
|
|
91
139
|
|
|
92
140
|
### `docs/project/status.md`
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stitch-showcase
|
|
3
|
-
description: '
|
|
3
|
+
description: 'Turns Google Stitch design exports (zips holding `code.html` + `screen.png`) into a navigable showcase — gallery, viewer, component catalog — in about three seconds, and enriches it on demand. Use this for anything involving those exports: "organiza mis diseños de Stitch", "arma el muestrario", "organize my Stitch designs", "build the showcase", "tengo los zips de Stitch", "mis exports de Stitch", or a bare path to a folder of design zips. Also for maintaining one that already exists: "optimiza el showcase", "mejora las descripciones", "agrega estas pantallas nuevas", "el cliente pidió otra pantalla", "estandariza los navbars", "make all the footers the same". Not for: Figma or Sketch exports, loose screenshots, redesigning the screens themselves, or building the real app from them.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# stitch-showcase
|
|
7
7
|
|
|
8
8
|
Converts Google Stitch exports (zips with `code.html` + `screen.png`) into a navigable showcase with `index.html` + `viewer.html` + `catalog.html`.
|
|
9
9
|
|
|
10
|
-
**Architecture**: Python script generates all HTML from pre-built templates in ~3 seconds. AI enrichment (descriptions, sections, hero text) is **optional and on-demand** — only when the user asks to optimize.
|
|
10
|
+
**Architecture**: a Python script generates all HTML from pre-built templates in ~3 seconds. AI enrichment (descriptions, sections, hero text) is **optional and on-demand** — only when the user asks to optimize.
|
|
11
11
|
|
|
12
12
|
## Prerequisites
|
|
13
13
|
|
|
@@ -39,7 +39,11 @@ digraph showcase {
|
|
|
39
39
|
}
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
Two things about this that are easy to get wrong and expensive to undo:
|
|
43
|
+
|
|
44
|
+
Run `build_showcase.py` **without** `--context`, since that's the invocation that writes the HTML. `--context` only dumps the data JSON for inspection, so a run with it leaves you with no showcase and no error saying why.
|
|
45
|
+
|
|
46
|
+
Don't write `index.html` or `viewer.html` by hand. The templates already carry the layout, grid, viewer, theme, tabs, search and every interactive behavior, and every build regenerates both files — so hand-written HTML costs a lot to produce and disappears on the next rebuild.
|
|
43
47
|
|
|
44
48
|
## Mode 1: Build (default — instant)
|
|
45
49
|
|