linear-sdk-cli 0.5.3 → 0.6.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/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ Release Please generates this file from Conventional Commits. Feature and fix pu
4
4
  not edit it directly; their squash-commit titles are the release-note source of truth. This project
5
5
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.6.0](https://github.com/zhendalf/linear-sdk-cli/compare/v0.5.3...v0.6.0) (2026-09-17)
8
+
9
+ ### Features
10
+
11
+ - add project label resource commands ([#73](https://github.com/zhendalf/linear-sdk-cli/issues/73)) ([198ee7a](https://github.com/zhendalf/linear-sdk-cli/commit/198ee7af00b29b45653d6ca07195d1433c4af844))
12
+ - add project status resource commands ([#71](https://github.com/zhendalf/linear-sdk-cli/issues/71)) ([2120a43](https://github.com/zhendalf/linear-sdk-cli/commit/2120a43496132955932a6af3af3a70364ae8493d))
13
+
14
+ ### Bug Fixes
15
+
16
+ - expose credential scope capabilities ([#74](https://github.com/zhendalf/linear-sdk-cli/issues/74)) ([9efa3c1](https://github.com/zhendalf/linear-sdk-cli/commit/9efa3c1a2405be6dba79cf808b1c14737b280015)), closes [#70](https://github.com/zhendalf/linear-sdk-cli/issues/70)
17
+
7
18
  ## [0.5.3](https://github.com/zhendalf/linear-sdk-cli/compare/v0.5.2...v0.5.3) (2026-09-14)
8
19
 
9
20
  ### Bug Fixes
package/README.md CHANGED
@@ -140,6 +140,13 @@ linear auth status # credential kind and source (value r
140
140
  linear auth logout --workspace acme # revoke OAuth (if used) and remove the profile
141
141
  ```
142
142
 
143
+ `auth status --json` also reports `scopeVisibility`, `scopes`, and `adminScope`. Stored browser
144
+ OAuth grants are inspectable because the CLI records their granted scopes. Personal API keys and
145
+ injected OAuth access tokens are reported as `scopeVisibility: "unknown"` and `adminScope: null`:
146
+ Linear provides no safe read-only scope introspection for them. `whoami --json` keeps the Linear
147
+ member's workspace role in `admin` and reports credential authorization separately under
148
+ `authorization`; an admin member can still hold a credential that lacks the `admin` scope.
149
+
143
150
  Browser login generates a cryptographically random verifier and CSRF state, requires PKCE S256,
144
151
  opens Linear, and listens temporarily on the registered `127.0.0.1` callback. It validates the
145
152
  viewer and workspace before saving the access token, rotating refresh token, expiry, granted
@@ -542,7 +549,9 @@ value per command:
542
549
  - **mutations** (`create`/`update`/`delete`/`archive`/…) emit the affected object — typically a
543
550
  small shape like `{ "id", "identifier", "url" }`, or `{ "id", "success": true }` when the API
544
551
  returns no body. Destructive commands add a flag such as `{ "deleted": true }` / `{ "archived": true }`.
545
- - **errors** go to **stderr** as `{"error":{"message":"…","code":"…"}}` and never to stdout. With
552
+ - **errors** go to **stderr** as `{"error":{"message":"…","code":"…"}}` and never to stdout.
553
+ Scope-related forbidden errors add stable `error.details` such as `requiredScope`,
554
+ `credentialType`, `scopeVisibility`, and remediation; callers never need to parse prose. With
546
555
  `--debug`, the extra detail is carried _inside_ that object as `error.detail` rather than appended
547
556
  after it, so `--json --debug` output stays parseable.
548
557
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "linear-sdk-cli",
3
- "version": "0.5.3",
3
+ "version": "0.6.0",
4
4
  "description": "Ergonomic command-line interface for Linear, built on @linear/sdk",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -100,6 +100,13 @@ An explicit credential flag overrides environment credentials. If both credentia
100
100
  the same precedence level, the CLI fails rather than silently choosing an actor. Inspect resolution
101
101
  with `linear auth status`. `linear auth token` exports stored API keys only and never OAuth tokens.
102
102
 
103
+ Treat workspace role and credential authorization as separate facts. `whoami.admin` is the Linear
104
+ member role; it does not prove the active credential has the `admin` scope. Check
105
+ `auth status --json`: stored browser OAuth grants report known `scopes` and `adminScope`, while
106
+ personal API keys and injected access tokens honestly report `scopeVisibility: "unknown"` and
107
+ `adminScope: null` because Linear exposes no safe read-only introspection for them. Scope-related
108
+ forbidden errors include stable `error.details` with the required scope and remediation.
109
+
103
110
  ## Agent best practices
104
111
 
105
112
  This CLI is built for non-interactive use. Follow these and it will never hang and
@@ -441,6 +448,23 @@ linear project milestones
441
448
  linear project update
442
449
  linear project view
443
450
 
451
+ linear project-label
452
+ linear project-label create
453
+ linear project-label delete
454
+ linear project-label list
455
+ linear project-label restore
456
+ linear project-label retire
457
+ linear project-label update
458
+ linear project-label view
459
+
460
+ linear project-status
461
+ linear project-status archive
462
+ linear project-status create
463
+ linear project-status list
464
+ linear project-status unarchive
465
+ linear project-status update
466
+ linear project-status view
467
+
444
468
  linear project-update
445
469
  linear project-update create
446
470
  linear project-update list
@@ -513,6 +537,8 @@ prints the same). These are supplementary — `--help` on any command is authori
513
537
  - [open](references/open.md) — Open the workspace, an issue, team, project, or URL
514
538
  - [organization](references/organization.md) — Inspect the current workspace
515
539
  - [project](references/project.md) — Work with projects
540
+ - [project-label](references/project-label.md) — Manage project labels (distinct from issue labels)
541
+ - [project-status](references/project-status.md) — Manage workspace project-status definitions
516
542
  - [project-update](references/project-update.md) — Post and list project status updates
517
543
  - [roadmap](references/roadmap.md) — Work with roadmaps
518
544
  - [schema](references/schema.md) — Print the Linear GraphQL schema as SDL
@@ -159,6 +159,9 @@ key: string
159
159
  keyring: string | null
160
160
  scopes: string[] | null
161
161
  expiresAt: string | null
162
+ scopeVisibility: string
163
+ adminScope: boolean | null
164
+ scopeNote: string
162
165
  ```
163
166
 
164
167
  ### `linear auth token`
@@ -192,5 +195,6 @@ name: string
192
195
  displayName: string
193
196
  email: string
194
197
  admin: boolean
198
+ authorization: {credentialType: string | null, scopeVisibility: string, scopes: string[] | null, adminScope: boolean | null, note: string}
195
199
  organization: {id: string, name: string, urlKey: string}
196
200
  ```
@@ -0,0 +1,170 @@
1
+ # linear project-label
2
+
3
+ > Manage project labels (distinct from issue labels)
4
+
5
+ Group alias: `pl`
6
+
7
+ _Generated from `linear commands --json`. `linear project-label --help` (or `<subcommand> --help`) is authoritative._
8
+
9
+ Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
10
+
11
+ ### `linear project-label`
12
+
13
+ Manage project labels (distinct from issue labels)
14
+
15
+ Aliases: `pl`
16
+
17
+ ```
18
+ linear project-label [options]
19
+ ```
20
+
21
+ ### `linear project-label create`
22
+
23
+ Create a project label or label group
24
+
25
+ Aliases: `new`
26
+
27
+ ```
28
+ linear project-label create [options]
29
+ ```
30
+
31
+ | Option | Description |
32
+ | -------------------------- | ----------------------------------------- |
33
+ | `--name <name>` | project label name |
34
+ | `--color <hex>` | label color (six-digit hex, e.g. #5E6AD2) |
35
+ | `-d, --description <text>` | label description |
36
+ | `--group` | create a non-assignable label group |
37
+ | `--parent <name-or-id>` | put the label in this group |
38
+
39
+ **Output (`--json`)**: a receipt object
40
+
41
+ ```text
42
+ id: string
43
+ name: string
44
+ color: string
45
+ ```
46
+
47
+ ### `linear project-label delete`
48
+
49
+ Permanently delete a project label
50
+
51
+ Aliases: `rm`
52
+
53
+ ```
54
+ linear project-label delete [options] <name-or-id>
55
+ ```
56
+
57
+ **Output (`--json`)**: a receipt object
58
+
59
+ ```text
60
+ id: string
61
+ name: string
62
+ deleted: boolean
63
+ ```
64
+
65
+ ### `linear project-label list`
66
+
67
+ List project labels
68
+
69
+ Aliases: `ls`
70
+
71
+ ```
72
+ linear project-label list [options]
73
+ ```
74
+
75
+ | Option | Description |
76
+ | ------------------- | -------------------------------------------------- |
77
+ | `--include-retired` | include labels retired from new project assignment |
78
+
79
+ **Output (`--json`)**: a bare array of objects
80
+
81
+ ```text
82
+ id: string
83
+ name: string
84
+ color: string
85
+ description: string | null
86
+ isGroup: boolean
87
+ parent: {id: string, name: string} | null
88
+ retiredAt: string | null
89
+ ```
90
+
91
+ ### `linear project-label restore`
92
+
93
+ Restore a retired project label
94
+
95
+ Aliases: `unretire`
96
+
97
+ ```
98
+ linear project-label restore [options] <name-or-id>
99
+ ```
100
+
101
+ **Output (`--json`)**: a receipt object
102
+
103
+ ```text
104
+ id: string
105
+ name: string
106
+ restored: boolean
107
+ ```
108
+
109
+ ### `linear project-label retire`
110
+
111
+ Retire a label so it cannot be assigned to new projects
112
+
113
+ ```
114
+ linear project-label retire [options] <name-or-id>
115
+ ```
116
+
117
+ **Output (`--json`)**: a receipt object
118
+
119
+ ```text
120
+ id: string
121
+ name: string
122
+ retired: boolean
123
+ ```
124
+
125
+ ### `linear project-label update`
126
+
127
+ Update a project label by exact name or id
128
+
129
+ Aliases: `edit`
130
+
131
+ ```
132
+ linear project-label update [options] <name-or-id>
133
+ ```
134
+
135
+ | Option | Description |
136
+ | -------------------------- | --------------------------------------- |
137
+ | `--name <name>` | new name |
138
+ | `--color <hex>` | new color (six-digit hex, e.g. #5E6AD2) |
139
+ | `-d, --description <text>` | new description |
140
+ | `--parent <name-or-id>` | move the label into this group |
141
+ | `--clear-parent` | remove the label from its group |
142
+
143
+ **Output (`--json`)**: a receipt object
144
+
145
+ ```text
146
+ id: string
147
+ name: string
148
+ color: string
149
+ ```
150
+
151
+ ### `linear project-label view`
152
+
153
+ View a project label or label group by exact name or id
154
+
155
+ ```
156
+ linear project-label view [options] <name-or-id>
157
+ ```
158
+
159
+ **Output (`--json`)**: a bare object
160
+
161
+ ```text
162
+ id: string
163
+ name: string
164
+ color: string
165
+ description: string | null
166
+ isGroup: boolean
167
+ parent: {id: string, name: string} | null
168
+ retiredAt: string | null
169
+ children: Array<{id: string, name: string, color: string, retiredAt: string | null}>
170
+ ```
@@ -0,0 +1,158 @@
1
+ # linear project-status
2
+
3
+ > Manage workspace project-status definitions
4
+
5
+ Group alias: `project-statuses`
6
+
7
+ _Generated from `linear commands --json`. `linear project-status --help` (or `<subcommand> --help`) is authoritative._
8
+
9
+ Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
10
+
11
+ ### `linear project-status`
12
+
13
+ Manage workspace project-status definitions
14
+
15
+ Aliases: `project-statuses`
16
+
17
+ ```
18
+ linear project-status [options]
19
+ ```
20
+
21
+ ### `linear project-status archive`
22
+
23
+ Archive a project status (requires no active projects and another status of its type)
24
+
25
+ ```
26
+ linear project-status archive [options] <name-or-id>
27
+ ```
28
+
29
+ **Output (`--json`)**: a receipt object
30
+
31
+ ```text
32
+ id: string
33
+ name: string
34
+ archived: boolean
35
+ ```
36
+
37
+ ### `linear project-status create`
38
+
39
+ Create a workspace project status (explicit because duplicate names are valid)
40
+
41
+ Aliases: `new`
42
+
43
+ ```
44
+ linear project-status create [options]
45
+ ```
46
+
47
+ | Option | Description |
48
+ | --------------------------- | -------------------------------------------------------------------- |
49
+ | `--name <name>` | status name |
50
+ | `-d, --description <text>` | status description |
51
+ | `--description-file <path>` | read description from a file ('-' = stdin) |
52
+ | `--color <hex>` | six-digit hex color (e.g. #5E6AD2) |
53
+ | `--position <number>` | position within the status type |
54
+ | `--type <type>` | status type (backlog\|planned\|started\|paused\|completed\|canceled) |
55
+ | `--indefinite` | allow projects to remain in this status indefinitely |
56
+
57
+ **Output (`--json`)**: a receipt object
58
+
59
+ ```text
60
+ id: string
61
+ name: string
62
+ type: string
63
+ ```
64
+
65
+ ### `linear project-status list`
66
+
67
+ List workspace project statuses
68
+
69
+ Aliases: `ls`
70
+
71
+ ```
72
+ linear project-status list [options]
73
+ ```
74
+
75
+ | Option | Description |
76
+ | -------------------- | --------------------------------- |
77
+ | `--include-archived` | include archived project statuses |
78
+
79
+ **Output (`--json`)**: a bare array of objects
80
+
81
+ ```text
82
+ id: string
83
+ name: string
84
+ description: string | null
85
+ color: string
86
+ position: number
87
+ type: string
88
+ indefinite: boolean
89
+ archivedAt: string | null
90
+ ```
91
+
92
+ ### `linear project-status unarchive`
93
+
94
+ Unarchive a project status by exact name or id
95
+
96
+ ```
97
+ linear project-status unarchive [options] <name-or-id>
98
+ ```
99
+
100
+ **Output (`--json`)**: a receipt object
101
+
102
+ ```text
103
+ id: string
104
+ name: string
105
+ archived: boolean
106
+ ```
107
+
108
+ ### `linear project-status update`
109
+
110
+ Update a project status by exact name or id
111
+
112
+ Aliases: `edit`
113
+
114
+ ```
115
+ linear project-status update [options] <name-or-id>
116
+ ```
117
+
118
+ | Option | Description |
119
+ | --------------------------- | -------------------------------------------------------------------- |
120
+ | `--name <name>` | new status name |
121
+ | `-d, --description <text>` | new status description |
122
+ | `--description-file <path>` | read description from a file ('-' = stdin) |
123
+ | `--color <hex>` | six-digit hex color (e.g. #5E6AD2) |
124
+ | `--position <number>` | position within the status type |
125
+ | `--type <type>` | status type (backlog\|planned\|started\|paused\|completed\|canceled) |
126
+ | `--indefinite` | allow projects to remain in this status indefinitely |
127
+ | `--no-indefinite` | do not allow projects to remain indefinitely |
128
+
129
+ **Output (`--json`)**: a receipt object
130
+
131
+ ```text
132
+ id: string
133
+ name: string
134
+ type: string
135
+ ```
136
+
137
+ ### `linear project-status view`
138
+
139
+ Show a project status by exact name or id
140
+
141
+ ```
142
+ linear project-status view [options] <name-or-id>
143
+ ```
144
+
145
+ **Output (`--json`)**: a bare object
146
+
147
+ ```text
148
+ id: string
149
+ name: string
150
+ description: string | null
151
+ color: string
152
+ position: number
153
+ type: string
154
+ indefinite: boolean
155
+ archivedAt: string | null
156
+ createdAt: string
157
+ updatedAt: string
158
+ ```
@@ -71,24 +71,24 @@ Aliases: `new`
71
71
  linear project create [options]
72
72
  ```
73
73
 
74
- | Option | Description |
75
- | --------------------------- | ---------------------------------------------- |
76
- | `--name <name>` | project name |
77
- | `-d, --description <text>` | project description (one-line summary) |
78
- | `--description-file <path>` | read description from a file ('-' = stdin) |
79
- | `--content <text>` | project content (markdown body) |
80
- | `--content-file <path>` | read content from a file ('-' = stdin) |
81
- | `--teams <key>` | team (repeatable / comma-separated) |
82
- | `-t, --team <key>` | same as --teams (repeatable / comma-separated) |
83
- | `--lead <who>` | project lead (me\|email\|name\|id) |
84
- | `--member <who>` | project member (repeatable / comma-separated) |
85
- | `--state <name>` | initial status (name, type, or id) |
86
- | `--start <date>` | planned start date (YYYY-MM-DD) |
87
- | `--target <date>` | planned target date (YYYY-MM-DD) |
88
- | `-P, --priority <0-4>` | priority (0 none, 1 urgent … 4 low) |
89
- | `-l, --label <name>` | project label (repeatable / comma-separated) |
90
- | `--icon <name>` | Linear icon name, capitalized (e.g. Rocket) |
91
- | `--color <hex>` | project color (e.g. #EB5757) |
74
+ | Option | Description |
75
+ | --------------------------- | ---------------------------------------------------------------------- |
76
+ | `--name <name>` | project name |
77
+ | `-d, --description <text>` | project description (one-line summary) |
78
+ | `--description-file <path>` | read description from a file ('-' = stdin) |
79
+ | `--content <text>` | project content (markdown body) |
80
+ | `--content-file <path>` | read content from a file ('-' = stdin) |
81
+ | `--teams <key>` | team (repeatable / comma-separated) |
82
+ | `-t, --team <key>` | same as --teams (repeatable / comma-separated) |
83
+ | `--lead <who>` | project lead (me\|email\|name\|id) |
84
+ | `--member <who>` | project member (repeatable / comma-separated) |
85
+ | `--state <name>` | initial status (name, type, or id) |
86
+ | `--start <date>` | planned start date (YYYY-MM-DD) |
87
+ | `--target <date>` | planned target date (YYYY-MM-DD) |
88
+ | `-P, --priority <0-4>` | priority (0 none, 1 urgent … 4 low) |
89
+ | `-l, --label <name>` | project label from `project-label list` (repeatable / comma-separated) |
90
+ | `--icon <name>` | Linear icon name, capitalized (e.g. Rocket) |
91
+ | `--color <hex>` | project color (e.g. #EB5757) |
92
92
 
93
93
  **Output (`--json`)**: a receipt object
94
94
 
@@ -175,23 +175,23 @@ Aliases: `edit`
175
175
  linear project update [options] <id>
176
176
  ```
177
177
 
178
- | Option | Description |
179
- | --------------------------- | -------------------------------------------------- |
180
- | `--name <name>` | new name |
181
- | `-d, --description <text>` | new description (one-line summary) |
182
- | `--description-file <path>` | read description from a file ('-' = stdin) |
183
- | `--content <text>` | new content (markdown body) |
184
- | `--content-file <path>` | read content from a file ('-' = stdin) |
185
- | `--teams <key>` | set teams (repeatable / comma-separated) |
186
- | `--lead <who>` | project lead (me\|email\|name\|id) |
187
- | `--member <who>` | replace the members (repeatable / comma-separated) |
188
- | `--state <name>` | status (name, type, or id) |
189
- | `--start <date>` | planned start date (YYYY-MM-DD) |
190
- | `--target <date>` | planned target date (YYYY-MM-DD) |
191
- | `-P, --priority <0-4>` | priority (0 none, 1 urgent … 4 low) |
192
- | `-l, --label <name>` | replace the labels (repeatable / comma-separated) |
193
- | `--icon <name>` | Linear icon name, capitalized (e.g. Rocket) |
194
- | `--color <hex>` | project color (e.g. #EB5757) |
178
+ | Option | Description |
179
+ | --------------------------- | ------------------------------------------------------------------------------- |
180
+ | `--name <name>` | new name |
181
+ | `-d, --description <text>` | new description (one-line summary) |
182
+ | `--description-file <path>` | read description from a file ('-' = stdin) |
183
+ | `--content <text>` | new content (markdown body) |
184
+ | `--content-file <path>` | read content from a file ('-' = stdin) |
185
+ | `--teams <key>` | set teams (repeatable / comma-separated) |
186
+ | `--lead <who>` | project lead (me\|email\|name\|id) |
187
+ | `--member <who>` | replace the members (repeatable / comma-separated) |
188
+ | `--state <name>` | status (name, type, or id) |
189
+ | `--start <date>` | planned start date (YYYY-MM-DD) |
190
+ | `--target <date>` | planned target date (YYYY-MM-DD) |
191
+ | `-P, --priority <0-4>` | priority (0 none, 1 urgent … 4 low) |
192
+ | `-l, --label <name>` | replace project labels from `project-label list` (repeatable / comma-separated) |
193
+ | `--icon <name>` | Linear icon name, capitalized (e.g. Rocket) |
194
+ | `--color <hex>` | project color (e.g. #EB5757) |
195
195
 
196
196
  **Output (`--json`)**: a receipt object
197
197
 
@@ -22,5 +22,6 @@ name: string
22
22
  displayName: string
23
23
  email: string
24
24
  admin: boolean
25
+ authorization: {credentialType: string | null, scopeVisibility: string, scopes: string[] | null, adminScope: boolean | null, note: string}
25
26
  organization: {id: string, name: string, urlKey: string}
26
27
  ```
package/src/cli.ts CHANGED
@@ -13,6 +13,8 @@ import { registerAgentSession } from "./commands/agent-session.js";
13
13
  import { registerAttach } from "./commands/attach.js";
14
14
  import { registerTeam } from "./commands/team.js";
15
15
  import { registerProject } from "./commands/project.js";
16
+ import { registerProjectStatus } from "./commands/project-status.js";
17
+ import { registerProjectLabel } from "./commands/project-label.js";
16
18
  import { registerProjectUpdate } from "./commands/project-update.js";
17
19
  import { registerMilestone } from "./commands/milestone.js";
18
20
  import { registerCycle } from "./commands/cycle.js";
@@ -70,6 +72,8 @@ export function createProgram(): Command {
70
72
  // Phase 2: teams, projects, milestones, cycles.
71
73
  registerTeam(program);
72
74
  registerProject(program);
75
+ registerProjectStatus(program);
76
+ registerProjectLabel(program);
73
77
  registerProjectUpdate(program);
74
78
  registerMilestone(program);
75
79
  registerCycle(program);
@@ -38,6 +38,10 @@ import { resolveTeam } from "../lib/resolve.js";
38
38
  import { ISSUE_SORTS } from "../services/issue.js";
39
39
  import { firstTeam, type Context } from "../context.js";
40
40
  import { openUrl } from "../lib/open.js";
41
+ import {
42
+ authorizationCapabilities,
43
+ credentialType as resolvedCredentialType,
44
+ } from "../lib/authorization.js";
41
45
  import {
42
46
  DEFAULT_OAUTH_SCOPES,
43
47
  buildAuthorizationUrl,
@@ -59,6 +63,7 @@ export const DEFAULT_OAUTH_CLIENT_ID = "eda60862e4bb8b8af82cfb3193b65c2f";
59
63
  const whoamiAction = action(async (ctx: Context) => {
60
64
  const me = await withRetry(() => ctx.client.viewer);
61
65
  const org = await withRetry(() => ctx.client.organization);
66
+ const authorization = authorizationCapabilities(ctx.config);
62
67
  ctx.output.detail(
63
68
  {
64
69
  id: me.id,
@@ -66,13 +71,17 @@ const whoamiAction = action(async (ctx: Context) => {
66
71
  displayName: me.displayName,
67
72
  email: me.email,
68
73
  admin: me.admin,
74
+ authorization,
69
75
  organization: { id: org.id, name: org.name, urlKey: org.urlKey },
70
76
  },
71
77
  [
72
78
  ["Name", me.name],
73
79
  ["Display name", me.displayName],
74
80
  ["Email", me.email],
75
- ["Admin", me.admin],
81
+ ["Workspace admin", me.admin],
82
+ ["Credential type", authorization.credentialType ?? "(none)"],
83
+ ["Credential scopes", authorization.scopes?.join(", ") ?? "unknown"],
84
+ ["Credential admin scope", authorization.adminScope ?? "unknown"],
76
85
  ["User ID", me.id],
77
86
  ["Organization", `${org.name} (${org.urlKey})`],
78
87
  ],
@@ -481,13 +490,8 @@ export function registerMeta(program: Command): void {
481
490
  const c = ctx.config;
482
491
  if (c.workspaceChoices) throw c.apiKeyError;
483
492
  const credential = c.accessToken ?? c.apiKey;
484
- const credentialType = c.oauthCredential
485
- ? "oauth-user"
486
- : c.accessToken
487
- ? "oauth-access-token"
488
- : c.apiKey
489
- ? "api-key"
490
- : null;
493
+ const credentialType = resolvedCredentialType(c);
494
+ const authorization = authorizationCapabilities(c);
491
495
  const source = c.accessToken ? c.accessTokenSource : c.apiKeySource;
492
496
  const backend = keyring();
493
497
  ctx.output.detail(
@@ -502,6 +506,9 @@ export function registerMeta(program: Command): void {
502
506
  expiresAt: c.oauthCredential
503
507
  ? new Date(c.oauthCredential.expiresAt).toISOString()
504
508
  : null,
509
+ scopeVisibility: authorization.scopeVisibility,
510
+ adminScope: authorization.adminScope,
511
+ scopeNote: authorization.note,
505
512
  },
506
513
  [
507
514
  ["Authenticated", !!credential],
@@ -511,6 +518,9 @@ export function registerMeta(program: Command): void {
511
518
  ["Credential", redactKey(credential)],
512
519
  ["Keyring", backend ? backend.label : "(none on this platform)"],
513
520
  ["Scopes", c.oauthCredential?.scopes.join(", ")],
521
+ ["Scope visibility", authorization.scopeVisibility],
522
+ ["Admin scope", authorization.adminScope ?? "unknown"],
523
+ ["Scope note", authorization.note],
514
524
  [
515
525
  "Expires",
516
526
  c.oauthCredential ? new Date(c.oauthCredential.expiresAt).toISOString() : undefined,