@workser/cli 0.3.0 → 0.6.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/dist/index.js +2516 -315
- package/package.json +4 -2
- package/skills/workser/reference/analysis.md +54 -0
- package/skills/workser/reference/api.md +79 -0
- package/skills/workser/reference/brand.md +33 -0
- package/skills/workser/reference/checks.md +70 -0
- package/skills/workser/reference/deliverables.md +38 -0
- package/skills/workser/reference/deploy.md +37 -24
- package/skills/workser/reference/docs.md +55 -0
- package/skills/workser/reference/env.md +115 -0
- package/skills/workser/reference/neon-backend.md +42 -8
- package/skills/workser/reference/sdlc-entities.md +20 -43
- package/skills/workser/reference/tasks.md +21 -0
- package/skills/workser/reference/usage.md +48 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workser/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Workser CLI — give your local AI agent native DevOps & infrastructure on Workser. The agent runs `workser …` to provision, deploy, and manage real apps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
38
38
|
"start": "node dist/index.js",
|
|
39
39
|
"test": "npm run build && vitest run",
|
|
40
|
-
"
|
|
40
|
+
"preversion": "npm run typecheck && npm run test",
|
|
41
|
+
"postversion": "git push -u origin HEAD && git push --tags && npm publish",
|
|
42
|
+
"prepublishOnly": "npm run build && npm run typecheck && npm run test"
|
|
41
43
|
},
|
|
42
44
|
"dependencies": {
|
|
43
45
|
"commander": "^14.0.0",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: analysis
|
|
3
|
+
title: Analysis — running Python on this project's data
|
|
4
|
+
summary: Run pandas locally under a sandbox and a clock, so the code, the output and the timing land in the task where the owner can see them.
|
|
5
|
+
commands: [analysis]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Analysis — running Python on this project's data
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
workser analysis runtime [--app <webAppId>]
|
|
12
|
+
workser analysis run --app <webAppId> --file report.py [--timeout <ms>]
|
|
13
|
+
workser analysis run --app <webAppId> --code 'print(1)'
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Why not just run `python` yourself
|
|
17
|
+
|
|
18
|
+
Two reasons, and the second matters more.
|
|
19
|
+
|
|
20
|
+
It runs inside the same OS sandbox a structured agent run gets, scoped to the
|
|
21
|
+
app's own folder — so a script that goes wrong goes wrong in one directory.
|
|
22
|
+
|
|
23
|
+
And it is **recorded**. The code, the output and how long it took land in the
|
|
24
|
+
task, where the owner can see them. An analysis nobody can see is an assertion,
|
|
25
|
+
which is the same problem `workser api call` solves for a service with no
|
|
26
|
+
screen. If a number is going to end up in front of the customer, run it here.
|
|
27
|
+
|
|
28
|
+
## Check the runtime before you write the script
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
workser analysis runtime --app <id> --json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
It reports the interpreter that would be used — the app's own `.venv` first, if
|
|
35
|
+
it has one — and whether `pandas` and `matplotlib` are importable. Exit code is
|
|
36
|
+
non-zero when Python is missing, so you find out in a second rather than after
|
|
37
|
+
writing a hundred lines.
|
|
38
|
+
|
|
39
|
+
## Limits, said plainly
|
|
40
|
+
|
|
41
|
+
Five minutes by default, fifteen at most. Output is capped per stream and
|
|
42
|
+
truncation is reported. Nothing is silently dropped.
|
|
43
|
+
|
|
44
|
+
These are local limits and they are the right ones: this work does **not** go in
|
|
45
|
+
a deployed function. `maxDuration` is for a slow request; an analysis reads a lot
|
|
46
|
+
of rows and takes as long as it takes, so putting it behind a serverless timeout
|
|
47
|
+
means the useful analyses are exactly the ones that fail.
|
|
48
|
+
|
|
49
|
+
## What counts as evidence
|
|
50
|
+
|
|
51
|
+
A number on its own is not a finding. When you report a result, say what the
|
|
52
|
+
query was, how many rows it covered, and what window of time — a figure with no
|
|
53
|
+
denominator is the easiest thing in this product to get wrong and the hardest
|
|
54
|
+
for the owner to check.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: api
|
|
3
|
+
title: Services — calling one, and describing it
|
|
4
|
+
summary: Call this project's API through the same console the owner sees, and make sure every route it serves is written down before you call the task done.
|
|
5
|
+
commands: [api]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Services — calling one, and describing it
|
|
9
|
+
|
|
10
|
+
A service has no screen. Everything else you build can be looked at; an API can
|
|
11
|
+
only be *called* — so unless the calls go somewhere the owner can see, "the API
|
|
12
|
+
works" is an assertion with nothing behind it.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
workser api list [--app <webAppId>]
|
|
16
|
+
workser api call <path> [--app <id>] [--method <verb>] [--body <text>]
|
|
17
|
+
[--header 'Name: value'] [--env local|preview|production]
|
|
18
|
+
workser api spec [--check]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Call it through the console, not through curl
|
|
22
|
+
|
|
23
|
+
`workser api call` goes through the same request console the owner has open. The
|
|
24
|
+
status, the timing and the body you see are the ones they see, and the
|
|
25
|
+
credentials come from the app's own environment rather than from your command
|
|
26
|
+
line — so a token never lands in a transcript.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
workser api call /orders --app <id> --json
|
|
30
|
+
workser api call /orders --app <id> --method POST --body '{"item":"latte"}' --json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`--env` picks which copy to call. `local` is the dev server on this machine and
|
|
34
|
+
is the default; `preview` and `production` are the deployments. The host always
|
|
35
|
+
comes from that choice — a path is a path, never a URL, and passing one is
|
|
36
|
+
refused.
|
|
37
|
+
|
|
38
|
+
Exit code: non-zero only when nothing answered. A 404 or a 422 is a *successful*
|
|
39
|
+
call with an informative answer, so checking that a route correctly rejects bad
|
|
40
|
+
input works exactly as you would expect.
|
|
41
|
+
|
|
42
|
+
## Save the calls that matter
|
|
43
|
+
|
|
44
|
+
Requests saved at `api/requests.json` in the service's repo show up in the
|
|
45
|
+
owner's console. Write the handful that describe what the service does — not a
|
|
46
|
+
test suite:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
[
|
|
50
|
+
{ "id": "list-orders", "name": "List today's orders", "method": "GET",
|
|
51
|
+
"path": "/api/orders", "note": "What the shop screen loads." },
|
|
52
|
+
{ "id": "place-order", "name": "Place an order", "method": "POST",
|
|
53
|
+
"path": "/api/orders", "body": "{\"item\":\"latte\"}" }
|
|
54
|
+
]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
They are in the repo on purpose: a call worth saving outlives the session that
|
|
58
|
+
saved it, and it shows up in the diff.
|
|
59
|
+
|
|
60
|
+
## Describe every route before you call it done
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
workser api spec --check
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
It compares the routes the repo actually serves — read from the file layout, so
|
|
67
|
+
it cannot be fooled by a comment — with the paths your OpenAPI document
|
|
68
|
+
declares, and fails when one is missing. Write the document at
|
|
69
|
+
`api/openapi.json` (YAML also works).
|
|
70
|
+
|
|
71
|
+
It is not an OpenAPI validator and does not check schemas or responses. It asks
|
|
72
|
+
one question, so that it is cheap enough to run every time: is every route
|
|
73
|
+
written down. A health probe is exempt. A path in the spec that the repo does
|
|
74
|
+
not serve is reported but does not fail — you may be documenting something
|
|
75
|
+
built next.
|
|
76
|
+
|
|
77
|
+
Run it alongside `workser verify` before declaring an API task finished. An API
|
|
78
|
+
somebody can call and an API somebody can integrate with are different products,
|
|
79
|
+
and the spec is the difference.
|
|
@@ -58,3 +58,36 @@ other surface the brand feeds.
|
|
|
58
58
|
|
|
59
59
|
For generating artwork *in* the brand's palette, see `workser help images` —
|
|
60
60
|
put the colours from `design show` into the prompt.
|
|
61
|
+
|
|
62
|
+
## The three places design lives — and which one you are in
|
|
63
|
+
|
|
64
|
+
They are separate on purpose, and confusing them is the commonest mistake here.
|
|
65
|
+
|
|
66
|
+
| What | Scope | Where |
|
|
67
|
+
| --- | --- | --- |
|
|
68
|
+
| **Brand** — colours, fonts, logo | The **project** | `business_settings`, read with `design show` |
|
|
69
|
+
| **Design files** — the `.fig` work | The **project**, many files | the project's design workspace folder |
|
|
70
|
+
| **Layout options** — choices to show the owner | **One app** | `design/options.json` in that app's folder |
|
|
71
|
+
|
|
72
|
+
**Design is not an app.** It has no port, no URL, nothing to deploy. Never create
|
|
73
|
+
an app for it.
|
|
74
|
+
|
|
75
|
+
When you write `design/options.json`, put the design file each option came from
|
|
76
|
+
in a `source` field:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{ "options": [
|
|
80
|
+
{ "id": "warm", "name": "Warm and simple", "route": "/",
|
|
81
|
+
"note": "Bigger type, more space.", "source": "hero-v2.fig" }
|
|
82
|
+
] }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`source` is a path **inside the project's design workspace** — relative, no
|
|
86
|
+
`..`, no absolute paths, no URLs. Anything else is dropped. Leave it out when the
|
|
87
|
+
option was written straight into code with no design file behind it; that is an
|
|
88
|
+
ordinary case and inventing a source is worse than omitting one.
|
|
89
|
+
|
|
90
|
+
Why it matters: the owner picks an option in one app and later opens the design
|
|
91
|
+
workspace. Without `source`, nothing connects the decision they just made to the
|
|
92
|
+
file it came from, and "why does the site look like this?" has three unrelated
|
|
93
|
+
answers.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: checks
|
|
3
|
+
title: Checks — is it safe, and is it still up
|
|
4
|
+
summary: Scan the code for leaked secrets, known-bad dependencies and over-broad permissions, and check that what you published is still answering.
|
|
5
|
+
commands: [scan, health]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Checks — is it safe, and is it still up
|
|
9
|
+
|
|
10
|
+
Two questions nothing else in this CLI asks. `verify` tells you the code
|
|
11
|
+
compiles. These tell you it is not dangerous, and that it is still working an
|
|
12
|
+
hour after you shipped it.
|
|
13
|
+
|
|
14
|
+
Run both before you say a task is done.
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
workser scan # deps · secrets · permissions, over this folder
|
|
18
|
+
workser scan --check # same, but exits non-zero on anything serious
|
|
19
|
+
workser scan --only secrets # one check: deps, secrets, permissions
|
|
20
|
+
workser scan --staged # look at staged changes only
|
|
21
|
+
|
|
22
|
+
workser health # is every published app still answering?
|
|
23
|
+
workser health --app <webAppId> # just one
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## scan
|
|
27
|
+
|
|
28
|
+
Three checks, all local — no login, no project, no network except for `deps`.
|
|
29
|
+
|
|
30
|
+
**secrets** looks at what your changes ADD (`git diff HEAD`), not at the whole
|
|
31
|
+
tree, so it fires on the key you just wrote rather than on every example file
|
|
32
|
+
forever. It knows the shapes that are actually credentials — AWS, GitHub,
|
|
33
|
+
Stripe, OpenAI, Anthropic, Google, Slack, private keys, database URLs with a
|
|
34
|
+
password in them, and `API_KEY = "…"` with something real on the right. It
|
|
35
|
+
ignores placeholders (`your-api-key`, `process.env.X`, `<REPLACE_ME>`) and
|
|
36
|
+
example, fixture and lockfile paths.
|
|
37
|
+
|
|
38
|
+
**deps** runs `npm audit` and reports high and critical only. Moderate and low
|
|
39
|
+
advisories on transitive dev dependencies are real and are not worth a report
|
|
40
|
+
nobody finishes reading.
|
|
41
|
+
|
|
42
|
+
**permissions** catches three specific mistakes: a `NEXT_PUBLIC_…SECRET`
|
|
43
|
+
compiled into the browser bundle, an API that accepts credentialed requests
|
|
44
|
+
from any website, and a real `.env` committed to the repository.
|
|
45
|
+
|
|
46
|
+
**A check that could not run says so.** Offline, `deps` reports "not checked"
|
|
47
|
+
with the reason — never "nothing found". If you are quoting a scan result, quote
|
|
48
|
+
what it checked as well as what it found.
|
|
49
|
+
|
|
50
|
+
If it finds a secret: move the value to `workser env set`, and treat the old one
|
|
51
|
+
as leaked. Rotating it is the owner's decision, not yours — say so and let them.
|
|
52
|
+
|
|
53
|
+
## health
|
|
54
|
+
|
|
55
|
+
Probes the stable preview and production addresses of every app in the project
|
|
56
|
+
and reports up or down, with the round trip. It exits non-zero if anything is
|
|
57
|
+
down, so a step can gate on it.
|
|
58
|
+
|
|
59
|
+
Two things worth knowing:
|
|
60
|
+
|
|
61
|
+
* It is the same check the desktop runs on a timer. Both fold into one streak,
|
|
62
|
+
so a run of yours counts toward the same total.
|
|
63
|
+
* After three failed checks in a row on a **production** address that has
|
|
64
|
+
worked before, an incident task is opened on the owner's board automatically.
|
|
65
|
+
A preview address is checked and reported but never escalated — it is not
|
|
66
|
+
customer-facing, and waking the owner for it teaches them to ignore the ones
|
|
67
|
+
that are.
|
|
68
|
+
|
|
69
|
+
An app that has never been published has no address, so there is nothing to
|
|
70
|
+
check. That is reported as a note, not as a pass.
|
|
@@ -13,6 +13,7 @@ them.
|
|
|
13
13
|
```
|
|
14
14
|
workser artifact add <path> [--kind <k>] [-d <text>] # record a finished deliverable
|
|
15
15
|
workser artifact add --url <url> --kind app # record a deployed app
|
|
16
|
+
workser artifact add <path> --kind <shape> --data <json> [--promote]
|
|
16
17
|
workser artifact run # which task you're attached to
|
|
17
18
|
|
|
18
19
|
workser ask "<question>" [--type <t>] [--option <o>] # ask the user, WAIT for the answer
|
|
@@ -39,6 +40,43 @@ are detected automatically); pass it explicitly for `app` / `url`.
|
|
|
39
40
|
To publish an app: `workser deploy` (preview) or `workser deploy --prod` (live), then
|
|
40
41
|
register the URL it returns as an `app` artifact so the user can open it from the task.
|
|
41
42
|
|
|
43
|
+
## The shapes the task draws as cards
|
|
44
|
+
|
|
45
|
+
Most kinds say what kind of FILE something is. A few say what the user **asked
|
|
46
|
+
for**, and those get a card of their own on the task:
|
|
47
|
+
|
|
48
|
+
| `--kind` | What the card shows | `--data` it reads |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `report` | the chart behind a number | — |
|
|
51
|
+
| `walkthrough` | the flow, as frames | `frames` |
|
|
52
|
+
| `before_after` | a wipe between two pictures | `shots: [{url,label}, …]` |
|
|
53
|
+
| `checks` | what was tested | `passed`, `total` |
|
|
54
|
+
| `web_app` | a published app | `deployedAt`, `pagesChanged` |
|
|
55
|
+
| `service` | a job and what it reaches | `nextRun` |
|
|
56
|
+
| `design` | a layout | — |
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
workser artifact add ./checks.json --kind checks --data '{"passed":12,"total":12}'
|
|
60
|
+
workser artifact add --url https://acme.workser.app --kind web_app \
|
|
61
|
+
--data '{"deployedAt":"2026-08-20T14:02:00Z","pagesChanged":3}'
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Every `--data` field is optional, and a missing one is left off the card — it
|
|
65
|
+
is never drawn as zero.** `0 pages changed` is a claim you cannot support and
|
|
66
|
+
reads as "it did nothing"; saying nothing reads as "not measured", which is
|
|
67
|
+
true. Only pass a figure you actually counted.
|
|
68
|
+
|
|
69
|
+
## Handing something up to the task
|
|
70
|
+
|
|
71
|
+
`--promote` marks an artifact as one of the things the user asked for, so it
|
|
72
|
+
appears on the task itself instead of inside your step.
|
|
73
|
+
|
|
74
|
+
Use it when you know: the report they wanted, the app you published, the
|
|
75
|
+
document explaining what changed. Do **not** promote working material —
|
|
76
|
+
screenshots you took to check your own work, intermediate exports, a scratch
|
|
77
|
+
file. A task that hands up everything buries the six things they wanted under
|
|
78
|
+
sixty they did not.
|
|
79
|
+
|
|
42
80
|
## Ask the user something (and get an answer back)
|
|
43
81
|
|
|
44
82
|
When you're blocked — a missing value, an ambiguous requirement, permission for
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
topic: deploy
|
|
3
|
-
title: Deploy,
|
|
4
|
-
summary: Ship the app,
|
|
5
|
-
commands: [deploy,
|
|
3
|
+
title: Deploy, addresses & logs
|
|
4
|
+
summary: Ship the app, find its address, and find out why it is down.
|
|
5
|
+
commands: [deploy, logs, versions, urls, deployments, domain, open, verify]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Deploy, environment variables & logs
|
|
@@ -10,33 +10,53 @@ commands: [deploy, env, logs, versions, domain, open, verify]
|
|
|
10
10
|
Getting the app online and configured, and finding out why it isn't.
|
|
11
11
|
|
|
12
12
|
```
|
|
13
|
-
workser deploy [--
|
|
13
|
+
workser deploy [--env production] [--watch] # deploy (git → Vercel); default is preview
|
|
14
14
|
workser deploy status [id] # status of a deploy (default: latest)
|
|
15
|
-
workser
|
|
16
|
-
workser
|
|
17
|
-
workser
|
|
15
|
+
workser urls # every app's stable preview + live address
|
|
16
|
+
workser logs [-n 100] [-f] [--env production] [--app <id>]
|
|
17
|
+
workser versions [--env production] # history; the badge says which env is live
|
|
18
|
+
workser deployments list [--env production] [--app <id>]
|
|
19
|
+
workser deployments inspect <id> [--logs]
|
|
20
|
+
workser deployments promote # ship the latest build (the owner confirms)
|
|
21
|
+
workser deployments rollback <version> # put an earlier one back (the owner confirms)
|
|
22
|
+
workser domain list # custom domains
|
|
23
|
+
workser domain add shop.co.th # attach one (the owner confirms)
|
|
24
|
+
workser domain add app.shop.co.th --app <webAppId>
|
|
25
|
+
workser domain rm shop.co.th # detach one (the owner confirms)
|
|
18
26
|
workser open # open the live app
|
|
19
27
|
workser verify # run typecheck/lint/build
|
|
20
28
|
|
|
21
|
-
workser env set KEY=VALUE [K2=V2…] # set env vars
|
|
22
|
-
workser env list # list keys (values masked)
|
|
23
|
-
workser env get KEY # one value (sensitive)
|
|
24
29
|
```
|
|
25
30
|
|
|
31
|
+
Settings — `workser env` — are their own topic: `workser help env`.
|
|
32
|
+
|
|
26
33
|
## Notes that matter
|
|
27
34
|
|
|
28
35
|
- **`verify` gates "done".** Run `workser verify --json` before you say a task is
|
|
29
36
|
finished. `"ok": false` means fix the listed errors and re-run — a green build is
|
|
30
37
|
the bar, not your reading of the diff.
|
|
31
|
-
- **`deploy` without `--
|
|
32
|
-
risky; `--
|
|
38
|
+
- **`deploy` without `--env` is a preview.** Preview first when the change is
|
|
39
|
+
risky; `--env production` (or the older `--prod`, which means the same) puts it
|
|
40
|
+
in front of real users. Passing both, disagreeing, is refused rather than
|
|
41
|
+
resolved.
|
|
42
|
+
- **`urls` is where the address comes from — not the deploy response.** The host
|
|
43
|
+
in a deploy response is per-build and the next deploy retires it. `urls`
|
|
44
|
+
returns the stable ones, and says why an app has none rather than printing a
|
|
45
|
+
blank.
|
|
46
|
+
- **`promote` and `rollback` are the same upstream call and two commands on
|
|
47
|
+
purpose.** Promote ships the newest build; rollback puts version N back. Both
|
|
48
|
+
ask the owner and return exit 7 (`awaiting_approval`) until they answer — and
|
|
49
|
+
that gate holds even on a "just do it" run.
|
|
50
|
+
- **There is no `deployments cancel`.** Nothing upstream can stop a build that is
|
|
51
|
+
already running. Wait for it and then promote or roll back.
|
|
33
52
|
- **`--watch` blocks until there's a live URL.** Without it you get a deploy id and
|
|
34
53
|
have to poll `deploy status`.
|
|
35
|
-
- **`
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
54
|
+
- **`domain add` and `domain rm` ask the owner to confirm** and return exit 7
|
|
55
|
+
(`awaiting_approval`) until they do — tell them to approve, then retry the same
|
|
56
|
+
command. Domains Workser owns (`workser.ai` and its subdomains) and hostnames
|
|
57
|
+
the hosting provider assigns (`*.vercel.app`) are refused outright: those are
|
|
58
|
+
not attachable, and the app's own preview and live URLs already exist without
|
|
59
|
+
attaching anything.
|
|
40
60
|
|
|
41
61
|
## After a successful deploy
|
|
42
62
|
|
|
@@ -47,10 +67,3 @@ workser artifact add --url https://acme.workser.app --kind app -t "Storefront"
|
|
|
47
67
|
```
|
|
48
68
|
|
|
49
69
|
See `reference/deliverables.md`.
|
|
50
|
-
|
|
51
|
-
## Local vs cloud environment
|
|
52
|
-
|
|
53
|
-
`env set` configures the **cloud** environment (production and preview). The `.env`
|
|
54
|
-
files in the app folder configure **this computer** — the user edits those in Orbit
|
|
55
|
-
under Settings → "On this computer", and saving there restarts the dev server. Don't
|
|
56
|
-
hand-edit `.env.local` to change cloud behaviour; they are different environments.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: docs
|
|
3
|
+
title: Project documents
|
|
4
|
+
summary: Write and revise the project's pages, keep the markdown mirror readable, and put the diagram in the document rather than in your reply.
|
|
5
|
+
commands: [doc]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Project documents
|
|
9
|
+
|
|
10
|
+
A document is a page in the project's Docs panel and a git-tracked markdown
|
|
11
|
+
mirror at `.workser/docs/<id>.md`. Both are the same document: the panel renders
|
|
12
|
+
the rich text, the mirror is what you, git and the next agent can read as text.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
workser doc list [--work-item <id>]
|
|
16
|
+
workser doc show <id> [--markdown]
|
|
17
|
+
workser doc create <title> [--work-item <id>] [--markdown <text>]
|
|
18
|
+
[--content-json <json>]
|
|
19
|
+
workser doc update <id> [--title <text>] [--markdown <text>]
|
|
20
|
+
workser doc diagram <id> [--check]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Revise the page that exists
|
|
24
|
+
|
|
25
|
+
The project outlives your session, and a second copy of a page is worse than no
|
|
26
|
+
page — nobody can tell which one is current.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
workser doc list --json # is there already a page for this?
|
|
30
|
+
workser doc update <id> --markdown "$(cat updated.md)"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`workser doc show <id> --markdown` reports the mirror's path so you can open the
|
|
34
|
+
file with your normal tools instead of reconstructing prose from blocks.
|
|
35
|
+
|
|
36
|
+
`--work-item <id>` links a document to a Board card (a card has at most one). A
|
|
37
|
+
linked document renders on its card and is *hidden* from the Docs panel, so a
|
|
38
|
+
plan spanning several phases should stay unlinked — it belongs to the project,
|
|
39
|
+
not to phase 1.
|
|
40
|
+
|
|
41
|
+
## Put the diagram in the document
|
|
42
|
+
|
|
43
|
+
A page explaining how something fits together should contain the picture, not a
|
|
44
|
+
paragraph describing one. Write it as a ```mermaid fence in the markdown: the
|
|
45
|
+
Docs panel renders it, `git diff` shows it as changed lines, and the next agent
|
|
46
|
+
reads it without a screenshot.
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
workser doc diagram <id> --check # exits non-zero when the page has none
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Use `--check` on any page whose job is to explain a structure — an architecture
|
|
53
|
+
page, a data model, a flow. It reads the mirror on disk rather than the block
|
|
54
|
+
content, which is deliberate: a diagram that exists in the editor but not in the
|
|
55
|
+
mirror is invisible to git, to you, and to whoever opens the file next.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: env
|
|
3
|
+
title: Settings — cloud, per environment, and on this computer
|
|
4
|
+
summary: Set and read an app's settings, hold a different value in production, and pull them onto this computer without clobbering local ones.
|
|
5
|
+
commands: [env]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Settings — cloud, per environment, and on this computer
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
workser env set KEY=VALUE [K2=V2…] [--env production]
|
|
12
|
+
workser env list [--env production] # keys, masked; marks where they differ
|
|
13
|
+
workser env get KEY [--env production] # one value (sensitive)
|
|
14
|
+
workser env pull [--env production] [--overwrite]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## `--env` — say which environment you mean
|
|
18
|
+
|
|
19
|
+
`deploy`, `logs` and `versions` take `--env preview` or `--env production`.
|
|
20
|
+
`env set` takes those and `--env development` as well.
|
|
21
|
+
|
|
22
|
+
Without it: `deploy` builds a preview, `logs` and `versions` talk about
|
|
23
|
+
whichever deployment is newest, and `env set` writes to all three environments.
|
|
24
|
+
Those are the old defaults and they have not changed.
|
|
25
|
+
|
|
26
|
+
**There is no development deployment.** Nothing is ever built into it — it is
|
|
27
|
+
the environment the app uses when it runs on this computer — so `deploy --env
|
|
28
|
+
development` and `logs --env development` are refused rather than quietly shown
|
|
29
|
+
preview.
|
|
30
|
+
|
|
31
|
+
**A key can now hold a different value per environment.** `env set --env
|
|
32
|
+
production DATABASE_URL=…` writes an override; every other environment keeps
|
|
33
|
+
the shared value. `env list --env production` and `env get KEY --env production`
|
|
34
|
+
read it back.
|
|
35
|
+
|
|
36
|
+
Without `--env` you get the **shared** value — what the key is everywhere unless
|
|
37
|
+
overridden — and `env list` marks which keys differ:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
API_KEY = sk-••• (different in production)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
That marker is the one to read before changing anything: editing the shared
|
|
44
|
+
value will not touch production if production has its own.
|
|
45
|
+
|
|
46
|
+
`env rm KEY --env production` removes just that override and the key keeps its
|
|
47
|
+
shared value. `env rm KEY` removes the key entirely.
|
|
48
|
+
|
|
49
|
+
## Local settings are this computer's, and are not overwritten
|
|
50
|
+
|
|
51
|
+
`env pull` writes into the app folder's own env file — `.env` for most runtimes,
|
|
52
|
+
`.env.local` for Next.js, because that is the file each one actually reads.
|
|
53
|
+
|
|
54
|
+
**It fills in what is missing and leaves what is already there alone.** A local
|
|
55
|
+
`DATABASE_URL` usually points at the developer's own database on purpose;
|
|
56
|
+
replacing it because somebody asked to pull one missing key destroys work
|
|
57
|
+
Workser cannot give back. Keys it left alone are **named** in the output.
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
workser env pull # fill the gaps, touch nothing else
|
|
61
|
+
workser env pull --env production # fill them from production's values
|
|
62
|
+
workser env pull --overwrite # replace local values too
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Starting an app for the first time does the same thing automatically, with the
|
|
66
|
+
same rule.
|
|
67
|
+
|
|
68
|
+
## A key can hold a different value per environment
|
|
69
|
+
|
|
70
|
+
`workser env set --env production DATABASE_URL=…` writes an override; every
|
|
71
|
+
other environment keeps the shared value.
|
|
72
|
+
|
|
73
|
+
Without `--env` you get the **shared** value — what the key is everywhere unless
|
|
74
|
+
overridden — and `env list` marks which keys differ:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
API_KEY = sk-••• (different in production)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Read that marker before changing anything: editing the shared value will not
|
|
81
|
+
touch production if production has its own.
|
|
82
|
+
|
|
83
|
+
`env rm KEY --env production` removes just that override and the key keeps its
|
|
84
|
+
shared value. `env rm KEY` removes the key entirely.
|
|
85
|
+
|
|
86
|
+
## Local settings are this computer's, and are not overwritten
|
|
87
|
+
|
|
88
|
+
`env pull` writes into the app folder's own env file — `.env` for most runtimes,
|
|
89
|
+
`.env.local` for Next.js, because that is the file each one actually reads.
|
|
90
|
+
|
|
91
|
+
**It fills in what is missing and leaves what is already there alone.** A local
|
|
92
|
+
`DATABASE_URL` usually points at the developer's own database on purpose;
|
|
93
|
+
replacing it because somebody asked to pull one missing key destroys work
|
|
94
|
+
Workser cannot give back. Keys it left alone are **named** in the output.
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
workser env pull # fill the gaps, touch nothing else
|
|
98
|
+
workser env pull --env production # fill them from production's values
|
|
99
|
+
workser env pull --overwrite # replace local values too
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Starting an app for the first time does the same thing automatically, with the
|
|
103
|
+
same rule.
|
|
104
|
+
|
|
105
|
+
## Notes that matter
|
|
106
|
+
|
|
107
|
+
- **`env set` writes a value you never see.** That's the point — when the user
|
|
108
|
+
has a secret, have them run it (or set it in Orbit) rather than pasting it to
|
|
109
|
+
you.
|
|
110
|
+
- **`env get` returns a secret.** Don't echo it into the conversation.
|
|
111
|
+
- **`env rm` is owner-only** (exit 6). Tell the user to do it in Orbit; don't
|
|
112
|
+
look for a workaround.
|
|
113
|
+
- **Cloud and local are different environments.** `env set` configures the
|
|
114
|
+
cloud; the files in the app folder configure this computer. Don't hand-edit
|
|
115
|
+
one to change the other.
|
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
topic: neon
|
|
3
|
-
title: The project's own
|
|
4
|
-
summary: Neon-branch object storage and functions. Dedicated tenancy only.
|
|
3
|
+
title: The project's own database
|
|
4
|
+
summary: Branches, databases, compute, plus Neon-branch object storage and functions. Dedicated tenancy only.
|
|
5
5
|
commands: [neon]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# The project's own
|
|
8
|
+
# The project's own database
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
The project's database, run the way an operator runs one: branches (copies of
|
|
11
|
+
the data), the databases on them, and the compute that serves them. Plus
|
|
12
|
+
S3-compatible object storage and Node.js HTTP functions on the same branch.
|
|
13
13
|
|
|
14
14
|
```
|
|
15
15
|
workser neon status # tenancy + toggles + region verdict
|
|
16
|
+
|
|
17
|
+
workser neon branch list # copies of the data; the live one is marked
|
|
18
|
+
workser neon branch create qa-run # a copy to work on, made in a second
|
|
19
|
+
workser neon branch create qa --from <id> --no-compute
|
|
20
|
+
workser neon branch reset <branchId> # throw its changes away (asks the owner)
|
|
21
|
+
workser neon branch rm <branchId> # delete it and its data (asks the owner)
|
|
22
|
+
|
|
23
|
+
workser neon database list [--branch <id>]
|
|
24
|
+
workser neon database create <name> [--branch <id>] [--owner <role>]
|
|
25
|
+
workser neon database rm <name> [--branch <id>] # asks the owner
|
|
26
|
+
|
|
27
|
+
workser neon endpoints # what compute is running, and idle
|
|
28
|
+
|
|
16
29
|
workser neon storage list | create <name> | rm <bucket>
|
|
17
30
|
workser neon storage ls <bucket> [prefix]
|
|
18
31
|
workser neon storage put <bucket> <local> [key]
|
|
@@ -30,6 +43,24 @@ Region is fixed when the project is created. `regionSupportsNeonBackend: false`
|
|
|
30
43
|
**final, not retryable** — no amount of waiting or retrying changes it. When you see
|
|
31
44
|
it, say so plainly and fall back to `workser storage` (the default bucket).
|
|
32
45
|
|
|
46
|
+
## Branches are the useful one
|
|
47
|
+
|
|
48
|
+
A branch is a **full copy of the data**, made in about a second, costing almost
|
|
49
|
+
nothing until something writes to it. That is what lets a check run against real
|
|
50
|
+
data without being able to damage it — give a QA step its own branch instead of
|
|
51
|
+
pointing it at the live database.
|
|
52
|
+
|
|
53
|
+
Two things cannot happen at all, whatever anyone approves: **the branch the app
|
|
54
|
+
runs on cannot be deleted or reset**, and neither can **the database it connects
|
|
55
|
+
to**. Those refusals come from the server, not from the approval prompt. If you
|
|
56
|
+
meant to reset a copy and got that message, you named the live one.
|
|
57
|
+
|
|
58
|
+
`reset` deletes nothing by name and destroys just as much: it replaces a
|
|
59
|
+
branch's contents with its source's. It asks the owner for exactly that reason.
|
|
60
|
+
|
|
61
|
+
`--no-compute` makes a branch with no compute. It is cheaper and **nothing can
|
|
62
|
+
connect to it** — useful as a snapshot, useless as somewhere to run tests.
|
|
63
|
+
|
|
33
64
|
## Notes that matter
|
|
34
65
|
|
|
35
66
|
- **`neon storage rm <bucket>` deletes the bucket and everything in it.** Not
|
|
@@ -38,5 +69,8 @@ it, say so plainly and fall back to `workser storage` (the default bucket).
|
|
|
38
69
|
through Workser.
|
|
39
70
|
- **Functions deploy from a zip.** Build the bundle first, then
|
|
40
71
|
`workser neon functions deploy <slug> <zip>`.
|
|
41
|
-
-
|
|
42
|
-
|
|
72
|
+
- **`neon endpoints` is the cost question.** `active` means it is billing;
|
|
73
|
+
`idle` means it is not. It is the only place in the product that answers "what
|
|
74
|
+
is this database costing me while nothing is happening".
|
|
75
|
+
- **Most apps never need the storage or functions half.** If the user just wants
|
|
76
|
+
to store uploads, the default bucket in `reference/storage.md` is the answer.
|