@pikku/skills 0.12.57 → 0.12.59

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.
Files changed (72) hide show
  1. package/dist/skills.gen.js +2 -2
  2. package/package.json +10 -7
  3. package/skills/pikku-a11y/SKILL.md +5 -3
  4. package/skills/pikku-addon/SKILL.md +8 -9
  5. package/skills/pikku-agent/SKILL.md +16 -13
  6. package/skills/pikku-agent/references/runner-vercel.md +1 -1
  7. package/skills/pikku-architect/SKILL.md +7 -10
  8. package/skills/pikku-auth/SKILL.md +16 -20
  9. package/skills/pikku-auth/references/better-auth.md +74 -37
  10. package/skills/pikku-auth/references/sessions.md +8 -0
  11. package/skills/pikku-build/SKILL.md +36 -68
  12. package/skills/pikku-build/references/app.md +27 -828
  13. package/skills/pikku-build/references/feature.md +3 -5
  14. package/skills/pikku-build/references/phase-1-what-it-is.md +167 -0
  15. package/skills/pikku-build/references/phase-2-people-and-apps.md +133 -0
  16. package/skills/pikku-build/references/phase-3-plan.md +62 -0
  17. package/skills/pikku-build/references/phase-4-build.md +249 -0
  18. package/skills/pikku-build/references/phase-5-prove-and-ship.md +148 -0
  19. package/skills/pikku-build/references/platform.md +5 -6
  20. package/skills/pikku-build/references/quick.md +2 -2
  21. package/skills/pikku-build/references/ship.md +4 -5
  22. package/skills/pikku-changes/SKILL.md +13 -7
  23. package/skills/pikku-concepts/SKILL.md +19 -258
  24. package/skills/pikku-concepts/references/cli.md +63 -0
  25. package/skills/pikku-concepts/references/functions.md +117 -0
  26. package/skills/pikku-concepts/references/language.md +5 -5
  27. package/skills/pikku-concepts/references/packages.md +6 -4
  28. package/skills/pikku-concepts/references/testing.md +14 -0
  29. package/skills/pikku-convert-screen/SKILL.md +7 -1
  30. package/skills/pikku-deploy/SKILL.md +29 -30
  31. package/skills/pikku-deploy/references/ws.md +1 -1
  32. package/skills/pikku-emails/SKILL.md +7 -3
  33. package/skills/pikku-guide/SKILL.md +7 -10
  34. package/skills/pikku-i18n/SKILL.md +18 -19
  35. package/skills/pikku-i18n/references/messages.md +6 -8
  36. package/skills/pikku-knowledge/SKILL.md +42 -45
  37. package/skills/pikku-kysely/SKILL.md +50 -13
  38. package/skills/pikku-list-query/SKILL.md +27 -14
  39. package/skills/pikku-meta/SKILL.md +13 -16
  40. package/skills/pikku-meta/references/audit.md +1 -45
  41. package/skills/pikku-meta/references/versioning.md +1 -1
  42. package/skills/pikku-middleware/SKILL.md +23 -13
  43. package/skills/pikku-middleware/references/middleware-patterns.md +2 -2
  44. package/skills/pikku-n8n-import/SKILL.md +7 -8
  45. package/skills/pikku-permissions/SKILL.md +14 -8
  46. package/skills/pikku-react/SKILL.md +7 -6
  47. package/skills/pikku-realtime/SKILL.md +16 -11
  48. package/skills/pikku-report/SKILL.md +8 -10
  49. package/skills/pikku-scenario/SKILL.md +15 -18
  50. package/skills/pikku-scenario/references/steps.md +3 -4
  51. package/skills/pikku-scenario/references/virtual-users.md +1 -1
  52. package/skills/pikku-seo/SKILL.md +16 -8
  53. package/skills/pikku-service-backends/SKILL.md +26 -28
  54. package/skills/pikku-services/SKILL.md +8 -9
  55. package/skills/pikku-services/references/services.md +1 -1
  56. package/skills/pikku-software-archaeology/README.md +12 -1
  57. package/skills/pikku-software-archaeology/SKILL.md +9 -2
  58. package/skills/pikku-software-archaeology/references/pikku-mapping.md +1 -1
  59. package/skills/pikku-software-archaeology/references/sources/express.md +75 -0
  60. package/skills/pikku-software-archaeology/references/sources/laravel.md +77 -0
  61. package/skills/pikku-software-archaeology/references/sources/nestjs.md +73 -0
  62. package/skills/pikku-software-archaeology/references/sources/rails.md +72 -0
  63. package/skills/pikku-software-archaeology/references/tests-to-scenarios.md +72 -0
  64. package/skills/pikku-tailwind/SKILL.md +15 -16
  65. package/skills/pikku-theme/SKILL.md +15 -17
  66. package/skills/pikku-ui/SKILL.md +4 -3
  67. package/skills/pikku-webhook/SKILL.md +10 -11
  68. package/skills/pikku-wiring/SKILL.md +45 -47
  69. package/skills/pikku-wiring/references/channel.md +1 -1
  70. package/skills/pikku-wiring/references/scheduler.md +1 -1
  71. package/skills/pikku-wiring/references/trigger.md +24 -1
  72. package/skills/pikku-workflow/SKILL.md +7 -8
