CLI tool
schpet/linear-cli avatar
schpet/linear-cli

linear-cli puts the Linear issue tracker in the terminal

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

1,018 stars90 forksRustISC

At a glance

What is it?
linear-cli is a Rust client for Linear that lists, starts and creates issues without leaving the shell, works out which issue you are on from either a git branch name or a Jujutsu commit trailer, can open the web app or the desktop app, and ships a skill so coding agents can drive it too.
Who is it for?
linear-cli is worth adopting if your team runs Linear and wants the issue tracker to be reachable from a terminal, because the part that is genuinely hard, working out which issue the current branch or commit refers to, is handled for both git and Jujutsu, and the agent oriented JSON output and skill make it usable from a tool that is not a human.
Can I use it commercially?
Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The current issue is inferred, not asked for

The readme describes the tool as a CLI to list, start and create issues in the Linear issue tracker, and it says it is git and jj aware to keep you in the right views in Linear. That phrase, the right views, is the whole point of the project.

The mechanism is in the commands section. The current issue is determined in one of two ways. With git, it is the issue id in the current branch name, for example eng-123-my-feature. With jj, it is the Linear-issue trailer in the current or ancestor commits. And the readme notes that Linear's GitHub integration will suggest git branch names in that format.

So the workflow is: you are on a branch, the CLI reads the branch, it knows you are working on ENG-123, and every command that needs an issue identifier takes it from where you already are. That is what keeps the issue tracker and the code in sync without you passing identifiers around, and it is why the project is compatible with both git and Jujutsu, the version control system whose documentation it links.

The commands reflect it. linear issue view shows the current branch's issue as markdown. linear issue id prints the issue id from the current branch, for example ENG-123. linear issue title prints just the title, and linear issue url prints the Linear.app URL. And linear issue start creates or switches to the issue branch and marks the issue as started, with a variant that takes a specific identifier, linear issue start ABC-123.

The audience is a developer who wants Linear to behave like git and gh do, in an interactive shell or in a script.

Two version control systems, two conventions

The setup section of the readme spends a paragraph on how each version control system is expected to name things, and it is worth quoting the substance because getting it wrong makes every command fail.

For git, it works best when your branches include Linear issue IDs, for example eng-123-my-feature. You get that by using linear issue start, or the copy git branch name button in the Linear UI, along with the related automations that Linear documents for git.

For jj, the CLI detects issues from Linear-issue trailers in your commit descriptions. The readme gives two ways to get the trailer in place: linear issue start adds it automatically, or you add it yourself with jj describe, for example jj describe "$(linear issue describe ABC-123)".

The reason the CLI exposes an issue describe command at all is that it is a piece of the integration rather than an issue command. It emits the trailer text, and the shell command substitution pipes it into jj describe, which writes it into the commit. That is a small design decision with a large effect on how much typing a Jujutsu user has to do.

There is one more command that only makes sense in one of the two systems: linear issue commits, which shows all commits for an issue, and the readme marks it as jj only. In git the equivalent information is already in the branch history, so the command exists for the case where the mapping lives in the commit metadata instead of the branch name.

And the comment subcommands have the same shape. linear issue comment add can reply to an existing comment with --reply-to, with -p and --parent as aliases, and linear issue comment list --json returns comments as JSON with quotedText and parent for inline comments and replies.

Listing, querying, creating and updating

The command surface is wide, and the readme groups it under issue commands, so it is worth taking the important shapes at once.

Listing is linear issue list, described as listing your issues in a table view, with a -s or --state filter, a --sort option, and filters for --project and --milestone. The -w flag opens the issue list in a web browser and -a opens it in Linear.app, which is the same jump-to-the-app pattern you get from a gh command.

Querying is separate from listing. linear issue query searches issues by text in your configured team, with --all-teams to search across every team. The query command takes richer filters, teams by key, name or ID and states by type, name or ID, and the --json output is described as structured search output for agents. The export form, linear issue query --all-teams --json --limit all, dumps every issue as JSON.

