From c276c1508c0c6c46ac37eb0226c46002b8187986 Mon Sep 17 00:00:00 2001 From: Peter Schilling Date: Fri, 4 Sep 2026 11:30:14 -0700 Subject: [PATCH] Accept team names and IDs, and state names, wherever the CLI takes them Every command that takes a team now accepts its key, name, or UUID through one shared resolver (findTeam / resolveTeam / resolveTeams), replacing the key-only getTeamIdByKey and the ad-hoc uppercasing spread across commands. One aliased ResolveTeam operation looks up key, name, and (for UUID-shaped input) id in a single round trip; precedence is key, then id, then name, applied client-side so a reference that equals one team's key and another team's name always means the key. Keys stay the canonical downstream form: filters that matched on team.key still do, with the server's uppercase key, and callers that need a UUID take it from the same resolved object. An unknown team now errors with the list of valid keys instead of an empty result or a raw "Entity not found" from the API. Only explicit input goes through the resolver. The configured default team is already a normalized key, and resolving it would add a round trip to every default-team invocation of the most-used commands for no gain. In issue create, the interactive substring picker survives only for that default; an explicit --team that matches nothing errors like everywhere else. issue query --state and issue mine --state take a workflow state name or ID as well as the six type tokens. Names and IDs are resolved within the queried scope (the team, the teams, or the whole workspace under --all-teams, where a name matches every team's same-named state), so a state from another team errors instead of silently matching nothing, and the error lists the scope's states. Type-only input still sends the same { type: { in } } filter with no extra request; a mix of types and names becomes an or-filter. The MCP server already describes these parameters as "key, name, or ID" and "type, name, or ID"; this brings the CLI to parity so an agent does not need a preliminary team list to translate a name into a key. Claude-Session: https://claude.ai/code/session_01A9qEGri4p2HZMQSuYsBmub --- CHANGELOG.md | 2 + README.md | 3 +- docs/usage.md | 12 +- skills/linear-cli/references/cycle.md | 12 +- skills/linear-cli/references/document.md | 7 +- skills/linear-cli/references/issue.md | 88 ++-- skills/linear-cli/references/label.md | 31 +- skills/linear-cli/references/project.md | 6 +- skills/linear-cli/references/team.md | 34 +- src/commands/cycle/cycle-list.ts | 12 +- src/commands/cycle/cycle-view.ts | 12 +- src/commands/document/attachment-target.ts | 14 +- src/commands/document/document-create.ts | 2 +- src/commands/document/document-list.ts | 2 +- src/commands/document/document-update.ts | 2 +- src/commands/issue/issue-create.ts | 64 +-- src/commands/issue/issue-mine.ts | 41 +- src/commands/issue/issue-query.ts | 71 ++-- src/commands/issue/issue-start.ts | 2 +- src/commands/issue/issue-update.ts | 21 +- src/commands/label/label-create.ts | 18 +- src/commands/label/label-delete.ts | 13 +- src/commands/label/label-list.ts | 17 +- src/commands/project/project-create.ts | 13 +- src/commands/project/project-list.ts | 58 +-- src/commands/project/project-update.ts | 15 +- src/commands/team/team-delete.ts | 18 +- src/commands/team/team-members.ts | 17 +- src/commands/team/team-states.ts | 21 +- src/utils/linear.ts | 338 ++++++++++++++- .../__snapshots__/cycle-list.test.ts.snap | 32 +- .../__snapshots__/cycle-view.test.ts.snap | 6 +- test/commands/cycle/cycle-list.test.ts | 60 ++- test/commands/cycle/cycle-view.test.ts | 22 +- .../document-create.test.ts.snap | 2 +- .../__snapshots__/document-list.test.ts.snap | 16 +- .../document-update.test.ts.snap | 3 +- .../commands/document/document-create.test.ts | 26 +- test/commands/document/document-list.test.ts | 69 ++- .../commands/document/document-update.test.ts | 12 +- .../__snapshots__/issue-create.test.ts.snap | 21 +- .../__snapshots__/issue-list.test.ts.snap | 36 +- .../__snapshots__/issue-mine.test.ts.snap | 54 ++- .../__snapshots__/issue-query.test.ts.snap | 313 ++++++++++++-- .../__snapshots__/issue-update.test.ts.snap | 13 +- test/commands/issue/issue-create.test.ts | 194 ++++++--- test/commands/issue/issue-list.test.ts | 6 +- test/commands/issue/issue-mine.test.ts | 161 ++++++- test/commands/issue/issue-query.test.ts | 237 ++++++++++- test/commands/issue/issue-update.test.ts | 362 ++++++++++++---- .../__snapshots__/label-create.test.ts.snap | 34 ++ .../__snapshots__/label-delete.test.ts.snap | 29 ++ .../__snapshots__/label-list.test.ts.snap | 25 ++ test/commands/label/label-create.test.ts | 61 +++ test/commands/label/label-delete.test.ts | 71 ++++ test/commands/label/label-list.test.ts | 54 ++- .../__snapshots__/project-create.test.ts.snap | 12 +- .../__snapshots__/project-list.test.ts.snap | 23 +- .../__snapshots__/project-update.test.ts.snap | 2 +- test/commands/project/project-create.test.ts | 101 ++++- test/commands/project/project-list.test.ts | 47 ++ .../__snapshots__/team-delete.test.ts.snap | 38 ++ .../__snapshots__/team-members.test.ts.snap | 4 +- .../__snapshots__/team-states.test.ts.snap | 74 +++- test/commands/team/team-delete.test.ts | 113 +++++ test/commands/team/team-members.test.ts | 7 + test/commands/team/team-states.test.ts | 77 ++++ test/utils/linear.test.ts | 400 ++++++++++++++++++ test/utils/test-helpers.ts | 18 + 69 files changed, 3197 insertions(+), 604 deletions(-) create mode 100644 test/commands/label/__snapshots__/label-create.test.ts.snap create mode 100644 test/commands/label/__snapshots__/label-delete.test.ts.snap create mode 100644 test/commands/label/label-create.test.ts create mode 100644 test/commands/label/label-delete.test.ts create mode 100644 test/commands/team/__snapshots__/team-delete.test.ts.snap create mode 100644 test/commands/team/team-delete.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 820c2b6a..db0ed4b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Added +- every command that takes a team now accepts its key, name, or UUID, resolved through one shared lookup: `team states`, `team members`, `team delete`, `label list/create/delete --team`, `cycle list/view --team`, `project list/create/update --team`, `document list/create/update --team`, and `issue query/mine/create/update --team`. Keys stay canonical and win over a same-spelled name; an unknown team errors with the list of valid keys instead of an empty result or a raw API error. Previously only keys worked, which is why [#276](https://github.com/schpet/linear-cli/issues/276) asked for `team list --json` as a name-to-key lookup +- `issue query --state` and `issue mine --state` accept a workflow state name or ID as well as the six state types, looked up within the queried team scope (all teams under `--all-teams`, where a name matches every team's same-named state). An unknown name errors and lists the scope's states, and types and names can be mixed - `project update --content ` and `--content-file ` replace a project's long-form overview body, matching the flags `project create` already had. Previously the only way to change the body after creation was a hand-written `projectUpdate` mutation through `linear api` - `--json` (`-j`) on `team list`, `cycle list`, `cycle view`, `milestone list`, `milestone view`, and `project view`, the last read commands without machine-readable output. List commands emit the same `{ nodes, pageInfo }` connection shape as the other list commands, after the same filtering and ordering as the table; view commands emit the GraphQL object as fetched, including every issue rather than the ten-item preview, and `milestone view --all --json` includes every page. (A 2.0.0 entry claimed `cycle list --json`; that change never actually landed.) ([#276](https://github.com/schpet/linear-cli/issues/276); thanks @lakardion) diff --git a/README.md b/README.md index 1bb974cf..3d6caa4b 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ linear issue list -w # open issue list in web browser linear issue list -a # open issue list in Linear.app linear issue query --search "login bug" # search issues by text in your configured team linear issue query --search "oauth timeout" --team ENG --json # structured search output for agents +linear issue query --team "Engineering" --state "In Review" --json # teams by key, name, or ID; states by type, name, or ID linear issue query --all-teams --json --limit 0 # export all issues as JSON linear issue start # create/switch to issue branch and mark as started linear issue create # create a new issue (interactive prompts) @@ -205,7 +206,7 @@ linear project update --content-file overview.md # replace the proj ### cycle commands ```bash -linear cycle list --team ENG # list a team's cycles +linear cycle list --team ENG # list a team's cycles (--team takes a key, name, or ID) linear cycle list --team ENG --json # as JSON linear cycle view 12 --team ENG # view a cycle by number or name linear cycle view 12 --team ENG --json # cycle details and its issues, as JSON diff --git a/docs/usage.md b/docs/usage.md index cb481cb2..df690608 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -35,6 +35,10 @@ linear issue list --all-states # List multiple states linear issue list --state unstarted --state started + +# A state name or ID works too, and mixes with types +linear issue list --state "In Review" +linear issue list --state started --state "In Review" ``` filter by assignee: @@ -56,8 +60,9 @@ linear issue list --all-assignees other options: ```bash -# List issues for specific team +# List issues for specific team (key, name, or ID) linear issue list --team TEAM +linear issue list --team "Team Name" # Sort by priority instead of manual order linear issue list --sort priority @@ -138,7 +143,7 @@ linear issue create --estimate 3 # Create with labels linear issue create --label bug --label frontend -# Create for specific team +# Create for specific team (key, name, or ID) linear issue create --team TEAM # Create and start working on it @@ -210,6 +215,8 @@ linear issue delete TEAM-123 ### teams +wherever a command takes a team, pass its key, its name, or its UUID. keys are canonical; an unknown team errors and lists the valid keys. + #### list teams ```bash @@ -237,6 +244,7 @@ list members of a specific team: ```bash linear team members TEAM +linear team members "Team Name" ``` #### create a team diff --git a/skills/linear-cli/references/cycle.md b/skills/linear-cli/references/cycle.md index 762b4f37..a2500685 100644 --- a/skills/linear-cli/references/cycle.md +++ b/skills/linear-cli/references/cycle.md @@ -37,9 +37,9 @@ Description: Options: - -h, --help - Show this help. - --workspace - Target workspace (uses credentials) - --team - Team key (defaults to current team) + -h, --help - Show this help. + --workspace - Target workspace (uses credentials) + --team - Team key, name, or ID (defaults to current team) -j, --json - Output as JSON ``` @@ -56,8 +56,8 @@ Description: Options: - -h, --help - Show this help. - --workspace - Target workspace (uses credentials) - --team - Team key (defaults to current team) + -h, --help - Show this help. + --workspace - Target workspace (uses credentials) + --team - Team key, name, or ID (defaults to current team) -j, --json - Output as JSON ``` diff --git a/skills/linear-cli/references/document.md b/skills/linear-cli/references/document.md index 3b81e037..9fecfb2d 100644 --- a/skills/linear-cli/references/document.md +++ b/skills/linear-cli/references/document.md @@ -53,7 +53,7 @@ Options: --project - Attach to project (UUID, slug ID, or name) --issue - Attach to issue (identifier like TC-123) --initiative - Attach to initiative (UUID, slug ID, or name) - --team - Attach to team (key); with --cycle, scopes the cycle lookup instead + --team - Attach to team (key, name, or ID); with --cycle, scopes the cycle lookup instead --cycle - Attach to cycle: name, number, 'active'/'now', 'next', 'previous', or a relative offset like +1 (team from --team or config) --release - Attach to release (UUID, name, or version) @@ -100,7 +100,7 @@ Options: --project - Filter by project (UUID, slug ID, or name) --issue - Filter by issue (identifier like TC-123) --initiative - Filter by initiative (UUID, slug ID, or name) - --team - Filter by team (key); with --cycle, scopes the cycle lookup instead + --team - Filter by team (key, name, or ID); with --cycle, scopes the cycle lookup instead --cycle - Filter by cycle: name, number, 'active'/'now', 'next', 'previous', or a relative offset like +1 (team from --team or config) --release - Filter by release (UUID, name, or version) @@ -135,7 +135,8 @@ Options: --project - Re-point to project (UUID, slug ID, or name); replaces the current attachment --issue - Re-point to issue (identifier like TC-123); replaces the current attachment --initiative - Re-point to initiative (UUID, slug ID, or name); replaces the current attachment - --team - Re-point to team (key); with --cycle, scopes the cycle lookup instead + --team - Re-point to team (key, name, or ID); with --cycle, scopes the cycle lookup + instead --cycle - Re-point to cycle: name, number, 'active'/'now', 'next', 'previous', or a relative offset like +1 (team from --team or config) --release - Re-point to release (UUID, name, or version); replaces the current attachment diff --git a/skills/linear-cli/references/issue.md b/skills/linear-cli/references/issue.md index 23fca896..3df9f9d7 100644 --- a/skills/linear-cli/references/issue.md +++ b/skills/linear-cli/references/issue.md @@ -271,7 +271,7 @@ Options: -d, --description - Description of the issue --description-file - Read description from a file (preferred for markdown content) -l, --label