@@ -0,0 +1,148 @@
1
+ # Phase 5 — Prove it, make it look designed, ship it (§7-§9)
2
+
3
+ Part of the app workflow (`app.md` is the index and the rules that hold throughout). Building a changeset is §6-§6b, in `phase-4-build.md`.
4
+
5
+ ## 7. Prove it — scenarios
6
+
7
+ A scenario is a user journey run as one of your virtual users, over the real
8
+ transport, with that virtual user's session. It is the only kind of test worth writing
9
+ here, because a passing one proves the app works the way a signed-in person
10
+ experiences it. Three ship in `packages/functions/test/scenarios/` — keep them
11
+ green — and every scenario a changeset's plan names becomes one more.
12
+
13
+ **Read the scenarios reference (see SKILL.md) before writing the changeset's scenarios,
14
+ and again whenever one of these describes what you are doing.** It is the file
15
+ where the expensive lessons live, and most of them produce a GREEN suite that
16
+ proves nothing:
17
+
18
+ - the shape of a scenario, and `do` vs `given`/`when`/`then`
19
+ - what survives DSL extraction — a `then` in `return` position asserts nothing,
20
+ and a shared setup helper credits its steps to the wrong virtual user
21
+ - what to assert — refusals must read the REASON, totals must be deltas, and the
22
+ assertion nobody writes is the row count
23
+ - living without a state reset: the suite must be green on its SECOND run
24
+ - how a shared step rots as later changesets add writers of the rows it selects
25
+ - browser specifics — the click/navigate race, testids, and `Outlet` nesting
26
+
27
+ Run them:
28
+
29
+ ```sh
30
+ bunx --bun pikku scenario run local --spawn # server-side, the fast path
31
+ bunx --bun pikku scenario run local --spawn --run browser # the same journeys, driven as a human
32
+ ```
33
+
34
+ In a multi-app project that one run covers both frontends: each virtual user carries
35
+ its own `app` and `@pikku/playwright` resolves the base url from the
36
+ environment's `appUrls` map, so there is no second environment to run.
37
+
38
+ **Run the whole suite, not the changeset's own scenarios.** The changeset's
39
+ scenarios are the ones you wrote to pass; the regression lives in someone
40
+ else's. Tightening what "archived" means is a one-function change that reads as
41
+ local and quietly breaks the first changeset's scenario nobody re-ran.
42
+
43
+ **Restart the server after adding a function, and never edit one while a run is
44
+ in flight.** Hot reload does not register a new RPC and does not re-run
45
+ `afterStart`, so a fresh function answers 404 and anything provisioned at boot
46
+ is missing — failures that read like a wiring bug and are nothing but a stale
47
+ process. The same reload is what makes a run unrepeatable if you edit during
48
+ it: a browser pass is long enough to feel like free time, and a schema touched
49
+ at minute four hot-reloads into a half-generated contract, so every scenario
50
+ after that point fails on something you have already fixed. Wait for the run or
51
+ kill it — a run you edited under is not a result.
52
+
53
+ ### 7a. Coverage — which functions have actually been run
54
+
55
+ Run it as each changeset closes, read `coverage/scenario-coverage.json`, and report the number when you hand
56
+ the changeset over. The scenarios reference (see SKILL.md), "Coverage", has the commands and how to tell a
57
+ missing scenario from a function that should not exist from a real deferral.
58
+
59
+ ## 8. Make it look like someone designed it
60
+
61
+ **This section numbers 8, but half of it has already happened.** Read
62
+ the design reference (see SKILL.md) before the first screen is built — a design pass run on
63
+ eight changesets of scaffolded screens is a repaint, and it shows. What is left
64
+ here at §8 is the theme you may have deferred and the critique you cannot run
65
+ until there are screens to critique.
66
+
67
+ Three separate jobs, and conflating them is why open-source builds come out
68
+ looking like the template:
69
+
70
+ - **Direction** — deciding what it should look like. **No open-source tool does
71
+ this.** A hosting platform may offer one; you have §1's answer and 8a below.
72
+ - **Execution** — whether the screens actually realise that direction, or
73
+ default to whatever component was nearest. No theme does this, and it is where
74
+ "works but looks like nobody decided anything" comes from.
75
+ the design reference (see SKILL.md) carries the process for it, and it belongs at §6, per
76
+ screen.
77
+ - **Critique** — judging how well the built screens execute the direction.
78
+ `impeccable` does this well, and it is free.
79
+
80
+ Impeccable audits the design you chose. It will never tell you the app should
81
+ have looked like something else — it will happily award a clean bill of health to
82
+ a perfectly-executed default. Skip the first two and you ship Neutral with good
83
+ spacing.
84
+
85
+ ### 8a. Author the theme — the step nothing does for you
86
+
87
+ The look lives in `packages/theme` as data. **Read the theming reference (see SKILL.md)**: the file layout, what
88
+ each field changes, turning a direction in words into a theme, setting the theme once instead of hardcoding
89
+ colours, sharing it across apps (vary the register, not the palette), and writing the direction into
90
+ `knowledge/decisions/design/`.
91
+
92
+ ### 8b. Compose real components, then critique
93
+
94
+ **The design reference (see SKILL.md) is where design actually lives** — committing to a
95
+ direction before the first screen, judging the result from screenshots rather
96
+ than from source, the two screens that get skipped, and why you reset the dev
97
+ database before judging anything. It prescribes no layouts on purpose: two apps
98
+ built from this skill should not look like each other. What follows here is only
99
+ the component inventory.
100
+
101
+ **Compose with rich components — not tables and text everywhere:**
102
+
103
+ - **shadcn `chart`** (Recharts underneath, coloured by `--chart-1` to `--chart-5`) for overviews — area,
104
+ bar, line and pie charts. A metric worth showing is
105
+ worth a chart, not a number in a paragraph.
106
+ - **shadcn `calendar` and `date-picker`** for anything time-based, including
107
+ range inputs. Never hand-roll a date field.
108
+ - Composed layouts over flat lists — a timeline for history, steps for
109
+ multi-step progress, `Card` + a CSS grid for a gallery, `Progress` for
110
+ completion, `Badge` for status.
111
+
112
+ Add each one with the shadcn CLI and use the real component.
113
+
114
+ Then critique it. Free, and works across coding agents:
115
+
116
+ ```sh
117
+ npx impeccable install # current releases need Node 22.18+
118
+ ```
119
+
120
+ Impeccable scores a screen against interaction heuristics and names what is
121
+ wrong: hierarchy, spacing, type registers, states you forgot. Run it on **every**
122
+ screen in **every** app, fix what it finds, and re-run the ones you changed.
123
+
124
+ Screenshots (desktop and ~390px), feeding them to impeccable, and resetting the dev database before you judge
125
+ are in the design reference (see SKILL.md), "Judge it" and "Facts, not taste". The template already mounts a
126
+ phone navigation per `AGENTS.md` — pick `MobileTabBar` or `MobileNavDrawer` deliberately per app, never both.
127
+
128
+ The gate: **no P0 findings left on any screen, in any app, at either width**,
129
+ and every screen honestly answers the questions in the design reference —
130
+ including whether it looks like the direction you committed to or like the
131
+ components you had. Don't silence a finding by deleting the feature it is
132
+ about.
133
+
134
+ ## 9. Ship it, and stay deploy-ready
135
+
136
+ When the queue is empty, `pikku knowledge gaps` lists nothing and the scenarios are green, read
137
+ the ship reference (see SKILL.md). It carries the open-source deploy paths (`--provider
138
+ standalone`, `cloudflare`, `aws`), how to serve several frontends behind one
139
+ API, the pre-release gate to run, and the contract that keeps the project
140
+ importable by a hosting platform later rather than a migration.
141
+
142
+ The app is not handed over without its user guide. The scenarios you wrote are
143
+ already its skeleton: read **pikku-guide**, write one page per audience citing
144
+ every feature, and build it from a full, passing `--run browser --screenshots`
145
+ run.
146
+
147
+ The deploy-readiness contract in that reference (no hardcoded host, port or `process.env` in a function; generated
148
+ files stay generated) is cheaper to honour while building than to retrofit.
@@ -26,9 +26,9 @@ failed; a showcase where every surface is a stub has also failed. The bar for
26
26
  each surface below: **it does something the app genuinely needs, and a scenario
