@brunyee-studio/onus-cli 2.28.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/README.md ADDED
@@ -0,0 +1,436 @@
1
+ # Onus CLI
2
+
3
+ The official command-line interface and TypeScript SDK for the
4
+ [Onus](https://github.com/BrunyeeStudio/onus) issue tracking platform. It is
5
+ **generated from the Onus OpenAPI specification** via
6
+ `@openapitools/openapi-generator-cli`, so the CLI and its types are always in
7
+ sync with the backend API.
8
+
9
+ The CLI is designed to be equally useful to human developers and autonomous
10
+ AI coding agents (`Pi`, `Claude Code`, `Codex`, `Cursor`, ...). Agent-focused
11
+ commands (`onus context`, `onus schema`) and deterministic `--json` output make
12
+ it trivial to script and to drive programmatically.
13
+
14
+ ---
15
+
16
+ ## Features
17
+
18
+ - ๐Ÿ”‘ **`onus auth`** โ€” store, inspect, and clear your access token and API endpoint.
19
+ - ๐Ÿค– **Agent-friendly** โ€” `onus context`, `onus schema`, machine-readable `--json`
20
+ output, and auto-JSON detection when stdout is piped.
21
+ - โœ… **Typesafe SDK** โ€” the client models and runtime are generated directly from
22
+ the Onus OpenAPI spec, so the CLI can't drift from the API.
23
+ - ๐Ÿ“ฆ **Automated publishing** โ€” versions, changelog, git tags, GitHub releases,
24
+ and npm publishing are handled automatically from Conventional Commits via
25
+ `semantic-release`.
26
+ - ๐Ÿงญ **Rich terminal output** โ€” aligned tables, semantic colors, and clear errors
27
+ with standardized exit codes.
28
+
29
+ ---
30
+
31
+ ## Installation
32
+
33
+ ### Global install
34
+
35
+ ```bash
36
+ npm i -g @brunyee-studio/onus-cli@latest
37
+ ```
38
+
39
+ ### Run without installing
40
+
41
+ ```bash
42
+ npx onus --help
43
+ ```
44
+
45
+ ### From a local checkout (workspace build)
46
+
47
+ ```bash
48
+ pnpm install
49
+ pnpm openapi:export # regenerate openapi.json from src/lib/public-api/openapi.ts
50
+ pnpm cli:generate # regenerate the typesafe SDK into packages/cli/src/generated
51
+ pnpm cli:build # bundle packages/cli/dist/bin.js
52
+ node packages/cli/dist/bin.js --help
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Quick start
58
+
59
+ ```bash
60
+ # Authenticate interactively with browser OAuth
61
+ onus auth login
62
+
63
+ # Or pass an access token directly (headless/agent mode)
64
+ onus auth login --token <your-onus-token>
65
+
66
+ # Under WSL2 mirror networking, bind the OAuth callback server to 0.0.0.0
67
+ # (or set the ONUS_OAUTH_HOST env var instead)
68
+ onus auth login --loopback-host 0.0.0.0
69
+
70
+ # Show the current user
71
+ onus me --json
72
+
73
+ # List issues
74
+ onus issue list --status in_progress --json
75
+
76
+ # List teams
77
+ onus team list
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Configuration
83
+
84
+ Settings are resolved with the following precedence **(highest wins)**:
85
+
86
+ 1. CLI flags: `-t, --token <token>`, `-u, --api-url <url>`
87
+ 2. Environment variables (see table below)
88
+ 3. The persistent config file
89
+
90
+ ### Environment variables
91
+
92
+ | Variable | Purpose | Notes |
93
+ | -------------------- | ---------------------- | ------------------------------------------------------------------- |
94
+ | `ONUS_TOKEN` | Access token / API key | Alias: `ONUS_API_KEY` |
95
+ | `ONUS_REFRESH_TOKEN` | OAuth refresh token | Used for automatic token rotation on expiration |
96
+ | `ONUS_API_URL` | API base URL | Alias: `ONUS_BASE_URL`; default `https://onus.brunyeestudio.com/v1` |
97
+ | `ONUS_OUTPUT` | Force output mode | `json` enables deterministic JSON output |
98
+
99
+ ### Config file
100
+
101
+ On Unix/macOS, credentials persist to `~/.config/onus/config.json`
102
+ (`${XDG_CONFIG_HOME}/onus/config.json` if set). On Windows, they persist to
103
+ `%APPDATA%\onus\config.json`. The file is written with `0600`/`0700` permissions.
104
+
105
+ ```json
106
+ {
107
+ "token": "<your-onus-token>",
108
+ "apiUrl": "https://onus.brunyeestudio.com/v1"
109
+ }
110
+ ```
111
+
112
+ > **Note for agents**: prefer passing the token via `ONUS_TOKEN` so you never
113
+ > persist credentials on a machine โ€” the environment variable is read at the
114
+ > start of each invocation.
115
+
116
+ ---
117
+
118
+ ## Command reference
119
+
120
+ ### `onus auth` โ€” authentication
121
+
122
+ | Command | Description |
123
+ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
124
+ | `onus auth login` | Authenticate interactively via browser OAuth PKCE loopback flow |
125
+ | `onus auth login --loopback-host <host>` | Bind the callback server to a custom host (`0.0.0.0` for WSL2 mirror networking); also configurable via `ONUS_OAUTH_HOST` |
126
+ | `onus auth login --token <token>` | Store an access token directly (optionally `--api-url <url>`) |
127
+ | `onus auth login --manual` | Authenticate with manual out-of-band authorization code prompt (no browser) |
128
+ | `onus auth logout` | Clear stored credentials |
129
+ | `onus auth status [--json]` | Show masked token, refresh token status, and active API endpoint |
130
+
131
+ ### `onus context` โ€” agent environment snapshot
132
+
133
+ Emit a structured snapshot of the CLI environment: version, API endpoint, auth
134
+ state, the authenticated viewer, available resources, capabilities, and quick
135
+ examples.
136
+
137
+ ```bash
138
+ onus context --json
139
+ ```
140
+
141
+ ```json
142
+ {
143
+ "cliVersion": "1.0.0",
144
+ "apiUrl": "https://onus.brunyeestudio.com/v1",
145
+ "authenticated": true,
146
+ "viewer": { "id": "uuid", "full_name": "Alice" },
147
+ "resources": ["team", "project", "issue", "comment", "label"],
148
+ "capabilities": {
149
+ "jsonOutputSupported": true,
150
+ "envAuthSupported": true,
151
+ "standardExitCodes": {
152
+ "success": 0,
153
+ "generalError": 1,
154
+ "validationError": 2,
155
+ "authError": 3,
156
+ "notFound": 4
157
+ }
158
+ },
159
+ "quickExamples": [
160
+ "onus me --json",
161
+ "onus team list --json",
162
+ "onus project list --json",
163
+ "onus issue list --status in_progress --json",
164
+ "onus issue create --title \"Fix login\" --team <team-id> --json",
165
+ "onus comment list <issue-id> --json"
166
+ ]
167
+ }
168
+ ```
169
+
170
+ ### `onus schema [resource]` โ€” OpenAPI schema introspection
171
+
172
+ Fetch and print the exact OpenAPI component schemas so you can inspect
173
+ payload shapes, required fields, and validation constraints without guessing.
174
+
175
+ ```bash
176
+ onus schema issue --json # schema for a single resource
177
+ onus schema # full OpenAPI document
178
+ onus schema --all # full OpenAPI document
179
+ ```
180
+
181
+ ### `onus me`
182
+
183
+ Get the authenticated viewer profile.
184
+
185
+ ```bash
186
+ onus me [--json]
187
+ ```
188
+
189
+ ### `onus team`
190
+
191
+ Read-only team access.
192
+
193
+ ```bash
194
+ onus team list [--json]
195
+ onus team get <id> [--json]
196
+ ```
197
+
198
+ ### `onus project`
199
+
200
+ ```bash
201
+ onus project list [--json]
202
+ onus project get <id> [--json]
203
+ onus project create --name <name> --team <teamId> [--status <status>] [--priority <priority>] [--lead <leadId>] [--target-date <date>] [--json]
204
+ onus project update <id> [--name <name>] [--status <status>] [--priority <priority>] [--lead <leadId>] [--target-date <date>] [--json]
205
+ ```
206
+
207
+ ### `onus issue`
208
+
209
+ Issues are addressed by human reference (`ENG-42`); UUIDs are also accepted.
210
+
211
+ ```bash
212
+ onus issue list [--team <id>] [--project <id>] [--assignee <id>] [--parent <id>] [--status <status>] [--q <query>] [--limit <n>] [--cursor <cursor>] [--json]
213
+ onus issue get <ref> [--json]
214
+ onus issue create --title <title> --team <teamId> [-d <description>] [--status <status>] [--priority <priority>] [--assignee <id>] [--project <id>] [--parent <id>] [--label <labelId>] [--json]
215
+ onus issue update <ref> [--title <title>] [-d <description>] [--status <status>] [--priority <priority>] [--assignee <id>] [--project <id>] [--parent <id>] [--add-label <labelId>] [--remove-label <labelId>] [--json]
216
+ onus issue delete <ref> [--yes] [--json]
217
+ ```
218
+
219
+ `--status` accepts `backlog | todo | in_progress | done | canceled`; `--priority`
220
+ accepts `none | urgent | high | medium | low`. `--label` / `--add-label` /
221
+ `--remove-label` are repeatable (pass the flag once per label). `update` is
222
+ aliased as `edit`.
223
+
224
+ #### Comment subcommands
225
+
226
+ ```bash
227
+ onus issue comment create <ref> --body <body> [--json]
228
+ onus issue comment list <ref> [--json]
229
+ onus issue comment edit <ref> --comment <commentId> --body <body> [--json]
230
+ onus issue comment delete <ref> --comment <commentId> [--json]
231
+ ```
232
+
233
+ #### Relation subcommands
234
+
235
+ ```bash
236
+ onus issue relation add <ref> --with <ref> --type <type> [--json]
237
+ onus issue relation remove <ref> --relation <relationId> [--json]
238
+ ```
239
+
240
+ `--type` accepts `blocks | duplicate | related | similar`.
241
+
242
+ #### Attachment subcommands
243
+
244
+ ```bash
245
+ onus issue attachment upload <ref> --file <path> [--name <name>] [--type <type>] [--json]
246
+ onus issue attachment list <ref> [--json]
247
+ onus issue attachment download <ref> --attachment <attachmentId> [--output <path>] [--json]
248
+ onus issue attachment delete <ref> --attachment <attachmentId> [--json]
249
+ ```
250
+
251
+ Uploads go through a presigned URL: the CLI requests an upload URL, PUTs the
252
+ file bytes to it, and reports the attachment id. Downloads resolve a presigned
253
+ read URL and write the file.
254
+
255
+ #### Subscription subcommands
256
+
257
+ ```bash
258
+ onus issue subscribe <ref> [--json]
259
+ onus issue unsubscribe <ref> [--json]
260
+ ```
261
+
262
+ #### GitHub pull-request link subcommands
263
+
264
+ ```bash
265
+ onus issue link-pr <ref> --repo <owner/name> --pr <number> [--json]
266
+ onus issue unlink-pr <ref> --pr-link <linkId> [--json]
267
+ ```
268
+
269
+ ### `onus comment`
270
+
271
+ ```bash
272
+ onus comment list <issueId> [--json]
273
+ onus comment create <issueId> --body <body> [--json]
274
+ ```
275
+
276
+ ### `onus label`
277
+
278
+ ```bash
279
+ onus label list [--json]
280
+ onus label create --name <name> --team <teamId> [--color <color>] [--json]
281
+ ```
282
+
283
+ ### `onus skill` โ€” agent skill management
284
+
285
+ The package bundles an `@brunyee-studio/onus-cli` agent skill (a `SKILL.md` teaching AI coding
286
+ agents how to drive the Onus CLI). Installation and lifecycle go through the
287
+ [`skills`](https://www.npmjs.com/package/skills) npm package, which detects
288
+ installed agents (Claude Code, Codex, Cursor, โ€ฆ) and symlinks or copies the
289
+ skill into their skill directories.
290
+
291
+ ```bash
292
+ onus skill install # install into detected agents (project scope)
293
+ onus skill install --global # user-wide (~/<agent>/skills/)
294
+ onus skill install --agent claude-code codex
295
+ onus skill install --copy # copy instead of symlink
296
+ onus skill update # refresh installed copies to the bundled version
297
+ onus skill remove # uninstall from agents (alias: onus skill rm)
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Agent usage guidance
303
+
304
+ The Onus CLI is built to be driven reliably by AI agents.
305
+
306
+ ### 1. Deterministic JSON output
307
+
308
+ Add the global `-j, --json` flag (available on every command) for pure,
309
+ deterministic JSON with no ANSI codes, banners, or table borders:
310
+
311
+ ```bash
312
+ onus issue list --json | jq '.[0].title'
313
+ ```
314
+
315
+ ### 2. Auto-JSON when piping
316
+
317
+ When stdout is **not a TTY** (piped, redirected, or captured by an agent), the
318
+ CLI automatically switches to JSON output. You can also force it with
319
+ `ONUS_OUTPUT=json`:
320
+
321
+ ```bash
322
+ onus issue list | jq . # auto-JSON because stdout is piped
323
+ ONUS_OUTPUT=json onus issue list # force JSON mode
324
+ ```
325
+
326
+ Diagnostic and informational logs go to **stderr**, so stdout stays clean and
327
+ pipeable.
328
+
329
+ ### 3. Introspect before acting
330
+
331
+ Run `onus context --json` first to learn the environment, then use
332
+ `onus schema <resource> --json` to discover exact field names, required
333
+ properties, and enum values before constructing a write operation.
334
+
335
+ ### 4. Standardized exit codes
336
+
337
+ | Exit code | Meaning |
338
+ | --------- | ----------------------------------------------------- |
339
+ | `0` | Success |
340
+ | `1` | General / server error |
341
+ | `2` | Validation / usage error (e.g. missing required flag) |
342
+ | `3` | Authentication error (`401` / `403`) |
343
+ | `4` | Not found (`404`) |
344
+
345
+ ### 5. Headless authentication
346
+
347
+ Agents can operate without interactive prompts by supplying the token via
348
+ `ONUS_TOKEN`:
349
+
350
+ ```bash
351
+ export ONUS_TOKEN="<your-onus-token>"
352
+ onus me --json
353
+ ```
354
+
355
+ ---
356
+
357
+ ## How the CLI is generated from OpenAPI
358
+
359
+ The type-safe SDK boundary of the CLI is produced from the Onus OpenAPI
360
+ specification:
361
+
362
+ ```
363
+ src/lib/public-api/openapi.ts (Zod schemas = single source of truth)
364
+ โ”‚ pnpm openapi:export
365
+ โ–ผ
366
+ openapi.json
367
+ โ”‚ pnpm cli:generate (@openapitools/openapi-generator-cli, typescript-fetch)
368
+ โ–ผ
369
+ packages/cli/src/generated/** (models + runtime + DefaultApi)
370
+ โ”‚ wrapped by packages/cli/src/client.ts
371
+ โ–ผ
372
+ packages/cli/src/commands/** (Commander.js CLI surface)
373
+ ```
374
+
375
+ - `pnpm openapi:export` statically serializes `/v1/openapi.json` to
376
+ `openapi.json` without needing a running dev server.
377
+ - `pnpm cli:generate` runs the generator configured in `openapitools.json`,
378
+ emitting the `typescript-fetch` client into `packages/cli/src/generated`.
379
+ - Because it is generated from the canonical spec, the CLI always reflects the
380
+ real API: adding or changing a `/v1` route + its Zod schema, then re-running
381
+ `pnpm openapi:export && pnpm cli:generate`, updates the SDK and CLI surface
382
+ in lockstep.
383
+
384
+ ---
385
+
386
+ ## Development
387
+
388
+ ### Commands
389
+
390
+ | Command | Purpose |
391
+ | --------------------- | -------------------------------------------------- |
392
+ | `pnpm cli:generate` | Regenerate the SDK from `openapi.json` |
393
+ | `pnpm cli:build` | Bundle `packages/cli/dist` with `tsup` |
394
+ | `pnpm cli:test` | Run Vitest unit tests for the CLI |
395
+ | `pnpm cli:typecheck` | Run `tsc --noEmit` for the CLI |
396
+ | `pnpm openapi:export` | Regenerate `openapi.json` from the API definitions |
397
+
398
+ Run from the repository root. Each script delegates to the `packages/cli`
399
+ workspace package via `pnpm --filter onus`.
400
+
401
+ ---
402
+
403
+ ## Automated versioning & publishing
404
+
405
+ The CLI package is released automatically on push to `main` by a GitHub Actions
406
+ workflow (`.github/workflows/release.yml`) running `semantic-release`, driven by
407
+ **Conventional Commits** (enforced by the repo's `commitlint` config):
408
+
409
+ | Commit type | Version bump |
410
+ | ------------------------------------- | --------------- |
411
+ | `feat:` | Minor (`1.1.0`) |
412
+ | `fix:` | Patch (`1.0.1`) |
413
+ | `feat!:` / `BREAKING CHANGE:` | Major (`2.0.0`) |
414
+ | `chore:`, `docs:`, `refactor:`, `ci:` | No release |
415
+
416
+ The release pipeline:
417
+
418
+ 1. Checks out with full git history (`fetch-depth: 0`).
419
+ 2. Exports the OpenAPI spec and regenerates the SDK.
420
+ 3. Runs tests, typechecks, and builds the CLI.
421
+ 4. Runs `semantic-release`, which:
422
+ - Bumps `packages/cli/package.json` and appends to `packages/cli/CHANGELOG.md`.
423
+ - Creates a git tag and a GitHub Release with auto-generated notes.
424
+ - Publishes to npm (`@semantic-release/npm`); configure an `NPM_TOKEN`
425
+ repository secret to enable publishing. The GitHub release assets are the
426
+ built `dist/**` bundles.
427
+
428
+ `packages/cli/CHANGELOG.md` is **auto-generated** by `semantic-release` on each
429
+ release and is excluded from formatting and checks โ€” do not edit it by hand
430
+ (manual edits are overwritten on the next release).
431
+
432
+ ---
433
+
434
+ ## License
435
+
436
+ [MIT](./LICENSE) ยท ยฉ Brunyee Studio