Creating is linear issue create, which asks for the title, or asks for every field with -i, or takes everything as flags with -t and -d, and can set --project and --milestone, and can build from a template with --template.

Updating is linear issue update, and the readme makes a point of the shape: you change only the fields you pass, linear issue update ENG-123 -s started. There is a matching set of clearing flags, --clear-due-date, --clear-parent, and the readme adds --clear-estimate, --clear-project, --clear-milestone, --clear-cycle, and --unassign. And there is archiving, linear issue archive ENG-123 --yes, with a bulk form for several identifiers, and a note that Linear normally auto-archives closed issues.

The pull request command is a wrapper around gh

One command in the list deserves its own paragraph, because it tells you what the tool is and is not.

linear issue pr makes a PR with the title and body preset, and it does it using the gh cli. Elsewhere the readme describes the project as allowing jumping to the web or the Linear desktop app similar to gh.

So the relationship is explicit. Electron-PDF, to use the analogy the readme itself makes, is the gh of the issue tracker, and this is the gh of the pull request. The command does not implement GitHub authentication or the GitHub API, it prepares the PR description from the Linear issue and hands the work to gh pr create, which the readme states explicitly as the mechanism.

That has two consequences. The first is a dependency: using linear issue pr means having the GitHub CLI installed and authenticated, which is a reasonable thing to assume in a GitHub-centric workflow and a real constraint in a GitLab or Bitbucket one. The second is that the preset title and body are the part this project controls, and the rest is gh's behaviour, including its flags and its error messages.

For a team whose workflow is Linear plus GitHub, this is the pragmatic choice, and it means the tool does not duplicate functionality that gh already does well. For a team on a different forge, the command is simply not usable, and the rest of the CLI still is.

Four installation routes

The install section is a good illustration of a project that expects several kinds of user, because it offers four ways to get the binary.

Homebrew is the first, and it installs a globally available command:

bash
brew install schpet/tap/linear

Then npm, bun and pnpm, installed as a development dependency so the version is pinned in your project:

bash
npm install -D @schpet/linear-cli
# or
bun add -D @schpet/linear-cli
# or
pnpm add -D @schpet/linear-cli

and run through the package manager with npx linear issue list or bunx linear issue list. The readme notes that this package ships pre-built binaries, which is the point of the npm route, and the package is published as @schpet/linear-cli.

For macOS and Linux there is a shell installer:

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

Binaries are also published directly on the releases page, and from source with a Rust toolchain installed:

bash
cargo install --locked --git https://github.com/schpet/linear-cli linear

The setup sequence is three steps. Create an API key in the Linear account security settings, authenticate with linear auth login, and then run linear config in the project directory, which writes a config file. The documentation points at docs/authentication.md for multi-workspace support and other authentication options, which suggests that the single key model is the simple case and that a team with several workspaces needs more.

And there is a migration note for anyone on the 2.x line, with the changelog holding a section on upgrading from 2.x.

Built for agents: a skill, JSON output and a generated schema

The project description ends with two words that explain a lot of the design, agent friendly, and the readme expands on it.

The CLI includes a skill that lets agents create issues, update status and manage your Linear workflow alongside your code. The repository makes that concrete. There is a skills directory with skills/linear-cli/SKILL.md and its references, and the justfile has a target that regenerates it. The skill-docs target runs an example, cargo run --locked --quiet --example skill_docs, and the comment on that line says it regenerates skills/linear-cli/SKILL.md and its references from the cli's help.

That is a neat loop. The agent facing documentation is generated from the binary's own help output, so the two cannot drift apart.

The other agent facing piece is the GraphQL schema. There is a graphql directory with schema.graphql, and the justfile target sync-schema refreshes it from Linear's API, which needs a logged in CLI. So the tool ships a copy of the upstream schema, refreshed by hand, rather than shipping a hard coded client for it.

And the output modes back this up. The list command has -w and -a to jump to the app, the query command has --json, and the comment list has --json with quotedText and parent so an agent can reconstruct the reply structure.