27
27
  proves it.** A cron job that logs "tick" is not a schedule — it is a comment.
28
28
 
29
- Each surface lands with its console link, filtered by the person's level
30
- (SKILL.md, "Who you are talking to"): a non-technical person sees the workflow
31
- or agent page, never the queue, scheduler or wire pages behind it.
29
+ Each surface is reported at the person's level (SKILL.md, "Who you are talking
30
+ to"): a non-technical person hears about the workflow or the agent, never the
31
+ queue, scheduler or wire behind it.
32
32
 
33
33
  Budget the extra surfaces at one changeset each. They are not free, and a
34
34
  half-wired workflow engine is worse than no workflow engine.
@@ -46,7 +46,7 @@ at §1, and it is much cheaper than contriving a use later.
46
46
 
47
47
  The rest — MCP, triggers and webhooks, extra locales, contract versioning,
48
48
  addons — are chosen on merit. Write the motivation into the note. If you cannot
49
- name what one of *those* is for in this app, drop it and say why in
49
+ name what one of _those_ is for in this app, drop it and say why in
50
50
  `knowledge/decisions/`: a documented omission is a stronger showcase than a
51
51
  contrived inclusion.
52
52
 
@@ -63,7 +63,6 @@ bunx --bun pikku enable events # realtime events channel + SSE stream
63
63
  bunx --bun pikku enable remote-rpc # internal RPC queue worker + HTTP endpoint
64
64
  bunx --bun pikku enable webhook # outgoing webhook delivery queue worker
65
65
  bunx --bun pikku enable scenarios # scenario instrumentation
66
- bunx --bun pikku enable console # console functions
67
66
  bunx --bun pikku enable rpc # public RPC endpoint
