@nuucognition/ops-cli 0.1.0-dev.2 → 0.1.0-dev.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +353 -100
- package/bin/ops-prod.js +2 -2
- package/dist/.build-stamp.json +1 -1
- package/dist/index.js +4218 -1860
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ org
|
|
|
39
39
|
├── section (role backlog) the backlog of the project
|
|
40
40
|
├── section a list of tasks with no deliverable yet
|
|
41
41
|
├── deliverable done when a person marks it done
|
|
42
|
-
│ └── section ─ task ─ subtask
|
|
42
|
+
│ └── section ─ task ─ subtask (one level: a subtask has no subtasks)
|
|
43
43
|
└── deployment (live, paused, retired; a free version label)
|
|
44
44
|
└── section (role inbox) the tasks that come up while it runs
|
|
45
45
|
section (role backlog) of the org the master backlog
|
|
@@ -52,8 +52,9 @@ section (role backlog) of the org the master backlog
|
|
|
52
52
|
- **No closer and no "Delivered" task.** `ops deliverable done|reopen`.
|
|
53
53
|
- **The backlog is a section** (role `backlog`). The backlog folders of
|
|
54
54
|
before the revamp became sections (Main became the backlog, Queue a section
|
|
55
|
-
with the role `queue`). `ops folder`
|
|
56
|
-
- **Subtasks** are full tasks with a parent.
|
|
55
|
+
with the role `queue`). The hidden `ops folder` group is gone (0.1.0-dev.3).
|
|
56
|
+
- **Subtasks** are full tasks with a parent. They have one level: a subtask
|
|
57
|
+
has no subtasks (`subtask_too_deep`). A list shows root tasks with a
|
|
57
58
|
count (`1/3 subtasks`). A move takes the subtree. A delete of a task with
|
|
58
59
|
subtasks needs `--with-subtasks`.
|
|
59
60
|
- **Deployments are abstract.** A live deployment has an **inbox**. Inbox
|
|
@@ -126,11 +127,48 @@ links both bins (`ops` → `bin/ops-prod.js`, `ops-dev` → `bin/ops.js`). Do no
|
|
|
126
127
|
expect `ops-dev` on PATH outside the monorepo. The published package has only
|
|
127
128
|
`ops`.
|
|
128
129
|
|
|
130
|
+
### Update: `ops update`
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
ops update --check # is a newer ops available? It installs and builds nothing
|
|
134
|
+
ops update # get the newer ops
|
|
135
|
+
ops update --check --json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`ops update` finds how ops is installed:
|
|
139
|
+
|
|
140
|
+
- **An npm install** reads the dist-tags of `@nuucognition/ops-cli` (the
|
|
141
|
+
registry of `npm_config_registry`, else registry.npmjs.org). The newest
|
|
142
|
+
release is `latest`, and also `next` when this install is a prerelease.
|
|
143
|
+
When it is newer, `ops update` runs `npm install -g @nuucognition/ops-cli@<version>`.
|
|
144
|
+
- **A build of a checkout** (ndv) compares the bundle (`dist`, or `dist-dev`
|
|
145
|
+
for `ops-dev`) with the source of the checkout. When the source is newer,
|
|
146
|
+
`ops update` runs `ndv build ops prod` (or `ndv build ops`). It does not
|
|
147
|
+
pull the checkout.
|
|
148
|
+
|
|
149
|
+
**The update notice.** An npm install checks the registry at most once a
|
|
150
|
+
day, in a background process, so a command never waits for the network.
|
|
151
|
+
When a newer release is available, a command that exits 0 shows one line on
|
|
152
|
+
stderr, at most once a day:
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
ops 0.1.0-dev.4 is available (this machine has 0.1.0-dev.3). Next: ops update
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The notice is only for a person at a terminal. It does not show in a pipe,
|
|
159
|
+
with `--json`, in CI, in an Orbh session, or in a test. To turn it off, set
|
|
160
|
+
`OPS_NO_UPDATE_CHECK=1`. The state file is in the cache folder of the system
|
|
161
|
+
(`~/Library/Caches/nuucognition/ops/` on macOS). A build of a checkout gets
|
|
162
|
+
no notice from the registry: its launcher warns when the bundle is older
|
|
163
|
+
than the source (`Next: ops update`).
|
|
164
|
+
|
|
129
165
|
### Before the first write: which build and which data
|
|
130
166
|
|
|
131
167
|
**The `ops` on PATH can be the prod build.** A prod build always uses prod
|
|
132
168
|
data and ignores `OPS_DATA_MODE`: `OPS_DATA_MODE=dev ops task create …` with a
|
|
133
|
-
prod build **writes to prod data**.
|
|
169
|
+
prod build **writes to prod data**. **A dev build also uses PROD data by
|
|
170
|
+
default** (Task 415): set `OPS_DATA_MODE=dev` for dev data. So, before the
|
|
171
|
+
first write:
|
|
134
172
|
|
|
135
173
|
1. Run `ops mode` and read two lines: `build mode` (`prod` or `dev`) and
|
|
136
174
|
`data mode`. Write only when the data mode is the data that the work needs.
|
|
@@ -158,14 +196,14 @@ turns the check off.
|
|
|
158
196
|
|
|
159
197
|
## Modes
|
|
160
198
|
|
|
161
|
-
|
|
162
|
-
|
|
199
|
+
There are two modes. The build mode says which code runs. The data mode says
|
|
200
|
+
which deployment and which credential that code uses:
|
|
163
201
|
|
|
164
202
|
| | Build mode | Data mode |
|
|
165
203
|
|---|---|---|
|
|
166
204
|
| Says | which code runs | which deployment and which credential |
|
|
167
205
|
| Prod build (`bin/ops-prod.js`, `dist/`) | prod | always prod |
|
|
168
|
-
| Dev build (`bin/ops.js`, `dist-dev/`, source) | dev |
|
|
206
|
+
| Dev build (`bin/ops.js`, `dist-dev/`, source) | dev | prod by default, as `nuu` (Task 415) |
|
|
169
207
|
|
|
170
208
|
| Data mode | Gateway site | Credential | Web links |
|
|
171
209
|
|---|---|---|---|
|
|
@@ -174,18 +212,28 @@ together:
|
|
|
174
212
|
|
|
175
213
|
A dev build reads its data mode in this order:
|
|
176
214
|
|
|
177
|
-
1. `OPS_DATA_MODE=dev|prod` (one run
|
|
178
|
-
2.
|
|
179
|
-
3. `dev
|
|
215
|
+
1. `OPS_DATA_MODE=dev|prod` (ops only, one run).
|
|
216
|
+
2. A test run (`node --test`, Vitest): dev. A suite never uses prod data.
|
|
217
|
+
3. `NUU_DATA_MODE=dev|prod` (the variable of cli-core, one run).
|
|
218
|
+
4. `~/.nuucognition/dev-data.json`, the shared file of cli-core (Task 1051).
|
|
219
|
+
`ops mode dev|prod` and `flint env use dev|prod` write it, so the dev
|
|
220
|
+
builds of ops and flint use the same data.
|
|
221
|
+
5. `prod`: with no choice, a dev build uses the sign-in of `nuu login`.
|
|
222
|
+
|
|
223
|
+
A prod build reads neither the variables nor the file. A value that is not
|
|
224
|
+
`dev` or `prod` is not a choice. Before Task 415 the dev build read
|
|
225
|
+
`~/.nuucognition/ops-dev-data.json` and used dev data by default. No build
|
|
226
|
+
reads that file now, and `ops mode` says so when it is still on disk.
|
|
180
227
|
|
|
181
|
-
A
|
|
182
|
-
|
|
228
|
+
A dev build on prod data writes one note on stderr before each command
|
|
229
|
+
(`note: this dev build uses PROD data …`; no note with `--json`, and none for
|
|
230
|
+
`ops mode`). Each write of such a run is a real write that people see.
|
|
183
231
|
|
|
184
232
|
```bash
|
|
185
|
-
ops mode # build mode, data mode, site, credential file
|
|
186
|
-
ops mode
|
|
187
|
-
ops mode
|
|
188
|
-
OPS_DATA_MODE=
|
|
233
|
+
ops mode # build mode, data mode and its source, site, credential file
|
|
234
|
+
ops mode dev # dev build only: dev data from now on (the shared file)
|
|
235
|
+
ops mode prod # dev build only: back to prod data
|
|
236
|
+
OPS_DATA_MODE=dev node apps/cli-ops/bin/ops.js whoami # the dev launcher, dev data, this run only
|
|
189
237
|
```
|
|
190
238
|
|
|
191
239
|
## Auth
|
|
@@ -200,7 +248,10 @@ or `$NUU_HOME`):
|
|
|
200
248
|
| dev | `~/.nuucognition/auth.local.json` | `http://localhost:3000` | a dev login, or `ops login` of a dev build in dev data |
|
|
201
249
|
|
|
202
250
|
So a machine that ran `nuu login` or `flint login` needs no other step for
|
|
203
|
-
the
|
|
251
|
+
`ops`: the prod build, and a dev build with no choice of data mode, use
|
|
252
|
+
`auth.json`. Each Ops deployment trusts one CLI issuer (`NUU_CLI_ISSUER`):
|
|
253
|
+
the dev deployment trusts only the local account service, so dev data needs
|
|
254
|
+
its own sign-in. The code is
|
|
204
255
|
`requireValidAuth(resolveEnv("ops", { mode: dataMode() }))` of cli-core.
|
|
205
256
|
`ops login` runs the browser sign-in of cli-core (the same flow as
|
|
206
257
|
`flint login`) and writes the credential file of the current data mode.
|
|
@@ -211,14 +262,15 @@ token.
|
|
|
211
262
|
|
|
212
263
|
```bash
|
|
213
264
|
ops login # browser sign-in for the current data mode (a person only)
|
|
214
|
-
ops whoami # user, email, data mode, active org
|
|
265
|
+
ops whoami # user, email, sign-in (for example "device login; does not expire"), data mode, active org
|
|
215
266
|
ops mode # the credential file and who is signed in
|
|
216
267
|
```
|
|
217
268
|
|
|
218
269
|
When the credential is missing or does not refresh, a command fails with
|
|
219
|
-
`error auth_required:
|
|
220
|
-
agent cannot sign in
|
|
221
|
-
`ops login`).
|
|
270
|
+
`error auth_required: Not signed in for <mode> data.` and exit code 3. An
|
|
271
|
+
agent cannot sign in. On prod data the hint asks the operator for
|
|
272
|
+
`nuu login` (or `ops login`). On dev data it asks for `ops login` of the dev
|
|
273
|
+
build (the local account service), and names the way back to prod data.
|
|
222
274
|
|
|
223
275
|
## Orgs
|
|
224
276
|
|
|
@@ -239,7 +291,7 @@ A record argument takes any of these forms:
|
|
|
239
291
|
|---|---|---|
|
|
240
292
|
| Convex ID | `k57b2m4x9q8r7t6y5u4i3o2p1a0s9d8f` | `agent.resolve` (kind, org, title, breadcrumb) |
|
|
241
293
|
| Web URL | `https://ops.nuucognition.com/me/tasks/<t>`, `…/projects/<p>/deliverables/<d>?task=<t>` | the ID in the path or query, then `agent.resolve` |
|
|
242
|
-
| Ops address | `@v1/acme/task/<id>#ops`, `@v1/acme/
|
|
294
|
+
| Ops address | `@v1/acme/task/<id>#ops`, `@v1/acme/section/<id>#ops`, `@v1/acme/deployment/<id>#ops`, `@v1/acme/project/alpha#ops`, `@v1/acme/project/alpha/deliverable/v1#ops`, `@v1/acme/taskgroup/<id>#ops`, `@v1/acme/notepad/<id>#ops` | `agent.resolve` (the object that the address names now); an old task address with the type word `task.dev` (`@v1/acme/task.dev/<id>#ops`, in old Flint task notes) names the same task; other text that starts with `@` is a title |
|
|
243
295
|
| Title | `"Write the docs"` | `agent.searchTasks` for tasks; the headers of the org (`headers.forOrg`) for projects, deliverables, sections, and deployments; the list queries for the other kinds |
|
|
244
296
|
| Path | `"Alpha › v1 › Backend"`, `"Alpha > v1"`, `"Alpha / Backlog"` | the path of a place in the headers (`›`, `>`, and `/` are the same separator) |
|
|
245
297
|
|
|
@@ -256,13 +308,14 @@ An ID, URL, or address never needs a scope.
|
|
|
256
308
|
|
|
257
309
|
`agent.resolve` reads each kind of record: a project, a deliverable, a
|
|
258
310
|
section, a task, a task group, a backlog folder, a plan, a step, a deadline,
|
|
259
|
-
a
|
|
311
|
+
a deployment, a blocker, and a notepad (a blocker and a notepad
|
|
260
312
|
from fleet ops-cli-publish-1023; a deleted notepad, and a personal notepad of
|
|
261
313
|
another person, are not found). Five kinds have an address row: a project, a
|
|
262
314
|
deliverable, a task, a task group, and a notepad (the display address is the
|
|
263
|
-
alias, else the id form). A section and a
|
|
264
|
-
|
|
265
|
-
|
|
315
|
+
alias, else the id form). A section, a deployment, and a blocker have the id
|
|
316
|
+
form only (a blocker: `@v1/<org>/blocker/<id>#ops`, R32 of ADDRESS.md; a
|
|
317
|
+
backend of before it gives none). A plan, a step, and a deadline have no
|
|
318
|
+
address: use the ID. `ops address <record>` prints the address of a record, and the
|
|
266
319
|
record that an address names now.
|
|
267
320
|
|
|
268
321
|
### Places (`--to` of `task move`)
|
|
@@ -271,7 +324,7 @@ record that an address names now.
|
|
|
271
324
|
|---|---|
|
|
272
325
|
| `section:<ref>` | the section |
|
|
273
326
|
| `project:<ref>` | the backlog section of the project (made on first need) |
|
|
274
|
-
| `deliverable:<ref>` | the
|
|
327
|
+
| `deliverable:<ref>` | the main section of the deliverable (role `main`, with the name of the deliverable; made when none, Task 406) |
|
|
275
328
|
| `deployment:<ref>` | the inbox section of the deployment |
|
|
276
329
|
| `parent:<task>` (or `task:<task>`) | under the task, as a subtask |
|
|
277
330
|
| `backlog` | the backlog section of the project of the task |
|
|
@@ -283,7 +336,8 @@ record that an address names now.
|
|
|
283
336
|
A **link spec** (deadline links, step links, title links, blocker links) is
|
|
284
337
|
`kind:ref`, a URL, an address, or an ID: `task:"Write docs"`, `step:<id>`,
|
|
285
338
|
`project:Alpha`, `https://…/plans/<id>`, `@v1/acme/task/<id>#ops`. A title
|
|
286
|
-
needs the kind prefix.
|
|
339
|
+
needs the kind prefix. Only a blocker link can be a deployment
|
|
340
|
+
(`deployment:acme.com`).
|
|
287
341
|
|
|
288
342
|
## Output and errors
|
|
289
343
|
|
|
@@ -310,12 +364,17 @@ Gateway codes pass through: `unauthenticated`, `org_unauthorized`,
|
|
|
310
364
|
`reorder_anchor_outside`, `position_unknown`, `confirm_required`,
|
|
311
365
|
`place_ambiguous`, `place_not_found`, `deployment_no_inbox`. Codes of the
|
|
312
366
|
revamp from the service: `task_has_subtasks` (a delete needs
|
|
313
|
-
`--with-subtasks`), `subtask_too_deep` (
|
|
367
|
+
`--with-subtasks`), `subtask_too_deep` (one level: a subtask has no
|
|
368
|
+
subtasks), `subtask_cycle`. The share refusals keep their codes:
|
|
369
|
+
`not-reachable`, `same-org`, `personal-target`, `org-unknown`,
|
|
370
|
+
`self-target`, `person-unknown`. A hold refuses a write with `held`.
|
|
314
371
|
|
|
315
372
|
An op that a deployment of Ops does not have yet fails with
|
|
316
|
-
`agent_unknown_operation` and names the deploy.
|
|
317
|
-
|
|
318
|
-
|
|
373
|
+
`agent_unknown_operation` and names the deploy. The CLI needs a deployment
|
|
374
|
+
with the current ops: since 0.1.0-dev.3 it has no fallback to the former ops
|
|
375
|
+
of before the revamp (a move through `tasks.place`, a close through
|
|
376
|
+
`tasks.update`, the section writes of `subsections.*`, the old project
|
|
377
|
+
snapshot).
|
|
319
378
|
|
|
320
379
|
The guards exit 2: `confirm_required` (a delete that removes other records
|
|
321
380
|
or cannot be undone needs `--yes`: project, deliverable, section, deployment, plan, blocker),
|
|
@@ -337,6 +396,7 @@ reads stdin.
|
|
|
337
396
|
| `ops login [--verbose]` | `ops login` |
|
|
338
397
|
| `ops whoami` | `ops whoami --json` |
|
|
339
398
|
| `ops mode [dev\|prod]` | `ops mode prod` |
|
|
399
|
+
| `ops update [--check]` — get the newer ops: an npm install gets the newest npm release, a build of a checkout is built again (see Update) | `ops update --check` |
|
|
340
400
|
| `ops ops [--area <area\|module>]` — the gateway manifest (no credential needed); `--area` matches the manifest area (`history`) or the op module (`waybill`) | `ops ops --area waybill` |
|
|
341
401
|
| `ops call <op> [json\|-] [--query\|--mutation\|--action] [--inject-org]` — any allowlisted op; always prints JSON; the manifest gives the kind (`--action` is for `route.suggest`) | `ops call plans.listLite '{}' --inject-org` |
|
|
342
402
|
|
|
@@ -347,7 +407,8 @@ reads stdin.
|
|
|
347
407
|
| `ops headers [--project <p>] [--archived]` — the map of the org (`headers.forOrg`): each project, its sections, its deliverables and their sections, its deployments and their sections, then the sections and deployments of the org; each with its id, role, done mark, and address | `ops headers --project Alpha` |
|
|
348
408
|
| `ops route <text> [--want task\|idea\|any] [--no-smart] [--limit 1-8]` — the route decision: `route.suggest` (an action: Jev with a limit of 1.5 s, else the text match), or with `--no-smart` the query twin `route.candidates`; each line: the score, the `kind:<id>` form, the path, the reason, and the address; `--json`: `{orgSlug, op, model, latencyMs, intent, candidates[]}`, where `op` is the op that answered (`route.suggest` or `route.candidates`) and each candidate has `place {kind, id, title, path}`, `score`, `confidence` (the confidence of the decision model, when it gave one), `reason`, and `address`. **A score below 0.3, or a reason that is only "A recent project", means that no place fits**: name a place, or make one (see the skill `create_task` of the Ops shard) | `ops route "Fix the login bug on Safari"` |
|
|
349
409
|
| `ops search <text> [--type task,section,deliverable,project,deployment] [--include-done] [--limit 1-50]` — `opsSearch.search`: tasks and places in one list, each with its path and address | `ops search billing --type section,deliverable` |
|
|
350
|
-
| `ops address <record> [--kind project\|deliverable\|section\|task\|deployment\|taskgroup\|notepad\|plan\|step\|deadline\|blocker]` — the address of a record: `addresses.of` gives the display address, the id address, the `nuu://ops/<type>/<id>` URI, and `canRename` (the owner rights) of a project, a deliverable, a task, a task group, or a notepad; a section and a deployment have the id form (from the headers); the other kinds print `none`. For an address, `addresses.find` sets `moved` when the text is an old alias or an old form. A title needs `--kind`; `--json`: `{kind, id, orgSlug, title, address, idAddress, uri, canRename, moved}` | `ops address @v1/acme/project/alpha#ops` |
|
|
410
|
+
| `ops address <record> [--kind project\|deliverable\|section\|task\|deployment\|taskgroup\|notepad\|plan\|step\|deadline\|blocker]` — the address of a record: `addresses.of` gives the display address, the id address, the `nuu://ops/<type>/<id>` URI, and `canRename` (the owner rights) of a project, a deliverable, a task, a task group, or a notepad; a section and a deployment have the id form (from the headers), and a blocker has the id form (from `blockers.get`); the other kinds print `none`. For an address, `addresses.find` sets `moved` when the text is an old alias or an old form. A title needs `--kind`; `--json`: `{kind, id, orgSlug, title, address, idAddress, uri, canRename, moved}` | `ops address @v1/acme/project/alpha#ops` |
|
|
411
|
+
| `ops address rename <record> (<name> \| --clear) [--kind …]` — `addresses.rename`: set the alias of the address of a project, a deliverable, a task, a task group, or a notepad (the owner rights are needed); `--clear` removes the alias, and the id address stays; the previous address still names the record (a moved address); a refusal keeps its code (for example a taken name); another kind is `address_not_renamable`; `--json`: `{kind, id, orgSlug, address, previous}` | `ops address rename <projectId> billing-v2` |
|
|
351
412
|
| `ops people search <text> [--limit 1-50]` and `ops people show <@handle\|email\|user_…>` — `people.search`, `people.getByHandle`, `people.getByEmail`, and `people.get` in the scope of the active org: the name, the handle, the email, and the Clerk user id of each person that the caller can see (the personal workspace shows only the caller); none is `person_not_found`. `ops member list` gives the `users` rows (the owners and assignees of tasks) | `ops people search ada` |
|
|
352
413
|
|
|
353
414
|
### org, member
|
|
@@ -364,7 +425,7 @@ reads stdin.
|
|
|
364
425
|
| Command | Example |
|
|
365
426
|
|---|---|
|
|
366
427
|
| `ops project list [--status active\|paused\|archived\|all]` — each with its address | `ops project list --status active` |
|
|
367
|
-
| `ops project show <project>` — its sections (the backlog first), its deliverables and deployments with their sections, and the root tasks, each with its address
|
|
428
|
+
| `ops project show <project>` — its sections (the backlog first), its deliverables and deployments with their sections, and the root tasks, each with its address | `ops project show Alpha` |
|
|
368
429
|
| `ops project create <name> [--description] [--kind project\|operation] [--start] [--end] [--next-update] [--context <md>] [--deployment <d>]` — `--deployment` is the deployment that the project ships to (`originDeploymentId`, a link: the two records stay independent) | `ops project create "Alpha" --next-update +7d` |
|
|
369
430
|
| `ops project update <project> [--name] [--description] [--next-update <date\|none>] [--status] [--kind] [--start <date\|none>] [--end <date\|none>] [--deployment <d\|none>]` | `ops project update Alpha --status paused` |
|
|
370
431
|
| `ops project link <project> <uri...>` / `ops project unlink <project> <uri>` — the linked things of a project: NUU Connect URIs (`nuu://<app>/<type>/<id>`) of other NUU apps (`projectLinks.link`, `projectLinks.unlink`); each URI is stored once, at most 50; a bad URI refuses with `connect_bad_request`; `--json` gives `{id,connectRefs}` | `ops project link Alpha nuu://chat/thread/abc` |
|
|
@@ -381,6 +442,7 @@ reads stdin.
|
|
|
381
442
|
| `ops deliverable create <title> --project <project> [--due <date>] [--section <title>] [--deployment <d>] [--context <md>]` — no closer and no task; `--section` adds a first section | `ops deliverable create "v1 launch" --project Alpha --section Backend` |
|
|
382
443
|
| `ops deliverable update <deliverable> [--title] [--deployment <d\|none>] [--from-deployment <d\|none>]` — `deliverables.setDeployment` | `ops deliverable update "v1.1" --deployment Production` |
|
|
383
444
|
| `ops deliverable done <deliverable>` / `ops deliverable reopen <deliverable>` — `deliverables.setDone`: a person decides; the sections do not | `ops deliverable done "Alpha › v1 launch"` |
|
|
445
|
+
| `ops deliverable move <deliverable> --to <project> [--project <p>]` — `deliverables.move`: the deliverable goes to another project with its sections and tasks, and its address moves too; the links to a deployment of the old project are removed, and the text says how many | `ops deliverable move "v1 launch" --to Beta` |
|
|
384
446
|
| `ops deliverable rename <deliverable> <title>` | `ops deliverable rename "v1 launch" "v1.0 launch"` |
|
|
385
447
|
| `ops deliverable context show\|set <deliverable> …` — `deliverables.setContext` | `ops deliverable context set "v1 launch" "The first public release"` |
|
|
386
448
|
| `ops deliverable delete <deliverable> --yes` — deletes its sections and tasks; refuses without `--yes`; only an owner or an admin of the org can delete it (an org member gets `owner-only`) | `ops deliverable delete "v1.0 launch" --yes` |
|
|
@@ -400,8 +462,8 @@ reads stdin.
|
|
|
400
462
|
| `ops section move <section> --to <project:<p>\|deliverable:<d>\|deployment:<d>\|org>` — `sections.moveHome`; the tasks go with it; a section with a role does not move | `ops section move Ideas --to deliverable:"Alpha › v2"` |
|
|
401
463
|
| `ops section reorder <section> (--before <s>\|--after <s>\|--top\|--bottom)` — inside its home (`sections.reorder` takes every section of the home) | `ops section reorder Backend --top` |
|
|
402
464
|
| `ops section deps set\|add\|remove <section> [deps...]` — the sections it comes after | `ops section deps set QA Backend Frontend` |
|
|
403
|
-
| `ops section priority <section> on\|off` | `ops section priority Backend on` |
|
|
404
465
|
| `ops section archive\|unarchive <sections...>` — `sections.archive` | `ops section archive Backend` |
|
|
466
|
+
| `ops section deployment set <section> <deployment>` / `ops section deployment clear <section>` — `subsections.setDeployment`: the deployment that the section ships to (its shipping link, a field of its own, not its home); a name is a deployment of the project of the section or a deployment of the org (no project), and two matches are `deployment_ambiguous` (exit 2) | `ops section deployment set Backend Production` |
|
|
405
467
|
| `ops section context show\|set <section> …` — `sections.update` | `ops section context set Backend "The API and the queue"` |
|
|
406
468
|
| `ops section delete <section> --yes` — deletes its tasks; refuses without `--yes` | `ops section delete Backend --yes` |
|
|
407
469
|
| `ops section to-task <section> [--into <section>]` — an empty section becomes a task | `ops section to-task "Tiny fix"` |
|
|
@@ -410,20 +472,28 @@ reads stdin.
|
|
|
410
472
|
|
|
411
473
|
| Command | Example |
|
|
412
474
|
|---|---|
|
|
413
|
-
| `ops task list [--project \| --deliverable \| --section \| --deployment \| --master \| --mine [--all-orgs]] [--backlog] [--status open\|todo\|doing\|done\|all] [--priority <p\|none>] [--owner <me\|member\|none>] [--
|
|
414
|
-
| `ops task list --all [--
|
|
415
|
-
| `ops task list --unplaced [--
|
|
416
|
-
| `ops task show <task>` — also the address, the parent, the
|
|
475
|
+
| `ops task list [--project \| --deliverable \| --section \| --deployment \| --master \| --mine [--all-orgs]] [--backlog] [--status open\|todo\|doing\|done\|all] [--priority <p\|none>] [--owner <me\|member\|none>] [--limit n]` — root tasks, each with its place and address; `--section` keeps the order of the section and gives the subtask counts (`sections.tasks`); `--deployment` lists the inbox (`deployments.inbox`); default `--status open`; more than one scope flag is a usage error | `ops task list --section "Alpha › v1 › Backend" --status all` |
|
|
476
|
+
| `ops task list --all [--status …] [--limit n]` — every task of the org, placed and unplaced, newest first, as task summaries (address, home label); `--limit` is the total (default 200) | `ops task list --all --status done --json` |
|
|
477
|
+
| `ops task list --unplaced [--status …] [--limit n]` — the tasks with no home; when the tasks need more bytes than one read (`task_read_too_large`), the CLI reads the pages of `tasks.listAllPage`; a page that is not the last and does not move the cursor stops the list (`pagination_stalled`, exit 1, no rows) | `ops task list --unplaced` |
|
|
478
|
+
| `ops task show <task>` — also the address, the parent, the people looped in (a `looped in` line with each name and users ID; `--json`: `loopedIn: [{userId, name}]`, `name` is `null` for a person who is not a member; an empty list when no person is looped in), the subtasks (the tree with the done count; `--json`: `subtasks`), the lineage, the task groups, the related links, and the attachments; when the incoming lineage stops at its byte budget, `--json` has `linksCut: true` and the text says so; a task with a Flint task note gives the lines `note` (the label, else the address) and `note link` (the open link), and `--json` has `note`, `noteLabel`, and `noteUrl` at the top (each `null` when the task has no note); the open review requests (the reviewer, the requester, the age, and the note; `--json`: `reviews: {open, closed}`, from `reviews.forTask`; a deployment without the op gives no `reviews`) | `ops task show @v1/test/task/<id>#ops` |
|
|
417
479
|
| `ops task search <query> [--limit 1-100]` | `ops task search docs --limit 5` |
|
|
418
|
-
| `ops task create <title> [--section <s> \| --project <p> \| --deliverable <d> \| --deployment <d> \| --parent <task> \| --route [text] \| --master \| --unplaced] [--tag feedback\|hotfix\|ongoing\|recurring] [--every day\|week\|month] [--
|
|
480
|
+
| `ops task create <title> [--section <s> \| --project <p> \| --deliverable <d> \| --deployment <d> \| --parent <task> \| --route [text] \| --master \| --unplaced] [--tag feedback\|hotfix\|ongoing\|recurring] [--every day\|week\|month] [--repo <name>] [--note <address> [--note-label <text>]] [--body <md\|-> \| --body-file <path>] [--priority low\|medium\|high\|urgent] [--assign <me\|member>] [--top]` — default: the master backlog, at the end; `--project` is its backlog section, `--deliverable` its main section (role `main`, with the name of the deliverable; the service makes it, Task 406), `--deployment` its inbox, `--parent` a subtask; `--route` asks `route.suggest` with the text (default: the title) and prints the place, the score, and the reason; `--repo` adds a `repo` related link (`taskRelations.add`); the output gives the stored title (a trailing digit of the title is the rarity: "Fix login 1" is stored as "Fix login"), the address, and the section | `ops task create "Login fails on Safari" --deployment Production --tag hotfix` |
|
|
419
481
|
| `ops task update <task> [--title] [--body <md\|-> \| --body-file <path>] [--priority <p\|none>] [--assign <member\|none>] [--rarity <1-7\|none>] [--tag <tag\|none>] [--every day\|week\|month\|none]` — `--tag` and `--every` need `tasks.update` with `tag` and `recurrence` (MODEL; a deployment without them refuses with `agent_invalid_input`) | `ops task update "Write docs" --body-file notes.md` |
|
|
420
482
|
| `ops task start <task>` — doing | `ops task start "Write docs"` |
|
|
421
|
-
| `ops task done <task>` — the same as `close` with
|
|
422
|
-
| `ops task reopen <task>` — doing
|
|
423
|
-
| `ops task move <tasks...> --to <place> [--priority <p\|none>]` — one task: `tasks.move`; more tasks: `tasks.moveMany`; each takes its subtree; the places are in [Places](#places---to-of-task-move); the former `--subsection
|
|
483
|
+
| `ops task done <task>` — the same as `close` with no result | `ops task done "Write docs"` |
|
|
484
|
+
| `ops task reopen <task>` — doing | `ops task reopen "Write docs"` |
|
|
485
|
+
| `ops task move <tasks...> --to <place> [--priority <p\|none>]` — one task: `tasks.move`; more tasks: `tasks.moveMany`; each takes its subtree; the places are in [Places](#places---to-of-task-move); the former `--subsection` and `--backlog` still work, hidden (`--folder` is gone) | `ops task move <a> <b> --to section:"Alpha › v1 › Backend"` |
|
|
424
486
|
| `ops task reorder <task> (--before <t>\|--after <t>\|--top\|--bottom)` | `ops task reorder "Write docs" --after "Draft outline"` |
|
|
425
487
|
| `ops task delete <task> [--with-subtasks]` — the service refuses a task with subtasks without the flag (`task_has_subtasks`) | `ops task delete "Write docs"` |
|
|
426
488
|
| `ops task to-section <task> [--deliverable <d>]` — `to-subsection` is its former name | `ops task to-section "Big item" --deliverable "v1 launch"` |
|
|
489
|
+
| `ops task review request <task> [--to <member>] [--note <md\|->]` — `reviews.request`: ask a person to review the task (see [review](#review)); `--to` takes a member as `--assign` does; with no `--to`, the reviewer is the owner of the task (a task with no owner: you in the personal workspace, `review_no_reviewer` in a team org); a second request to the same reviewer while one is open changes its note, and the text says `again`; the request loops the reviewer into the task (see `ops task loop`), unless the reviewer is the owner; `--json`: `{itemId, id, orgSlug, reviewerUserId, again, note?}` | `ops task review request <task> --to @ana --note "Check the copy"` |
|
|
490
|
+
| `ops task review approve <task> [--note <md\|->] [--keep-open]` — `reviews.resolve` with the verdict `approved` on the open request where you are the reviewer; the task closes, unless `--keep-open`; the note goes to the requester; `--json`: `{itemId, id, orgSlug, verdict, closed, reopened, note?}` | `ops task review approve <task>` |
|
|
491
|
+
| `ops task review changes <task> [--note <md\|->]` — the verdict `changes`: the task stays open, and a done task opens again (`reopened: true`) | `ops task review changes <task> --note "The redirect fails on Safari."` |
|
|
492
|
+
| `ops task review dismiss <task> [--note <md\|->]` — the verdict `dismissed`: the task does not change | `ops task review dismiss <task>` |
|
|
493
|
+
| `ops task review cancel <task> [--to <member>]` — `reviews.cancel`: withdraw the open request that you made; when you asked more than one reviewer, `--to` names the reviewer (else `review_ambiguous`, exit 2, with the reviewers as candidates); `--json`: `{itemId, id, orgSlug, reviewerUserId, cancelled: true}` | `ops task review cancel <task>` |
|
|
494
|
+
| `ops task loop add <task> <person>` — `taskLoops.add`: loop a member of the org into the task; the person follows the task beside its owner, hears every comment on it, and gets a notification; `<person>` takes `me` or a member as `--assign` does; a person in the loop already gives `no change`; a task loops in at most 50 people (`loop_full`); a review request loops in the reviewer, and a mention in a comment loops in the mentioned member; `--json`: `{id, orgSlug, userId, added}` | `ops task loop add <task> @ana` |
|
|
495
|
+
| `ops task holds <task>` — `holds.ofTask`: the hold of a task, a short lease of an actor (an agent session or a person) that takes (`take`) or chairs (`chair`) the task: the holder, since when, until when, and the open requests; a hold whose time has passed is `expired` (`live: false`); a write by another actor on a held task is refused with `held`; `--json`: `{taskId, orgSlug, hold, live}` (`hold` is `null` with no hold) | `ops task holds <taskId>` |
|
|
496
|
+
| `ops task loop remove <task> <person>` — `taskLoops.remove`: take a person out of the loop of the task; a person who is not in it gives `no change`; `--json`: `{id, orgSlug, userId, removed}` | `ops task loop remove <task> @ana` |
|
|
427
497
|
|
|
428
498
|
#### Subtasks and the task map
|
|
429
499
|
|
|
@@ -433,7 +503,8 @@ reads stdin.
|
|
|
433
503
|
| `ops task subtask list <task>` — the subtree with the done count (`subtasks.tree`; cut at 200 tasks) | `ops task subtask list <taskId>` |
|
|
434
504
|
| `ops task subtask move <task> (--under <parent> \| --root) [--index n]` — `subtasks.reparent`; `--root`: a root task in the home of its old root | `ops task subtask move <taskId> --under <parentId>` |
|
|
435
505
|
| `ops task subtask reorder <task> --index n` — its place among its siblings (0 is first) | `ops task subtask reorder <taskId> --index 0` |
|
|
436
|
-
| `ops task subtask
|
|
506
|
+
| `ops task subtask children <task>` — `subtasks.children`: the subtasks as full task rows, in order (at most 200); a share viewer gets the rows that it can read | `ops task subtask children <taskId> --json` |
|
|
507
|
+
| `ops task subtask outdent <task>` — make a subtask a root task again, after its parent. There is no `indent`: subtasks have one level, and a subtask has no subtasks (`subtask_too_deep`) | `ops task subtask outdent <taskId>` |
|
|
437
508
|
| `ops task map <task>` — `taskMap.get`: the root and the subtree, the home (project, deliverable, deployment, section), the task groups with their members, the lineage (split, merged, continues, after, before), the related links, each with its address, and the web page of the map | `ops task map <taskId> --json` |
|
|
438
509
|
|
|
439
510
|
A task order bucket is one section **and** one priority band (before the
|
|
@@ -447,33 +518,28 @@ unplaced task has no order bucket: `ops task reorder` refuses it
|
|
|
447
518
|
|
|
448
519
|
#### The task primitive v0.1 ((Task) 1287 of the NUU Flint)
|
|
449
520
|
|
|
450
|
-
A task has one status (`todo`, `doing`, `done`). A done task
|
|
451
|
-
outcome
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
normal.
|
|
521
|
+
A task has one status (`todo`, `doing`, `done`). A done task can have a
|
|
522
|
+
result. A task has no outcome (removed 2026-11-04): a done task is done.
|
|
523
|
+
The CLI sends no outcome; `--outcome` is an unknown option. A task has no
|
|
524
|
+
type and no stage: each task has the address `@v1/<org>/task/<id>#ops`,
|
|
525
|
+
and a task closes at any time. A write is by an agent when
|
|
526
|
+
`ORBH_SESSION_ID` is set (the CLI sends it as `X-Agent-Session`). A task
|
|
527
|
+
has 0 or 1 home and 0 or more related links. A task with no home is
|
|
528
|
+
**unplaced**, and that is normal.
|
|
459
529
|
|
|
460
530
|
| Command | Example |
|
|
461
531
|
|---|---|
|
|
462
|
-
| `ops task
|
|
463
|
-
| `ops task retype <task> (<type>[@<version>] \| --none) [--type-version <v>]` — `tasks.setType` (amendment 6); a new type takes its active version; the stage and the fields stay only when the new type defines them (the same name and kind); `--none` makes the task untyped; the same type and version changes nothing; a done task refuses with `task_type_done` (reopen it first) | `ops task retype <task> task.dev` |
|
|
464
|
-
| `ops task close <task> [--outcome completed\|dropped\|superseded] [--result <md\|->]` — `tasks.close`; default `completed` | `ops task close <task> --outcome dropped` |
|
|
532
|
+
| `ops task close <task> [--result <md\|->]` — `tasks.close`: the status `done`, with an optional result; `--json`: `{id, checkbox: "done", result?}` | `ops task close <task> --result "The pin works on dev."` |
|
|
465
533
|
| `ops task result <task> <md\|->` — `""` clears it | `ops task result <task> "The pin works on dev."` |
|
|
466
534
|
| `ops task note <task> <address> [--label <text>]` / `ops task note <task> --clear` — `tasks.setNote` ((Task) 1291): the Flint task note holds the content, and Ops keeps its address, `@v1/<org>/task/<note id>#flint/<flint>` (`flint resolve @v1//task/<n> --json` gives it); a new address with no `--label` clears the label; `--json` gives `{taskId, address, note, noteLabel, noteUrl}`; `noteUrl` is `obsidian://nuu-flint?address=` and the encoded note address, and the NUU Flint plugin opens it; a wrong address refuses with `task_note_invalid` | `ops task note <task> @v1/nuucognition/task/<uuid>#flint/nuu-flint --label "Task 1291 · NUU Flint"` |
|
|
467
|
-
| `ops task field <task> <name> <value> [--append \| --remove]` — `tasks.setFields`; `""` clears the field; a list field gets the value as its one item; `--append` adds one item, once; `--remove` (amendment 6) deletes each item equal to the value from a list field in one write, so an append of another person at the same time stays (an item that is not in the list is no change); `--append` and `--remove` together are a usage error | `ops task field <task> wipCommits 1a2b3c4 --remove` |
|
|
468
|
-
| `ops task commit <task> <sha> [--repo <name>]` — appends `<sha>` or `<sha> (<repo>)` to `wipCommits` | `ops task commit <task> 1a2b3c4d --repo flint` |
|
|
469
535
|
| `ops task home <task> (--section <s> \| --backlog [--project <p>] [--folder <f>] \| --none)` — `tasks.home`; `--project` and `--folder` imply `--backlog`; `--backlog` alone is the master backlog; `--none` unplaces the task; for a deliverable, a deployment, or a parent, use `ops task move --to` | `ops task home <task> --backlog --project Alpha` |
|
|
470
536
|
| `ops task relate <task> <kind> <ref> [--label <text>]` — kinds: `project`, `deliverable` (an ID, URL, or title), `repo` (a name), `flint` (a Flint id), `address` (a v1 address); a second relate changes only the label | `ops task relate <task> repo main` |
|
|
471
537
|
| `ops task unrelate <task> <kind> <ref>` | `ops task unrelate <task> project Alpha` |
|
|
472
538
|
| `ops task related <kind> <ref>` — `taskRelations.listForRef`: the tasks with a related link to a `project`, a `deliverable` (an ID, URL, or title), a `repo`, a `flint`, or an `address`, as task summaries | `ops task related repo main` |
|
|
473
539
|
| `ops task hints [--flint <id>] [--repo <name>] [--text <text>]` — proposed homes from a Flint, a repository, or a text, best first; each line ends with the flags for `ops task home`; for a text, `ops route` is the decision of the revamp | `ops task hints --text "Fix the login page"` |
|
|
474
|
-
| `ops task split <task> --part <title> [--part <title> ...] [--keep-open]` — the parts get the home
|
|
475
|
-
| `ops task merge <task> <task>... (--into <task> \| --title <title>)` — the open absorbed tasks close
|
|
476
|
-
| `ops task continue <task> [--title <title>]` — default title `<old title> (continued)`; an open old task closes
|
|
540
|
+
| `ops task split <task> --part <title> [--part <title> ...] [--keep-open]` — the parts get the home and the related links; an open old task closes, unless `--keep-open` | `ops task split <task> --part Backend --part Frontend` |
|
|
541
|
+
| `ops task merge <task> <task>... (--into <task> \| --title <title>)` — the open absorbed tasks close | `ops task merge <a> <b> --into <c>` |
|
|
542
|
+
| `ops task continue <task> [--title <title>]` — default title `<old title> (continued)`; an open old task closes | `ops task continue <task>` |
|
|
477
543
|
| `ops task chain <task> <task> [<task>...]` — in order; a task is ready when the task before it is done | `ops task chain <first> <second> <third>` |
|
|
478
544
|
| `ops task unchain <task>` — removes the `after` link of the task | `ops task unchain <task>` |
|
|
479
545
|
| `ops task link <task> <previous>` — `taskLinks.link`: two tasks that exist; `<task>` continues from `<previous>` (kind `continues-from`); a new link replaces the old one; no task closes (`ops task continue` makes a new task) | `ops task link <task> <previous>` |
|
|
@@ -485,10 +551,7 @@ normal.
|
|
|
485
551
|
|
|
486
552
|
`--json` output: `show` gives the C6 detail with `address` at the top
|
|
487
553
|
level, and the present keys (`breadcrumb`, `orgSlug`, `url`). `create`,
|
|
488
|
-
`split`, `merge`, and `continue` give the new ids and their addresses.
|
|
489
|
-
`retype` gives `{taskId, address, type, typeVersion, stage, fields}` after
|
|
490
|
-
the write (`null` for an absent value): the address follows the type
|
|
491
|
-
(`task.dev/<id>` or `task/<id>`), and an old address still resolves. When
|
|
554
|
+
`split`, `merge`, and `continue` give the new ids and their addresses. When
|
|
492
555
|
the read of an address after a write fails, the result keeps the new id with
|
|
493
556
|
`address: null` (exit 0), and stderr names the read to run again: do not run
|
|
494
557
|
the write again.
|
|
@@ -514,13 +577,6 @@ open). The attachments of a group show on each of its tasks.
|
|
|
514
577
|
| `ops task group list [--open]` | `ops task group list --open` |
|
|
515
578
|
| `ops task group delete <group>` — deletes the group and its members, not the tasks | `ops task group delete "Login fixes"` |
|
|
516
579
|
|
|
517
|
-
### task type
|
|
518
|
-
|
|
519
|
-
| Command | Example |
|
|
520
|
-
|---|---|
|
|
521
|
-
| `ops task type list` — the active types | `ops task type list` |
|
|
522
|
-
| `ops task type show <type>[@<version>] [--type-version <v>]` — the fields and the stages; with no version, the latest active version. The program owns `--version` (it prints the version of the CLI anywhere on the line), so a type version is `<type>@<version>` or `--type-version` | `ops task type show task.dev@0.1` |
|
|
523
|
-
|
|
524
580
|
### comment
|
|
525
581
|
|
|
526
582
|
| Command | Example |
|
|
@@ -532,16 +588,16 @@ open). The attachments of a group show on each of its tasks.
|
|
|
532
588
|
| `ops comment react <task> <commentId> <emoji>` | `ops comment react "Write docs" <commentId> 👍` |
|
|
533
589
|
| `ops comment unreact <task> <commentId> <emoji>` | `ops comment unreact "Write docs" <commentId> 👍` |
|
|
534
590
|
| `ops comment count <tasks...>` — the comment count of each task (`updates.counts`, at most 200 tasks, one call for each org); `--json`: `[{taskId, title, count}]` | `ops comment count <taskId> <taskId>` |
|
|
591
|
+
| `ops comment people` — `updates.people`: the people of the active org that a comment can mention, each with its `users` ID, name, handle, and actor ID (`user:<Clerk user ID>`) | `ops comment people --json` |
|
|
535
592
|
|
|
536
593
|
### backlog
|
|
537
594
|
|
|
538
595
|
| Command | Example |
|
|
539
596
|
|---|---|
|
|
540
|
-
| `ops backlog show [--project <p>] [--all]` — the backlog section of the project (or of the org) by priority band, each task with its address
|
|
597
|
+
| `ops backlog show [--project <p>] [--all]` — the backlog section of the project (or of the org) by priority band, each task with its address | `ops backlog show --project Alpha` |
|
|
541
598
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
turns each folder into a section.
|
|
599
|
+
The migration of the revamp turned each backlog folder into a section. The
|
|
600
|
+
hidden `ops folder` group is gone (0.1.0-dev.3).
|
|
545
601
|
|
|
546
602
|
### deadline
|
|
547
603
|
|
|
@@ -567,9 +623,11 @@ turns each folder into a section.
|
|
|
567
623
|
A blocker says why work waits (Task 376 of the NUU Operations Flint): a
|
|
568
624
|
title, who or what the work waits on, the next step, an owner, and one date,
|
|
569
625
|
the next check-up. It links any number of records (project, deliverable,
|
|
570
|
-
section, task, step). It gates no status. A blocker has
|
|
571
|
-
|
|
572
|
-
|
|
626
|
+
section, task, step, deployment). It gates no status. A blocker has the id
|
|
627
|
+
address `@v1/<org>/blocker/<id>#ops` (`ops blocker show` prints it). A
|
|
628
|
+
`<blocker>` argument is an address (it names the org of the blocker), an ID,
|
|
629
|
+
or a title that matches one blocker of the org (two matches fail with
|
|
630
|
+
`blocker_ambiguous`, exit 2, and list the IDs). An
|
|
573
631
|
open blocker is **due** when its check-up date is today or earlier in local
|
|
574
632
|
time. The CLI sends local dates, also the default check-up date (tomorrow),
|
|
575
633
|
as the web app does.
|
|
@@ -580,7 +638,7 @@ as the web app does.
|
|
|
580
638
|
| `ops blocker show <blocker>` — the fields, each link with its path and status (or `broken`), and the log with the actor names | `ops blocker show "No API key"` |
|
|
581
639
|
| `ops blocker create <title> [--check <date>] [--waiting-on <text>] [--next <text>] [--owner <member>] [--on <record>]...` — default check-up: tomorrow; default owner: you; an ID, URL, or address in `--on` names the org of the blocker | `ops blocker create "No API key" --check +3d --on <taskId>` |
|
|
582
640
|
| `ops blocker update <blocker> [--title] [--waiting-on <text\|none>] [--next <text\|none>] [--owner <member\|none>]` | `ops blocker update <blockerId> --next "Call the vendor"` |
|
|
583
|
-
| `ops blocker attach <blocker> <record>` — a record that is attached changes nothing | `ops blocker attach <blockerId> section:"Alpha › v1 › Backend"` |
|
|
641
|
+
| `ops blocker attach <blocker> <record>` — a record that is attached changes nothing; a record is a project, deliverable, section, task, step, or deployment (`deployment:<name>`) | `ops blocker attach <blockerId> section:"Alpha › v1 › Backend"` |
|
|
584
642
|
| `ops blocker detach <blocker> <record>` — the ID of a broken link works too | `ops blocker detach <blockerId> <taskId>` |
|
|
585
643
|
| `ops blocker delay <blocker> <date> [--note <text>]` — a new check-up date (counts as a delay); the same date with a note only logs the note; a closed blocker gives `blocker_closed` | `ops blocker delay <blockerId> +1w --note "Legal needs a week"` |
|
|
586
644
|
| `ops blocker resolve <blocker> [--note <text>]` — the work can go on | `ops blocker resolve <blockerId> --note "The key came"` |
|
|
@@ -596,6 +654,39 @@ Codes from the service: `blocker_not_found`, `blocker_closed`,
|
|
|
596
654
|
on dev data: on a deployment without them, the error says that they are not
|
|
597
655
|
deployed yet.
|
|
598
656
|
|
|
657
|
+
### review
|
|
658
|
+
|
|
659
|
+
The review queue (Task 402 of the NUU Operations Flint). A person or an
|
|
660
|
+
agent asks a person to review a task (`ops task review request`). The
|
|
661
|
+
request goes to the review queue of the reviewer. The request also loops
|
|
662
|
+
the reviewer into the task (`ops task loop`), unless the reviewer is the
|
|
663
|
+
owner. The reviewer approves the work, asks for changes, or dismisses the
|
|
664
|
+
request (`ops task review approve|changes|dismiss`). The requester can
|
|
665
|
+
cancel it (`ops task review cancel`). Your queue also lists the open
|
|
666
|
+
requests that you asked of other people. These verbs take the task, not
|
|
667
|
+
the request: the CLI reads the open requests of the task
|
|
668
|
+
(`reviews.forTask`) and takes the one where you are the reviewer (a
|
|
669
|
+
verdict) or the requester (a cancel). When no request matches, the verb is
|
|
670
|
+
a usage error (exit 2) and writes nothing. A note has at most 2000
|
|
671
|
+
characters; `--note -` reads stdin.
|
|
672
|
+
|
|
673
|
+
| Command | Example |
|
|
674
|
+
|---|---|
|
|
675
|
+
| `ops review list [--org <org>] [--state open\|all]` — `reviews.mine`: your queue; the queue is personal, so with no `--org` it lists every org of yours (the stored default org does not apply); `--org` keeps one org; one line for each open request, oldest first: the age, the task title, the home label (or `unplaced`), the requester, and the task address; when the queue has more than 200 open requests, a line says so; then, when you asked other people for reviews that are still open, the section `you asked for (open, oldest first)` gives one line for each, with the reviewer (`to <name>`) in place of the requester; `--state all` adds the newest closed requests (at most 25) with the verdict, newest first; `--json`: `{open, closed, sent, truncated}` as the service gives it (`sent` is the open requests that you asked of other people; each entry is a request with `task` and `href`; a deployment before `sent` has no field) | `ops review list --state all` |
|
|
676
|
+
|
|
677
|
+
Codes from the service: `review_not_found`, `review_not_open` (the request
|
|
678
|
+
is closed already), `review_not_reviewer` (only the reviewer gives the
|
|
679
|
+
verdict), `review_not_requester` (only the requester cancels; the reviewer
|
|
680
|
+
dismisses), `review_no_reviewer` (a team task with no owner: pass `--to`),
|
|
681
|
+
`review_task_done` (reopen the task first), `review_task_gone`,
|
|
682
|
+
`review_note_too_long`, and `assignee_not_member` (the reviewer). `ops task
|
|
683
|
+
loop add` can refuse with `loop_full` (a task loops in at most 50 people:
|
|
684
|
+
take a person out first), `assignee_not_found`, or `assignee_not_member`
|
|
685
|
+
(the person). The client code `review_ambiguous` is a cancel that matches
|
|
686
|
+
two requests. The ops are new on dev data: on a deployment without them,
|
|
687
|
+
the error says that they are not deployed yet, and `ops task show` gives no
|
|
688
|
+
review requests.
|
|
689
|
+
|
|
599
690
|
### plan
|
|
600
691
|
|
|
601
692
|
| Command | Example |
|
|
@@ -673,6 +764,121 @@ zero-length move writes nothing. A downstream step with no stored position
|
|
|
673
764
|
stays where it is and is reported as `kept` (the UI moves it from a
|
|
674
765
|
fallback layout that the CLI does not compute).
|
|
675
766
|
|
|
767
|
+
### Trident: stream, workspace, and the board verbs of step
|
|
768
|
+
|
|
769
|
+
The Trident board ((Task) 399 of the NUU Operations Flint) has lanes. A
|
|
770
|
+
lane is a **stream**. A stream is a second home for the same step rows as a
|
|
771
|
+
plan, so the `ops step` verbs work on a step of a plan and on a step of a
|
|
772
|
+
stream. Each step has a **zone**: `planned`, `active`, or `done`. A
|
|
773
|
+
**goal** is a planned step on the **shore** (above the planned steps). A
|
|
774
|
+
**parked** step is off the board (in the Parked menu) and keeps its place,
|
|
775
|
+
state, links, and substream. A **substream** is a named box of steps in one
|
|
776
|
+
stream. A **cross-stream link** joins a step to a step of another stream; it
|
|
777
|
+
gates nothing. The **attachments** of a stream are the projects,
|
|
778
|
+
deliverables, and sections whose open tasks show in the side panel of its
|
|
779
|
+
lane. A **workspace** is a named set of streams of one person: no other
|
|
780
|
+
member sees it.
|
|
781
|
+
|
|
782
|
+
References: a stream takes an ID, a Trident URL (`/<org>/trident?stream=<id>`),
|
|
783
|
+
or a title. A step takes an ID, a URL, or an address; a title or a short ID
|
|
784
|
+
needs `--stream <stream>` (or `--plan <plan>` for a step of a plan). A
|
|
785
|
+
substream takes an ID; a title needs `--stream <stream>`. A workspace takes
|
|
786
|
+
an ID or a title. A step title matches the title that the board shows: the
|
|
787
|
+
title of the one linked record of the step, else its own title.
|
|
788
|
+
|
|
789
|
+
These `ops step` verbs take a stream step and `--stream <stream>`:
|
|
790
|
+
`update`, `assign`, `requires set|add|remove`, `links set|add|remove`,
|
|
791
|
+
`delete`, `split`, `split-beside`, `state`, `done-next`, `move-links`,
|
|
792
|
+
`remove-links`, and `place`. Two do not: `ops step add` adds a step to a
|
|
793
|
+
plan only (use `ops stream step add` for a stream), and `ops step move` is
|
|
794
|
+
for the plan canvas only (a stream step refuses with `node_not_in_plan`;
|
|
795
|
+
use `ops step place`).
|
|
796
|
+
|
|
797
|
+
**Recovery.** A removal that an undo takes back (`stream delete`, `stream
|
|
798
|
+
detach`, `stream step cross remove`, `stream substream ungroup`, `stream
|
|
799
|
+
drawing remove`, `step remove-links`) prints an `undo:` line: the guarded
|
|
800
|
+
undo of the gesture that it made (`ops stream undo <id> --expect <seq> --org
|
|
801
|
+
<org>`, or `ops plan undo` for a plan step), with its label and the history
|
|
802
|
+
command to read first. The CLI reads the head of the stack before and after
|
|
803
|
+
the write: when the head did not move, the command made no gesture (for
|
|
804
|
+
example a drawing ID that the lane does not have, or a link that is gone),
|
|
805
|
+
and it prints `no change:` and no undo. `stream history`, `stream undo`, and
|
|
806
|
+
`stream redo` take the ID or the URL of a deleted stream. `workspace delete`
|
|
807
|
+
has no undo: it prints the `workspace create` command (shell-quoted, with
|
|
808
|
+
`--org`) that makes the workspace again. `plan show` and `stream show` print
|
|
809
|
+
the title that a step title matches.
|
|
810
|
+
|
|
811
|
+
| Command | Example |
|
|
812
|
+
|---|---|
|
|
813
|
+
| `ops stream list [--state active\|paused\|done\|all]` | `ops stream list --state active` |
|
|
814
|
+
| `ops stream show <stream>` — the attachments, the substreams, and the steps by zone (shore, planned, active, done, parked); `--json` prints the raw `streams.get` result | `ops stream show Backend` |
|
|
815
|
+
| `ops stream create <title> [--description]` | `ops stream create Backend` |
|
|
816
|
+
| `ops stream update <stream> [--title] [--description] [--state active\|paused\|done]` | `ops stream update Backend --state paused` |
|
|
817
|
+
| `ops stream delete <stream>` — soft: `stream undo` brings the lane back with its steps | `ops stream delete Backend` |
|
|
818
|
+
| `ops stream attach <stream> <places...>` — `project:<ref>`, `deliverable:<ref>`, `section:<ref>`, an ID, or a URL | `ops stream attach Backend section:"Alpha › v1 › Backend"` |
|
|
819
|
+
| `ops stream detach <stream> [places...] [--all]` | `ops stream detach Backend --all` |
|
|
820
|
+
| `ops stream size <stream> [--width <n\|default>] [--shore-height <n\|default>]` — board units | `ops stream size Backend --width 640` |
|
|
821
|
+
| `ops stream history <stream>` — your undo and redo stacks in the scope `stream:<id>`; a deleted stream by its ID or URL | `ops stream history Backend` |
|
|
822
|
+
| `ops stream undo\|redo <stream> (--expect <seq> \| --dry-run)` — the undo safety of `plan undo`; a deleted stream by its ID or URL | `ops stream undo <streamId> --expect 12` |
|
|
823
|
+
| `ops stream step add <stream> <title> [--after <step>]... [--state planned\|active\|done] [--shore] [--description] [--assign <member>]` | `ops stream step add Backend "Ship the API" --shore` |
|
|
824
|
+
| `ops stream step add-task <stream> <task> [--state planned\|active\|done] [--shore]` — a step that follows the task; `--state` moves the task | `ops stream step add-task Backend "Fix login"` |
|
|
825
|
+
| `ops stream step create-task <step> --to section:<ref>\|project:<ref> [--stream]` — `project:` is its backlog; the step then follows the task | `ops stream step create-task <stepId> --to project:Alpha` |
|
|
826
|
+
| `ops stream step move <steps...> --to <stream> [--stream]` — a link to a step that stays becomes a cross-stream link | `ops stream step move <stepId> --to Frontend` |
|
|
827
|
+
| `ops stream step park\|unpark <steps...> [--stream]` | `ops stream step park Build --stream Backend` |
|
|
828
|
+
| `ops stream step shore\|unshore <steps...> [--stream]` — planned steps only | `ops stream step shore <stepId>` |
|
|
829
|
+
| `ops stream step cross set <step> [steps...] [--stream]` — replace the cross-stream links (steps of other streams, by ID); no steps removes them | `ops stream step cross set <stepId>` |
|
|
830
|
+
| `ops stream step cross add\|remove <step> <steps...> [--stream]` — steps of other streams, by ID | `ops stream step cross add <stepId> <otherStepId>` |
|
|
831
|
+
| `ops stream step substream <steps...> --to <substream\|none> [--stream]` | `ops stream step substream <stepId> --to Auth` |
|
|
832
|
+
| `ops stream substream create <stream> <title> [--step <step>]... [--box <x,y,width,height>]` | `ops stream substream create Backend Auth --step <stepId>` |
|
|
833
|
+
| `ops stream substream rename <substream> <title> [--stream]` | `ops stream substream rename Auth Login --stream Backend` |
|
|
834
|
+
| `ops stream substream park\|unpark <substream> [--stream]` — with its steps | `ops stream substream park <substreamId>` |
|
|
835
|
+
| `ops stream substream place <substream> --box <x,y,width,height> [--stream]` | `ops stream substream place <substreamId> --box 0,0,400,240` |
|
|
836
|
+
| `ops stream substream ungroup <substream> [--stream]` — the steps stay, in no substream | `ops stream substream ungroup Auth --stream Backend` |
|
|
837
|
+
| `ops stream drawing list <stream>` | `ops stream drawing list Backend` |
|
|
838
|
+
| `ops stream drawing add <stream> --kind line\|free\|text --points <x1,y1,...> [--text]` — a line has 2 points, a free line 2 to 1000, a text 1 | `ops stream drawing add Backend --kind text --points 40,80 --text "Freeze"` |
|
|
839
|
+
| `ops stream drawing text <stream> <drawing> <text>` — empty text removes it | `ops stream drawing text Backend <drawingId> "Freeze Friday"` |
|
|
840
|
+
| `ops stream drawing move <stream> <drawings...> [--dx] [--dy]` | `ops stream drawing move Backend <drawingId> --dy 40` |
|
|
841
|
+
| `ops stream drawing remove <stream> <drawings...>` | `ops stream drawing remove Backend <drawingId>` |
|
|
842
|
+
| `ops workspace list` — in their order; the first is ⌃1 | `ops workspace list` |
|
|
843
|
+
| `ops workspace show <workspace>` | `ops workspace show "Launch week"` |
|
|
844
|
+
| `ops workspace create [title] [--stream <stream>]...` | `ops workspace create "Launch week" --stream Backend` |
|
|
845
|
+
| `ops workspace update <workspace> --title <title>` | `ops workspace update "Launch week" --title Launch` |
|
|
846
|
+
| `ops workspace streams set <workspace> [streams...]` — replace the streams, in this order; no streams empties it | `ops workspace streams set Launch Backend Design` |
|
|
847
|
+
| `ops workspace streams add\|remove <workspace> <streams...>` | `ops workspace streams add Launch Design` |
|
|
848
|
+
| `ops workspace reorder <workspaces...>` — each of your workspaces once | `ops workspace reorder Launch "Workspace 1"` |
|
|
849
|
+
| `ops workspace delete <workspace>` — the streams stay; no undo (it prints the `workspace create` command); your last workspace refuses (`workspace_last`) | `ops workspace delete Launch` |
|
|
850
|
+
| `ops step split <step> [--before] [--title] [--start] [--shore] [--assign]` — a new step joined to it; default: after it | `ops step split Build --stream Backend --title Review` |
|
|
851
|
+
| `ops step split-beside <step> [--title] [--assign]` — a new step beside it, with all its links and its state | `ops step split-beside <stepId>` |
|
|
852
|
+
| `ops step state <planned\|active\|done> <steps...> [--shore\|--no-shore]` — put back, start, or finish; a step with one task moves the task | `ops step state active <stepId>` |
|
|
853
|
+
| `ops step done-next <step> [--title] [--assign]` — finish it and start the next step, one undo | `ops step done-next <stepId> --title Deploy` |
|
|
854
|
+
| `ops step move-links --link <from>:<to>... --end from\|to --target <step>` — the links meet at one step; one undo | `ops step move-links --link <a>:<b> --end to --target <c>` |
|
|
855
|
+
| `ops step remove-links <from>:<to>...` — one undo | `ops step remove-links Build:Test --stream Backend` |
|
|
856
|
+
| `ops step place <step> --x <x> --y <y>` — the place on the lane, in board units; the server keeps it in the zone of its state | `ops step place <stepId> --x 120 --y 40` |
|
|
857
|
+
|
|
858
|
+
`ops stream show` prints:
|
|
859
|
+
|
|
860
|
+
```
|
|
861
|
+
stream <id> Backend [active] 3 steps
|
|
862
|
+
The API work
|
|
863
|
+
attachments: project:<id> Alpha
|
|
864
|
+
size: width default shore 120 drawings 1
|
|
865
|
+
substreams:
|
|
866
|
+
substream <id> Auth 1 steps
|
|
867
|
+
shore (goals): 1
|
|
868
|
+
step <id> Ship the API short k57b
|
|
869
|
+
planned: 0
|
|
870
|
+
active: 1
|
|
871
|
+
step <id> Build short k57c cross <id> in Auth
|
|
872
|
+
done: 0
|
|
873
|
+
parked: 1
|
|
874
|
+
step <id> Old idea short k57d after k57c is task:<id> Fix login
|
|
875
|
+
https://ops.nuucognition.com/<org>/trident?stream=<id>
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
A deployment without an op of this section answers `agent_unknown_operation`;
|
|
879
|
+
the CLI then says that the op is not deployed there yet and that (Task) 399
|
|
880
|
+
brings it.
|
|
881
|
+
|
|
676
882
|
### notify
|
|
677
883
|
|
|
678
884
|
| Command | Example |
|
|
@@ -684,6 +890,8 @@ fallback layout that the CLI does not compute).
|
|
|
684
890
|
| `ops notify read-all [--this-org]` | `ops notify read-all` |
|
|
685
891
|
| `ops notify dismiss <id>` | `ops notify dismiss <notificationId>` |
|
|
686
892
|
| `ops notify read-key <key>` — mark every notification with one collapse key read (`notifications.markKeyRead`) | `ops notify read-key <key>` |
|
|
893
|
+
| `ops notify read-prefix <prefix>` — mark every notification whose collapse key starts with the prefix read (`notifications.markReadByKeyPrefix`): one thing with many keys, for example `thread:<id>:`; an empty prefix is a usage error | `ops notify read-prefix thread:<id>:` |
|
|
894
|
+
| `ops notify dismiss-all [--this-org]` — dismiss every notification (`notifications.dismissAll`): it deletes them, and there is no undo; only when the operator asks | `ops notify dismiss-all --this-org` |
|
|
687
895
|
| `ops notify prefs list` | `ops notify prefs list` |
|
|
688
896
|
| `ops notify prefs set <category> on\|off [--channel <c>]` — categories: tasks, deadlines, plans, updates | `ops notify prefs set plans off --channel push` |
|
|
689
897
|
|
|
@@ -692,14 +900,14 @@ fallback layout that the CLI does not compute).
|
|
|
692
900
|
| Command | Example |
|
|
693
901
|
|---|---|
|
|
694
902
|
| `ops activity list [--on <id\|url> \| --scope <scope>] [--mine] [--action <a>]... [--text <t>] [--limit n] [--cursor c]` — the Waybill feed of the org, or of one scope | `ops activity list --on <planId> --limit 10` |
|
|
695
|
-
| `ops activity row <record> [--limit n] [--cursor c]` — the Waybill history of one row (`waybill.rowHistory`): each event that changed the record, newest first, with actor names. A record is an ID, an address, or a URL of a project, deliverable, section, task, backlog folder, plan, step, deadline,
|
|
903
|
+
| `ops activity row <record> [--limit n] [--cursor c]` — the Waybill history of one row (`waybill.rowHistory`): each event that changed the record, newest first, with actor names. A record is an ID, an address, or a URL of a project, deliverable, section, task, backlog folder, plan, step, deadline, deployment, task group, blocker, or notepad | `ops activity row <deadlineId> --json` |
|
|
696
904
|
| `ops activity facets [--on <id\|url> \| --scope <scope>] [--limit n]` — the counts of the actors (with names), actions, tables, kinds, and scopes of the newest events (`waybill.facets`); use them as filters of `activity list` | `ops activity facets --on <planId>` |
|
|
697
905
|
|
|
698
906
|
Scopes are `org:<slug>`, `project:<id>`, `deliverable:<id>`,
|
|
699
907
|
`subsection:<id>`, `backlog:<projectId>`, `backlog:org:<slug>`, and
|
|
700
908
|
`plan:<id>`. `org:me` and `backlog:org:me` name the personal workspace.
|
|
701
909
|
`--on` maps a record to its scope (a task to its section or backlog, a
|
|
702
|
-
step to its plan, a deadline
|
|
910
|
+
step to its plan, a deadline or deployment to `org:<slug>`).
|
|
703
911
|
|
|
704
912
|
### history, undo, redo (any scope)
|
|
705
913
|
|
|
@@ -720,21 +928,13 @@ is in `project:<projectId>`.
|
|
|
720
928
|
| `ops favourite list` — your favourites in the active org, in star order (`home.favourites`) | `ops favourite list --json` |
|
|
721
929
|
| `ops favourite add <record> [--kind project\|deliverable\|section]` — star a record; a title needs `--kind`, an ID or URL does not | `ops favourite add <deliverableId>` |
|
|
722
930
|
| `ops favourite remove <record> [--kind]` — remove the star; the ID of a deleted record works too | `ops favourite remove <recordId>` |
|
|
931
|
+
| `ops favourite reorder <records...>` — `home.reorderFavourites`: a new order of your favourites (the order of the Pinned favourites): the given record IDs first, in the given order, then the others; a record that is not a favourite is `favourite_not_found` | `ops favourite reorder <recordId> <recordId>` |
|
|
723
932
|
|
|
724
933
|
A record of another kind gives `wrong_kind`. Both ops are idempotent. More
|
|
725
934
|
than 100 favourites in one org gives `favourites_full`. The ops come from
|
|
726
935
|
(Task) 316: on a deployment without them, the error says that they are not
|
|
727
936
|
deployed yet.
|
|
728
937
|
|
|
729
|
-
### day-label
|
|
730
|
-
|
|
731
|
-
| Command | Example |
|
|
732
|
-
|---|---|
|
|
733
|
-
| `ops day-label list` | `ops day-label list` |
|
|
734
|
-
| `ops day-label create <label> --start <date> [--end <date>] [--color water\|fire\|earth\|air\|sun\|moon\|muted]` | `ops day-label create Offsite --start 2026-10-12 --end 2026-10-14 --color sun` |
|
|
735
|
-
| `ops day-label update <day-label> [--label] [--start] [--end] [--color]` | `ops day-label update Offsite --color moon` |
|
|
736
|
-
| `ops day-label delete <day-label>` | `ops day-label delete Offsite` |
|
|
737
|
-
|
|
738
938
|
### home
|
|
739
939
|
|
|
740
940
|
The homepage reads of the active org. They come from fleet
|
|
@@ -756,13 +956,20 @@ says that they are not deployed yet.
|
|
|
756
956
|
| `ops notepad show <notepad> [--md]` — the blocks, the mentioned tasks, the scope, and the rev | `ops notepad show "Standup notes"` |
|
|
757
957
|
| `ops notepad create <title> [--general] [--body <md\|->] [--section s]` — personal unless `--general` | `ops notepad create Ideas --body - < ideas.md` |
|
|
758
958
|
| `ops notepad rename <notepad> <title>` | `ops notepad rename <notepadId> "Weekly standup"` |
|
|
759
|
-
| `ops notepad
|
|
959
|
+
| `ops notepad section <notepad> (<section> \| none \| --clear)` — link the notepad to one section, or clear the link (`notepads.setSection`); `scope` is its former name | `ops notepad section <notepadId> Backend` |
|
|
760
960
|
| `ops notepad share <notepad> (--general \| --personal)` — share it with the org or make it personal (`notepads.setScope`); only its owner can, and a notepad of the personal workspace stays personal | `ops notepad share <notepadId> --general` |
|
|
761
961
|
| `ops notepad mentions <task>` — the notepads that hold a chip of the task (`notepads.mentioning`) | `ops notepad mentions <taskId>` |
|
|
762
962
|
| `ops notepad append <notepad> [<md\|->] [--task <task>]` | `ops notepad append <notepadId> --task <taskId>` |
|
|
763
963
|
| `ops notepad write <notepad> <md\|-> (--expected-rev n \| --force)` | `ops notepad write <notepadId> - --expected-rev 3 < notes.md` |
|
|
764
964
|
| `ops notepad to-task <notepad> <text> [--section s \| --project p [--folder f] \| --backlog] [--title t] [--keep]` — make a task from a text; a task chip replaces the text | `ops notepad to-task <notepadId> "Plan the demo"` |
|
|
765
965
|
| `ops notepad move-to-task <notepad> <task> <text> [--copy]` — move a text to the end of a task description | `ops notepad move-to-task <notepadId> <taskId> "The budget is 4k."` |
|
|
966
|
+
| `ops notepad block list <notepad>` — the ID and the text of each block, in order, and the rev | `ops notepad block list <notepadId>` |
|
|
967
|
+
| `ops notepad block add <notepad> <text\|-> [--after <block>]` — `notepads.addBlock`: a new text block after a block, or at the top; `--json` gives the new `blockId` | `ops notepad block add <notepadId> "Call Sam" --after <blockId>` |
|
|
968
|
+
| `ops notepad block edit <notepad> <block> <text\|-> [--expect <text>]` — `notepads.updateBlock`: replace the text of one block when its text is still the text that the CLI read (or `--expect`), else `notepad_text_conflict`; an empty text removes the block | `ops notepad block edit <notepadId> <blockId> "Call Sam on Monday"` |
|
|
969
|
+
| `ops notepad block remove <notepad> <block>` — `notepads.removeBlock`; notepad blocks have no Waybill scope, so the text prints the undo: `ops call notepads.setBlocks '<the blocks of before, at the new rev>' --mutation` (it works while the notepad is unchanged); `--json` has `previousBlocks`, `rev`, and `undo` | `ops notepad block remove <notepadId> <blockId>` |
|
|
970
|
+
| `ops notepad block move <notepad> <block> (--after <block> \| --top)` — `notepads.moveBlock` | `ops notepad block move <notepadId> <blockId> --top` |
|
|
971
|
+
| `ops notepad make-task <notepad> <text\|-> [--title t]` — `notepads.makeTask`: a task from a line (the first line is the title), in the section of the notepad, else the backlog of the org; the notepad text does not change; the text prints the undo command, with the state quoted for the shell and `--org` of the notepad | `ops notepad make-task <notepadId> "Call Sam about the beta"` |
|
|
972
|
+
| `ops notepad undo-make-task <notepad> <task> --expect <state>` — `notepads.undoMakeTask`: delete the task when it is unchanged (`taskState` of the make-task result), else `notepad_undo_conflict` | `ops notepad undo-make-task <notepadId> <taskId> --expect '<state>'` |
|
|
766
973
|
| `ops notepad delete <notepad>` — a soft delete | `ops notepad delete <notepadId>` |
|
|
767
974
|
|
|
768
975
|
A `<notepad>` is a web URL (`.../notepads/<id>`), an Ops address
|
|
@@ -770,9 +977,8 @@ A `<notepad>` is a web URL (`.../notepads/<id>`), an Ops address
|
|
|
770
977
|
the owner of a shared (general) notepad can delete it; make it personal
|
|
771
978
|
first with `ops notepad share <notepad> --personal`, or ask the owner.
|
|
772
979
|
|
|
773
|
-
The
|
|
774
|
-
|
|
775
|
-
`undoGesture`) have no typed command: use `ops call <op> '<json>'`.
|
|
980
|
+
The ops `notepads.setBlocks`, `insertTask`, and `undoGesture` have no typed
|
|
981
|
+
command: use `ops call <op> '<json>'`.
|
|
776
982
|
|
|
777
983
|
### day
|
|
778
984
|
|
|
@@ -784,11 +990,57 @@ or an offset like `+1d`.
|
|
|
784
990
|
|---|---|
|
|
785
991
|
| `ops day show [date]` — the done count and the tasks in plan order | `ops day show tomorrow` |
|
|
786
992
|
| `ops day add <task...> [--date d] [--top] [--source-org o]` | `ops day add <taskId> --date tomorrow` |
|
|
993
|
+
| `ops day new <title> [--date d] [--top]` — create a task and add it to the plan of the day: in the backlog of your personal workspace, or of the org of `--org` | `ops day new "Call Sam" --top` |
|
|
787
994
|
| `ops day remove <task...> [--date d]` | `ops day remove <taskId>` |
|
|
788
995
|
| `ops day reorder <task> (--before t \| --after t \| --top \| --bottom) [--date d]` | `ops day reorder <taskId> --top` |
|
|
789
996
|
| `ops day carry [--date d]` — add the unfinished tasks of the 7 days before the date | `ops day carry` |
|
|
790
997
|
| `ops day candidates [--date d]` — the open tasks that you can plan (`dayPlans.candidates`): your own tasks of every org and the tasks of your personal workspace; `--date` marks the planned ones | `ops day candidates --date today --json` |
|
|
791
998
|
|
|
999
|
+
### share
|
|
1000
|
+
|
|
1001
|
+
A share gives another org, or one person, access to a project, a
|
|
1002
|
+
deliverable, or a task, as `reader` or `editor`. A share of a project or a
|
|
1003
|
+
deliverable reaches the records under it. Only a person with `admin` on the
|
|
1004
|
+
record manages its shares. A `<record>` is `task:<ref>`, `project:<ref>`,
|
|
1005
|
+
`deliverable:<ref>`, an ID, an address, or a web URL.
|
|
1006
|
+
|
|
1007
|
+
| Command | Example |
|
|
1008
|
+
|---|---|
|
|
1009
|
+
| `ops share list <record>` — `shares.forEntity`: who reaches the record and why (the owner org, the creator, the org, each share), each line with its permission, a share with its share ID, an inherited line with the record it comes from; your level, and if you can manage the shares | `ops share list task:<taskId>` |
|
|
1010
|
+
| `ops share access <record>` — `shares.viewerAccess`: how you reach the record (`member` or `share`), your level, and if you can manage its shares | `ops share access project:Alpha` |
|
|
1011
|
+
| `ops share add <record> --to org:<slug>\|person:<user ID> [--permission reader\|editor]` — `shares.share` (default `reader`); a share to the same org or person again changes its permission; a person is the Clerk user ID `user_…` (`ops people search` and `ops comment people` show it); `--json`: `{kind, id, subject, shareId, created, changed, permission}` | `ops share add task:<taskId> --to org:acme` |
|
|
1012
|
+
| `ops share permission <share> reader\|editor` — `shares.setPermission` | `ops share permission <shareId> editor` |
|
|
1013
|
+
| `ops share remove <share> [--record <record>]` — `shares.unshare`; it sends no notice, and there is no undo (shares have no Waybill scope); with `--record`, the CLI reads the subject and the permission of the share first and prints the `share add` command that gives the access back (`--json`: `restore`) | `ops share remove <shareId> --record task:<taskId>` |
|
|
1014
|
+
| `ops share with` — `shares.sharedWith`: the records that other orgs shared with the active workspace, newest first (`--org` picks the workspace; the personal workspace gives the shares to you) | `ops share with --org me` |
|
|
1015
|
+
|
|
1016
|
+
### calendar and event
|
|
1017
|
+
|
|
1018
|
+
The calendars of a workspace and their events (Task 385). A calendar of the
|
|
1019
|
+
personal workspace is personal; a calendar of a team workspace belongs to
|
|
1020
|
+
its org. Each person has a default calendar for new events. An event is
|
|
1021
|
+
timed (a start and an end in a time zone) or all day (whole days). **A
|
|
1022
|
+
period is an all-day event of more than one day** (`--date` and `--until`).
|
|
1023
|
+
An event can repeat; an edit or a delete of one occurrence takes
|
|
1024
|
+
`--occurrence <day>` and `--scope this|following|all`. An `<event>` is an
|
|
1025
|
+
event ID, or the occurrence ID `<eventId>:<day>` of `event list`. A
|
|
1026
|
+
`<calendar>` is an ID or a name.
|
|
1027
|
+
|
|
1028
|
+
| Command | Example |
|
|
1029
|
+
|---|---|
|
|
1030
|
+
| `ops calendar list` — the calendars of the active workspace, oldest first; `default` marks your default calendar (`calendar.listCalendars`) | `ops calendar list` |
|
|
1031
|
+
| `ops calendar show <calendar>` | `ops calendar show Events` |
|
|
1032
|
+
| `ops calendar create <name> [--color water\|fire\|earth\|air\|sun\|moon\|muted]` — `calendar.createCalendar` (default `water`) | `ops calendar create "Releases" --color fire` |
|
|
1033
|
+
| `ops calendar update <calendar> [--name] [--color]` — `calendar.updateCalendar` | `ops calendar update Releases --color sun` |
|
|
1034
|
+
| `ops calendar delete <calendar> --yes` — `calendar.removeCalendar`: it deletes each event of the calendar; refuses without `--yes`; the calendars and the events are in the Waybill scope of the org, so the text prints the undo: `ops history --scope org:<slug>`, then `ops undo --scope org:<slug> --expect <seq>` | `ops calendar delete Releases --yes` |
|
|
1035
|
+
| `ops calendar default <calendar>` — `calendar.setDefaultCalendar`: your new events go there | `ops calendar default Releases` |
|
|
1036
|
+
| `ops event list [--from <day>] [--to <day> \| --days <n>] [--calendar <c>] [--tz <zone>]` — `calendar.listEvents`: the occurrences in a window of 1 to 100 days (default: 7 days from today), each repeat expanded; `--to` is not included | `ops event list --days 14` |
|
|
1037
|
+
| `ops event show <event>` — `calendar.getEvent`: the fields, the repeat, the people, the guests, and the attached tasks and deadlines; `<eventId>:<day>` shows that occurrence with its own fields (the time, the calendar, the place, the notes, the link, the colour, the people, and the guests, read from `calendar.listEvents`), and the repeat rule and the attachments of the series; a day that is not an occurrence, or a day of an event that does not repeat, is `event_invalid_key` (exit 2) | `ops event show <eventId>` |
|
|
1038
|
+
| `ops event create <title> (--start <datetime> (--end <datetime> \| --duration <30m\|1h…>) [--tz <zone>] \| --date <day> [--until <day>]) [--calendar] [--repeat daily\|weekly\|monthly\|yearly [--every n] [--weekdays mon,wed] [--month-by day\|weekday] [--count n \| --repeat-until <day>]] [--notes] [--place] [--link <url>] [--color] [--person <member>]... [--guest "Name <email>"]... [--attach task:<ref>\|deadline:<ref>]...` — `calendar.createEvent`; a datetime is `YYYY-MM-DDTHH:mm` in `--tz` (default: the zone of this machine), `tomorrow 09:00` (a day word is a date in `--tz`, also for `--repeat-until`), or an ISO time with an offset (a day that does not exist is a usage error); at a clock change the CLI reads a time as the service does: a time in a gap moves forward by the change, and a time in an overlap is the first one | `ops event create "Offsite" --date 2026-11-16 --until 2026-11-18` |
|
|
1039
|
+
| `ops event update <event> [--title] [--start --end\|--duration --tz \| --date --until] [--calendar] [--repeat … \| --repeat none] [--notes] [--place] [--link] [--color] [--person]... [--guest]... [--no-guests] [--occurrence <day>] [--scope this\|following\|all]` — `calendar.updateEvent`: only the given fields; `none` clears `--notes`, `--place`, `--link`, `--color`, and `--repeat`; `--person` and `--guest` replace the lists; a day word of `--repeat-until` is a date in the zone of the event (of the new time, else of the stored event; an all-day event: the date of this machine). It takes no `--attach`: use `ops event attach` and `ops event detach` | `ops event update <eventId> --place none` |
|
|
1040
|
+
| `ops event delete <event> [--occurrence <day>] [--scope this\|following\|all]` — `calendar.removeEvent`; the text prints the undo in the Waybill scope of the org (`ops history --scope org:<slug>`, then `ops undo --scope org:<slug> --expect <seq>`) | `ops event delete <eventId>:2026-11-20 --scope this` |
|
|
1041
|
+
| `ops event attach <event> task:<ref>\|deadline:<ref>` / `ops event detach <event> …` — `calendar.attach`, `calendar.detach` (of a series: all its occurrences) | `ops event attach <eventId> task:<taskId>` |
|
|
1042
|
+
| `ops event for task:<ref>\|deadline:<ref>` — `calendar.eventsForRecord`: the events that a task or a deadline is attached to, soonest first | `ops event for task:<taskId>` |
|
|
1043
|
+
|
|
792
1044
|
### deployment
|
|
793
1045
|
|
|
794
1046
|
A deployment is abstract: a name, a free version label, a status (`live`,
|
|
@@ -814,8 +1066,9 @@ optional check schedule. A live deployment has an inbox section.
|
|
|
814
1066
|
The program owns `--version` (it prints the version of the CLI anywhere on
|
|
815
1067
|
the line), so the label is `--version-label`. The version chain of before the
|
|
816
1068
|
revamp is deprecated: `--previous`, `--url`, `--identifier`, `--not-owned`,
|
|
817
|
-
`list --chains
|
|
818
|
-
|
|
1069
|
+
and `list --chains` stay hidden, print a note, and work while the service
|
|
1070
|
+
keeps them. The hidden `end-chain` and `reopen-chain` are gone
|
|
1071
|
+
(0.1.0-dev.3).
|
|
819
1072
|
|
|
820
1073
|
### query
|
|
821
1074
|
|
|
@@ -846,9 +1099,9 @@ The rules:
|
|
|
846
1099
|
`subsectionId`. Run `ops query describe <table>` first.
|
|
847
1100
|
- Each row belongs to the org. A table that holds a secret, a token, a
|
|
848
1101
|
credential, a push subscription, or a Strike sync internal is not
|
|
849
|
-
readable, and neither is a table with no org field (`users`,
|
|
850
|
-
`
|
|
851
|
-
`ops day
|
|
1102
|
+
readable, and neither is a table with no org field (`users`,
|
|
1103
|
+
`day_plans`). Use the typed commands for them (`ops member list`,
|
|
1104
|
+
`ops day`).
|
|
852
1105
|
- A page holds at most `--limit` rows (default 50, max 500), and one call
|
|
853
1106
|
reads at most 5000 documents. When the output ends with `more: --cursor
|
|
854
1107
|
<c>`, give that cursor to read the next page, or use `--all`. `--all` and
|