@pplethai/cli 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -16
- package/dist/bin.js +32 -48
- package/package.json +2 -4
- package/templates/golden-path/AGENTS.md +1 -0
- package/templates/golden-path/CLAUDE.md +44 -24
- package/templates/golden-path/gitignore +5 -0
- package/templates/golden-path/shared/api.ts +17 -0
- package/templates/golden-path/src/auth.ts +27 -0
- package/templates/golden-path/src/dev-personas.ts +67 -3
- package/templates/golden-path/src/env.ts +6 -0
- package/templates/golden-path/src/legal-identity.ts +161 -0
- package/templates/golden-path/test/legal-identity.test.ts +256 -0
- package/templates/golden-path/wrangler.jsonc +14 -1
- package/skills/pple-platform/SKILL.md +0 -114
- package/skills/pple-platform/evals/evals.json +0 -29
- package/skills/pple-platform/references/deployment.md +0 -129
- package/skills/pple-platform/references/design-system.md +0 -55
- package/skills/pple-platform/references/mini-app.md +0 -111
- package/skills/pple-platform/references/pple-id-auth.md +0 -99
- package/skills/pple-platform/references/project-scaffold.md +0 -75
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# pple CLI
|
|
2
2
|
|
|
3
|
-
The Builder's terminal tool: three commands between a PPLE ID and a live app
|
|
3
|
+
The Builder's terminal tool: three commands between a PPLE ID and a live app,
|
|
4
|
+
and everything else a Builder can do in the Console.
|
|
4
5
|
|
|
5
6
|
```bash
|
|
6
7
|
pple auth login # sign in with your PPLE ID (browser, no password in the terminal)
|
|
@@ -9,8 +10,69 @@ pple init --name "Sign-up" # same, without a prompt (for agents/scripts)
|
|
|
9
10
|
pple init brave-otter # set up an app that already exists on the platform
|
|
10
11
|
pple deploy -m "Add the form" # send the changes and put them live
|
|
11
12
|
pple upgrade # update pple itself from npm
|
|
13
|
+
pple help # every command; `pple <command> help` explains one
|
|
12
14
|
```
|
|
13
15
|
|
|
16
|
+
## Builder Parity
|
|
17
|
+
|
|
18
|
+
Anything a Builder can view or change in the Console can be viewed or changed
|
|
19
|
+
here ([ADR-0020](../docs/adr/0020-builder-parity-between-console-and-cli.md)).
|
|
20
|
+
Platform Admin work (the approval queue, the all-apps index, direct edits,
|
|
21
|
+
Move owner, running a Code Review, admin Retire / Purge / Delete) stays in the
|
|
22
|
+
Console, and the CLI has no command for it.
|
|
23
|
+
|
|
24
|
+
| Area | Commands |
|
|
25
|
+
| ---- | -------- |
|
|
26
|
+
| Account | `auth login`, `auth logout`, `whoami`, `agreement` |
|
|
27
|
+
| Apps | `apps`, `init`, `info`, `rename`, `retire`, `retry-setup` |
|
|
28
|
+
| Deploys | `deploy`, `redeploy`, `deploys [<id>]` (reads a failed deploy's log) |
|
|
29
|
+
| Config | `env list`, `env set`, `env delete` |
|
|
30
|
+
| Publication | `promote`, `invites [add\|remove]`, `roles`, `request publish\|change\|limit\|retire`, `requests` |
|
|
31
|
+
| People | `collaborators [add\|remove]` |
|
|
32
|
+
| Notes and reviews | `notes [add]`, `reviews [<id>]` |
|
|
33
|
+
|
|
34
|
+
Every command that works on one app takes `--app <slug>` and otherwise uses
|
|
35
|
+
the App Link of the folder it runs in. Read commands take `--json` and print
|
|
36
|
+
the platform's own payload; Thai text is the default. `pple invites` and
|
|
37
|
+
`pple collaborators` print full phone numbers, as the Console does for an
|
|
38
|
+
Owner.
|
|
39
|
+
|
|
40
|
+
A CI test keeps this true. `test/builder-parity.test.ts` reads the Console's
|
|
41
|
+
`api` object (`console/web/console.ts`) and fails when a method that isn't
|
|
42
|
+
Platform Admin work has neither a command that names it in `covers`
|
|
43
|
+
(`src/registry.ts`) nor an entry with a reason in the test's `EXEMPT` list.
|
|
44
|
+
It proves a command *exists*, not that it behaves the same; permissions stay
|
|
45
|
+
aligned because only the Provisioner enforces them. CLI CI runs whenever
|
|
46
|
+
`console/web/console.ts` changes. A merged command reaches Builders only in a
|
|
47
|
+
CLI release (ADR-0008), so the published CLI can briefly lag the Console.
|
|
48
|
+
|
|
49
|
+
## Asking for help is safe
|
|
50
|
+
|
|
51
|
+
`pple help`, `pple <command> help`, `pple <command> <subcommand> help`, `--help`
|
|
52
|
+
and `-h` explain a command and nothing else: they never reach the network,
|
|
53
|
+
change anything, ask a question, need a sign-in, or run the daily update check.
|
|
54
|
+
`help` counts only directly after the command's own words, so
|
|
55
|
+
`pple info --app help` still means an app with that slug and
|
|
56
|
+
`pple env set API_URL help` still sets the value `help`; `--help` and `-h`
|
|
57
|
+
win anywhere. Agents explore with `--help`, so this is checked for every
|
|
58
|
+
command in `test/help.test.ts`.
|
|
59
|
+
|
|
60
|
+
## Consequential actions
|
|
61
|
+
|
|
62
|
+
At a terminal these ask a person, as the Console does. Run with nobody there
|
|
63
|
+
(an agent, a script, a pipe) each one refuses unless given the specific value
|
|
64
|
+
being confirmed, so the target is named in the Builder's transcript. There is
|
|
65
|
+
no generic `--yes`.
|
|
66
|
+
|
|
67
|
+
| Action | Unattended runs must pass |
|
|
68
|
+
| ------ | ------------------------- |
|
|
69
|
+
| `pple retire` | `--confirm <slug>` |
|
|
70
|
+
| `pple collaborators add <phone>` | the lookup's token, on a second run: `pple collaborators add --confirm <token>` |
|
|
71
|
+
| `pple request publish --address <name>` | `--confirm <name>` |
|
|
72
|
+
| `pple agreement` | nothing works: only a person at a terminal, or the Console, can accept |
|
|
73
|
+
|
|
74
|
+
The Skill tells agents to get the Builder's OK before passing any of these.
|
|
75
|
+
|
|
14
76
|
Git is an implementation detail, and so is GitHub. A Builder is told what
|
|
15
77
|
happened to *their app* — "Sending your changes…", "Volunteer Sign-up is live
|
|
16
78
|
at https://brave-otter.ppleth.ai" — never what happened to a branch, and never
|
|
@@ -45,20 +107,55 @@ the same Provisioner `POST /apps` the Console uses, waits until the app is
|
|
|
45
107
|
ready, then scaffolds it — or, given an App Slug, scaffolds an app that
|
|
46
108
|
already exists. Either way it fetches the app's code, copies the golden-path
|
|
47
109
|
template under the app's own name, writes `.pple/app.json` linking the folder
|
|
48
|
-
to the app, and installs the
|
|
49
|
-
agent
|
|
110
|
+
to the app, and installs the Skill and Platform Rules the Builder's AI coding
|
|
111
|
+
agent reads (ADR-0001, ADR-0019). The App Slug stays platform-generated;
|
|
50
112
|
bare `pple init` in a folder that already has an App Link is refused.
|
|
51
113
|
|
|
52
|
-
**`pple deploy`**
|
|
114
|
+
**`pple deploy`** records everything in
|
|
53
115
|
the folder, sends it to the app's repo — merging in a Collaborator's work if
|
|
54
116
|
there is any — then watches the platform build it and reports the live URL,
|
|
55
117
|
or the build output that explains why nothing changed. It needs no
|
|
56
118
|
arguments: the link file says which app. Account-only commands
|
|
57
|
-
(`auth login` / `logout` / `whoami`) never touch
|
|
119
|
+
(`auth login` / `logout` / `whoami`) never touch the Skill or the Platform Rules.
|
|
120
|
+
|
|
121
|
+
**Skill and Platform Rules** are not in this package. `pple init`, `deploy`,
|
|
122
|
+
`info` and `env`, run in an app's folder, ask the platform for the current
|
|
123
|
+
hash of both and download one whole version only when it differs from the copy
|
|
124
|
+
on disk, so a merge to `main` reaches Builders on their next command with no CLI
|
|
125
|
+
release (ADR-0019). The copy is written once per agent, in the format it
|
|
126
|
+
reads, and every path is git-ignored:
|
|
127
|
+
|
|
128
|
+
| Agent | Skill | Platform Rules |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| Claude Code | `.claude/skills/pple-platform/` | `.claude/rules/pple-platform.md` |
|
|
131
|
+
| Cursor | `.agents/skills/pple-platform/` | `.cursor/rules/pple-platform.mdc` (`alwaysApply`) |
|
|
132
|
+
| Codex | `.agents/skills/pple-platform/` | `.pple/rules.md`, by the one-line pointer in `AGENTS.md` |
|
|
133
|
+
| Gemini CLI | `.agents/skills/pple-platform/` | none |
|
|
134
|
+
|
|
135
|
+
Which folder is refreshed is the one the command was run in, never the app
|
|
136
|
+
`--app` names; outside an app folder nothing happens, and asking for help never
|
|
137
|
+
refreshes. A refresh says something only when files changed (first install, a
|
|
138
|
+
location put back, a new version), and says so on stderr, so `--json` output
|
|
139
|
+
stays parseable. A refresh that fails warns, keeps the last copy and never
|
|
140
|
+
blocks the command; each location is replaced by renaming a finished copy over
|
|
141
|
+
the old one, so a download that dies halfway leaves nothing half-written.
|
|
142
|
+
Sibling skills, other rule files and an `AGENTS.md` the Builder wrote are never
|
|
143
|
+
touched: the pointer is created only when the file is missing. The version the
|
|
144
|
+
platform sends is untrusted — a file path that would leave its folder refuses
|
|
145
|
+
the whole version.
|
|
146
|
+
|
|
147
|
+
**`pple apps`, `rename`, `retire`, `retry-setup`, `redeploy`, `deploys`,
|
|
148
|
+
`promote`, `invites`, `request`, `requests`, `roles`, `collaborators`, `notes`,
|
|
149
|
+
`reviews`** are the Console's buttons from the terminal; each calls the same
|
|
150
|
+
Provisioner route the Console does. `request publish` and `request change`
|
|
151
|
+
upload an icon from a file path (`--icon`) the way the Console's picker does,
|
|
152
|
+
and name roles by key or Thai label, resolved against the Provisioner's
|
|
153
|
+
`GET /role-options` (`pple roles`) — the list the Console's picker shows.
|
|
58
154
|
|
|
59
155
|
**`pple upgrade`** asks npm what the latest `@pplethai/cli` is and, when
|
|
60
156
|
this copy is one npm's global root holds, installs it — which is also how
|
|
61
|
-
|
|
157
|
+
the golden-path template moves forward (ADR-0007; the Skill no longer
|
|
158
|
+
travels with the CLI, ADR-0019). Any
|
|
62
159
|
other install channel is told the manual `npm install -g @pplethai/cli`
|
|
63
160
|
line rather than having a second copy installed over the first, and so is a
|
|
64
161
|
failed install, carrying npm's own reason. The CLI never uses `sudo`: a global
|
|
@@ -91,14 +188,19 @@ echo '{ "updateCheck": false }' > ~/.config/pple/config.json # this machine
|
|
|
91
188
|
|
|
92
189
|
| File | What it holds |
|
|
93
190
|
| ---- | ------------- |
|
|
94
|
-
| `src/
|
|
95
|
-
| `src/
|
|
96
|
-
| `src/
|
|
191
|
+
| `src/registry.ts` | the command table: every command, declared once with its help and what it covers; resolves a command line |
|
|
192
|
+
| `src/command.ts` | what a command is, and parsing its options |
|
|
193
|
+
| `src/help.ts` | the text of `pple help`, built from the table |
|
|
194
|
+
| `src/cli.ts` | runs one command line: help first, then the update check, then the command |
|
|
195
|
+
| `src/target.ts` | which app a command acts on (`--app`, else the App Link) |
|
|
196
|
+
| `src/commands/` | the commands, each taking `Deps` and what it was given |
|
|
197
|
+
| `src/labels.ts`, `src/requests.ts` | the Thai a Builder reads for platform values and Requests |
|
|
198
|
+
| `src/deps.ts` | every seam: fetch, clock, subprocesses, output, template dir |
|
|
97
199
|
| `src/device-flow.ts` | RFC 8628 against PPLE ID |
|
|
98
200
|
| `src/api.ts` | the Provisioner API, and the only place that knows its error codes |
|
|
99
201
|
| `src/git.ts` | git, and the only place that names it or holds the repo token |
|
|
100
202
|
| `src/scaffold.ts` | copying the golden-path template |
|
|
101
|
-
| `src/
|
|
203
|
+
| `src/guidance.ts` | refreshing the Skill and Platform Rules into an app folder |
|
|
102
204
|
| `src/npm.ts` | npm: the registry's latest version, and the install channel |
|
|
103
205
|
| `src/update.ts` | the daily update check, its cadence state, and its opt-outs |
|
|
104
206
|
| `askpass/pple-askpass.mjs` | what git runs to be told the app's repo token |
|
|
@@ -109,7 +211,7 @@ echo '{ "updateCheck": false }' > ~/.config/pple/config.json # this machine
|
|
|
109
211
|
npm install
|
|
110
212
|
npm test # drives whole commands against a fake Provisioner and real git
|
|
111
213
|
npm run typecheck
|
|
112
|
-
npm run build # bundles the template
|
|
214
|
+
npm run build # bundles the template, then esbuild → dist/bin.js
|
|
113
215
|
```
|
|
114
216
|
|
|
115
217
|
Tests run the real command path — real `git` in a temp directory, a fake
|
|
@@ -122,11 +224,10 @@ minted. A local path would let every clone and push succeed with no credential
|
|
|
122
224
|
at all, and nothing would show that the platform's token is what opens a
|
|
123
225
|
private repo.
|
|
124
226
|
|
|
125
|
-
The published package carries its own
|
|
126
|
-
(`npm run build:template` copies `../template`)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
`PPLE_SKILLS_DIR`, `PPLE_API_BASE`, `PPLE_SSO_BASE`, `PPLE_CLIENT_ID`,
|
|
227
|
+
The published package carries its own copy of the golden-path template
|
|
228
|
+
(`npm run build:template` copies `../template`). Running from a checkout falls
|
|
229
|
+
back to that repo path directly. The Skill is not bundled: tests serve it from
|
|
230
|
+
the fake platform. `PPLE_TEMPLATE_DIR`, `PPLE_API_BASE`, `PPLE_SSO_BASE`, `PPLE_CLIENT_ID`,
|
|
130
231
|
`PPLE_REPO_BASE`, and `PPLE_REGISTRY_BASE` override the defaults for staging
|
|
131
232
|
work.
|
|
132
233
|
|