68
67
  ```
69
68
 
@@ -73,7 +72,7 @@ write the function — not the other way round.
73
72
  ## The surfaces
74
73
 
75
74
  Each has an installed skill that is authoritative on its API. Read it before
76
- writing the wiring; this section says what the surface is *for* and how to prove
75
+ writing the wiring; this section says what the surface is _for_ and how to prove
77
76
  it, not how to call it.
78
77
 
79
78
  ### Workflows — `pikku-workflow`
@@ -49,7 +49,7 @@ defaults are the point.
49
49
  Do not ask about language either — take the defaults and note them in §6.
50
50
  Identifiers are English in every project, whatever the product's market;
51
51
  `metaLocale` in `pikku.config.json` (the language of `description`/`title`/step
52
- `template`, which the Console renders) stays `en` unless the user already told
52
+ `template`) stays `en` unless the user already told
53
53
  you otherwise. If the request says the app's UI is not English, that is the
54
54
  message catalogue only: add the locale and set `defaultLocale`, and leave
55
55
  `baseLocale` at `en`. the app workflow's §1a has the three axes in full; getting
@@ -262,7 +262,7 @@ bunx --bun pikku scenario run local --spawn
262
262
  ## 6. Hand it over honestly
263
263
 
264
264
  Tell the user, in one short paragraph and at their level (SKILL.md, "Who you
265
- are talking to"), with console links rather than descriptions: what runs, what
265
+ are talking to"), with the app and API links `bun run dev` printed: what runs, what
266
266
  it is seeded with, and that this is a quick build — no knowledge base, no
267
267
  changesets, no design pass, access control clicked-through rather than proven.
268
268
 
@@ -41,7 +41,6 @@ shape:
41
41
  "grouping": {
42
42
  "strategy": "single",
43
43
  "rules": [
44
- { "unit": "console", "addon": "console" },
45
44
  { "unit": "pdf", "tags": ["pdf"] }
46
45
  ]
47
46
  }
@@ -50,11 +49,11 @@ shape:
50
49
 
51
50
  `strategy` is the fallback for a function no rule matches:
52
51
 
53
- | strategy | fallback |
54
- | --- | --- |
52
+ | strategy | fallback |
53
+ | ---------- | ------------------------------------------------------------- |
55
54
  | `services` | one unit per distinct set of singleton services (the default) |
56
- | `function` | one unit each |
57
- | `single` | one shared unit |
55
+ | `function` | one unit each |
56
+ | `single` | one shared unit |
58
57
 
59
58
  Rules are ordered, first match wins, and match on `tags`, an `addon` namespace
60
59
  or `routes` globs. A rule always beats the strategy, so under `function` a rule
@@ -1,6 +1,12 @@
1
1
  ---
2
2
  name: pikku-changes
3
- description: 'Work a project''s changes queue — the todo list someone filed by circling things in the running app. Covers `pikku changes wait|claim|show|ask|reply|shot|done`: waiting for work without polling, asking instead of guessing, saying why an item is left undone, offering options as images, one commit per item. TRIGGER when: the user says "run the changes against a stage", "work the changes (queue)", "watch the changes", "pick up the changes", names a change by its #number, or you are otherwise idle in a checkout with open changes (`pikku changes list`). DO NOT TRIGGER for git changes, diffs or changelogs, and not for deploying or debugging a stage.'
3
+ description: >-
4
+ Work a project's changes queue, the todo list filed by circling things in the running app: `pikku
5
+ changes wait|claim|show|ask|reply|shot|done`, asking instead of guessing, saying why an item is
6
+ undone, options as images, one commit per item. TRIGGER when: the user says to run/work/watch/pick
7
+ up the changes (e.g. against a stage), names a change by #number, or you are idle in a checkout
8
+ with open changes (`pikku changes list`). DO NOT TRIGGER for git changes, diffs or changelogs, or
9
+ for deploying or debugging a stage.
4
10
  ---
5
11
 
6
12
  # Working a changes queue
@@ -39,12 +45,12 @@ something changed. `wait` does the waiting and exits only when there is work.
39
45
 
40
46
  2. When it exits, read the exit code:
41
47
 
42
- | code | meaning | do |
43
- | ---- | ------------------------------------------------------ | ----------------------------------------------- |
44
- | 0 | work printed (claimed, and/or `Answered`) | work it, then step 3 |
45
- | 2 | `--timeout`/`--once` found nothing | stop, or restart `wait` |
46
- | 3 | auth refused | relay the CLI's message; stop |
47
- | 1 | anything else | report the message; stop |
48
+ | code | meaning | do |
49
+ | ---- | ----------------------------------------- | ----------------------------- |
50
+ | 0 | work printed (claimed, and/or `Answered`) | work it, then step 3 |
51
+ | 2 | `--timeout`/`--once` found nothing | stop, or restart `wait` |
52
+ | 3 | auth refused | relay the CLI's message; stop |
53
+ | 1 | anything else | report the message; stop |
48
54
 
49
55
  3. For each item: `show` → fix → commit → `done`; or `ask` and move on; or `reply`
50
56
  saying why you are leaving it. Then start `wait` again, in the background.
@@ -1,13 +1,12 @@
1
1
  ---
2
2
  name: pikku-concepts
3
3
  description: >-
4
- Use FIRST in any Pikku codebase, before writing an import or reaching for another pikku skill.
5
- Covers the core mental model, function types, project structure, code generation and testing,
6
- and how to read `pikku doc` — the API surface of the pikku actually installed here, which also
7
- indexes which skill teaches each door. TRIGGER when: starting any Pikku task, about to import
8
- from `#pikku/*`, unsure whether an export exists or what its options are called, choosing which
9
- pikku skill to load, a build failed on an unknown import or option, or migrating an existing
10
- backend to Pikku. DO NOT TRIGGER when: the task is not a Pikku project.
4
+ Use FIRST, and whenever you are about to write or change Pikku code: core mental model, function
5
+ types, project structure, code generation, testing, and reading `pikku doc` (the installed API surface, which also indexes which
6
+ skill teaches each area). TRIGGER when: starting any Pikku task, about to import from `#pikku/*`,
7
+ unsure an export or option exists, choosing which pikku skill to load, a build failed on an
8
+ unknown import or option, or migrating a backend to Pikku. DO NOT TRIGGER when: the task is not a
9
+ Pikku project.
11
10
  installGroups: [core]
