114 Commits

Author SHA1 Message Date
WhiteMind 7ec58b0dc1 fix: strip stray characters from pasted API key on Windows
Cliffy's Secret.prompt injects tilde (~) characters at the start and
end of pasted text on Windows terminals (bracket paste mode side-effect).
This causes `auth login` to always fail with "Invalid API key" when the
key is pasted interactively.

Trim whitespace and strip non-key characters from both ends of the input.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-06 09:59:19 -08:00
Jeffrey Holm 6f4d6e7530 feat: add milestone filter to issue list command
Adds --milestone flag to `linear issue list` to filter issues by project
milestone name. Requires --project since milestones belong to projects.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-05 07:26:51 -08:00
schpetbot ce8585c8d7 fix: move date validation inside try-catch in project update (#165)
Validation errors thrown before the `try` block in `project update` were
bypassing `handleError`, resulting in raw stack traces instead of clean
`✗` error messages.

Moves the no-options check, `--start-date` format check, and
`--target-date` format check inside the `try` block so they display
consistently with other error messages.

Found during manual QA of #148.

Co-authored-by: Peter Schilling <code@schpet.com>
2026-03-04 20:49:53 -08:00
Jay Reardon 69e59eed4d feat(project): add update, delete, and --json support (#127) (#148)
- Add 'project update' subcommand with --name, --description, --status,
--lead, --start-date, --target-date, --team options
- Add 'project delete' subcommand with --force to skip confirmation
- Add --json to 'project list' for machine-readable output with UUIDs
- Add --json to 'project create' to return project id/slugId/name/url

Enables automation use cases: create, rename, delete, list project IDs
programmatically without raw GraphQL API calls.
2026-03-04 20:44:33 -08:00
David Roizenman ab3f83b03c fix(issue-view): don't send auth headers to non-linear domains 2026-03-04 20:34:25 -08:00
David Roizenman c05f6fcb69 refactor: move all linear domain usage to shared const.ts 2026-03-04 20:34:25 -08:00
Dan Wager ca3b04bd19 feat: add cycle list/view commands and issue list --cycle filter (#162)
### Summary
- Add `linear cycle list` and `linear cycle view` commands for browsing
team cycles
- Add `--cycle` filter to `linear issue list` for filtering issues by
cycle
- Regenerate skill docs to include new commands

### Problem
PR #150 added cycle support to issue create/update/view, but there was
no way to browse cycles themselves or filter issue lists by cycle. Users
had to know cycle names/numbers without being able to look them up from
the CLI. See #64.

### Fix
Adds a `cycle` command group (aliased `cy`) with two subcommands,
following the same patterns as the existing `milestone` commands:

**`cycle list`** shows all cycles for a team with number, name, dates,
and status. Active cycle is highlighted in green, upcoming cycles use
default color, and completed/past cycles are muted.

```
$ linear cycle list --team XXX
#  NAME       START      END        STATUS
3  Sprint 3   2026-03-10 2026-03-24 Upcoming
2  Sprint 2   2026-02-24 2026-03-10 Active
1  Sprint 1   2026-02-10 2026-02-24 Completed
```

**`cycle view`** shows full cycle details including a progress
indicator, description, issue breakdown by state, and first 10 issues.
Accepts cycle name, number, or "active".

```
$ linear cycle view active --team XXX
# Sprint 2

**Number:** 2
**Start:** 2026-02-24
**End:** 2026-03-10
**Status:** Active
**Team:** MyTeam (XXX)

## Issues

**Progress:** 17/50 (34%)
**Total Issues:** 50
**Completed:** 17
**In Progress:** 12
**To Do:** 21

**Issues:**
- XXX-412: Fix auth token refresh (In Progress)
- XXX-398: Add dark mode toggle (Todo)
...
```

**`issue list --cycle`** filters the issue list to a specific cycle,
reusing the existing `getCycleIdByNameOrNumber()` utility and the
GraphQL `IssueFilter.cycle` field.

```
$ linear issue list --cycle active --team XXX --sort priority
◌   ID      TITLE                  LABELS          E STATE UPDATED
--- XXX-101 Some task              Backend, Feature - Todo  1 day ago
--- XXX-102 Another task           Feature          - Todo  1 day ago
```

### Why
Cycles are a core part of the Linear workflow and the CLI should support
browsing them. `cycle list` lets you see what's available, `cycle view`
gives you sprint progress at a glance, and `--cycle` on issue list lets
you scope your view to a specific sprint.

### Test Plan
- Tested all three commands against a real Linear workspace with 11
cycles and 50+ issues
- `cycle view` tested with active, by number, and by exact name lookup
- All 220 unit/snapshot tests pass
2026-03-04 13:59:59 -08:00
Jeffrey Holm 47011e77d1 feat: add comment delete command
Adds `linear issue comment delete <commentId>` to delete comments via
the commentDelete GraphQL mutation. Includes snapshot test and updated
skill documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-04 13:45:00 -08:00
Peter Schilling 36db5b9ebb test: add issue update -p priority test and regenerate skill docs
- Add snapshot test for 'issue update -p <priority>' to verify -p maps
  to --priority (not --parent), mirroring the fix tested in issue create
- Regenerate skill docs to reflect corrected flag assignments:
  --parent (no short flag) and -p, --priority
2026-03-03 11:54:28 -08:00
Michael Pearson 5eebaeaa33 fix: fall back to slugId match in getProjectIdByName
When the --project flag value doesn't match any project by exact name
(e.g. because the name contains special characters like quotes or
parentheses), try matching by slugId before returning undefined.

This lets users pass either the full project name or the 12-char hex
slug ID (visible in `project list` output and Linear URLs) as the
--project value.

Fixes #157

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019ca8f4-4000-732f-91e2-5ad51d27008c
2026-03-01 06:33:52 -08:00
Peter Schilling 12be1d17eb fix: correct success message order for 'blocked-by' relation
When using 'relation add X blocked-by Y', the API is called with swapped
IDs (Y blocks X), but the success message was showing the API's returned
identifiers (in the swapped order) instead of the user-specified order.

Fixes: the message now uses the original issueIdentifier and
relatedIssueIdentifier variables, so 'relation add ENG-123 blocked-by ENG-456'
correctly shows '✓ Created relation: ENG-123 blocked-by ENG-456'.

Closes #152
2026-02-26 22:23:45 -08:00
Jeffrey Holm e24ef1de21 feat: add cycle support to issue commands
Add --cycle flag to issue create and update commands, accepting cycle
name, number, or 'active' keyword. Display cycle in issue view output
alongside project and milestone metadata.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:09:15 -08:00
Jeffrey Holm b65ba20565 feat: add milestone support to issue commands (#149)
## Summary

- Adds `--milestone` flag to `issue create` and `issue update` commands
- Resolves milestones by name (case-insensitive) within the specified
project
- For `issue update`, automatically falls back to the issue's existing
project if `--project` is not explicitly provided
- Validates that a project context exists before attempting milestone
lookup, with helpful error messages
- Shows **project** and **milestone** in `issue view` output (displayed
below the title when present)

## Example usage

```sh
# Create an issue with a milestone
linear issue create --title "Implement feature" --team ENG --project "My Project" --milestone "Phase 1"

# Update an issue's milestone (project inferred from issue)
linear issue update ENG-123 --milestone "Phase 2"

# View an issue — now shows project and milestone
linear issue view ENG-123
# => Project: My Project | Milestone: Phase 1
```

## Test plan

- [x] Happy path tests for create and update with milestone
- [x] Snapshot test for `issue view` with project and milestone
displayed
- [x] All 205 tests pass
- [x] `deno check` and `deno lint` pass
- [x] GraphQL codegen regenerated
- [x] Verified end-to-end against Linear API

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-24 08:57:39 -08:00
Peter Schilling fc8530ad26 fix: improve git command error handling with CliError
- Use CliError instead of generic Error for all git command failures
- Add proper error checking to getCurrentBranch() and getRepoDir()
- Improve error handling in startVcsWork() git operations
- Add comprehensive tests for git error handling
- Ensure consistent error reporting across git utilities

Fixes #62
2026-02-17 20:49:58 -08:00
Sergio Francisco 265a37f760 fix: correct API key creation URL in auth login (#146)
## Summary

- Replace incorrect URL `https://linear.app/settings/api` with
`https://linear.app/settings/account/security` in the `auth login`
command prompt and error message
- The old URL isn't the correct one where you can create those API keys.
The new one correctly redirects to the API key management page.

## Test plan

- `deno task check` isn't passing due to pre-existing failures on `main`
- [x] `deno lint` passes
- [x] `deno task dev auth login` shows the corrected URL in the prompt
hint


## Test evidence:
<img width="759" height="134" alt="CleanShot 2026-02-16 at 17 05 16"
src="https://github.com/user-attachments/assets/a8d7813b-f609-4599-93f5-cc9a20e71bad"
/>
2026-02-16 19:47:47 -08:00
Peter Schilling f8efda78d8 Add best practices for markdown content to Linear CLI skill
- Regenerate skill documentation with file-based flag guidance
- Update test snapshots to reflect new --description-file and --body-file flags
- Add section explaining why file-based flags prevent markdown formatting issues

Addresses: https://github.com/schpet/linear-cli/issues/133
2026-02-12 15:50:21 -08:00
Peter Schilling d640db8b1a fix: don't create new commit after describing in issue start
Previously,  with jj would:
1. Prepare working state (create empty commit if needed)
2. Describe the commit with issue details
3. Create a new empty commit to work on

This left the user on an empty commit with the described commit as parent.

Now it stops after step 2, leaving the user on the described commit itself.
This matches the expected behavior where you work directly on the commit
associated with the issue.
2026-02-11 12:36:27 -08:00
Ben Drucker 3582fc5700 feat: add api subcommand for raw GraphQL access (#121)
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
2026-02-09 09:36:55 -08:00
Paymahn Moghadasian 338ce75299 feat: increase sub-issues limit from 50 to 250
The children query defaulted to 50 items, which truncated issues with
many sub-issues (e.g., INFRA-823 has 179 sub-issues but only showed ~50).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 09:25:28 -08:00
Ben Drucker 4dd3878f2a feat: add --sort-order flag to milestone update command
Expose the sortOrder field (already in the GraphQL schema) as a CLI
option for updating milestone ordering within a project.
2026-02-02 20:58:14 -08:00
Peter Schilling 430ac0402d feat: add user-friendly error handling with LINEAR_DEBUG support
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
2026-02-01 22:51:12 -08:00
Peter Schilling 59dce3cf19 fix: use centralized shouldShowSpinner() for all spinner checks
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
2026-02-01 20:38:23 -08:00
Peter Schilling 5e845e2ee3 fix: disable spinners in non-TTY environments
Add shouldShowSpinner() utility that checks both Deno.stdout.isTerminal()
and the NO_COLOR environment variable before showing spinners. This
prevents garbled spinner output when the CLI is used with tools that
capture output (e.g., AI assistants, scripts).

Removes --no-color flags from commands where they only controlled spinner
visibility, since spinners now automatically disable in non-TTY
environments.

Fixes #113
2026-02-01 20:38:23 -08:00
Paymahn Moghadasian 23d20f77d7 feat: show sourceType for attachments in issue view
Adds sourceType field (e.g., github, githubCommit, zendesk) to attachment
display so users can identify what kind of link they're looking at.

Closes #21

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:32:13 -08:00
Zach Trayner bd007f378d feat: add issue relation command for managing dependencies (#115)
## Summary

Adds `linear issue relation` command with subcommands for managing issue
relations/dependencies:

- **`add`** - Create relations between issues
- **`remove`** - Remove existing relations  
- **`list`** - List all relations for an issue

## Supported Relation Types

| Type | Description | Example |
|------|-------------|---------|
| `blocks` | Issue blocks another | `linear issue relation add ENG-123
blocks ENG-456` |
| `blocked-by` | Issue is blocked by another | `linear issue relation
add ENG-123 blocked-by ENG-100` |
| `related` | Issues are related | `linear issue relation add ENG-123
related ENG-456` |
| `duplicate` | Issue is duplicate of another | `linear issue relation
add ENG-123 duplicate ENG-100` |

## Examples

```bash
# Mark ENG-123 as blocked by ENG-100
linear issue relation add ENG-123 blocked-by ENG-100

# Mark ENG-123 as blocking ENG-456
linear issue relation add ENG-123 blocks ENG-456

# List all relations for an issue
linear issue relation list ENG-123

# Remove a relation
linear issue relation remove ENG-123 blocked-by ENG-100
```

## Implementation Notes

- The `blocked-by` relation type is implemented by reversing the issue
order with the `blocks` API type, providing a more intuitive CLI
experience
- Uses existing utilities (`getIssueIdentifier`, `getIssueId`) for
consistent issue resolution
- Follows the existing command structure and patterns in the codebase

## Motivation

This enables CLI users to manage issue dependencies, which is useful
for:
- Automating issue management in scripts
- AI agents that need to set up dependency relationships
- Quick dependency management without leaving the terminal
2026-01-30 09:17:19 -08:00
Peter Schilling 992f05afe1 fix: add type annotations and CI workflow for type checking
- Add explicit type annotations to team-list.ts and project-list.ts to fix implicit any errors
- Add CI workflow (.github/workflows/ci.yml) that runs type check, format, lint, and tests on PRs
- Update justfile to use 'deno check src/main.ts' instead of '--all' to avoid npm dependency type errors
2026-01-29 05:48:54 +00:00
Andrew Kline 86bdd3744f fix: add pagination to project-list 2026-01-28 15:00:28 -08:00
andrew-kline ae305250c0 fix: add pagination to team-list (#107)
team-list currently caps at 50 team responses. this adds pagination to
list all teams in the workspace.
2026-01-28 09:55:36 -08:00
Peter Schilling 908bae467f fix: error when --workspace flag specifies unknown workspace
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.
2026-01-27 13:02:46 -08:00
Peter Schilling 1b4135ba59 feat: add file attachment support for issues and comments
- Add `issue attach` command to attach files to issues
- Add `--attach` flag on `issue comment add`
- Show attachments section in `issue view` with auto-download
- Add `attachment_dir` and `auto_download_attachments` config options
- Add network permission for storage.googleapis.com (upload destination)
2026-01-27 12:51:59 -08:00
Temirlan ab13420293 Fix lookupUserId to handle 'self' keyword (#104)
## Problem

`--assignee self` fails with:
```
Could not determine user ID for assignee self
```

## Root Cause

The code in `issue-create.ts` uses `"self"` as the keyword for
auto-assigning to the current user (lines 184, 389, 648), but
`lookupUserId()` only checks for `"@me"`.

When `"self"` is passed, it falls through to the user search query which
looks for a user literally named "self" - which doesn't exist.

## Fix

Add `"self"` as an alias alongside `"@me"` in `lookupUserId()`:

```typescript
if (input === "@me" || input === "self") {
```

Now both `--assignee self` and `--assignee @me` work correctly.
2026-01-27 09:14:09 -08:00
Peter Schilling f633f5b6e3 feat: support multi-workspace auth in config command
When no LINEAR_API_KEY is set, the config command now uses stored
credentials. Single workspace is auto-selected; multiple workspaces
prompt the user to choose.
2026-01-26 14:17:44 -08:00
Peter Schilling 540818c0b1 feat: add multi-workspace authentication support
Add built-in credential storage for managing multiple Linear workspaces:
- ~/.config/linear/credentials.toml stores API keys by workspace slug
- auth login: add credentials (auto-detects workspace from API)
- auth logout: remove credentials
- auth list: show configured workspaces with org/user info  
- auth default: set the default workspace
- global -w/--workspace flag to target specific workspace

API key precedence: CLI flag > env var > config > workspace flag > project workspace > default
2026-01-23 14:28:45 -08:00
Paymahn Moghadasian 1f11e946ad fix: pass sort parameter to fetchIssuesForState (#96)
- Fixes a bug where `--sort` flag was ignored after interactive prompts
(like project selection)
- The sort option was validated in `issue-list.ts` but
`fetchIssuesForState` independently read sort from config only, causing
the CLI flag to be lost
2026-01-23 13:25:43 -08:00
Peter Schilling b32381308a fix: add TTY checks before interactive prompts to prevent hanging in non-interactive mode
Commands with confirmation prompts now exit with a helpful error message
when stdin is not a TTY, directing users to use the appropriate flag
(--force, --yes, --confirm, or --team) instead of hanging forever.

Affected commands:
- initiative remove-project, archive, delete, unarchive
- document delete
- issue delete
- label delete
- team delete
- milestone delete
2026-01-21 09:40:06 -08:00
Sam Gbafa cd45a8a6aa Add initiative, label, and bulk operation support (#95)
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)
2026-01-21 08:45:54 -08:00
Paymahn Moghadasian 3ceb8bdca8 feat: add --project filter to issue list command
Adds the ability to filter issues by project name when listing issues.
If the project name does not match exactly, it fuzzy-searches and prompts
the user to select from matching projects.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 08:54:24 -08:00
Peter Schilling 9a091bc022 add User-Agent header to GraphQL requests 2026-01-09 13:33:55 -08:00
Peter Schilling 71757e52b4 fix: merge global and project configs instead of only loading one 2026-01-09 13:28:32 -08:00
Kirt Lillywhite 1268b667fb feat: support loading config from user home directory
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>
2026-01-09 13:28:32 -08:00
Jeffrey Holm 77aa22b9d9 feat: add milestone management commands (#92)
## Summary

Adds comprehensive milestone management functionality to linear-cli,
enabling full CRUD operations for Linear project milestones.

## Motivation

The Linear API supports project milestones, but the CLI didn't expose
this functionality. This PR adds milestone management commands to
complement the existing project and issue commands.

## Changes

### New Commands

- `linear milestone list --project <id>` - List milestones for a project
- `linear milestone create` - Create new project milestones  
- `linear milestone update <id>` - Update existing milestones
- `linear milestone delete <id>` - Delete milestones with confirmation
- Short alias: `linear m` for all milestone commands

### Features

- Full CRUD operations for project milestones
- Table-formatted output for list command
- Interactive confirmation prompts for deletion (with `--force` option
to skip)
- Support for milestone name, description, and target date
- Follows existing CLI patterns and conventions

### Implementation

- Uses GraphQL Code Generator for type-safe queries/mutations
- Built with Cliffy for command structure and prompts
- Leverages existing graphql client utilities
- Includes spinner for loading states
- Updated README with usage examples

## Testing

All commands have been tested with the Linear API:

- ✅ List milestones for a project (empty and populated)
- ✅ Create milestones with name, description, target date
- ✅ Update milestone properties
- ✅ Delete milestones with confirmation prompt
- ✅ Delete with `--force` flag (skip confirmation)

## Documentation

Updated README.md with:
- Milestone commands section
- Usage examples for all operations
- Command aliases

## Example Usage

```bash
# List milestones
linear milestone list --project abc123
linear m list --project abc123  # alias

# Create a milestone
linear milestone create --project abc123 --name "Q1 Goals" --target-date "2026-03-31"
linear m create --project abc123  # interactive mode

# Update a milestone  
linear milestone update xyz789 --name "Q1 Objectives"
linear m update xyz789 --target-date "2026-04-15"

# Delete a milestone
linear milestone delete xyz789
linear m delete xyz789 --force  # skip confirmation
```
2026-01-09 12:41:19 -08:00
Kirt Lillywhite 0a732c3838 fix: environment variables now correctly take precedence over config file values
The README documented that environment variables take precedence over
config file values, but the code had the opposite behavior. This fix
corrects the precedence order in getRawOption to match the documentation:

1. CLI flags (highest priority)
2. Environment variables
3. Config file (lowest priority)

Also adds subprocess-based tests that verify:
- Env vars win when both env var and config file are present
- Config file is used as fallback when no env var is set

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 09:34:34 -08:00
Peter Schilling 87a442a0a7 Prefix issue title with identifier in issue view
Add the issue identifier (e.g., TEST-123) before the title in the
issue view command output. The title now displays as "TEST-123: Fix
authentication bug" instead of just "Fix authentication bug".

- Add identifier field to fetchIssueDetails return type
- Include identifier in both GraphQL queries
- Update issue-view.ts to prefix title with identifier
- Update all test mocks to include identifier field

Claude-session-id: a1d9f23b-b88b-4571-b44a-37003734e4a1
2026-01-05 16:07:29 -08:00
Paymahn Moghadasian f3e9b9f348 feat: add parent and sub-issues to issue view output (#86)
## Summary

- Add parent issue display to `linear issue view` output (when the issue
has a parent)
- Add sub-issues list to `linear issue view` output (when the issue has
children)
- Enables agents and users to easily navigate up and down the issue
hierarchy

Closes #84

## Example Output

```
# Implement user authentication

Add user authentication to the application.

Parent:
  TEST-100: Epic: Security Improvements [In Progress]

Sub-issues:
  TEST-457: Add login form [Done]
  TEST-458: Add password reset flow [Todo]
  TEST-459: Add OAuth support [In Progress]
```

## Test plan

- [x] Added new test case "With Parent And Sub-issues" to verify
hierarchy display
- [x] Updated existing tests to include parent/children fields in mock
data
- [x] All snapshot tests updated and passing
- [x] `deno check` passes
- [x] `deno lint` passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 11:25:03 -08:00
peter schilling 51ff1b2db6 Add 'issue commits' command (jj-vcs only) (#79)
use case: 

- you are addressing feedback on an issue ABC-123
- run `linear issue start 123` to re-start that issue
- fire up claude code
- run `! linear issue view` to drop the issue, and comments into context
- run `! linear issue commits` to dump the diff of previous work into
context
- ask claude to address the feedback (it will have a much better shot of
knowing what you are talking about)
2025-12-14 08:33:34 -08:00
Peter Schilling 0eacbe45cf Add schema command to print GraphQL schema
Implement a new top-level command that fetches the GraphQL schema from
Linear's API via introspection and prints it to stdout. Supports SDL
format by default and JSON output with --json flag.

Claude-session-id: 84fcd993-f47a-44d2-b173-69f9415ed989
2025-12-08 21:55:15 -08:00
Peter Schilling cf0d28a720 Add OSC-8 hyperlink support for images in comments
Extend hyperlink support to work consistently for both issue descriptions
and comments by using charmd markdown rendering with OSC-8 extensions.

- Use renderMarkdown with extensions for comment body rendering
- Remove formatWrappedText function, replaced by markdown rendering
- Pass extensions array through captureCommentsForTerminal function
- Apply proper indentation to rendered reply comments

Claude-session-id: 49101792-03cc-423f-8162-4e8fd125d1b4
2025-12-03 22:51:49 -08:00
Peter Schilling b47f95e7fb Add image download functionality to issue view
Implement local image caching for issue view command to avoid
exposing authenticated Linear URLs. Images are downloaded to a
temporary directory and cached for reuse.

- Add image download and caching system
- Update deno.json permissions for temporary directories and
  uploads.linear.app domain access
- Add dependencies: remark, unified, mdast, valibot, sanitize-filename
- Add LINEAR_DOWNLOAD_IMAGES env var and download_images config option
  (enabled by default, disable with --no-download flag)

Claude-session-id: 626af003-386f-486b-8357-db352b0b5766
2025-12-03 22:45:28 -08:00
Peter Schilling 14064b6fc3 Add manual sort as secondary priority sort
When sorting issues by priority, apply manual sort order (drag
position) as a tertiary sort after priority, matching the behavior
of the Linear app. This ensures issues within each priority group
maintain their manual ordering.

Claude-session-id: f15ec08b-4174-460c-a3bd-b00629eb708e
2025-12-03 21:21:03 -08:00
Peter Schilling 52171194ae Capture jj command output and only print on error
Update prepareJjWorkingState, setJjDescription, and
createJjNewChange to capture stdout and stderr instead of
inheriting them. Only print errors to the console if the
command fails.

Claude-session-id: ae02c694-fdfb-4a59-b56a-72b3761afb1a
2025-12-01 21:01:49 -08:00