@workser/cli 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workser/cli",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
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",
@@ -29,8 +29,9 @@
29
29
  "access": "public"
30
30
  },
31
31
  "scripts": {
32
- "build": "tsup",
33
- "dev": "tsup --watch",
32
+ "build": "npm run build:help && tsup",
33
+ "build:help": "node scripts/build-help.mjs",
34
+ "dev": "npm run build:help && tsup --watch",
34
35
  "typecheck": "tsc --noEmit",
35
36
  "lint": "eslint \"src/**/*.ts\"",
36
37
  "format": "prettier --write \"src/**/*.ts\"",
@@ -11,7 +11,48 @@ Neon Postgres database, deploy it, manage its env vars and bucket, provision aut
11
11
  and read its logs — **on the user's own account**, through the Workser Orbit app
12
12
  (which handles auth and shows the user what you're doing).
13
13
 
14
+ For writing code, keep using your normal tools. Use `workser` for the last mile.
15
+
16
+ ## Read one guide, not all of them
17
+
18
+ This page is the index. The detail lives in the CLI itself — `workser help <topic>`
19
+ prints one focused guide, about a screen long. Find your row, run that **one**
20
+ command. Don't print them all; you are paying for every line you load.
21
+
22
+ | You need to… | Commands | Run |
23
+ | --- | --- | --- |
24
+ | Provision or query Postgres; list end users | `db …`, `auth …` | `workser help database` |
25
+ | Deploy, set env vars, read logs, check a domain | `deploy`, `env …`, `logs`, `versions`, `domain`, `open` | `workser help deploy` |
26
+ | Put files in the project's bucket | `storage …` | `workser help storage` |
27
+ | Read or write products, orders, customers, deals | `business …` | `workser help business` |
28
+ | Use the project's own Neon buckets or functions | `neon …` | `workser help neon` |
29
+ | Build an automation, or use Gmail/Slack/Stripe/Sheets | `workflow …`, `app …` | `workser help automation` |
30
+ | Generate an image | `image …` | `workser help images` |
31
+ | Hand a subtask to another agent | `agent …` | `workser help roles` |
32
+ | Remember or recall something across conversations | `memory …` | `workser help memory` |
33
+ | Record finished output, or ask the user a question | `artifact …`, `ask` | `workser help deliverables` |
34
+ | Control this machine — files, shell, screen, browser | `tool …` | `workser help computer-use` |
35
+
36
+ `workser help` with no topic lists them. **The CLI is the source of truth**: it ships
37
+ these guides with itself, so they match the version you are running. For exact flags
38
+ on any command, `workser <command> --help` is generated from the implementation and
39
+ cannot be out of date.
40
+
41
+ ## Orientation (no guide needed)
42
+
43
+ ```
44
+ workser status # connection + pinned project + latest deploy
45
+ workser whoami # who am I / which workspace
46
+ workser project show # the project pinned to this directory
47
+ workser project list # the workspace's projects (read)
48
+ workser verify # run typecheck/lint/build — gate "done" on this
49
+ workser doctor # resolved endpoint, mode, token presence, project
50
+ workser login # authenticate outside Orbit (CI/standalone)
51
+ workser logout # clear a saved standalone session
52
+ ```
53
+
14
54
  ## Scope (read this)
55
+
15
56
  You operate on **one project's own infrastructure**. You *can* provision and use it:
16
57
  create the Neon database, read its connection string, browse its tables / rows / run
17
58
  SQL, provision the bucket + auth, deploy, set env vars, manage files. Sensitive
@@ -24,25 +65,18 @@ Those return `error.code = "owner_only"` (exit 6) — tell the user it's an owne
24
65
  action to do in Orbit, then continue with what you can do. The project is already
25
66
  selected; you don't pick or switch it.
26
67
 
27
- ## When to use this
28
- Reach for `workser` whenever the task involves **running** the current app, not just writing it:
29
- - "deploy this", "put it online", "give me a URL"
30
- - "set an API key / env var", "what's the database URL?"
31
- - "upload this file", "list what's in storage"
32
- - "is it deployed?", "show logs", "why is it down?"
33
-
34
- For writing code, keep using your normal tools. Use `workser` for the last mile.
68
+ Owner-only, for reference: `project create` · `project use` · `env rm` · `domain set`.
35
69
 
36
70
  ## Golden rules
71
+
37
72
  1. **Always pass `--json`.** Output is then a single stable line:
38
73
  `{"ok":true,"data":...}` or `{"ok":false,"error":{"code","message",...}}`. Parse it.
39
74
  2. **Orient first.** Run `workser status --json` to see the connection, the pinned
40
75
  project, and the latest deploy before acting. You don't pick or switch projects.
41
- 3. **Stay in your lane.** `error.code = "owner_only"` (exit 6) means the action
42
- (creating/switching projects, deleting env vars, attaching domains) is reserved
43
- for the owner in Orbit. Don't retry or look for a workaround tell the user, then
44
- continue. Provisioning the *pinned project's own* db / bucket / auth is allowed
45
- (it may be approval-gated, not owner-only).
76
+ 3. **Stay in your lane.** `error.code = "owner_only"` (exit 6) means the action is
77
+ reserved for the owner in Orbit. Don't retry or look for a workaround — tell the
78
+ user, then continue. Provisioning the *pinned project's own* db / bucket / auth is
79
+ allowed (it may be approval-gated, not owner-only).
46
80
  4. **Approvals are normal.** Some allowed actions may return
47
81
  `{"error":{"code":"awaiting_approval"}}` (exit 5) while the user approves in the
48
82
  Orbit UI. Tell the user to approve, then retry — do **not** try to bypass it.
@@ -55,158 +89,8 @@ For writing code, keep using your normal tools. Use `workser` for the last mile.
55
89
  `git reset --hard`, `DROP`/`TRUNCATE`, `curl | sh`, …) are refused by Workser's
56
90
  safety policy — don't attempt them; use migrations + scoped changes instead.
57
91
 
58
- ## Command reference
59
- ```
60
- workser status # connection + pinned project + latest deploy
61
- workser whoami # who am I / which workspace
62
- workser project show # the project pinned to this directory
63
- workser project list # the workspace's projects (read)
64
-
65
- workser db create # provision the Neon Postgres database (idempotent)
66
- workser db url # connection string (sensitive; least-privilege role)
67
- workser db list # database status
68
- workser db tables # list tables in the database
69
- workser db schema <table> # a table's columns
70
- workser db data <table> [-n N] [--offset N] # read rows
71
- workser db query "<sql>" # run SQL (writes are approval-gated)
72
- workser auth enable # provision auth for the project (idempotent)
73
- workser auth status # is auth enabled? + Neon auth mode
74
-
75
- workser env set KEY=VALUE [K2=V2…] # set env vars
76
- workser env list # list keys (values masked)
77
- workser env get KEY # one value (sensitive)
78
-
79
- workser storage create [name] # provision the bucket (idempotent)
80
- workser storage list # the project's bucket
81
- workser storage ls [prefix] # list objects in the bucket
82
- workser storage put <local> <key> # upload a file into the bucket
83
- workser storage get <key> [dest] # download an object (or print its URL)
84
-
85
- workser deploy [--prod] [--watch] # deploy (git → Vercel); --watch waits for live URL
86
- workser deploy status [id] # status of a deploy (default: latest)
87
- workser logs [-n 100] [-f] # recent logs
88
- workser versions # deploy history
89
- workser domain list # custom domains (read)
90
- workser open # open the live app
91
- workser verify # run typecheck/lint/build — gate "done" on this passing
92
-
93
- workser agent list # main agent + configured roles (+ which are runnable)
94
- workser agent run <role> "<task>" # delegate a focused subtask to a role (runs isolated)
95
- workser agent main # show the configured main agent
96
-
97
- workser workflow list | create <name> [--body <json>] | get <id>
98
- workser workflow activate <id> | deactivate <id> | run <id> [--wait] [--body <json>]
99
- workser workflow runs <id> # past executions of a workflow
100
- workser workflow nodes [query] # search the node-type catalog
101
- workser app list [--toolkit <slug>] # connectable + connected third-party apps
102
- workser app connect <toolkit> | disconnect <connectionId>
103
- workser app tools <toolkit> # a connected app's callable actions
104
- workser app run <toolSlug> [--body <json>] # execute one action (e.g. GOOGLESHEETS_APPEND_ROW)
105
-
106
- workser tool list # computer-use tools available to you right now
107
- workser tool run <name> [--body <json>] # filesystem/shell/screenshot/input/clipboard/browser
108
-
109
- workser memory add "<content>" [--metadata <json>] # remember something across future conversations
110
- workser memory search "<query>" [--limit N] # recall what you (or a cloud agent) learned before
111
- workser memory forget <memoryId> # soft-delete an outdated/incorrect memory
112
-
113
- workser artifact add <path> [--kind <k>] [-d <text>] # record a finished deliverable
114
- workser artifact add --url <url> --kind app # record a deployed app
115
- workser artifact run # which task you're attached to
116
-
117
- workser ask "<question>" [--type <t>] [--option <o>] # ask the user, WAIT for the answer
118
-
119
- # owner-only (return owner_only / exit 6 — ask the user to do these in Orbit):
120
- # project create · project use · env rm · domain set
121
- ```
122
-
123
- ## Memory (remember across conversations, not just this one)
124
- Every conversation you run is otherwise a fresh start — no memory of what you or the
125
- user decided last time. `workser memory add "<content>"` fixes that: it stores durable,
126
- searchable memory for the CURRENT PROJECT, and it's the SAME memory space Workser's own
127
- cloud agents write to for this project — so add something here and a cloud agent (or
128
- your own next conversation) can `workser memory search` and find it. Use it for things
129
- worth remembering past this one conversation: user preferences, decisions made,
130
- important context, requirements — not routine chatter. Before assuming you don't know
131
- something about this project, `workser memory search "<topic>"` first; it may already be
132
- recorded. `forget` soft-deletes a specific memory if it's wrong or outdated — the
133
- content stays retrievable by ID but excluded from future searches.
134
-
135
- ## Record what you produced (deliverables)
136
- Workser shows the user a **Deliverables** list on the task. If you don't say what you
137
- made, it has to guess — it watches your file edits and treats any path it sees as a
138
- deliverable, so scratch files and half-finished drafts show up next to the real output,
139
- and things that aren't files at all (a folder of results, an app you deployed) can't
140
- show up correctly. Fix that by declaring finished output:
141
- ```
142
- workser artifact add ./report.pdf -d "Q3 sales summary"
143
- workser artifact add ./exports --kind folder -d "generated CSVs"
144
- workser artifact add --url https://acme.workser.app --kind app -t "Storefront"
145
- ```
146
- Only register FINISHED output the user should get — not temp files, not intermediate
147
- steps. `--kind` is inferred from the path when you omit it (directories are detected
148
- automatically); pass it explicitly for `app` / `url`. `workser artifact run` shows which
149
- task you're currently attached to.
150
-
151
- To publish an app: `workser deploy` (preview) or `workser deploy --prod` (live), then
152
- register the URL it returns as an `app` artifact so the user can open it from the task.
153
-
154
- ## Ask the user something (and get an answer back)
155
- When you're blocked — a missing value, an ambiguous requirement, permission for
156
- something consequential — don't guess and don't just write the question into your
157
- final message. Run:
158
- ```
159
- workser ask "Which email should order confirmations come from?"
160
- workser ask "Which plan should I wire up?" --option Free --option Pro --option Team
161
- workser ask "Delete the 1,240 archived rows?" --type approval
162
- ```
163
- This shows the user a real card in the conversation and **blocks until they answer**,
164
- then prints their answer — so you ask, read the reply, and keep working in the same
165
- turn. Types: `input` (default, free text), `choice` (with `--option`), `approval`
166
- (permission), `confirmation` (check an assumption), `information` (FYI, no answer
167
- needed). It times out (default 10 min) rather than hanging forever; if it does, carry
168
- on and state clearly what you assumed.
169
-
170
- **Never ask for a secret value this way** — the answer is stored and displayed. Ask
171
- where a key should go, then have the user set it (`workser env set` writes it without
172
- you ever seeing it).
173
-
174
- ## Computer-use tools (your hands on this machine)
175
- `workser tool list` shows what's available — filesystem (read/write/list/delete/move),
176
- shell (run a command/Python/Node), screenshots and screen info, mouse/keyboard input,
177
- clipboard, notifications, and basic browser control (open a URL, read the page, click/
178
- fill/type, screenshot). This is the SAME engine Workser's cloud Computer Use agent uses
179
- when it controls a user's machine remotely — you're getting it locally, gated by the
180
- same safety policy (blocked paths like `~/.ssh`, blocked destructive commands, rate
181
- limits). Sensitive actions (writing/deleting files, running a shell command, clicking/
182
- typing) may return `awaiting_approval` (exit 5) — same handling as any other gated
183
- action: tell the user to approve in Orbit, then retry. This is a curated subset, not
184
- full desktop automation — check `workser tool list` rather than assuming a capability
185
- exists.
186
-
187
- ## Workflow automation & app integrations
188
- Beyond one-shot code, wire up **automations** that keep running after you're done:
189
- `workser workflow create` builds an event-driven, multi-step automation (the same
190
- engine Workser's own web Workflow tab uses) — nodes/connections/triggers go in
191
- `--body` as JSON; browse `workser workflow nodes` first. Before an automation (or you,
192
- directly) can use a third-party app (Gmail, Slack, Stripe, Google Sheets, ...), the
193
- user connects it once via `workser app connect <toolkit>` — this opens an OAuth link,
194
- ask the user to complete it, then continue. After that, `workser app run <toolSlug>
195
- --body '{"...":...}'` calls any of its actions. Check `workser app list` before
196
- assuming you need to ask the user to connect something new.
197
-
198
- ## Delegate to roles
199
- The user can configure **roles** — named specialists each backed by a local CLI agent
200
- (e.g. `qa` → codex, `designer` → claude_code). Delegate a focused subtask with
201
- `workser agent run <role> "<task>" --json`; the role runs as an **isolated local
202
- subagent** (its own context) and returns `{role, agent, output, exitCode}`.
203
-
204
- - Run `workser agent list --json` first to see which roles are configured + runnable.
205
- - Hand off focused subtasks (review this diff, design this screen) to keep your own
206
- context lean and get a specialized second perspective. A non-zero `exitCode` means
207
- the role's run failed — surface that, don't silently ignore it.
208
-
209
92
  ## Typical flow: build → ship
93
+
210
94
  ```bash
211
95
  workser status --json # 1. orient (project is already pinned)
212
96
  workser db create --json # 2. provision infra the app needs (idempotent)
@@ -214,11 +98,13 @@ workser env set STRIPE_KEY=sk_live_… --json # 3. configure it
214
98
  # … you write the app code with your normal tools …
215
99
  workser deploy --prod --watch --json # 4. ship; returns the live URL
216
100
  ```
101
+
217
102
  Provisioning the pinned project's own database / bucket / auth is yours to do
218
103
  (`db create`, `storage create`, `auth enable`) — the user may need to approve it in
219
104
  Orbit (`awaiting_approval`). Only a **custom domain** is an owner action.
220
105
 
221
106
  ## Reading results
107
+
222
108
  - Success: use `.data` (e.g. `.data.url` after deploy, `.data` array after `list`).
223
109
  - Failure: check `.error.code`:
224
110
  - `not_connected` → tell the user to open Workser Orbit (or `workser login` for CI).
@@ -229,3 +115,10 @@ Orbit (`awaiting_approval`). Only a **custom domain** is an owner action.
229
115
 
230
116
  Keep the user informed in plain language ("Provisioned a database and deployed —
231
117
  it's live at <url>"), not raw JSON.
118
+
119
+ ## Writing app code, not operating the app
120
+
121
+ `workser db query` is for **you** to inspect the database while building. It is not
122
+ how the app reads its own data at runtime — that's `@workser/app`, covered by the
123
+ `workser-sdk` skill. Using the CLI where the SDK belongs is the most common mistake
124
+ here.
@@ -0,0 +1,55 @@
1
+ ---
2
+ topic: automation
3
+ title: Workflows & connected apps
4
+ summary: Build automations that outlive the run; use Gmail, Slack, Stripe, Sheets.
5
+ commands: [workflow, app]
6
+ ---
7
+
8
+ # Workflows & connected apps
9
+
10
+ Wire up **automations** that keep running after you're done, and use third-party
11
+ accounts (Gmail, Slack, Stripe, Google Sheets) the project has connected.
12
+
13
+ ```
14
+ workser workflow list | create <name> [--body <json>] | get <id>
15
+ workser workflow activate <id> | deactivate <id> | run <id> [--wait] [--body <json>]
16
+ workser workflow runs <id> # past executions of a workflow
17
+ workser workflow nodes [query] # search the node-type catalog
18
+
19
+ workser app list [--toolkit <slug>] # connectable + connected third-party apps
20
+ workser app connect <toolkit> | disconnect <connectionId>
21
+ workser app tools <toolkit> # a connected app's callable actions
22
+ workser app run <toolSlug> [--body <json>] # execute one action
23
+ ```
24
+
25
+ ## Building a workflow
26
+
27
+ `workser workflow create` builds an event-driven, multi-step automation — the same
28
+ engine Workser's own web Workflow tab uses. Nodes, connections and triggers go in
29
+ `--body` as JSON.
30
+
31
+ **Browse `workser workflow nodes` first.** Inventing a node type that doesn't exist
32
+ produces a workflow that saves and then never runs.
33
+
34
+ Created workflows start inactive: `workser workflow activate <id>` when it's ready.
35
+
36
+ ## Using a connected app
37
+
38
+ 1. `workser app list` — check what's already connected before asking for anything.
39
+ 2. If it isn't: `workser app connect <toolkit>` returns an OAuth link. The **user**
40
+ must open it; you cannot complete OAuth on their behalf. Wait, then continue.
41
+ 3. `workser app tools <toolkit>` — read the argument schema rather than guessing
42
+ field names.
43
+ 4. `workser app run <toolSlug> --body '{"…":…}'` — e.g. `GOOGLESHEETS_APPEND_ROW`,
44
+ `GMAIL_SEND_EMAIL`.
45
+
46
+ **A `run` is a real side effect in someone's real account.** Sending an email or
47
+ charging a card is not a dry run — say what you're about to do before you do it.
48
+
49
+ ## The half people forget
50
+
51
+ A workflow-backed feature is two-way. Triggering it is the outbound half; when the
52
+ workflow produces a result the app needs, its final node has to POST back to a
53
+ webhook route in the app. Build only the trigger and the workflow runs perfectly
54
+ while nothing ever appears in the product. The app-side receiver is covered in the
55
+ `workser-sdk` skill under workflows.
@@ -0,0 +1,51 @@
1
+ ---
2
+ topic: business
3
+ title: Business hub data
4
+ summary: Products, orders, customers, sales, content, marketing, support, analytics.
5
+ commands: [business]
6
+ ---
7
+
8
+ # Business hub data
9
+
10
+ The project's own commerce and CRM records — the **same rows** the Orbit desktop
11
+ Business tab and workser-web's Business hub show. One generic CRUD surface across
12
+ every resource rather than a command per domain.
13
+
14
+ ```
15
+ workser business resources # the known resource names
16
+ workser business list <resource> [subpath] # list/read (--query '<json>')
17
+ workser business get <resource> <id>
18
+ workser business create <resource> --body '<json>'
19
+ workser business update <resource> <id> --body '<json>'
20
+ workser business delete <resource> <id>
21
+ workser business action <resource> <id> <verb> # POST .../<id>/<verb>
22
+ ```
23
+
24
+ ## Resources
25
+
26
+ `business-config`, `business-settings`, `products`, `collections`, `navigations`,
27
+ `orders`, `customers`, `sales-pipelines`, `sales-deals`, `pages`, `blog-posts`,
28
+ `media`, `campaigns`, `email-templates`, `discounts`, `seo-configs`,
29
+ `social-accounts`, `support-conversations`, `automation-rules`, `analytics`.
30
+
31
+ Run `workser business resources --json` rather than trusting this list — the CLI's
32
+ copy is the current one.
33
+
34
+ ## Notes that matter
35
+
36
+ - **Sales and Support nest.** `sales-deals` maps to `/sales/deals`,
37
+ `support-conversations` to `/support/conversations`. Use the dashed names above;
38
+ the flat `resource/id` shape then works for `get`/`update`/`delete`/`action`.
39
+ - **`list` takes a raw subpath** for anything the map doesn't cover:
40
+ `workser business list sales-pipelines <id>/stages`.
41
+ - **`action` is for named verbs** — `workser business action orders <id> cancel`,
42
+ `workser business action sales-deals <dealId> win`. Check the resource's routes
43
+ before inventing a verb.
44
+ - **These are real business records.** Cancelling an order or deleting a customer is
45
+ not a dry run. Say what you're about to do first.
46
+
47
+ ## This is for you, not for the app
48
+
49
+ `workser business` is how **you** inspect and fix data while building. The app reads
50
+ the same records at runtime through `workser.business` in `@workser/app` — see the
51
+ `workser-sdk` skill. An app shelling out to this CLI per request is wrong.
@@ -0,0 +1,35 @@
1
+ ---
2
+ topic: computer-use
3
+ title: Computer-use tools
4
+ summary: Files, shell, screen, input, clipboard and browser on this machine.
5
+ commands: [tool]
6
+ ---
7
+
8
+ # Computer-use tools — your hands on this machine
9
+
10
+ ```
11
+ workser tool list # what's available to you right now
12
+ workser tool run <name> [--body <json>] # run one
13
+ ```
14
+
15
+ `workser tool list` shows what's available — filesystem (read/write/list/delete/move),
16
+ shell (run a command / Python / Node), screenshots and screen info, mouse and keyboard
17
+ input, clipboard, notifications, and basic browser control (open a URL, read the page,
18
+ click, fill, type, screenshot).
19
+
20
+ This is the **same engine** Workser's cloud Computer Use agent uses when it controls a
21
+ user's machine remotely — you're getting it locally, gated by the same safety policy.
22
+
23
+ ## Notes that matter
24
+
25
+ - **Check `tool list` rather than assuming a capability exists.** This is a curated
26
+ subset, not full desktop automation.
27
+ - **The safety policy applies.** Blocked paths (`~/.ssh` and friends), blocked
28
+ destructive commands, rate limits. Refusals are the policy working, not a bug to
29
+ route around.
30
+ - **Sensitive actions are approval-gated.** Writing or deleting files, running a shell
31
+ command, clicking or typing may return `awaiting_approval` (exit 5) — tell the user
32
+ to approve in Orbit, then retry.
33
+ - **You already have your own tools.** For editing files in this repo, use them. Reach
34
+ for `workser tool` when you need something *outside* the project — the screen, the
35
+ clipboard, a browser, another app on the machine.
@@ -0,0 +1,41 @@
1
+ ---
2
+ topic: database
3
+ title: Database & end users
4
+ summary: Provision Postgres, browse tables, run SQL, provision auth.
5
+ commands: [db, auth]
6
+ ---
7
+
8
+ # Database & end users
9
+
10
+ The project's Postgres (Neon behind Workser) and its end-user auth. Provisioning is
11
+ idempotent — running `create` twice is safe.
12
+
13
+ ```
14
+ workser db create # provision the Neon Postgres database (idempotent)
15
+ workser db url # connection string (sensitive; least-privilege role)
16
+ workser db list # database status
17
+ workser db tables # list tables in the database
18
+ workser db schema <table> # a table's columns
19
+ workser db data <table> [-n N] [--offset N] # read rows
20
+ workser db query "<sql>" # run SQL (writes are approval-gated)
21
+
22
+ workser auth enable # provision auth for the project (idempotent)
23
+ workser auth status # is auth enabled? + Neon auth mode
24
+ ```
25
+
26
+ ## Notes that matter
27
+
28
+ - **`db url` is a credential.** Don't print it into the conversation, don't paste it
29
+ into a file the user will commit. The app gets it from its environment already.
30
+ - **Writes are approval-gated.** A `db query` that mutates may return
31
+ `awaiting_approval` (exit 5). Ask the user to approve in Orbit, then retry.
32
+ - **`DROP` / `TRUNCATE` are refused** by the safety policy. Change schema with a
33
+ migration in the app's own migration folder, not with a destructive one-off.
34
+ - **The database is the project's, not the app's.** Sibling apps in the same project
35
+ share it. Don't assume a table is yours because you created it.
36
+
37
+ ## Reading rows vs. reading data at runtime
38
+
39
+ `db data` / `db query` are for **you**, inspecting while you build. The app itself
40
+ should read through `@workser/app` (`workser.db`, `workser.business`) — see the
41
+ `workser-sdk` skill. An app that shells out to the CLI at request time is wrong.
@@ -0,0 +1,65 @@
1
+ ---
2
+ topic: deliverables
3
+ title: Deliverables & asking the user
4
+ summary: Record finished output on the task, and ask a blocking question.
5
+ commands: [artifact, ask]
6
+ ---
7
+
8
+ # Deliverables & asking the user
9
+
10
+ Two things that reach the user directly: what you produced, and what you need from
11
+ them.
12
+
13
+ ```
14
+ workser artifact add <path> [--kind <k>] [-d <text>] # record a finished deliverable
15
+ workser artifact add --url <url> --kind app # record a deployed app
16
+ workser artifact run # which task you're attached to
17
+
18
+ workser ask "<question>" [--type <t>] [--option <o>] # ask the user, WAIT for the answer
19
+ ```
20
+
21
+ ## Record what you produced
22
+
23
+ Workser shows the user a **Deliverables** list on the task. If you don't say what you
24
+ made, it has to guess — it watches your file edits and treats any path it sees as a
25
+ deliverable, so scratch files and half-finished drafts show up next to the real
26
+ output, and things that aren't files at all (a folder of results, a deployed app)
27
+ can't show up correctly.
28
+
29
+ ```
30
+ workser artifact add ./report.pdf -d "Q3 sales summary"
31
+ workser artifact add ./exports --kind folder -d "generated CSVs"
32
+ workser artifact add --url https://acme.workser.app --kind app -t "Storefront"
33
+ ```
34
+
35
+ Only register **finished** output the user should get — not temp files, not
36
+ intermediate steps. `--kind` is inferred from the path when you omit it (directories
37
+ are detected automatically); pass it explicitly for `app` / `url`.
38
+
39
+ To publish an app: `workser deploy` (preview) or `workser deploy --prod` (live), then
40
+ register the URL it returns as an `app` artifact so the user can open it from the task.
41
+
42
+ ## Ask the user something (and get an answer back)
43
+
44
+ When you're blocked — a missing value, an ambiguous requirement, permission for
45
+ something consequential — don't guess, and don't just write the question into your
46
+ final message where nobody will answer it.
47
+
48
+ ```
49
+ workser ask "Which email should order confirmations come from?"
50
+ workser ask "Which plan should I wire up?" --option Free --option Pro --option Team
51
+ workser ask "Delete the 1,240 archived rows?" --type approval
52
+ ```
53
+
54
+ This shows the user a real card in the conversation and **blocks until they answer**,
55
+ then prints their answer — so you ask, read the reply, and keep working in the same
56
+ turn.
57
+
58
+ Types: `input` (default, free text), `choice` (with `--option`), `approval`
59
+ (permission), `confirmation` (check an assumption), `information` (FYI, no answer
60
+ needed). It times out (default 10 min) rather than hanging forever; if it does, carry
61
+ on and state clearly what you assumed.
62
+
63
+ **Never ask for a secret value this way** — the answer is stored and displayed. Ask
64
+ *where* a key should go, then have the user set it (`workser env set` writes it
65
+ without you ever seeing it).
@@ -0,0 +1,56 @@
1
+ ---
2
+ topic: deploy
3
+ title: Deploy, environment variables & logs
4
+ summary: Ship the app, configure it, and find out why it is down.
5
+ commands: [deploy, env, logs, versions, domain, open, verify]
6
+ ---
7
+
8
+ # Deploy, environment variables & logs
9
+
10
+ Getting the app online and configured, and finding out why it isn't.
11
+
12
+ ```
13
+ workser deploy [--prod] [--watch] # deploy (git → Vercel); --watch waits for live URL
14
+ workser deploy status [id] # status of a deploy (default: latest)
15
+ workser logs [-n 100] [-f] # recent logs
16
+ workser versions # deploy history
17
+ workser domain list # custom domains (read)
18
+ workser open # open the live app
19
+ workser verify # run typecheck/lint/build
20
+
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
+ ```
25
+
26
+ ## Notes that matter
27
+
28
+ - **`verify` gates "done".** Run `workser verify --json` before you say a task is
29
+ finished. `"ok": false` means fix the listed errors and re-run — a green build is
30
+ the bar, not your reading of the diff.
31
+ - **`deploy` without `--prod` is a preview.** Preview first when the change is
32
+ risky; `--prod` puts it in front of real users.
33
+ - **`--watch` blocks until there's a live URL.** Without it you get a deploy id and
34
+ have to poll `deploy status`.
35
+ - **`env set` writes a value you never see.** That's the point — when the user has
36
+ a secret, have them run it (or set it in Orbit) rather than pasting it to you.
37
+ - **`env get` returns a secret.** Don't echo it into the conversation.
38
+ - **`env rm` and `domain set` are owner-only** (exit 6). Tell the user to do it in
39
+ Orbit; don't look for a workaround.
40
+
41
+ ## After a successful deploy
42
+
43
+ Register the URL so it shows up on the user's task:
44
+
45
+ ```
46
+ workser artifact add --url https://acme.workser.app --kind app -t "Storefront"
47
+ ```
48
+
49
+ 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,35 @@
1
+ ---
2
+ topic: images
3
+ title: Image generation
4
+ summary: Generate images from a prompt, optionally conditioned on existing images.
5
+ commands: [image]
6
+ ---
7
+
8
+ # Image generation
9
+
10
+ ```
11
+ workser image generate "<prompt>" # alias: workser image gen
12
+ -r, --reference <url...> # condition on existing images (up to 4)
13
+ -o, --output <path> # also download the first image locally
14
+ ```
15
+
16
+ Returns the generated image's public URL, so the usual move is to generate, then use
17
+ that URL directly in the app.
18
+
19
+ ```bash
20
+ workser image generate "flat illustration of a farm delivery van, brand colors" --json
21
+ workser image gen "same van, from the side" -r https://… -o ./public/van.png --json
22
+ ```
23
+
24
+ ## Notes that matter
25
+
26
+ - **Reference images are image-to-image conditioning**, not attachments. Up to 4;
27
+ anything beyond that is dropped.
28
+ - **The model sometimes narrates instead of drawing** — a refusal or a clarifying
29
+ question comes back as text rather than an image. Check that you actually got an
30
+ image before wiring the URL into a page; an empty result is not a transport error
31
+ to retry.
32
+ - **`--output` writes only the first image.** If you asked for several, the rest
33
+ exist only as URLs.
34
+ - **Placeholder art is not a deliverable.** Generating a hero image to unblock a
35
+ layout is fine; shipping it as the user's brand asset without asking is not.
@@ -0,0 +1,34 @@
1
+ ---
2
+ topic: memory
3
+ title: Memory across conversations
4
+ summary: Store and recall durable project knowledge shared with cloud agents.
5
+ commands: [memory]
6
+ ---
7
+
8
+ # Memory — remember across conversations, not just this one
9
+
10
+ ```
11
+ workser memory add "<content>" [--metadata <json>] # remember for future conversations
12
+ workser memory search "<query>" [--limit N] # recall what was learned before
13
+ workser memory forget <memoryId> # soft-delete an outdated memory
14
+ ```
15
+
16
+ ## Why this exists
17
+
18
+ Every conversation you run is otherwise a fresh start — no memory of what you or the
19
+ user decided last time. This stores durable, searchable memory for the **current
20
+ project**, and it is the **same memory space** Workser's cloud agents write to for
21
+ this project. Add something here and a cloud agent — or your own next conversation —
22
+ can `memory search` and find it.
23
+
24
+ ## Using it well
25
+
26
+ - **Search before assuming you don't know.** Before concluding something about this
27
+ project is undocumented, run `workser memory search "<topic>"`. It may already be
28
+ recorded.
29
+ - **Store decisions, not chatter.** User preferences, decisions made, constraints,
30
+ requirements — things worth knowing next week. Not "the build passed".
31
+ - **`forget` is a soft delete.** The content stays retrievable by id but is excluded
32
+ from future searches. Use it when something is wrong or outdated, rather than
33
+ adding a contradicting memory on top.
34
+ - **Never store a secret.** Memory is retrievable and displayable.