stackfit 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,10 @@
1
+ # Copy to .env next to stackfit.json (it is gitignored). Never commit real values.
2
+
3
+ # Optional: where this catalog lives, so stackfit works from any folder.
4
+ # STACKFIT_CATALOG=~/code/my-skill-catalog
5
+
6
+ # Optional: lets `stackfit refresh` read private GitHub repositories.
7
+ # GITHUB_TOKEN=
8
+
9
+ # Any NAME here can be used as {{env:NAME}} in commands/, rules/, and agents/, e.g.
10
+ # REVIEWER_HANDLE=@your-handle
@@ -0,0 +1,12 @@
1
+ # My stackfit catalog
2
+
3
+ Started from the stackfit starter. This folder is yours: keep it in a (private) Git repository.
4
+
5
+ - `stackfit.json`: enabled skills and packs (which skills reach which repos).
6
+ - `skill-sources.json`: where each vendored skill comes from, when you last reviewed it, and sync-time overrides.
7
+ - `skills/`: the skills themselves. `stackfit refresh --all` vendors the upstream ones.
8
+ - `rules/`, `commands/`, `agents/`: shared adapters rendered for Cursor and Claude Code.
9
+ - `stackfit.local.json` (gitignored): where your projects live on each machine. Copy the example.
10
+ - `.env` (gitignored): personal values for `{{env:NAME}}` placeholders. Copy `.env.example`.
11
+
12
+ Add your own skills under `skills/<name>/SKILL.md`, list them in `stackfit.json` and a pack, set `kind: custom` in `skill-sources.json`, then `stackfit audit`.
@@ -0,0 +1,4 @@
1
+ stackfit.local.json
2
+ .env
3
+ skills/.*.refresh/
4
+ .DS_Store
@@ -0,0 +1,11 @@
1
+ ---
2
+ description: Starter defaults for any repository (edit or replace with your own)
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Defaults
7
+
8
+ - Follow the repository's own instructions (`AGENTS.md`, `CLAUDE.md`, contributing docs) over these.
9
+ - Match existing conventions, package manager, and scripts before introducing new ones.
10
+ - Keep changes focused on the request and say which checks you ran.
11
+ - Ask before running anything that changes external systems.
@@ -0,0 +1,315 @@
1
+ {
2
+ "$schema": "https://unpkg.com/stackfit/schemas/skill-sources.schema.json",
3
+ "schemaVersion": 2,
4
+ "skills": {
5
+ "animation-vocabulary": {
6
+ "kind": "external",
7
+ "source": {
8
+ "repository": "https://github.com/emilkowalski/skills.git",
9
+ "path": "skills/animation-vocabulary"
10
+ },
11
+ "reviewed": "2026-10-26"
12
+ },
13
+ "apple-design": {
14
+ "kind": "external",
15
+ "source": {
16
+ "repository": "https://github.com/emilkowalski/skills.git",
17
+ "path": "skills/apple-design"
18
+ },
19
+ "reviewed": "2026-10-26"
20
+ },
21
+ "baseline-ui": {
22
+ "kind": "external",
23
+ "source": {
24
+ "repository": "https://github.com/ibelick/ui-skills.git",
25
+ "path": "skills/baseline-ui"
26
+ },
27
+ "reviewed": "2026-10-26"
28
+ },
29
+ "emil-design-eng": {
30
+ "kind": "external",
31
+ "source": {
32
+ "repository": "https://github.com/emilkowalski/skills.git",
33
+ "path": "skills/emil-design-eng"
34
+ },
35
+ "reviewed": "2026-10-26"
36
+ },
37
+ "fixing-accessibility": {
38
+ "kind": "external",
39
+ "source": {
40
+ "repository": "https://github.com/ibelick/ui-skills.git",
41
+ "path": "skills/fixing-accessibility"
42
+ },
43
+ "reviewed": "2026-10-26"
44
+ },
45
+ "fixing-motion-performance": {
46
+ "kind": "external",
47
+ "source": {
48
+ "repository": "https://github.com/ibelick/ui-skills.git",
49
+ "path": "skills/fixing-motion-performance"
50
+ },
51
+ "reviewed": "2026-10-26"
52
+ },
53
+ "frontend-design": {
54
+ "kind": "external",
55
+ "source": {
56
+ "repository": "https://github.com/anthropics/skills.git",
57
+ "path": "skills/frontend-design"
58
+ },
59
+ "reviewed": "2026-10-26"
60
+ },
61
+ "grilling": {
62
+ "kind": "external",
63
+ "source": {
64
+ "repository": "https://github.com/mattpocock/skills.git",
65
+ "path": "skills/productivity/grilling"
66
+ },
67
+ "reviewed": "2026-10-26"
68
+ },
69
+ "improve": {
70
+ "kind": "external",
71
+ "source": {
72
+ "repository": "https://github.com/shadcn/improve.git",
73
+ "path": "skills/improve"
74
+ },
75
+ "reviewed": "2026-10-26"
76
+ },
77
+ "improve-animations": {
78
+ "kind": "external",
79
+ "source": {
80
+ "repository": "https://github.com/emilkowalski/skills.git",
81
+ "path": "skills/improve-animations"
82
+ },
83
+ "reviewed": "2026-10-26"
84
+ },
85
+ "interface-design": {
86
+ "kind": "external",
87
+ "source": {
88
+ "repository": "https://github.com/Dammyjay93/interface-design.git",
89
+ "path": ".claude/skills/interface-design"
90
+ },
91
+ "reviewed": "2026-10-26"
92
+ },
93
+ "make-interfaces-feel-better": {
94
+ "kind": "external",
95
+ "source": {
96
+ "repository": "https://github.com/jakubkrehel/make-interfaces-feel-better.git",
97
+ "path": "skills/make-interfaces-feel-better"
98
+ },
99
+ "reviewed": "2026-10-26"
100
+ },
101
+ "next-bundle-optimizer": {
102
+ "kind": "external",
103
+ "source": {
104
+ "repository": "https://github.com/vercel/next.js.git",
105
+ "path": "skills/next-bundle-optimizer"
106
+ },
107
+ "reviewed": "2026-10-26"
108
+ },
109
+ "next-cache-components-adoption": {
110
+ "kind": "external",
111
+ "source": {
112
+ "repository": "https://github.com/vercel/next.js.git",
113
+ "path": "skills/next-cache-components-adoption"
114
+ },
115
+ "reviewed": "2026-10-26",
116
+ "render": {
117
+ "frontmatter": {
118
+ "disable-model-invocation": true
119
+ }
120
+ }
121
+ },
122
+ "next-cache-components-optimizer": {
123
+ "kind": "external",
124
+ "source": {
125
+ "repository": "https://github.com/vercel/next.js.git",
126
+ "path": "skills/next-cache-components-optimizer"
127
+ },
128
+ "reviewed": "2026-10-26",
129
+ "render": {
130
+ "frontmatter": {
131
+ "disable-model-invocation": true
132
+ }
133
+ }
134
+ },
135
+ "next-dev-loop": {
136
+ "kind": "external",
137
+ "source": {
138
+ "repository": "https://github.com/vercel/next.js.git",
139
+ "path": "skills/next-dev-loop"
140
+ },
141
+ "reviewed": "2026-10-26"
142
+ },
143
+ "next-partial-prefetching-adoption": {
144
+ "kind": "external",
145
+ "source": {
146
+ "repository": "https://github.com/vercel/next.js.git",
147
+ "path": "skills/next-partial-prefetching-adoption"
148
+ },
149
+ "reviewed": "2026-10-26",
150
+ "render": {
151
+ "frontmatter": {
152
+ "disable-model-invocation": true
153
+ }
154
+ }
155
+ },
156
+ "next-partial-prefetching-optimizer": {
157
+ "kind": "external",
158
+ "source": {
159
+ "repository": "https://github.com/vercel/next.js.git",
160
+ "path": "skills/next-partial-prefetching-optimizer"
161
+ },
162
+ "reviewed": "2026-10-26",
163
+ "render": {
164
+ "frontmatter": {
165
+ "disable-model-invocation": true
166
+ }
167
+ }
168
+ },
169
+ "next-server-security": {
170
+ "kind": "custom",
171
+ "reviewed": "2026-10-26",
172
+ "note": "First-party stackfit starter skill."
173
+ },
174
+ "playwright-e2e-testing": {
175
+ "kind": "custom",
176
+ "reviewed": "2026-10-26",
177
+ "note": "First-party stackfit starter skill."
178
+ },
179
+ "react-doctor": {
180
+ "kind": "external",
181
+ "source": {
182
+ "repository": "https://github.com/millionco/react-doctor.git",
183
+ "path": "skills/react-doctor"
184
+ },
185
+ "reviewed": "2026-10-26"
186
+ },
187
+ "review-animations": {
188
+ "kind": "external",
189
+ "source": {
190
+ "repository": "https://github.com/emilkowalski/skills.git",
191
+ "path": "skills/review-animations"
192
+ },
193
+ "reviewed": "2026-10-26"
194
+ },
195
+ "shadcn": {
196
+ "kind": "external",
197
+ "source": {
198
+ "repository": "https://github.com/shadcn-ui/ui.git",
199
+ "path": "skills/shadcn"
200
+ },
201
+ "reviewed": "2026-10-26",
202
+ "render": {
203
+ "exclude": [
204
+ "evals/evals.json"
205
+ ]
206
+ }
207
+ },
208
+ "stackfit": {
209
+ "kind": "custom",
210
+ "reviewed": "2026-10-26",
211
+ "note": "First-party stackfit starter skill. Kept in sync with skills/stackfit in the stackfit repository."
212
+ },
213
+ "stripe-best-practices": {
214
+ "kind": "external",
215
+ "source": {
216
+ "repository": "https://github.com/stripe/ai.git",
217
+ "path": "skills/stripe-best-practices"
218
+ },
219
+ "reviewed": "2026-10-26"
220
+ },
221
+ "stripe-projects": {
222
+ "kind": "external",
223
+ "source": {
224
+ "repository": "https://github.com/stripe/ai.git",
225
+ "path": "skills/stripe-projects"
226
+ },
227
+ "reviewed": "2026-10-26",
228
+ "render": {
229
+ "frontmatter": {
230
+ "disable-model-invocation": true
231
+ }
232
+ }
233
+ },
234
+ "ui-ux-pro-max": {
235
+ "kind": "external",
236
+ "source": {
237
+ "repository": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git",
238
+ "path": ".claude/skills/ui-ux-pro-max"
239
+ },
240
+ "reviewed": "2026-10-26"
241
+ },
242
+ "upgrade-stripe": {
243
+ "kind": "external",
244
+ "source": {
245
+ "repository": "https://github.com/stripe/ai.git",
246
+ "path": "skills/upgrade-stripe"
247
+ },
248
+ "reviewed": "2026-10-26",
249
+ "render": {
250
+ "frontmatter": {
251
+ "disable-model-invocation": true
252
+ }
253
+ }
254
+ },
255
+ "vercel-composition-patterns": {
256
+ "kind": "external",
257
+ "source": {
258
+ "repository": "https://github.com/vercel-labs/agent-skills.git",
259
+ "path": "skills/composition-patterns"
260
+ },
261
+ "reviewed": "2026-10-26",
262
+ "render": {
263
+ "exclude": [
264
+ "AGENTS.md",
265
+ "README.md",
266
+ "metadata.json"
267
+ ]
268
+ }
269
+ },
270
+ "vercel-react-best-practices": {
271
+ "kind": "external",
272
+ "source": {
273
+ "repository": "https://github.com/vercel-labs/agent-skills.git",
274
+ "path": "skills/react-best-practices"
275
+ },
276
+ "reviewed": "2026-10-26",
277
+ "render": {
278
+ "exclude": [
279
+ "AGENTS.md",
280
+ "README.md",
281
+ "metadata.json"
282
+ ]
283
+ }
284
+ },
285
+ "vercel-react-view-transitions": {
286
+ "kind": "external",
287
+ "source": {
288
+ "repository": "https://github.com/vercel-labs/agent-skills.git",
289
+ "path": "skills/react-view-transitions"
290
+ },
291
+ "reviewed": "2026-10-26",
292
+ "render": {
293
+ "exclude": [
294
+ "AGENTS.md",
295
+ "README.md",
296
+ "metadata.json"
297
+ ],
298
+ "frontmatter": {
299
+ "disable-model-invocation": true
300
+ }
301
+ }
302
+ },
303
+ "web-design-guidelines": {
304
+ "kind": "external",
305
+ "source": {
306
+ "repository": "https://github.com/vercel-labs/agent-skills.git",
307
+ "path": "skills/web-design-guidelines"
308
+ },
309
+ "reviewed": "2026-10-26",
310
+ "render": {
311
+ "exclude": []
312
+ }
313
+ }
314
+ }
315
+ }
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: next-server-security
3
+ description: Next.js App Router server-side security - Server Actions as public endpoints, data access layer and DTOs, authz in proxy.ts vs at the data, Cache Components with user data, route handler CSRF, secrets and client-boundary leaks. Use when writing or reviewing Server Actions, route.ts, proxy/middleware, auth, data fetching, or caching of user-specific data.
4
+ ---
5
+
6
+ # Next.js server security
7
+
8
+ Next.js-specific failure modes that generic OWASP checklists miss. For the general OWASP pass, also use `owasp-security-check`. Canonical reference: https://nextjs.org/docs/app/guides/data-security.
9
+
10
+ ## Entry points (audit every one)
11
+
12
+ | Entry point | Why it is public |
13
+ | --- | --- |
14
+ | Every exported function in a `"use server"` file that the app uses | Reachable by direct `POST`, not only through your UI. Encrypted action IDs and dead-code elimination reduce exposure; they are not access control. |
15
+ | Inline `"use server"` functions in components | Same. A page-level auth check or `redirect()` does **not** protect the actions defined on that page. |
16
+ | `route.ts` handlers | Plain HTTP. No built-in Origin check (unlike Server Actions). |
17
+ | `proxy.ts` (Next 16; `middleware.ts` before) | Runs on matched requests only and is easy to bypass or mis-match. |
18
+ | `[param]` segments, `searchParams`, headers, cookies | User input. |
19
+
20
+ ## Rules
21
+
22
+ 1. **Authorize at the data, not the route.** Put auth + authorization in a server-only data access layer (DAL): `import "server-only"`, a `cache()`d `getCurrentUser()`, then ownership checks before every read or write. `proxy.ts` is for optimistic redirects only. (CVE-2025-29927 let attackers skip middleware entirely with one header; apps that also checked in the DAL were safe.)
23
+ 2. **Every Server Action re-verifies.** Inside the action (or the DAL function it calls): authenticate, authorize the specific resource (IDOR), then mutate. Identity comes from the session, never from an argument, a hidden input, or a `.bind()` value.
24
+ 3. **Validate every action argument at runtime.** TypeScript types are erased; parse `FormData` and arguments with a schema (`z.safeParse` or the repo's validator) and return a typed error state instead of throwing raw errors.
25
+ 4. **Return DTOs, not records.** Action return values and props passed to Client Components are serialized to the browser (RSC payload / HTML). Select only the fields the UI needs. Never pass a full ORM row, user object, or session to a `"use client"` component. For defense in depth enable `experimental.taint` and use `experimental_taintObjectReference` / `experimental_taintUniqueValue` on secrets and raw records.
26
+ 5. **Secrets stay in the DAL.** Only server-only modules read `process.env` secrets and DB clients. Anything prefixed `NEXT_PUBLIC_` ships in the client bundle; never put keys there. Validate env at startup with a schema.
27
+ 6. **Cache Components and user data.**
28
+ - `"use cache"` output is shared across users and requests. `cookies()`, `headers()`, and `searchParams` are not allowed inside it; pass values in as arguments, and they become part of the cache key.
29
+ - A cached function that takes `userId` returns that user's data to *any* caller who passes the id: authorize **before** calling it, outside the cache boundary.
30
+ - Per-user personalized results: `"use cache: private"` (never stored in a server cache across requests) or no cache.
31
+ - After a mutation, invalidate what you changed: `updateTag(tag)` inside the action for read-your-own-writes, `revalidateTag(tag, "max")` for stale-while-revalidate, or `revalidatePath`.
32
+ 7. **Route handlers that mutate with cookie auth need CSRF protection.** Prefer Server Actions (Next checks `Origin` against `Host`). Otherwise verify the `Origin` header, require a non-simple content type or a CSRF token, and keep session cookies `SameSite=Lax` or stricter, `HttpOnly`, `Secure`. Behind a reverse proxy or alternate domain, set `serverActions.allowedOrigins` instead of disabling checks.
33
+ 8. **No mutations during render.** Logging out, writing, or revalidating from a page because of a `searchParams` value is a GET side effect. Use an action.
34
+ 9. **Redirects.** `redirect(searchParams.callbackUrl)` is an open redirect. Allow only same-origin relative paths (starts with `/`, not `//`).
35
+ 10. **Headers.** Static security headers go in `next.config` `headers()`. A nonce-based CSP is generated in `proxy.ts` and forces dynamic rendering for those routes; choose that trade-off deliberately.
36
+ 11. **Self-hosting multiple instances:** set a stable `NEXT_SERVER_ACTIONS_ENCRYPTION_KEY` so closure encryption works across instances. Encryption of closed-over values is not a reason to close over secrets.
37
+ 12. **Rate-limit expensive actions** (email, signup, AI calls, uploads) by user and IP.
38
+ 13. **Stay on the latest patch of your Next.js and React line.** RSC protocol bugs are critical (React2Shell, CVE-2025-55182, was unauthenticated RCE in Next 15.x/16.0 App Router apps). Check the repo's audit command and https://github.com/vercel/next.js/security/advisories when touching dependencies.
39
+
40
+ ## Server Action shape
41
+
42
+ ```ts
43
+ // app/posts/actions.ts
44
+ "use server";
45
+
46
+ import { z } from "zod";
47
+ import { updateTag } from "next/cache";
48
+ import { deletePost } from "@/data/posts"; // server-only DAL: auth + ownership inside
49
+
50
+ const Input = z.object({ postId: z.string().uuid() });
51
+
52
+ export async function deletePostAction(_prev: unknown, formData: FormData) {
53
+ const parsed = Input.safeParse({ postId: formData.get("postId") });
54
+ if (!parsed.success) return { ok: false as const, error: "Invalid input" };
55
+ await deletePost(parsed.data.postId); // throws/returns forbidden if not the owner
56
+ updateTag(`posts`);
57
+ return { ok: true as const }; // minimal result, no DB row
58
+ }
59
+ ```
60
+
61
+ ## Review output
62
+
63
+ For each finding: entry point, file:line, what an attacker sends, impact, fix. Check the repo's actual auth library and DAL location first; do not assume paths.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: playwright-e2e-testing
3
+ description: Write, fix, or review Playwright end-to-end tests, especially for Next.js apps - locators, auth via storageState, flaky waits, server-side fetch mocking, CI against a production build. Use for *.spec.ts / e2e/ / playwright.config changes or flaky browser tests. For unit and component tests use frontend-testing.
4
+ ---
5
+
6
+ # Playwright E2E
7
+
8
+ ## Start from repository evidence
9
+
10
+ 1. Read `AGENTS.md` and the testing page linked from `docs/agent/index.md`.
11
+ 2. Read `playwright.config.*` (`testDir`, `projects`, `webServer`, `use.baseURL`, `testIdAttribute`), existing fixtures, page objects, and the auth setup project.
12
+ 3. Use the repo's package manager and scripts. Match existing file names, tags, and fixture style; do not introduce page objects or new fixtures if the suite does not use them.
13
+
14
+ ## Rules that prevent flaky tests
15
+
16
+ - **Locators:** `getByRole` with `name`, then `getByLabel`, `getByText`, then `getByTestId` (respect a configured `testIdAttribute`). No CSS chains, XPath, or `.nth()` on unstable lists.
17
+ - **Waiting:** only web-first assertions (`await expect(locator).toBeVisible()`, `toHaveURL`, `toHaveText`). Never `waitForTimeout`. Avoid `waitForLoadState("networkidle")`: Next.js prefetching and streaming keep the network busy. After navigation use `await expect(page).toHaveURL(...)` or `page.waitForURL`.
18
+ - **Hydration:** a click on a server-rendered button before hydration can be lost. Assert the result of the interaction (a visible state change), not just that the click ran; if the suite has a hydration-ready helper, use it.
19
+ - **Server Actions / forms:** assert on the UI that the action produces (toast, updated row, redirect URL), not on internal network calls.
20
+ - **Isolation:** every test creates the data it needs (API or DB fixture) and can run in parallel and in any order. No dependence on a previous test.
21
+ - **Auth:** log in once in a setup project and save `storageState` per role; tests reuse it. Do not log in through the UI in every test.
22
+
23
+ ## Next.js specifics
24
+
25
+ - **CI runs against a production build** (`next build` then `next start`) through `webServer`; `next dev` compiles routes on first hit and causes timeouts. Use `reuseExistingServer: !process.env.CI` locally.
26
+ - **`page.route` only intercepts browser requests.** Fetches made by Server Components, Route Handlers, or Server Actions run on the server and are not intercepted. Point the server at a test backend/database via env, or use the repo's existing server-side mocking (MSW in the server, or `next/experimental/testmode/playwright` if already set up).
27
+ - **Instant navigation / static shell guards** under Cache Components: use the `next-cache-components-optimizer` skill (`@next/playwright` `instant()`).
28
+ - **Visual snapshots:** fixed viewport, `animations: "disabled"`, mask dynamic regions (dates, avatars). Snapshots are per OS/browser; only update them on the platform CI uses.
29
+
30
+ ## Run and debug
31
+
32
+ - Narrow first: `<pm> playwright test <file> -g "<title>" --project=chromium`.
33
+ - Flaky: `--repeat-each=10 --workers=1`, then `--trace on` and `playwright show-trace`.
34
+ - Report the exact command, pass/fail, and any test you could not run (for example missing env or seed data).
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: stackfit
3
+ description: Set up and run stackfit, the CLI that gives each repository only the agent skills, rules, commands, and subagents that fit its stack, from one catalog, for Claude Code, Cursor, and Codex. Use when skills load in repos that don't need them, when syncing skills or rules across several repos or machines, when asked which skills a repo should have or what they cost in context, or when stackfit is mentioned.
4
+ license: MIT
5
+ ---
6
+
7
+ # stackfit
8
+
9
+ Every installed skill puts its name and description into every agent session. Install 30 skills globally and a Go service carries your React animation guides on every turn. stackfit keeps one **catalog** of skills and gives each repository only the **packs** its manifests call for, rendered natively for Claude Code, Cursor, and Codex.
10
+
11
+ Docs: https://github.com/amin0075/stackfit · Package: `npx stackfit` (Node 22+, no dependencies).
12
+
13
+ ## Ground rules for the agent
14
+
15
+ 1. **Measure, then dry-run, then write.** Run `report` and `status` before `sync`, and show the user what will change.
16
+ 2. **Every project command needs a selector:** `--project <path>`, `--root <dir>`, or `--all` (needs a machine profile). Bare `stackfit status` fails.
17
+ 3. **Never pass `--force` on your own.** A collision means a file stackfit did not create. Show it and follow `references/troubleshooting.md`.
18
+ 4. **Never commit, push, or publish** unless asked. Know what is tracked: stackfit excludes exactly the files it generates (via `.git/info/exclude`); files you create in `docs/agent/` (config, repo-owned skills) and the `init` scaffolding are meant to be committed. Check with `git check-ignore -v <file>` (ignored?) and `git ls-files <path>` (tracked?), and tell the user which files to commit.
19
+ 5. **No personal values in the catalog.** Emails, org names, and tokens go in the catalog's gitignored `.env`, used as `{{env:NAME}}`.
20
+ 6. **Report numbers honestly.** `report` estimates what loads in every session: skill names + descriptions and always-on rules, per repo, plus the global skill folders that load everywhere regardless. Compare per-repo numbers with today's global cost; if a repo goes up, say so. Never present "every catalog skill in every repo" as the user's previous state.
21
+ 7. Reuse the user's existing catalog (`stackfit audit` finds it); never create a second one silently.
22
+
23
+ ## Set up stackfit for someone's repos
24
+
25
+ 1. **Baseline.** Note what loads today, per tool: `~/.claude/skills` (Claude Code), `~/.cursor/skills` (Cursor), `~/.codex/skills` (Codex), `~/.agents/skills` (shared): `ls ~/.claude/skills ~/.agents/skills ~/.cursor/skills ~/.codex/skills 2>/dev/null`. Per repo, check `.claude/skills`, `.cursor/skills`, `.cursor/rules`, `.agents/skills`. stackfit writes for all three tools, so a user who only had Claude globals will see Cursor and Codex gain skills they did not have; say so.
26
+ 2. **Catalog.** `npx stackfit audit` first: if a catalog exists, use it. `No catalog found` (exit 1) is expected on a first run. Choose with the user:
27
+ - **Their own skills only** (they already have skills, or few globals): `npx stackfit catalog init`, then import their skills (recipe 3), skipping any the model doesn't need (recipe 11). Lowest context; nothing new is added.
28
+ - **Curated starter** (they want good skills per stack): `npx stackfit catalog init --starter`, then `npx stackfit refresh --all` (needs git + GitHub). Adds packs they never had: some repos may load more than today.
29
+ - Both: start empty, then copy chosen skills from a starter made in another folder (`catalog init /tmp/sf-starter --starter`).
30
+ Then `npx stackfit audit` (expect no errors).
31
+ 3. **Preview.**
32
+ ```bash
33
+ npx stackfit report --root ~/code
34
+ npx stackfit status --root ~/code
35
+ ```
36
+ **Record the `Global skills add ...` line now**: it is the baseline, and it disappears once the globals are cleaned up. Compare each repo's `per session` with it. Too high for a repo? Trim with `excludePacks` (recipe 4) or mark long one-off skills manual-only (recipe 7). If `status` stops at `unmanaged collision`, the repo already has its own skills or rules: move them (recipe 3), then preview again.
37
+ 4. **Write.** `npx stackfit sync --root ~/code`, then `status` again: every repo should say `up to date`. Besides what `status` listed, sync writes `.stackfit.lock.json` and a managed block in `.git/info/exclude` in each repo. Do step 6 right after: until the global copies move, those skills load twice.
38
+ 5. **Make `--all` work** (optional; for daily `sync --all` / `update --all`). Create `<catalog>/stackfit.local.json`:
39
+ ```json
40
+ { "schemaVersion": 1, "machines": [ { "id": "laptop", "match": { "platform": "darwin" }, "roots": ["~/code"] } ] }
41
+ ```
42
+ `platform` is `darwin`, `linux`, or `win32`. Without `projects`, every Git repo directly under the roots is included.
43
+ 6. **Clean up globals, carefully.** Global copies of skills that are now in the catalog still load everywhere; removing them is where most savings come from. For each one, with the user's OK:
44
+ - `diff -r ~/.claude/skills/<name> <catalog>/skills/<name>`: keep the user's edits if they differ;
45
+ - make sure it is in a pack that reaches every repo that needs it: an `always` pack (like `core`) for every synced repo, otherwise only repos whose manifests match;
46
+ - `always` means every repo stackfit syncs, not every session: folders outside the roots and non-repo sessions lose the skill. If the user wants it truly everywhere, keep that one global (and out of the catalog's packs, so it doesn't load twice) or add more roots;
47
+ - move rather than delete: `mkdir -p ~/.claude/skills-backup && mv ~/.claude/skills/<name> ~/.claude/skills-backup/`.
48
+ 7. **Report.** Run `report` again. Per repo: packs and `per session` against the baseline you recorded, per tool. If the absolute numbers are small, say so: the gain may be organisation, not context. Name the files to commit (`docs/agent/...`). Suggest keeping the catalog in a private Git repo; run `git init` / push only if the user agrees.
49
+
50
+ What `report` looks like (starter catalog, four repos, 31 skills installed globally):
51
+
52
+ ```text
53
+ project skills skill listings rules per session packs
54
+ ingest-worker 2 ~168 tok ~83 tok ~251 tok core
55
+ marketing-site 25 ~1.5k tok ~83 tok ~1.6k tok core, react, nextjs, ui, motion
56
+ payments-api 5 ~397 tok ~83 tok ~480 tok core, stripe
57
+ storefront 24 ~1.5k tok ~83 tok ~1.6k tok core, react, nextjs, e2e, ui, shadcn, stripe
58
+
59
+ With stackfit: ~4.0k tokens across 4 project(s). Every catalog skill in every repo would be ~8.7k.
60
+ Global skills add ~3.0k tokens to every session in every repo, with or without stackfit: ~/.claude/skills (31).
61
+ ```
62
+
63
+ Here the Go worker goes from ~3.0k (all globals) to ~251 once the globals are moved into the catalog; the Next.js apps need most packs and save little.
64
+
65
+ ## How it works
66
+
67
+ ```text
68
+ ~/.stackfit/ (the catalog; keep it in a private Git repo)
69
+ stackfit.json enabled skills + packs (which skills go where)
70
+ skill-sources.json upstream source, review date, render overrides per skill
71
+ skills/<name>/ the skills
72
+ rules/ commands/ agents/ shared adapters
73
+ stackfit.local.json (gitignored) project folders per machine
74
+ .env (gitignored) values for {{env:NAME}}
75
+
76
+ <project>/
77
+ .agents/skills/ selected skills, one physical copy (Codex reads this)
78
+ .claude/skills, .cursor/skills links to it
79
+ .claude/rules, .cursor/rules, .claude/commands, .cursor/commands, .claude/agents, .cursor/agents
80
+ .stackfit.lock.json what stackfit owns here (git-excluded with the rest)
81
+ docs/agent/config.json optional, tracked: this repo's pack choices
82
+ docs/agent/skills/<name>/ optional, tracked: skills only this repo uses
83
+ ```
84
+
85
+ **Packs** decide everything. A pack is `always` (every repo), `detect`ed (dependencies in `package.json`, `requirements*.txt`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `composer.json`, or marker files, at the root and in subfolders like `web/`, `apps/*`, `packages/*`), or opt-in. Projects are named by folder. Field reference: `references/configuration.md`.
86
+
87
+ ## Commands
88
+
89
+ | Command | Use it to |
90
+ | --- | --- |
91
+ | `catalog init [dir] [--starter]` | Create a catalog (default `~/.stackfit`) |
92
+ | `report [--json]` | Per repo: packs, skills, listing + rule tokens per session; global skill folders as baseline |
93
+ | `status [--check]` | Dry run; `--check` exits 1 if anything would change |
94
+ | `sync` | Write skills, rules, commands, agents into projects |
95
+ | `update` | `git pull --ff-only` the catalog, then sync (`--skip-pull` to skip) |
96
+ | `init` | Add tracked `AGENTS.md`, `CLAUDE.md`, `docs/agent/` (never overwrites; ask first) |
97
+ | `refresh --skill <name>` / `--all` | Re-vendor upstream skills into the catalog |
98
+ | `audit [--json]` | Provenance, staleness (180 days), packs, description sizes, cost |
99
+
100
+ The catalog is found from `--catalog`, `STACKFIT_CATALOG`, the nearest `stackfit.json` above the current folder, or `~/.stackfit`.
101
+
102
+ ## Common requests
103
+
104
+ | The user says | Do this | Recipe |
105
+ | --- | --- | --- |
106
+ | "Too many skills" / "what does this repo load?" | `report --project .`, explain the packs column and the global line | 1 |
107
+ | "Skill X should apply to every repo" | Put it in an `always` pack (e.g. `core`), sync, then remove the global copy | 3 |
108
+ | "Set this up for all my repos" | The setup steps above | 2, 3, 5 |
109
+ | "I already have skills in ~/.claude/skills or .cursor/rules" | Move shared ones to the catalog, repo-specific ones to `docs/agent/` | 3 |
110
+ | "This repo needs X but not Y" | `packs` / `excludePacks` / `skills` in `docs/agent/config.json` | 4 |
111
+ | "Same setup on my work laptop" | Clone the catalog there, add a machine entry, `sync --all` | 5 |
112
+ | "Add skill Z from GitHub" | `source` in `skill-sources.json`, then `refresh --skill` | 6 |
113
+ | "This upstream skill is too long" / "only when I ask" | `render.frontmatter` override | 7 |
114
+ | "Check this in CI" | Validate the repo config and the catalog in CI | 8 |
115
+ | "Share with my team" | Catalog in a team repo; everyone runs `update --all` | 9 |
116
+
117
+ Step-by-step versions: `references/recipes.md`. Every error message and its fix: `references/troubleshooting.md`.
118
+
119
+ ## After any change
120
+
121
+ Run `npx stackfit status` with the same selector (expect `up to date` for every repo) and `npx stackfit report`. Tell the user what changed per repo, the before/after figures, and which tracked files (`docs/agent/...`) to commit.