|
| 1 | +# annotask-init |
| 2 | + |
| 3 | +Initialize Annotask for this project by scanning the codebase and generating `.annotask/design-spec.json`. |
| 4 | + |
| 5 | +## When to use |
| 6 | + |
| 7 | +Use this skill when the user says any of: |
| 8 | +- "initialize Annotask" / "init Annotask" |
| 9 | +- "set up Annotask" / "configure Annotask" |
| 10 | +- "scan my project for Annotask" |
| 11 | +- `/annotask-init` |
| 12 | + |
| 13 | +## What it does |
| 14 | + |
| 15 | +Scans the project to detect the framework, design tokens (colors, typography, spacing, borders), icon library, and component library. Writes `.annotask/design-spec.json` which Annotask reads to populate the Theme page with editable design tokens. |
| 16 | + |
| 17 | +## Output schema |
| 18 | + |
| 19 | +Every token uses this shape: |
| 20 | + |
| 21 | +```json |
| 22 | +{ |
| 23 | + "role": "primary", |
| 24 | + "value": "#3b82f6", |
| 25 | + "cssVar": "--color-primary", |
| 26 | + "source": "var(--color-primary)", |
| 27 | + "sourceFile": "src/assets/main.css", |
| 28 | + "sourceLine": 12 |
| 29 | +} |
| 30 | +``` |
| 31 | + |
| 32 | +- `role` — semantic name (see vocabularies below) |
| 33 | +- `value` — resolved value (hex color, font string, size, etc.) |
| 34 | +- `cssVar` — the CSS custom property name, if backed by one. Omit if not a CSS variable. |
| 35 | +- `source` — human-readable provenance: `var(--x)`, `tailwind.config:colors.primary`, `@theme:--color-primary` |
| 36 | +- `sourceFile` — relative path to the file where the value is defined |
| 37 | +- `sourceLine` — line number in that file |
| 38 | + |
| 39 | +## Steps |
| 40 | + |
| 41 | +### 1. Detect framework |
| 42 | + |
| 43 | +Check `package.json` dependencies: |
| 44 | +- `vue` → name "vue", read version |
| 45 | +- `react` / `react-dom` → name "react" |
| 46 | +- `svelte` → name "svelte" |
| 47 | +- `solid-js` → name "solid" |
| 48 | + |
| 49 | +Check for styling: |
| 50 | +- `tailwindcss` in devDependencies or dependencies → add "tailwind" to styling array |
| 51 | +- Look for `<style scoped>` in `.vue` files → add "scoped-css" |
| 52 | +- Look for CSS module imports (`.module.css`) → add "css-modules" |
| 53 | + |
| 54 | +### 2. Scan colors |
| 55 | + |
| 56 | +**Find color sources:** |
| 57 | + |
| 58 | +1. **CSS variables**: Search for `:root` declarations across CSS files and Vue `<style>` blocks. Extract `--variable-name: value` pairs. |
| 59 | + |
| 60 | +2. **Tailwind v4** (version >= 4): Search for `@theme` blocks in CSS files. Extract custom properties defined within them. |
| 61 | + |
| 62 | +3. **Tailwind v3** (version < 4): Read `tailwind.config.js`, `tailwind.config.ts`, or `tailwind.config.mjs`. Extract `theme.extend.colors`. Convert to flat key-value pairs. |
| 63 | + |
| 64 | +**Classify into semantic roles using this fixed vocabulary:** |
| 65 | + |
| 66 | +| Role | Match heuristics (in variable/key name) | |
| 67 | +|------|----------------------------------------| |
| 68 | +| `primary` | primary, brand | |
| 69 | +| `secondary` | secondary | |
| 70 | +| `accent` | accent | |
| 71 | +| `background` | bg, background | |
| 72 | +| `surface` | surface, card | |
| 73 | +| `text` | text, foreground, fg (but not text-muted) | |
| 74 | +| `text-muted` | text-muted, muted, subtle | |
| 75 | +| `border` | border, divider, separator | |
| 76 | +| `danger` | danger, error, destructive, red | |
| 77 | +| `warning` | warning, amber, yellow (semantic) | |
| 78 | +| `success` | success, green (semantic) | |
| 79 | +| `info` | info, blue (semantic) | |
| 80 | + |
| 81 | +If a variable doesn't match any heuristic, use a descriptive role name derived from the variable name (e.g., `--sidebar-bg` → role `sidebar-bg`). |
| 82 | + |
| 83 | +**Limits**: Maximum 30 color tokens. Prioritize semantic roles first, then most-used custom colors. |
| 84 | + |
| 85 | +### 3. Scan typography |
| 86 | + |
| 87 | +**Font families**: Search for: |
| 88 | +- CSS variables containing `font`, `family` in `:root` or `@theme` |
| 89 | +- `fontFamily` in Tailwind config |
| 90 | +- Direct `font-family` declarations on `body`, `html`, `h1`-`h6` elements |
| 91 | + |
| 92 | +Classify as: |
| 93 | +- `heading` — used on h1-h6 or named heading/display |
| 94 | +- `body` — used on body/html or named sans/body/base |
| 95 | +- `mono` — monospace, code, named mono |
| 96 | + |
| 97 | +**Font scale**: Search for: |
| 98 | +- CSS variables containing `font-size`, `text-` size names |
| 99 | +- `fontSize` in Tailwind config |
| 100 | +- `@theme` size definitions |
| 101 | + |
| 102 | +Use roles: `xs`, `sm`, `base`, `lg`, `xl`, `2xl`, `3xl`, `4xl` (match by name or by ascending size order). |
| 103 | + |
| 104 | +**Weights**: Scan component files for `font-weight` values and Tailwind weight classes (`font-bold`, `font-semibold`, etc.). List unique weights as strings: `["400", "500", "600", "700"]`. |
| 105 | + |
| 106 | +### 4. Scan spacing |
| 107 | + |
| 108 | +Search for: |
| 109 | +- CSS variables containing `space`, `gap`, `margin`, `padding`, `size` |
| 110 | +- `spacing` in Tailwind config |
| 111 | +- `@theme` spacing definitions |
| 112 | + |
| 113 | +Use roles: `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl` (match by name or ascending size). |
| 114 | + |
| 115 | +**Limits**: Maximum 12 spacing tokens. |
| 116 | + |
| 117 | +### 5. Scan border radius |
| 118 | + |
| 119 | +Search for: |
| 120 | +- CSS variables containing `radius`, `rounded` |
| 121 | +- `borderRadius` in Tailwind config |
| 122 | +- `@theme` radius definitions |
| 123 | + |
| 124 | +Use roles: `sm`, `md`, `lg`, `xl`, `full` (match by name or ascending size). |
| 125 | + |
| 126 | +### 6. Scan breakpoints |
| 127 | + |
| 128 | +Detect responsive breakpoints from whatever styling system the project uses. Output as a flat object mapping name → min-width value. |
| 129 | + |
| 130 | +**Sources (check in order):** |
| 131 | + |
| 132 | +1. **Tailwind v4** (>= 4): Look in CSS files for `@theme` blocks defining `--breakpoint-*` custom properties, or `@custom-media` rules. |
| 133 | + |
| 134 | +2. **Tailwind v3** (< 4): Read `tailwind.config.{js,ts,mjs}`. Extract `theme.screens` or `theme.extend.screens`. Default Tailwind screens: `{ "sm": "640px", "md": "768px", "lg": "1024px", "xl": "1280px", "2xl": "1536px" }` — use these as fallback if Tailwind is detected but no custom screens are defined. |
| 135 | + |
| 136 | +3. **Bootstrap**: Check for `bootstrap` in package.json. Default Bootstrap breakpoints: `{ "sm": "576px", "md": "768px", "lg": "992px", "xl": "1200px", "xxl": "1400px" }`. |
| 137 | + |
| 138 | +4. **CSS custom properties**: Search `:root` for variables containing `breakpoint`, `screen`, `bp` in the name (e.g., `--bp-mobile: 480px`). |
| 139 | + |
| 140 | +5. **CSS `@media` patterns**: Scan `.css`, `.scss`, `.vue` files for `@media` queries with `min-width` or `max-width`. Extract the 3–6 most common breakpoint values and assign roles by ascending size: `sm`, `md`, `lg`, `xl`, `2xl`. |
| 141 | + |
| 142 | +**Output example:** |
| 143 | +```json |
| 144 | +"breakpoints": { |
| 145 | + "sm": "640px", |
| 146 | + "md": "768px", |
| 147 | + "lg": "1024px", |
| 148 | + "xl": "1280px", |
| 149 | + "2xl": "1536px" |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +If no breakpoints are detected, omit the `breakpoints` field (don't include an empty object). |
| 154 | + |
| 155 | +### 7. Detect icon library |
| 156 | + |
| 157 | +Check `package.json` dependencies for: |
| 158 | + |
| 159 | +| Package | Library name | |
| 160 | +|---------|-------------| |
| 161 | +| `lucide-vue-next` or `lucide-react` | lucide | |
| 162 | +| `@heroicons/vue` or `@heroicons/react` | heroicons | |
| 163 | +| `@fortawesome/vue-fontawesome` or `@fortawesome/react-fontawesome` | fontawesome | |
| 164 | +| `@phosphor-icons/vue` or `@phosphor-icons/react` | phosphor | |
| 165 | +| `@tabler/icons-vue` or `@tabler/icons-react` | tabler | |
| 166 | + |
| 167 | +Read the version from package.json. |
| 168 | + |
| 169 | +### 8. Detect component library |
| 170 | + |
| 171 | +Check `package.json` dependencies for: |
| 172 | + |
| 173 | +| Package | Library name | |
| 174 | +|---------|-------------| |
| 175 | +| `primevue` | PrimeVue | |
| 176 | +| `vuetify` | Vuetify | |
| 177 | +| `element-plus` | Element Plus | |
| 178 | +| `@headlessui/vue` | Headless UI | |
| 179 | +| `radix-vue` | Radix Vue | |
| 180 | +| `naive-ui` | Naive UI | |
| 181 | +| `@shadcn/ui` or `shadcn-vue` | shadcn/ui | |
| 182 | + |
| 183 | +If found, scan `src/` for import statements to find used components: |
| 184 | +```bash |
| 185 | +grep -rh "from '${package}" --include='*.vue' --include='*.ts' --include='*.js' src/ | sort -u |
| 186 | +``` |
| 187 | + |
| 188 | +Extract component names from the imports. Read the version from package.json. |
| 189 | + |
| 190 | +### 9. Write design spec |
| 191 | + |
| 192 | +Create `.annotask/design-spec.json`: |
| 193 | + |
| 194 | +```json |
| 195 | +{ |
| 196 | + "version": "1.0", |
| 197 | + "framework": { |
| 198 | + "name": "vue", |
| 199 | + "version": "3.5.0", |
| 200 | + "styling": ["tailwind", "scoped-css"] |
| 201 | + }, |
| 202 | + "colors": [ |
| 203 | + { "role": "primary", "value": "#3b82f6", "cssVar": "--color-primary", "source": "var(--color-primary)", "sourceFile": "src/assets/main.css", "sourceLine": 5 }, |
| 204 | + { "role": "background", "value": "#0b1120", "cssVar": "--bg", "source": "var(--bg)", "sourceFile": "src/assets/main.css", "sourceLine": 3 } |
| 205 | + ], |
| 206 | + "typography": { |
| 207 | + "families": [ |
| 208 | + { "role": "body", "value": "Inter, sans-serif", "cssVar": "--font-sans", "source": "var(--font-sans)", "sourceFile": "src/assets/main.css", "sourceLine": 10 } |
| 209 | + ], |
| 210 | + "scale": [ |
| 211 | + { "role": "base", "value": "1rem", "cssVar": "--text-base", "source": "var(--text-base)", "sourceFile": "src/assets/main.css", "sourceLine": 15 } |
| 212 | + ], |
| 213 | + "weights": ["400", "500", "600", "700"] |
| 214 | + }, |
| 215 | + "spacing": [ |
| 216 | + { "role": "sm", "value": "8px", "cssVar": "--space-sm", "source": "var(--space-sm)", "sourceFile": "src/assets/main.css", "sourceLine": 20 } |
| 217 | + ], |
| 218 | + "borders": { |
| 219 | + "radius": [ |
| 220 | + { "role": "md", "value": "8px", "cssVar": "--radius-md", "source": "var(--radius-md)", "sourceFile": "src/assets/main.css", "sourceLine": 25 } |
| 221 | + ] |
| 222 | + }, |
| 223 | + "breakpoints": { |
| 224 | + "sm": "640px", |
| 225 | + "md": "768px", |
| 226 | + "lg": "1024px", |
| 227 | + "xl": "1280px", |
| 228 | + "2xl": "1536px" |
| 229 | + }, |
| 230 | + "icons": { |
| 231 | + "library": "lucide", |
| 232 | + "version": "0.300.0" |
| 233 | + }, |
| 234 | + "components": { |
| 235 | + "library": "PrimeVue", |
| 236 | + "version": "4.5.4", |
| 237 | + "used": ["DataTable", "Column", "InputText", "Tag", "Button"] |
| 238 | + } |
| 239 | +} |
| 240 | +``` |
| 241 | + |
| 242 | +### 10. Clean up old config |
| 243 | + |
| 244 | +If `.annotask/config.json` exists, delete it — it's been replaced by `design-spec.json`. |
| 245 | + |
| 246 | +### 11. Update .gitignore |
| 247 | + |
| 248 | +Check if `.gitignore` contains `.annotask/`. If not, append: |
| 249 | +``` |
| 250 | +# Annotask (generated) |
| 251 | +.annotask/ |
| 252 | +``` |
| 253 | + |
| 254 | +### 12. Report to user |
| 255 | + |
| 256 | +Tell the user: |
| 257 | +- What was detected (framework, number of color/typography/spacing tokens, libraries) |
| 258 | +- That they can open the **Theme** page in Annotask to view and edit tokens |
| 259 | +- That they can re-run `/annotask-init` to rescan |
| 260 | + |
| 261 | +## Notes |
| 262 | + |
| 263 | +- This skill is idempotent — re-running overwrites the design spec with fresh data |
| 264 | +- The design spec is gitignored because it's generated and may vary per developer |
| 265 | +- If detection fails for any section, use empty defaults (empty array, null) rather than omitting the field |
| 266 | +- All top-level fields are required — use empty values for missing data |
| 267 | +- When a token has a CSS variable backing, always populate the `cssVar` field — this enables live preview in the Theme page |
0 commit comments