Skip to content

About

linear without leaving the command line: list, start, and create PRs for linear issues. agent friendly.

Topics

Resources

Contributing

Stars

989 stars

Watchers

2 watching

Forks

Latest commit

 

History

530 Commits

Folders and files

Repository files navigation

linear cli

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.

screencast demos

linear issue create -i screencast showing the linear issue create -i command, interactively adding issue details
linear issue start screencast showing the linear issue start command, interactively choosing an issue to start

install

homebrew

brew install schpet/tap/linear

npm / bun / pnpm

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

shell installer

for macOS and Linux:

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/schpet/linear-cli/releases/latest/download/linear-installer.sh | sh

binaries

https://github.com/schpet/linear-cli/releases/latest

from source

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.

setup

  1. create an API key at linear.app/settings/account/security1

  2. authenticate with the CLI:

    linear auth login
  3. configure your project:

    cd my-project-repo
    linear config

see docs/authentication.md for multi-workspace support and other authentication options.

the CLI works with both git and jj version control systems:

  • git: works best when your branches include Linear issue IDs (e.g. eng-123-my-feature). use linear issue start or linear UI's 'copy git branch name' button and related automations.
  • jj: detects issues from 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)"

commands

issue commands

the current issue is determined by:

  • git: the issue id in the current branch name (e.g. eng-123-my-feature)
  • jj: the Linear-issue trailer in the current or ancestor commits

note 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)

attaching files

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

team commands

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

user commands

linear user list        # list everyone in the workspace
linear user list --all  # include deactivated members
linear user list --json # machine-readable output

project commands

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

initiative commands

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

cycle commands

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

milestone commands

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

document commands

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.

template commands

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.

other commands

linear --help          # show all commands
linear --version       # show version
linear config          # setup the project
linear completions     # generate shell completions

configuration options

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:

  1. a command-line flag, where the command has one
  2. an environment variable, from the shell or a .env file (the shell wins)
  3. the project config file: the first that exists of ./linear.toml, ./.linear.toml, then linear.toml, .linear.toml, or .config/linear.toml at the repository root
  4. the global config file: $XDG_CONFIG_HOME/linear/linear.toml (or ~/.config/linear/linear.toml) on macOS and Linux, %APPDATA%\linear\linear.toml on Windows

so 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.

exit status

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.

skills

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.

claude code

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

skills.sh for other agents

install the skill using skills.sh:

npx skills add schpet/linear-cli

view the skill at skills.sh/schpet/linear-cli/linear-cli

development

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

updating skill documentation

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

updating the graphql schema

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

why

linear's UI is incredibly good but it slows me down. i find the following pretty grating to experience frequently:

  • switching context from my repo to linear
  • not being on the right view when i open linear
  • linear suggests a git branch, but i have to do the work of creating or switching to that branch
  • linear's suggested git branch doesn't account for it already existing or having a merged pull request

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.

Footnotes

  1. creating an API key requires member access, it is not available for guest accounts. ↩

About

linear without leaving the command line: list, start, and create PRs for linear issues. agent friendly.

Topics

Resources

Contributing

Stars

989 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages