@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/AGENTS.md +177 -0
- package/LICENSE +21 -0
- package/README.md +178 -0
- package/dist/index.js +5110 -0
- package/package.json +61 -0
- package/skills/workser/SKILL.md +231 -0
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.
|