schpet/linear-cli(新しいタブで開きます)
主要言語: Rust
linear without leaving the command line: list, start, and create PRs for linear issues. agent friendly.
- star 数
- 1,030
- watcher 数
- 2
- fork 数
- 93
- issue 数
- 14
- 最終更新
- 2026/10/23
主要言語: Rust
linear without leaving the command line: list, start, and create PRs for linear issues. agent friendly.
a cli to list, start and create issues in the linear issue tracker. git and jj aware to keep you in the right views in linear. allows jumping to the web or the linear desktop app similar to gh.
works great with AI agents — the CLI includes a skill that lets agents create issues, update status, and manage your Linear workflow alongside your code.
here's how it works:
linear config # setup your repo, it writes a config file linear issue list # list unstarted issues assigned to you linear issue query --all-teams # query issues across all teams linear issue query --search "login bug" # search issues in your configured team linear issue start # choose an issue to start, creates a branch linear issue start ABC-123 # start a specific issue linear issue view # see current branch's issue as markdown linear issue pr # makes a PR with title/body preset, using gh cli linear issue create # create a new issue
it aims to be a complement to the web and desktop apps that lets you stay on the command line in an interactive or scripted way.
linear issue create -i
linear issue start
brew install schpet/tap/linear
install as a dev dependency to pin a version in your project:
npm install -D @schpet/linear-cli # or bun add -D @schpet/linear-cli # or pnpm add -D @schpet/linear-cli
then run via your package manager:
npx linear issue list bunx linear issue list
note: this package ships pre-built binaries
package on npm: @schpet/linear-cli
for macOS and Linux:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/schpet/linear-cli/releases/latest/download/linear-installer.sh | sh
https://github.com/schpet/linear-cli/releases/latest
with a rust toolchain installed:
cargo install --locked --git https://github.com/schpet/linear-cli linear
upgrading from 2.x? see upgrading from 2.x in the changelog.
create an API key at linear.app/settings/account/security1
authenticate with the CLI:
linear auth login
configure your project:
cd my-project-repo
linear configsee docs/authentication.md for multi-workspace support and other authentication options.
the CLI works with both git and jj version control systems:
eng-123-my-feature). use linear issue start or linear UI's 'copy git branch name' button and related automations.Linear-issue trailers in your commit descriptions. use linear issue start to automatically add the trailer, or add it manually with jj describe, e.g. jj describe "$(linear issue describe ABC-123)"the current issue is determined by:
eng-123-my-feature)Linear-issue trailer in the current or ancestor commitsnote that Linear's GitHub integration will suggest git branch names.
linear issue view # view current issue details in terminal linear issue view ABC-123 linear issue view 123 linear issue view -w # open issue in web browser linear issue view -a # open issue in Linear.app linear issue id # prints the issue id from current branch (e.g., "ENG-123") linear issue title # prints just the issue title linear issue url # prints the Linear.app URL for the issue linear issue pr # creates a GitHub PR with issue details via `gh pr create` linear issue list # list your issues in a table view (supports -s/--state and --sort) linear issue list --project "My Project" --milestone "Phase 1" # filter by milestone 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 all # export all issues as JSON linear issue start # create/switch to issue branch and mark as started linear issue create # create a new issue, asking for the title linear issue create -i # create a new issue, asking for every field linear issue create -t "title" -d "description" # create with flags linear issue create --project "My Project" --milestone "Phase 1" # create with milestone linear issue create --template "Bug report" -t "Login fails" # create from a template (see template commands) linear issue update ENG-123 -s started # change only the fields you pass linear issue update ENG-123 --milestone "Phase 2" # set milestone on existing issue linear issue update ENG-123 --clear-due-date --clear-parent # remove values (also --clear-estimate, --clear-project, --clear-milestone, --clear-cycle, --unassign) linear issue archive ENG-123 --yes # archive an issue (Linear normally auto-archives closed issues; see docs/usage.md) linear issue archive --yes --bulk ENG-123 ENG-124 # archive several issues linear issue delete # delete an issue linear issue comment list # list comments on current issue linear issue comment add # add a comment to current issue linear issue comment add --reply-to <id> # reply to a comment (-p / --parent are aliases) linear issue comment list --json # comments as JSON, with quotedText and parent for inline comments and replies linear issue comment update <id> # update a comment linear issue commits # show all commits for an issue (jj only)
attach files to an issue or comment. uploads are private by default (readable only by workspace members), matching the Linear web app.
linear issue attach ENG-123 ./screenshot.png # attach a file to an issue linear issue attach ENG-123 ./doc.pdf -t "Spec" # custom attachment title linear issue attach ENG-123 ./img.png -c "see this" # add a linked comment linear issue comment add ENG-123 -a ./screenshot.png # attach a file to a comment linear issue comment add ENG-123 -a ./a.png -a ./b.png # attach multiple files
by default attachments are private. pass --public to upload raster images (png/jpeg/gif/webp/bmp/tiff) to a public public.linear.app URL readable by anyone, unauthenticated — useful for sharing outside the workspace, but a warning is printed since it bypasses workspace access controls. non-image files cannot be made public.
linear issue attach ENG-123 ./screenshot.png --public # public image URL linear issue comment add ENG-123 -a ./screenshot.png --public # public image URL
linear team list # list teams linear team list --json # as JSON, e.g. to map a team name to its key or id in scripts linear team id # print the configured team key (e.g. for scripts) linear team members # list team members linear team members --all --json # include inactive members, as JSON linear team create # create a new team linear team autolinks # configure GitHub repository autolinks for Linear issues
linear user list # list everyone in the workspace linear user list --all # include deactivated members linear user list --json # machine-readable output
linear project list # list projects linear project view https://linear.app/acme/project/mobile-launch-272f50ef9250 # paste a URL from Linear linear project view # pick from a searchable list of projects linear project view <projectId> # overview, milestones, resources, documents, related projects linear project view "Mobile launch" # a UUID, slug ID, or exact name all work linear project view <projectId> --json # project details as JSON linear project create --name "API v2" --team ENG --content-file overview.md linear project create --name "Mobile launch" --team APP --priority high --label Launch --member jane@example.com linear project create --name "Q3 launch" --team APP --template "Kickoff" # create from a project template linear project update <projectId> --content-file overview.md # replace the project's overview body linear project update <projectId> --clear-lead --clear-target-date # remove values (also --clear-start-date) linear project update <projectId> --add-team OPS --remove-label Launch --add-initiative "Q4 Bets" # change teams, labels, initiatives incrementally linear project update <projectId> --team ENG --team OPS # replace the whole team set (--label and --initiative replace likewise) linear project comment list <project> # list the project's discussion thread (UUID, slug, or name) linear project comment add <project> --body "Kickoff Monday" # comment on a project linear project comment add <project> --body "+1" --reply-to <commentId> # reply in a thread
linear initiative list # list initiatives linear initiative view <initiative> # view an initiative (UUID, slug, or name) linear initiative comment list <initiative> # list the initiative's discussion thread linear initiative comment add <initiative> --body-file note.md # comment on an initiative linear initiative comment add <initiative> --body "+1" --reply-to <commentId> # reply in a thread
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
linear milestone list --project <projectId> # list milestones for a project linear m list --project <projectId> # list milestones (alias) linear milestone list --project <projectId> --json # as JSON linear milestone view <milestoneId> # view milestone details linear m view <milestoneId> # view milestone (alias) linear milestone view <milestoneId> --all # list every issue, not just the first 10 linear milestone view <milestoneId> --json # milestone with every issue, as JSON linear milestone create --project <projectId> --name "Q1 Goals" --target-date "2026-03-31" # create a milestone linear m create --project <projectId> # create a milestone, asking for its name linear milestone update <milestoneId> --name "New Name" # update milestone name linear m update <milestoneId> --target-date "2026-04-15" # update target date linear milestone delete <milestoneId> # delete a milestone linear m delete <milestoneId> --yes # delete without confirmation
manage Linear documents from the command line. every document is attached to exactly one target: a project, issue, initiative, team, cycle, or release (Linear's API requires one).
# list documents linear document list # list all accessible documents linear docs list # alias for document linear document list --project <project> # filter by project (UUID, slug ID, or name) linear document list --issue TC-123 # filter by issue linear document list --team ENG # filter by team linear document list --initiative <initiative> # filter by initiative linear document list --team ENG --cycle active # filter by cycle (team scopes the lookup) linear document list --release <release> # filter by release (UUID, name, or version) linear document list --json # output as JSON # view a document linear document view <slug> # view document rendered in terminal linear document view <slug> --raw # output raw markdown (for piping) linear document view <slug> --web # open in browser linear document view <slug> --json # output as JSON, including document comments # comment on a document linear document comment list <slug> # list comments; inline comments show the text they quote linear document comment list <slug> --json # comments as JSON (quotedText, parent, ...) linear document comment add <slug> --body "Looks good" # add a top-level comment linear document comment add <slug> --body-file note.md --reply-to <commentId> # reply in a thread # create a document (exactly one attachment target is required) linear document create --title "Doc" --project <project> # attach to project linear document create --title "Notes" --issue TC-123 # attach to issue linear document create --title "Handbook" --team ENG # attach to team linear document create --title "Brief" --initiative <initiative> # attach to initiative linear document create --title "Sprint" --team ENG --cycle next # attach to cycle linear document create --title "Notes" --release 2026.8 # attach to release linear document create --title "Spec" --content-file ./spec.md --project <project> # content from file cat spec.md | linear document create --title "Spec" --project <project> # content from stdin # update a document linear document update <slug> --title "New Title" # update title linear document update <slug> --content-file ./updated.md # update content linear document update <slug> --edit # open in $EDITOR linear document update <slug> --team ENG # re-point attachment (replaces current) linear document update <slug> --content-file ./updated.md --force # bypass comment-anchor guard # delete a document linear document delete <slug> # soft delete (move to trash) linear document delete --bulk <slug1> <slug2> # bulk delete
content updates are refused by default when a document has active inline Linear comments, because replacing markdown can detach or hide those anchors. top-level document comments do not block updates. review the inline comment first, then rerun with --force if you intentionally want to replace the content anyway.
linear template list # every issue, project, and document template in the workspace linear template list --type issue --team ENG # ENG's issue templates plus workspace-level ones linear template list --json # the raw template objects (templateData is a JSON-encoded string) linear template view "Bug report" # what the template pre-fills: title, priority, labels, body, sub-issues, ... linear template view <template-id> --json # raw GraphQL object; `jq '.templateData | fromjson'` decodes the data # apply a template on create (name or ID). Linear fills the template in server-side. linear issue create --team ENG --template "Bug report" # the template supplies the title linear issue create --team ENG --template "Bug report" -t "Login fails" -l security # flags override, labels merge linear project create --name "Q3 launch" --team APP --template "Kickoff"
--template takes the place of the team's default template, so it never needs --no-use-default-template (passing both is fine). Anything you pass explicitly overrides the template's value; --label merges with the template's labels; --description replaces the template body, so leave it out to keep the body. Document templates can be listed and viewed, but Linear's API has no way to apply one when creating a document.
linear --help # show all commands linear --version # show version linear config # setup the project linear completions # generate shell completions
the CLI supports configuration via environment variables or a .linear.toml config file. environment variables take precedence over config file values.
| option | env var | toml key | example | description |
|---|---|---|---|---|
| Team ID | LINEAR_TEAM_ID |
team_id |
"ENG" |
default team for operations |
| Workspace | LINEAR_WORKSPACE |
workspace |
"mycompany" |
workspace slug for web/app URLs |
| Issue sort | LINEAR_ISSUE_SORT |
issue_sort |
"priority" or "manual" |
how to sort issue lists |
| Ask project | LINEAR_ISSUE_CREATE_ASK_PROJECT |
issue_create_ask_project |
true or false |
ask for a project during interactive issue create |
| Assign self | LINEAR_ISSUE_CREATE_ASSIGN_SELF |
issue_create_assign_self |
"always", "auto", or "never" |
control default self-assignment during issue creation |
| VCS | LINEAR_VCS |
vcs |
"git" or "jj" |
version control system (default: git) |
| Download images | LINEAR_DOWNLOAD_IMAGES |
download_images |
true or false |
download images when viewing issues |
| PR template | LINEAR_PR_TEMPLATE |
pr_template |
".github/pull_request_template.md" |
template file for issue pr bodies (the Linear issue URL is appended; --no-template skips it) |
settings are read from two config files, a project file and a global file. each option takes the first value it finds in this order:
.env file (the shell wins)./linear.toml, ./.linear.toml, then linear.toml, .linear.toml, or .config/linear.toml at the repository root$XDG_CONFIG_HOME/linear/linear.toml (or ~/.config/linear/linear.toml) on macOS and Linux, %APPDATA%\linear\linear.toml on Windowsso the global file can hold defaults such as issue_sort, and a repository's .linear.toml overrides them for that project. every value is validated, even one a higher tier overrides, and an invalid value is an error naming its file and key.
scripts can tell why a command failed from its exit status, without parsing the error message:
| status | meaning |
|---|---|
0 |
success |
1 |
any other failure, including GraphQL errors such as an invalid query in linear api |
2 |
usage error: bad flags or values, rejected before anything is sent to Linear |
3 |
not found: an issue, team, project, or other entity the command looked up does not exist |
4 |
authentication: no usable API key, or Linear rejected it (revoked, mistyped, or lacking access) |
5 |
unavailable: Linear could not be reached, timed out, rate limited the request, or failed with a server error. Retrying later may work, but a create or update may still have taken effect |
130 |
cancelled at a prompt or in the editor |
a bulk command (--bulk) that fails for several reasons exits with the first of 4, 5, 1, 3 among them, so 3 means every failure was a missing item. linear --help lists the statuses too.
linear-cli includes a skill that helps AI agents use the CLI effectively. for use cases outside the CLI, it includes instructions to interact directly with the graphql api, including authentication.
install the skill using claude code's plugin system:
# from claude code /plugin marketplace add schpet/linear-cli /plugin install linear-cli@linear-cli # from bash claude plugin marketplace add schpet/linear-cli claude plugin install linear-cli@linear-cli # to update claude plugin marketplace update linear-cli claude plugin update linear-cli@linear-cli
install the skill using skills.sh:
npx skills add schpet/linear-cli
view the skill at skills.sh/schpet/linear-cli/linear-cli
linear-cli is written in rust; the toolchain is pinned in rust-toolchain.toml. common tasks are in the justfile:
just dev issue list # run the cli from source (cargo run -- issue list) just install # install this checkout as `linear` just check # cargo fmt --check, clippy, and tests, as CI runs them
the skill's command list and skills/linear-cli/references/ are generated from the cli's help. edit skills/linear-cli/SKILL.template.md, then regenerate:
just skill-docs
graphql/schema.graphql is linear's api schema, used to type-check every query at compile time. refresh it with a logged in cli:
just sync-schema
linear's UI is incredibly good but it slows me down. i find the following pretty grating to experience frequently:
this cli solves this. it knows what you're working on (via git branches or jj commit trailers), does the work of managing your version control state, and will write your pull request details for you.
creating an API key requires member access, it is not available for guest accounts. ↩