12
11
  ---
13
12
 
@@ -72,70 +71,6 @@ which is what decides whether a thrown error becomes a 409 or a 500.
72
71
  `pikku doc` needs `@pikku/cli` 0.12.115 or newer. On an older pin, fall back to the door's
73
72
  skill and `pikku meta --json`, and do not guess at names the doc would have given you.
74
73
 
75
- ## The CLI commands
76
-
77
- `pikku doc` is the API surface — the `#pikku/*` exports. It does **not** list
78
- commands, so this table is where they exist. `pikku <command> --help` has the
79
- flags; the "Read" column is the skill that teaches the thing, where one does.
80
-
81
- **Generating**
82
-
83
- | Command | What it does | Read |
84
- | ------------------------------------------ | ---------------------------------------------------- | ----------------------------- |
85
- | `all` | Everything: types, schemas, wirings, clients | this skill |
86
- | `bootstrap` | Type files only (the setup phase) | this skill |
87
- | `schemas` | JSON Schemas for function input/output types | this skill |
88
- | `fetch` / `websocket` / `rpc` / `realtime` | One client each, when you do not want `all` | `pikku-wiring`, `pikku-react` |
89
- | `react-query` / `tanstack-start` | React Query hooks; the TanStack Start `makeApi` shim | `pikku-react` |
90
- | `queue-service` | The queue service wrapper | `pikku-wiring` |
91
- | `openapi` | An OpenAPI spec from the HTTP routes | — |
92
- | `nextjs` | Next.js backend and HTTP wrappers | `pikku-deploy` |
93
- | `new` | Scaffold a function or wiring | `pikku-wiring` |
94
- | `enable` | Turn a Pikku feature on | `pikku-build` |
95
- | `import` | Import workflows from another system | `pikku-n8n-import` |
96
-
97
- **Running**
98
-
99
- | Command | What it does | Read |
100
- | --------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------- |
101
- | `dev` | Local dev server, all services wired, watch + HMR | `pikku-build` |
102
- | `serve` | Bundled bun/node runner — no watch, no codegen | `pikku-deploy` |
103
- | `watch` | Regenerate on file change, without a server | — |
104
- | `scenario list\|run` | Scenarios as e2e tests and health checks | `pikku-scenario` |
105
- | `virtual-user run` | A declared virtual user, model-driven, against a stage | `pikku-scenario`, virtual-user-run reference |
106
- | `virtual-user list\|sync\|secret` | Who is declared; what an environment will provision; minting their credentials | `pikku-scenario`, virtual-user-run reference |
107
- | `db` | Local development database | `pikku-kysely` |
108
-
109
- **Inspecting and evolving**
110
-
111
- | Command | What it does | Read |
112
- | ---------------------- | ----------------------------------------------------------------------- | ---------------------------- |
113
- | `doc` | The installed API surface | this skill |
114
- | `meta` / `info` | What the project declares, machine- and human-readable | `pikku-meta` |
115
- | `validate` | Every check that applies — app structure, an addon's published file set | `pikku-build`, `pikku-addon` |
116
- | `versions` / `release` | Contract hashes, breaking-change detection, versioned releases | `pikku-meta` |
117
- | `audit` / `update` | Advisories; which `@pikku/*` can move and what peers that needs | `pikku-meta` |
118
- | `scopes` / `roles` | Declared authorization scopes; roles from `defineSystemRole` | `pikku-auth` |
119
- | `knowledge` | The knowledge base — what this app is, in its users' language | `pikku-knowledge` |
120
- | `emails` | Email template generation | `pikku-emails` |
121
-
122
- **Shipping, and the CLI itself**
123
-
124
- | Command | What it does | Read |
125
- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
126
- | `deploy` | Deploy to cloud infrastructure | `pikku-deploy` |
127
- | `binary` | Compile an entrypoint to a native binary (`bun build --compile`) | — |
128
- | `dist` | Copy what `tsc` cannot emit — `.gen.json` meta, hand-authored `.d.ts` — into the build output. Run it after `tsc`, as a package's build script | — |
129
- | `login` / `logout` / `whoami` | The CLI's session against a pikku server | — |
130
- | `skills` | Install these skills into an agent (Claude Code, opencode, pi) | — |
131
-
132
- `-c/--config`, `--log-level`, `--json` and the filter flags are **global
133
- options**, not commands — they attach to the generating commands above.
134
-
135
- A dash means no skill covers it beyond this line. `--help` is then the whole of
136
- it — which is a reason to read `--help` rather than to assume the command does
137
- what its name suggests.
138
-
139
74
  ## Core Mental Model
140
75
 
