lin
May 3, 2026 · View on GitHub
A fast, native CLI for Linear. Manage issues, projects, cycles, and more from your terminal.
Install
Homebrew (macOS)
brew install aaronkwhite/tap/lin
Cargo
cargo install lincli
Pre-built Binaries
Download from GitHub Releases — available for macOS (Intel & Apple Silicon) and Linux (x86 & ARM).
From Source
git clone https://github.com/aaronkwhite/linear-cli.git
cd linear-cli
cargo install --path .
Setup
Get your API key from Linear Settings > API > Personal API keys, then:
lin auth login # interactive — saves as a named workspace
Or set it directly:
export LINEAR_API_KEY="lin_api_..." # environment variable (simplest)
lin config set-token # save to config file
Multiple workspaces:
lin auth login # add each workspace by name
lin auth list # see configured workspaces
lin auth default myco # switch default
lin --workspace other-org issues list # one-off override
Usage
lin --help # Show all commands
lin issues list --team ENG # List issues for a team
lin issues list --state "In Progress" # Filter by state
lin issues list --label bug --label urgent # Filter by labels
lin issues get ENG-123 # Get issue details
lin issues update ENG-123 --team HP # Move issue to another team
lin projects list # List projects
lin projects update "My Project" --add-team ENG # Add team to project
lin cycles add ENG-123 --cycle <id> # Add issue to specific cycle
lin teams list # List teams
lin issues start ENG-123 # Create branch from issue
lin issues pr ENG-123 --draft # Create draft PR from issue
lin issues list --all-teams --updated-after 2026-04-01 # Cross-team date filter
lin auth login # Add a workspace
lin api '{ viewer { id displayName } }' # Raw GraphQL query
Global Flags
| Flag | Description |
|---|---|
--json | Output raw JSON for scripting |
--debug | Print GraphQL queries/responses to stderr |
--workspace <NAME> | Use a specific workspace |
--version | Show version |
Commands
| Group | Description |
|---|---|
auth | Manage workspaces and authentication |
issues | List, create, update, search, comment, start, pr, archive, branch lookup |
projects | List, create, update, search, archive, delete projects |
cycles | List, create, manage, archive cycles and cycle issues |
initiatives | Manage initiatives, status updates, link projects |
roadmap | Project updates and milestones |
labels | Create, manage, apply labels |
teams | List teams, members, states, workload |
relations | Issue dependencies and relations |
customers | Customer management, needs, tiers |
views | Custom views and their issues |
docs | Documents: create, search, manage |
notifications | View, read, archive, snooze notifications |
me | Show authenticated user info |
attachments | Manage issue attachments and links |
search | Search across issues, projects, and documents |
config | Manage API key, CLI configuration, and analytics |
completions | Generate shell completions (bash, zsh, fish, powershell) |
api | Raw GraphQL passthrough — any query or mutation with auth injected |
Using with Claude Code
Install the skill (recommended)
A Claude Code skill ships with this repo that teaches Claude how to use lin for any Linear task — creating issues, querying status, managing projects and cycles, and more.
cp -r .claude/skills/lin ~/.claude/skills/lin
The skill handles tool selection (lin first, Linear MCP as fallback), includes a full command reference, and documents which operations require MCP vs. lin.
Manual CLAUDE.md snippet
If you prefer a lightweight setup, add this to your project's CLAUDE.md:
## Linear
Use the `lin` CLI for all Linear operations. Always use `--json` for structured output.
- `lin issues list --team ENG --json` — list issues
- `lin issues get ENG-123 --json` — get issue details
- `lin issues create --team ENG --title "Title" --json` — create issue
- `lin issues update ENG-123 --status "Done" --json` — update status
- `lin search "query" --json` — search across issues, projects, docs
Run `lin <command> --help` for full flag details.
Why CLI over MCP?
MCP servers inject the full JSON schema for every tool into the LLM's context window on every message — whether those tools are used or not. This creates a permanent tax on every interaction.
Token Cost
| Metric | CLI | MCP | Difference |
|---|---|---|---|
| Idle context cost | 0 tokens | ~19,659 tokens | CLI loads nothing upfront |
| Simple query (e.g., repo info) | ~1,365 tokens | ~44,026 tokens | 32x more expensive |
| PR details + review | ~1,648 tokens | ~32,279 tokens | 20x more expensive |
| Complex multi-step task | ~8,750 tokens | ~37,402 tokens | 4x more expensive |
| Monthly cost @ 10K ops | ~$3.20 | ~$55.20 | 17x more expensive |
Source: Scalekit benchmark, 75 runs, Claude Sonnet 4, p < 0.05
Why the Gap Is So Large
MCP loads the entire API surface into context on every message. Linear's official MCP server injects 22 tool schemas (~19,659 tokens) before you ask a single question. Connect 3 MCP servers and you can lose 72% of your context window at idle.
A CLI pays only for what it uses. lin issues list --team ENG --json costs ~15 tokens for the command string. The other 200+ subcommands cost nothing because they're never loaded.
Reliability
| CLI | MCP | |
|---|---|---|
| Success rate | 100% | 72% |
| Failure modes | Exit code + stderr | TCP timeouts, schema injection failures, transport errors, silent tool dropping |
| Dependencies | Single binary in PATH | JSON-RPC, transport negotiation, schema validation |
Source: Scalekit benchmark, 25 runs per method
Industry Trend
- Perplexity dropped MCP internally, citing context window waste and authentication issues (source)
- mcp2cli (wraps MCP servers as CLIs) measured 96-99% token reduction (source)
- "MCP is dead, long live the CLI" hit the Hacker News front page (discussion)
When MCP Still Makes Sense
MCP works well for non-technical users in chat interfaces where CLI access isn't available, or for services that don't have a CLI wrapper. For developer tooling where you have shell access, CLI wins on every axis.
Analytics
lin collects anonymous usage statistics to help improve the tool. The defaults differ by context:
- Interactive sessions (terminal use): opt-out. Enabled on the first run, after a stderr notice prints and you've seen it. The first event is not recorded — only events from the second invocation onward.
- Non-interactive sessions (AI agents, CI, piped): opt-in. No data is collected unless you've previously opted in from a TTY.
What's collected: command name and subcommand (e.g. issues list), flags used (presence only — never values), success/failure, execution time, lin version, OS/arch, schema version. Each install gets a random anonymous ID.
What's never collected: API keys, issue content, workspace names, identifiers, query text, file paths, hostname, or any personal information.
Disable:
lin config analytics off # permanent — also deletes the local queue and install ID
DO_NOT_TRACK=1 lin ... # per-invocation (any non-empty value works)
Check status:
lin config analytics status
Re-enabling with lin config analytics on mints a fresh anonymous ID — the prior identity is not preserved.
Development
cargo build # Build
cargo test # Run tests (smoke + unit)
LINEAR_API_KEY=... cargo test -- --ignored # Run integration tests
Contributing
Contributions welcome! See CONTRIBUTING.md for guidelines.
License
MIT