Adds a `linear api` subcommand for making raw GraphQL requests,
mirroring [`gh api`](https://cli.github.com/manual/gh_api) conventions.
## Changes
- Accepts a GraphQL query as a positional arg, from stdin with `-`, or
via auto-detected piped input
- `--variable key=value` for typed variable coercion (booleans, numbers,
null, `@file` for file reads, `@-` for stdin)
- `--variables-json '{"key": "value"}'` for passing all variables as a
JSON object (merged with `--variable`, which takes precedence)
- `--paginate` walks `pageInfo.endCursor` automatically and outputs
concatenated `nodes` array
- `--silent` suppresses response output while exit code still reflects
errors
- Pretty-prints JSON when stdout is a TTY, raw JSON otherwise for piping
to `jq`
- Exits with code 1 on HTTP errors (status >= 400) and GraphQL-level
errors
- Uses raw `fetch` so users see the exact server response including both
`data` and `errors` fields
## Testing
- Snapshot tests using `MockLinearServer` cover query resolution,
variable handling (type coercion, `@file`, `--variables-json`,
precedence), output modes, pagination (multi-page, single-page,
non-connection), auth errors, and `--silent` behavior for both
successful and HTTP error responses
- Manual testing against live Linear API: cycles, workflow states,
notifications (with `--paginate`), non-existent issue lookup, variable
type mismatch errors, stdin piping
## Related
- Closes#123
Fixes#116
Error messages are now clean and user-friendly by default. Stack traces
are only shown when LINEAR_DEBUG=1 is set, similar to RUST_BACKTRACE.
Changes:
- Add src/utils/errors.ts with error handling infrastructure:
- CliError base class with user-facing messages and suggestions
- NotFoundError for entity lookups
- ValidationError for invalid input
- AuthError for authentication issues
- handleError() for consistent error display
- extractGraphQLMessage() to parse Linear API errors
- Update all commands to use handleError() for consistent error display
- Error output goes to stderr with ✗ prefix
- GraphQL errors show userPresentableMessage when available
Example before:
Error: Entity not found: Issue: {"response":{"data":null...
Example after:
✗ Issue not found: FAKE-9999
Updated bulk.ts to use the centralized shouldShowSpinner() function instead
of directly checking Deno.stdout.isTerminal(). This ensures progress display
during bulk operations also respects the NO_COLOR environment variable.
Fixes#113
Previously, --workspace would silently fall back to other credential
sources when the specified workspace wasn't found. Now it errors with
a helpful message suggesting `linear auth login` or `linear auth list`.
Also errors when both LINEAR_API_KEY env var and --workspace are set,
since these are conflicting ways to specify credentials.
Added error handling guidelines to CLAUDE.md to prevent silent failures.
This PR adds several major features to linear-cli:
- **Initiative management**: Full CRUD support for initiatives including
list, view, create, archive, unarchive, update, and delete commands
- **Initiative-project linking**: Commands to add and remove projects
from initiatives
- **Label management**: List, create, and delete commands for labels
with team filtering
- **Project creation**: New `project create` command with interactive
mode and initiative linking
- **Team deletion**: New `team delete` command with confirmation
- **Bulk operations**: New utility supporting bulk operations across
commands (issue delete now supports multiple IDs)
## New Commands
### Initiatives
- `linear initiative list` - List all initiatives with filtering options
- `linear initiative view <id>` - View initiative details including
linked projects
- `linear initiative create` - Create new initiative (interactive or via
flags)
- `linear initiative archive <id>` - Archive an initiative
- `linear initiative unarchive <id>` - Unarchive an initiative
- `linear initiative update <id>` - Update initiative properties
- `linear initiative delete <id>` - Delete an initiative (with
confirmation)
- `linear initiative add-project` - Link a project to an initiative
- `linear initiative remove-project` - Remove project from initiative
### Labels
- `linear label list` - List labels with optional team filter
- `linear label create` - Create a new label
- `linear label delete <id>` - Delete a label
### Projects
- `linear project create` - Create a new project with team, lead, dates,
status, and optional initiative linking
### Teams
- `linear team delete <id>` - Delete a team (with confirmation)
Add support for loading `.linear.toml` from user's home directory as a
fallback when no project-level config exists:
- Unix: `~/.config/linear/linear.toml` or `$XDG_CONFIG_HOME/linear/linear.toml`
- Windows: `%APPDATA%\linear\linear.toml`
Config precedence (highest to lowest):
1. CLI flags
2. Environment variables
3. Project config (`.linear.toml` in cwd or repo root)
4. User home config
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enable finding the current Linear issue from jj commit trailers, matching
the existing git branch-based detection. Users can now work with either git
or jj version control systems.
- Extract Linear-issue trailer parsing into getJjLinearIssue() utility
- Create getCurrentIssueFromVcs() abstraction for VCS-agnostic issue lookup
- Update getIssueIdentifier() to use new VCS-aware detection
- Support both git branch names and jj commit trailers seamlessly
Claude-session-id: cf951f85-34da-4328-be9d-241ff092feea
**Fixed:**
- state column is now dynamically sized with max 20 chars and
auto-truncation
**Changed:**
- linear issue list now sorts by workflow state first
- issue pr create no longer opens browser by default, added --web flag
- removed 'about' prefix from relative timestamps
**Added:**
- automatic paging for issue view command with --no-pager flag and pager
- pager support for issue list command with --no-pager option