141
76
  ```text
@@ -167,141 +102,6 @@ The function never imports Express, never reads `req.body`, never touches `ws.se
167
102
 
168
103
  Controllers/routes → `pikkuFunc`; auth/sessions and authorization checks → `pikku-auth`, a separate install; request interception → `pikku-middleware`; DI → `pikku-services`; transports (HTTP/WS/queue/cron) → their `wire*` + skill. For the full Generic Backend → Pikku mapping table (with side-by-side code examples), read `references/concept-mapping.md`.
169
104
 
170
- ## Functions
171
-
172
- Three main function types:
173
-
174
- ```typescript
175
- // Requires authentication — receives session in wire context.
176
- // input/output are Zod schemas; the data + return types are inferred from them.
177
- const updateTodo = pikkuFunc({
178
- input: UpdateTodoInput,
179
- output: TodoOutput,
180
- func: async (services, data, wire) => {
181
- const { session } = wire
182
- return services.todoStore.update(data.id, data)
183
- },
184
- })
185
-
186
- // No authentication required
187
- const listTodos = pikkuSessionlessFunc({
188
- input: ListTodosInput,
189
- output: TodoListOutput,
190
- func: async (services, data) => {
191
- return { todos: services.todoStore.list(data.filters) }
192
- },
193
- })
194
-
195
- // No input or output (for scheduled tasks, lifecycle hooks)
196
- const cleanup = pikkuVoidFunc(async (services) => {
197
- services.todoStore.cleanOldItems()
198
- })
199
- ```
200
-
201
- Services can be destructured inline in the `func` signature (e.g. `async ({ logger, todoStore }, { title }) => ...`). Full config options:
202
-
203
- ```typescript
204
- pikkuFunc({
205
- // Identity and documentation — prose, so it follows `metaLocale` in
206
- // pikku.config.json (default `en`). The identifier does not; see
207
- // "What Language You Write In".
208
- title?: string, // Human-readable name
209
- description?: string, // What the function does
210
- version?: number, // Contract version (see pikku-meta)
211
- override?: string, // Logical name override, so several exports share a versioned base
212
- tags?: string[], // For grouping and middleware targeting
213
-
214
- // Contract
215
- input?: ZodSchema, // Input validation schema
216
- output?: ZodSchema, // Output validation schema
217
- errors?: Array<typeof PikkuError>, // Errors this function may throw
218
-
219
- // Reachability
220
- expose?: boolean, // Allow external RPC calls (see pikku-wiring)
221
- remote?: boolean, // Allow remote RPC calls
222
- mcp?: boolean, // Expose as MCP tool (see pikku-wiring)
223
- readonly?: boolean, // Declares the function performs no writes
224
- deploy?: 'serverless' | 'server' | 'auto',
225
-
226
- // Authorization — see pikku-auth
227
- auth?: boolean, // Override default auth requirement
228
- scopes?: ScopeId[], // AND-ed, checked before permissions; session required
229
- permissions?: PermissionGroup, // OR-ed pool
230
- permissionsInBody?: boolean, // Last resort; needs allow.permissionsInBody in config
231
- middleware?: PikkuMiddleware[], // See pikku-middleware
232
-
233
- // Agent tooling — see pikku-agent
234
- approvalRequired?: boolean,
235
- approvalDescription?: (services, data) => Promise<string>,
236
-
237
- // Workflow step behavior — see pikku-workflow
238
- workflowQueued?: boolean, // Dispatch via queue instead of inline
239
- workflowRetries?: number,
240
- workflowTimeout?: string, // e.g. '30s', '5m'
241
-
242
- audit?: boolean | { durability?: 'best-effort' | 'transactional' },
243
-
244
- func: async (services, data, wire) => { ... },
245
- })
246
- ```
247
-
248
- `scopes` is the one option `pikkuSessionlessFunc` does not accept, and the
249
- omission is deliberate: scopes are AND-ed and fail closed, so an anonymous
250
- caller holds none and satisfies none — a sessionless function with scopes would
251
- reject every caller it exists to serve. Gate those with `permissions`, which
252
- receive the optional session and may pass anonymous.
253
-
254
- **Generics XOR `input`/`output` — never both.** A function's data and return
255
- types come from _one_ source: either the `input`/`output` schemas (preferred —
256
- they double as runtime validation and OpenAPI) or type generics
257
- (`pikkuFunc<In, Out>({ ... })`). Passing both makes the two disagree and forces
258
- `as any` casts. Do not annotate the `func` return type inline either — let the
259
- `output` schema (or the generic) be the single source of truth for the type.
260
-
261
- ```typescript
262
- // Correct — schema-based (no generics, no inline return type)
263
- pikkuFunc({ input: MyInput, output: MyOutput, func: async (s, d) => { ... } })
264
- // Correct — generic-based (no input/output)
265
- pikkuFunc<MyIn, MyOut>({ func: async (s, d) => { ... } })
266
- // WRONG — mixing the two
267
- pikkuFunc<MyIn, MyOut>({ input: MyInput as any, func: async (s, d) => { ... } })
268
- ```
269
-
270
- ## Schemas (Validation)
271
-
272
- Pikku uses Standard Schema — works with Zod, Valibot, ArkType:
273
-
274
- ```typescript
275
- import { z } from 'zod'
276
-
277
- const CreateTodoInputSchema = z.object({
278
- title: z.string().min(1).max(200),
279
- priority: z.enum(['low', 'medium', 'high']).optional(),
280
- tags: z.array(z.string()).optional(),
281
- })
282
- ```
283
-
284
- Schemas serve triple duty: runtime validation, TypeScript types, and OpenAPI documentation.
285
-
286
- ## Server Bootstrap
287
-
288
- Two ways to start a Pikku app, and the choice is whether you need to own the HTTP server.
289
-
290
- **Let Pikku own it** — `pikku dev` and `pikku serve` create the config and singleton services,
291
- start the server and shut it down cleanly, so you write no bootstrap code at all. Startup and
292
- shutdown work goes in one exported `pikkuServerLifecycle` (`beforeStart` / `afterStart` /
293
- `beforeStop`). **Only `dev` and `serve` invoke those hooks** — no deploy runtime does, so anything
294
- a Workers or serverless stage needs done belongs on the request path that needs it.
295
-
296
- **Bootstrap it yourself** — required for Express, Fastify, uWS, Lambda, Cloudflare and Next.js,
297
- where Pikku is embedded in a server you own. Lifecycle hooks do not run on this path; do the
298
- startup work in the entrypoint.
299
-
300
- `pikku validate` warns when a project starts a server by hand _and_ depends on no runtime adapter,
301
- because that means the first path was available and unused.
302
-
303
- **`references/bootstrap.md`** has both entrypoints in full.
304
-
305
105
  ## Code Generation
