@workser/cli 0.1.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/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@workser/cli",
3
+ "version": "0.1.0",
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
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "workser": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "skills",
13
+ "AGENTS.md",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "engines": {
18
+ "node": ">=20"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/workser-ai/workser-cli.git"
23
+ },
24
+ "homepage": "https://docs.workser.ai/developers/cli",
25
+ "bugs": {
26
+ "url": "https://github.com/workser-ai/workser-cli/issues"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "dev": "tsup --watch",
34
+ "typecheck": "tsc --noEmit",
35
+ "lint": "eslint \"src/**/*.ts\"",
36
+ "format": "prettier --write \"src/**/*.ts\"",
37
+ "start": "node dist/index.js",
38
+ "test": "npm run build && vitest run",
39
+ "prepublishOnly": "npm run typecheck && npm run test"
40
+ },
41
+ "dependencies": {
42
+ "commander": "^14.0.0",
43
+ "picocolors": "^1.1.1"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^22.10.0",
47
+ "tsup": "^8.3.0",
48
+ "typescript": "^5.9.0",
49
+ "vitest": "^2.1.9"
50
+ },
51
+ "keywords": [
52
+ "workser",
53
+ "ai-agent",
54
+ "devops",
55
+ "deploy",
56
+ "cli",
57
+ "mcp",
58
+ "claude-code",
59
+ "codex"
60
+ ]
61
+ }
@@ -0,0 +1,231 @@
1
+ ---
2
+ name: workser
3
+ description: Provision, deploy, and operate the current Workser app. Use when the user wants to provision or browse the Neon Postgres database, deploy, set env vars, manage files in the bucket, provision auth, or check deploy status/logs for the project linked to this directory. Runs the `workser` CLI.
4
+ ---
5
+
6
+ # Workser — ship & run the current app from the terminal
7
+
8
+ You have the `workser` CLI. It lets you act as the user's DevOps engineer for the
9
+ **one project** Workser Orbit has linked to this directory: provision and browse its
10
+ Neon Postgres database, deploy it, manage its env vars and bucket, provision auth,
11
+ and read its logs — **on the user's own account**, through the Workser Orbit app
12
+ (which handles auth and shows the user what you're doing).
13
+
14
+ ## Scope (read this)
15
+ You operate on **one project's own infrastructure**. You *can* provision and use it:
16
+ create the Neon database, read its connection string, browse its tables / rows / run
17
+ SQL, provision the bucket + auth, deploy, set env vars, manage files. Sensitive
18
+ actions are **gated** — the daemon may return `error.code = "awaiting_approval"`
19
+ (exit 5) and wait for the user to approve in Orbit; ask them to approve, then retry.
20
+
21
+ What you **cannot** do is administer the project set or destroy config: creating or
22
+ switching which project is pinned, deleting env vars, or attaching a custom domain.
23
+ Those return `error.code = "owner_only"` (exit 6) — tell the user it's an owner
24
+ action to do in Orbit, then continue with what you can do. The project is already
25
+ selected; you don't pick or switch it.
26
+
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.
35
+
36
+ ## Golden rules
37
+ 1. **Always pass `--json`.** Output is then a single stable line:
38
+ `{"ok":true,"data":...}` or `{"ok":false,"error":{"code","message",...}}`. Parse it.
39
+ 2. **Orient first.** Run `workser status --json` to see the connection, the pinned
40
+ 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).
46
+ 4. **Approvals are normal.** Some allowed actions may return
47
+ `{"error":{"code":"awaiting_approval"}}` (exit 5) while the user approves in the
48
+ Orbit UI. Tell the user to approve, then retry — do **not** try to bypass it.
49
+ 5. **Never ask for or store credentials.** Auth is handled by Orbit; you never see keys.
50
+ 6. **Verify before "done".** Before telling the user a task is complete, run
51
+ `workser verify --json` (runs the project's typecheck/lint/build). If it
52
+ reports `"ok": false`, fix the errors it lists and re-run until it passes —
53
+ a green build is the bar for "done", not your own judgement.
54
+ 7. **Destructive shell actions are blocked.** Irreversible commands (`rm -rf /`,
55
+ `git reset --hard`, `DROP`/`TRUNCATE`, `curl | sh`, …) are refused by Workser's
56
+ safety policy — don't attempt them; use migrations + scoped changes instead.
57
+
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
+ ## Typical flow: build → ship
210
+ ```bash
211
+ workser status --json # 1. orient (project is already pinned)
212
+ workser db create --json # 2. provision infra the app needs (idempotent)
213
+ workser env set STRIPE_KEY=sk_live_… --json # 3. configure it
214
+ # … you write the app code with your normal tools …
215
+ workser deploy --prod --watch --json # 4. ship; returns the live URL
216
+ ```
217
+ Provisioning the pinned project's own database / bucket / auth is yours to do
218
+ (`db create`, `storage create`, `auth enable`) — the user may need to approve it in
219
+ Orbit (`awaiting_approval`). Only a **custom domain** is an owner action.
220
+
221
+ ## Reading results
222
+ - Success: use `.data` (e.g. `.data.url` after deploy, `.data` array after `list`).
223
+ - Failure: check `.error.code`:
224
+ - `not_connected` → tell the user to open Workser Orbit (or `workser login` for CI).
225
+ - `unauthorized` → user needs to authenticate.
226
+ - `no_project` → no project is linked here; the user links it in Orbit.
227
+ - `owner_only` → an owner action; tell the user to do it in Orbit, then continue.
228
+ - `awaiting_approval` → user must approve in Orbit; then retry.
229
+
230
+ Keep the user informed in plain language ("Provisioned a database and deployed —
231
+ it's live at <url>"), not raw JSON.