The audience for this half of the project is the coding agent, and the design treats the CLI as an interface for a machine as much as for a person.

The release machinery, and the 3.0 line

The repository layout is that of a project with a serious release process, and the justfile is the clearest evidence.

The workspace has three members, crates/linear-cli, crates/linear-schema and xtask, with the first two as the default members so that a plain cargo run or cargo build stays on the command line, and a comment saying the schema crate is the one checked in CI while the tooling crate is built through xtask. The workspace uses resolver 3, edition 2024, a minimum Rust version of 1.93, and the ISC licence, which matches the repository metadata.

The justfile targets map out the whole workflow. The check target runs cargo fmt --all --check, then clippy with --locked --workspace --all-targets and -D warnings, then cargo test --locked --workspace, so formatting, linting and tests are one command. The licenses target runs cargo xtask licenses to write THIRD_PARTY_LICENSES.md, the dependency licence notices that releases ship. The tag target is a full release: it checks, reads the version from the changelog with svbump, writes it into Cargo.toml, updates the workspace, regenerates the skill docs, sets the plugin version in .claude-plugin/plugin.json and marketplace.json with jq, then commits with jj, sets a jj bookmark and tag, and pushes with both jj and git.

The use of Jujutsu to cut the release while pushing to git is a nice detail. There is also a .claude-plugin directory and .claude, plus an AGENTS.md, a CLAUDE.md and a .linear.toml at the root.

The releases themselves tell the story of the 3.0 line. v2.6.0 on 2026-09-02, v3.0.0-alpha.2 on 2026-10-06, and v3.0.0 on 2026-10-06, with the repository pushed to on 2026-10-07. A major version that lands the same day as its own alpha is a project that has stabilised quickly, and the presence of a documented 2.x to 3.0 upgrade path in the changelog suggests the break was worth checking before you adopt.

Editorial conclusion

linear-cli is worth adopting if your team runs Linear and wants the issue tracker to be reachable from a terminal, because the part that is genuinely hard, working out which issue the current branch or commit refers to, is handled for both git and Jujutsu, and the agent oriented JSON output and skill make it usable from a tool that is not a human. It is the wrong choice if you want the pull request step included, since linear issue pr shells out to the gh CLI and inherits that dependency, and it is the wrong choice if your branch naming does not carry issue identifiers. Before you adopt it, check the authentication document for multi-workspace setups, and note that the current release is v3.0.0 from 2026-10-06 with the repository pushed to on 2026-10-07.

Frequently asked questions

How does linear-cli know which issue I am working on?

With git it reads the issue id from the current branch name, for example eng-123-my-feature. With Jujutsu it reads the Linear-issue trailer in the current or ancestor commits, and linear issue start can add that trailer for you, or you can add it with jj describe using the output of linear issue describe.

How do I install linear-cli?

With brew install schpet/tap/linear, as a pinned dev dependency through npm, bun or pnpm using @schpet/linear-cli, with the shell installer for macOS and Linux, from the release binaries, or from source with cargo install --locked --git https://github.com/schpet/linear-cli linear. The npm package ships pre-built binaries.

What do I need to set up linear-cli against a Linear workspace?

Create an API key in the Linear account security settings, run linear auth login, and then run linear config inside the project directory so it writes a config file. For multi-workspace setups and other authentication options the readme points at docs/authentication.md.

Does linear-cli create pull requests itself?

No, it prepares the title and body and then uses the GitHub CLI. The readme describes linear issue pr as making a PR with the title and body preset, using the gh cli, and states the mechanism as gh pr create.

What can AI agents do with linear-cli?

The CLI ships a skill that lets agents create issues, update status and manage the Linear workflow alongside code, and the skill documentation is regenerated from the cli's own help output. The query commands have a --json mode for structured output, including a form that exports all issues as JSON.

Official sources

  1. Issues
  2. License: ISC
  3. README
  4. Releases
  5. schpet/linear-cli on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/schpet-linear-cli.svg)](https://hysenlabs.com/projects/schpet-linear-cli)

Was this useful?