306
106
 
307
107
  Run `npx pikku all` to generate:
@@ -351,59 +151,20 @@ src/
351
151
 
352
152
  ## What Language You Write In
353
153
 
354
- Three different things in a Pikku project have a human language, and they are **not** the same
355
- language. Collapsing them is the common mistake:
356
-
357
- | Axis | Covers | Decided by |
358
- | --------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------- |
359
- | **Identifiers** | Function, component, type and file names; tables and columns; commit messages | Nothing. **Always English.** There is no setting |
360
- | **Meta** | Prose authored inside the code — `description`, `title`, step `template` | `metaLocale` in `pikku.config.json` (default `en`) |
361
- | **Product UI** | Every string the app shows a user | `messages/<locale>.json`, and `active.json`'s `defaultLocale` |
362
-
363
- Identifiers are the surface every other tool binds to — the generated clients, the RPC map a
364
- scenario is typed over, the SQL types — and unlike a string an identifier cannot be translated
365
- later: renaming one is a migration. `metaLocale` exists so a team can read their own Console in
366
- their own language; it is not licence to rename anything. And `baseLocale` in
367
- `project.inlang/settings.json` stays `en`, because it names the message _source_ every other
368
- language is cloned from.
369
-
370
- **When a brief tells you the product speaks a language, it is telling you about the third axis and
371
- nothing else.** `references/language.md` has the three settings that satisfy such a brief, and the
372
- failure to avoid: reading one sentence about a product's users as an instruction about its codebase
373
- (German RPC names, German tables, no English catalogue to translate from).
374
-
375
- ## Environment Variables
376
-
377
- Never use `process.env` inside Pikku functions. Use the `variables` service (see `pikku-services`):
378
-
379
- ```typescript
380
- const apiKey = services.variables.get('API_KEY')
381
- ```
382
-
383
- `process.env` belongs in server bootstrap code (`start.ts`) only.
154
+ Identifiers (function, type, file, table and column names) are **always English**. `metaLocale` in
155
+ `pikku.config.json` is the language of authored meta (`description`, `title`, step `template`).
156
+ A product speaking another language is only about the UI strings in `messages/<locale>.json`.
157
+ Read `references/language.md` before touching any of the three.
384
158
 
385
- ## Secrets
386
-
387
- `secrets` is not part of a function's services. It is available only in
388
- `pikkuServices`, `pikkuWireServices`, addon service factories and middleware —
389
- read it there, give the value to a service, and have the function ask that
390
- service. Reaching for it through a cast throws at runtime.
391
-
392
- ## Testing
393
-
394
- Functions are easily testable because they're pure:
395
-
396
- ```typescript
397
- const mockServices = {
398
- logger: new MockLogger(),
399
- todoStore: new MockTodoStore(),
400
- }
159
+ ## Available Packages
401
160
 
402
- // Call function directly — no HTTP, no framework
403
- const result = await listTodos.func(mockServices, { userId: 'test' })
404
- expect(result.todos).toHaveLength(3)
405
- ```
161
+ Pikku ships runtime adapters (`@pikku/express`, `@pikku/fastify`, `@pikku/next`, `@pikku/lambda`, `@pikku/cloudflare`, `@pikku/uws`, `@pikku/modelcontextprotocol`, ...) and service packages (`@pikku/jose`, `@pikku/schema-ajv`, `@pikku/pino`, `@pikku/kysely`, `@pikku/redis`, `@pikku/queue-bullmq`, `@pikku/queue-pg-boss`, ...). For the full list with use cases, read `references/packages.md`.
406
162
 
407
- ## Available Packages
163
+ ## Where the rest lives
408
164
 
