@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.
- package/dist/skills.gen.js +2 -2
- package/package.json +10 -7
- package/skills/pikku-a11y/SKILL.md +5 -3
- package/skills/pikku-addon/SKILL.md +8 -9
- package/skills/pikku-agent/SKILL.md +16 -13
- package/skills/pikku-agent/references/runner-vercel.md +1 -1
- package/skills/pikku-architect/SKILL.md +7 -10
- package/skills/pikku-auth/SKILL.md +16 -20
- package/skills/pikku-auth/references/better-auth.md +74 -37
- package/skills/pikku-auth/references/sessions.md +8 -0
- package/skills/pikku-build/SKILL.md +36 -68
- package/skills/pikku-build/references/app.md +27 -828
- package/skills/pikku-build/references/feature.md +3 -5
- package/skills/pikku-build/references/phase-1-what-it-is.md +167 -0
- package/skills/pikku-build/references/phase-2-people-and-apps.md +133 -0
- package/skills/pikku-build/references/phase-3-plan.md +62 -0
- package/skills/pikku-build/references/phase-4-build.md +249 -0
- package/skills/pikku-build/references/phase-5-prove-and-ship.md +148 -0
- package/skills/pikku-build/references/platform.md +5 -6
- package/skills/pikku-build/references/quick.md +2 -2
- package/skills/pikku-build/references/ship.md +4 -5
- package/skills/pikku-changes/SKILL.md +13 -7
- package/skills/pikku-concepts/SKILL.md +19 -258
- package/skills/pikku-concepts/references/cli.md +63 -0
- package/skills/pikku-concepts/references/functions.md +117 -0
- package/skills/pikku-concepts/references/language.md +5 -5
- package/skills/pikku-concepts/references/packages.md +6 -4
- package/skills/pikku-concepts/references/testing.md +14 -0
- package/skills/pikku-convert-screen/SKILL.md +7 -1
- package/skills/pikku-deploy/SKILL.md +29 -30
- package/skills/pikku-deploy/references/ws.md +1 -1
- package/skills/pikku-emails/SKILL.md +7 -3
- package/skills/pikku-guide/SKILL.md +7 -10
- package/skills/pikku-i18n/SKILL.md +18 -19
- package/skills/pikku-i18n/references/messages.md +6 -8
- package/skills/pikku-knowledge/SKILL.md +42 -45
- package/skills/pikku-kysely/SKILL.md +50 -13
- package/skills/pikku-list-query/SKILL.md +27 -14
- package/skills/pikku-meta/SKILL.md +13 -16
- package/skills/pikku-meta/references/audit.md +1 -45
- package/skills/pikku-meta/references/versioning.md +1 -1
- package/skills/pikku-middleware/SKILL.md +23 -13
- package/skills/pikku-middleware/references/middleware-patterns.md +2 -2
- package/skills/pikku-n8n-import/SKILL.md +7 -8
- package/skills/pikku-permissions/SKILL.md +14 -8
- package/skills/pikku-react/SKILL.md +7 -6
- package/skills/pikku-realtime/SKILL.md +16 -11
- package/skills/pikku-report/SKILL.md +8 -10
- package/skills/pikku-scenario/SKILL.md +15 -18
- package/skills/pikku-scenario/references/steps.md +3 -4
- package/skills/pikku-scenario/references/virtual-users.md +1 -1
- package/skills/pikku-seo/SKILL.md +16 -8
- package/skills/pikku-service-backends/SKILL.md +26 -28
- package/skills/pikku-services/SKILL.md +8 -9
- package/skills/pikku-services/references/services.md +1 -1
- package/skills/pikku-software-archaeology/README.md +12 -1
- package/skills/pikku-software-archaeology/SKILL.md +9 -2
- package/skills/pikku-software-archaeology/references/pikku-mapping.md +1 -1
- package/skills/pikku-software-archaeology/references/sources/express.md +75 -0
- package/skills/pikku-software-archaeology/references/sources/laravel.md +77 -0
- package/skills/pikku-software-archaeology/references/sources/nestjs.md +73 -0
- package/skills/pikku-software-archaeology/references/sources/rails.md +72 -0
- package/skills/pikku-software-archaeology/references/tests-to-scenarios.md +72 -0
- package/skills/pikku-tailwind/SKILL.md +15 -16
- package/skills/pikku-theme/SKILL.md +15 -17
- package/skills/pikku-ui/SKILL.md +4 -3
- package/skills/pikku-webhook/SKILL.md +10 -11
- package/skills/pikku-wiring/SKILL.md +45 -47
- package/skills/pikku-wiring/references/channel.md +1 -1
- package/skills/pikku-wiring/references/scheduler.md +1 -1
- package/skills/pikku-wiring/references/trigger.md +24 -1
- 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
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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`
|
|
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:
|
|
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
|
|
43
|
-
| ---- |
|
|
44
|
-
| 0 | work printed (claimed, and/or `Answered`)
|
|
45
|
-
| 2 | `--timeout`/`--once` found nothing
|
|
46
|
-
| 3 | auth refused
|
|
47
|
-
| 1 | anything else
|
|
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
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
##
|
|
163
|
+
## Where the rest lives
|
|
408
164
|
|
|
409
|
-
|
|
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.
|