409
- Pikku ships runtime adapters (`@pikku/express-server`, `@pikku/fastify-server`, `@pikku/next`, `@pikku/aws-lambda`, `@pikku/cloudflare`, `@pikku/uws-server`, `@pikku/modelcontextprotocol`, ...) and service packages (`@pikku/jose`, `@pikku/schema-ajv`, `@pikku/pino`, `@pikku/kysely`, `@pikku/redis`, `@pikku/queue-bullmq`, `@pikku/queue-pg-boss`, ...). For the full list with use cases, read `references/packages.md`.
165
+ - `references/cli.md` — every CLI command, with its flags.
166
+ - `references/functions.md` — function types, config keys and schemas (Standard Schema).
167
+ - `references/bootstrap.md` — letting Pikku own the server versus bootstrapping it yourself.
168
+ - `references/testing.md` — calling `.func` directly with mock services.
169
+ - Env vars and secrets: `pikku-services`. Never `process.env` inside a function.
170
+ - `references/language.md`, `references/concept-mapping.md`, `references/packages.md`.
@@ -0,0 +1,63 @@
1
+ # The Pikku CLI commands
2
+
3
+ `pikku doc` is the API surface — the `#pikku/*` exports. It does **not** list
4
+ commands, so this table is where they exist. `pikku <command> --help` has the
5
+ flags; the "Read" column is the skill that teaches the thing, where one does.
6
+
7
+ **Generating**
8
+
9
+ | Command | What it does | Read |
10
+ | ------------------------------------------ | ---------------------------------------------------- | ----------------------------- |
11
+ | `all` | Everything: types, schemas, wirings, clients | this skill |
12
+ | `bootstrap` | Type files only (the setup phase) | this skill |
13
+ | `schemas` | JSON Schemas for function input/output types | this skill |
14
+ | `fetch` / `websocket` / `rpc` / `realtime` | One client each, when you do not want `all` | `pikku-wiring`, `pikku-react` |
15
+ | `react-query` / `tanstack-start` | React Query hooks; the TanStack Start `makeApi` shim | `pikku-react` |
16
+ | `queue-service` | The queue service wrapper | `pikku-wiring` |
17
+ | `openapi` | An OpenAPI spec from the HTTP routes | — |
18
+ | `nextjs` | Next.js backend and HTTP wrappers | `pikku-deploy` |
19
+ | `new` | Scaffold a function or wiring | `pikku-wiring` |
20
+ | `enable` | Turn a Pikku feature on | `pikku-build` |
21
+ | `import` | Import workflows from another system | `pikku-n8n-import` |
22
+
23
+ **Running**
24
+
25
+ | Command | What it does | Read |
26
+ | --------------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------- |
27
+ | `dev` | Local dev server, all services wired, watch + HMR | `pikku-build` |
28
+ | `serve` | Bundled bun/node runner — no watch, no codegen | `pikku-deploy` |
29
+ | `watch` | Regenerate on file change, without a server | — |
30
+ | `scenario list\|run` | Scenarios as e2e tests and health checks | `pikku-scenario` |
31
+ | `virtual-user run` | A declared virtual user, model-driven, against a stage | `pikku-scenario`, virtual-user-run reference |
32
+ | `virtual-user list\|sync\|secret` | Who is declared; what an environment will provision; minting their credentials | `pikku-scenario`, virtual-user-run reference |
33
+ | `db` | Local development database | `pikku-kysely` |
34
+
35
+ **Inspecting and evolving**
36
+
37
+ | Command | What it does | Read |
38
+ | ---------------------- | ----------------------------------------------------------------------- | ---------------------------- |
39
+ | `doc` | The installed API surface | this skill |
40
+ | `meta` / `info` | What the project declares, machine- and human-readable | `pikku-meta` |
41
+ | `validate` | Every check that applies — app structure, an addon's published file set | `pikku-build`, `pikku-addon` |
42
+ | `versions` / `release` | Contract hashes, breaking-change detection, versioned releases | `pikku-meta` |
43
+ | `audit` / `update` | Advisories; which `@pikku/*` can move and what peers that needs | `pikku-meta` |
44
+ | `scopes` / `roles` | Declared authorization scopes; roles from `defineSystemRole` | `pikku-auth` |
45
+ | `knowledge` | The knowledge base — what this app is, in its users' language | `pikku-knowledge` |
46
+ | `emails` | Email template generation | `pikku-emails` |
47
+
48
+ **Shipping, and the CLI itself**
49
+
50
+ | Command | What it does | Read |
51
+ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
52
+ | `deploy` | Deploy to cloud infrastructure | `pikku-deploy` |
53
+ | `binary` | Compile an entrypoint to a native binary (`bun build --compile`) | — |
54
+ | `dist` | Copy what `tsc` cannot emit — `.gen.json` meta, hand-authored `.d.ts` — into the build output. Run it after `tsc`, as a package's build script | — |
55
+ | `login` / `logout` / `whoami` | The CLI's session against a pikku server | — |
56
+ | `skills` | Install these skills into an agent (Claude Code, opencode, pi) | — |
57
+
58
+ `-c/--config`, `--log-level`, `--json` and the filter flags are **global
59
+ options**, not commands — they attach to the generating commands above.
60
+
61
+ A dash means no skill covers it beyond this line. `--help` is then the whole of
62
+ it — which is a reason to read `--help` rather than to assume the command does
63
+ what its name suggests.