Commit Graph

447 Commits

Author SHA1 Message Date
Peter Schilling 11da7da49e Merge branch 'main' into fix/linux-keyring-version-probe 2026-05-13 09:14:21 -07:00
Alex Broekhof 6ac47a801b fix(keyring): drop nonexistent secret-tool --version probe on Linux
The Linux keyring backend gated availability on the exit code of
`secret-tool --version`, but that flag has never existed in any release
of libsecret (including master). On every Linux system, `secret-tool
--version` prints usage and exits 2, so isAvailable() always returned
false and 'linear auth login' failed with 'No system keyring found',
even when gnome-keyring-daemon was running fine.

Drop the version probe and rely on the existing lookup probe, plus an
explicit check for the well-known 'was not provided by any .service
files' stderr that secret-tool emits when no Secret Service is
registered on the session bus. This matches the shape of the existing
test/keyring.integration.test.ts isKeyringAvailable() helper.
2026-05-01 12:09:25 -07:00
Peter Schilling b3b9960436 fix: order issue view comments chronologically
Linear's comments connection returns newest-first and the GraphQL schema
doesn't expose a direction argument, so sort root comments ascending
client-side to match the order shown in Linear's UI.
2026-04-21 15:53:19 -07:00
Peter Schilling 90767cbd07 chore: add plugin version bump step to release skill 2026-04-03 13:03:47 -07:00
Peter Schilling e5fa8d28da chore: bump plugin version to 2.0.0 2026-04-03 12:56:16 -07:00
Peter Schilling a3e2960b7f chore: Release linear-cli version 2.0.0 v2.0.0 2026-04-03 11:41:56 -07:00
Peter Schilling 26c418f4b8 feat: split issue list into mine and query commands
Introduce 'issue mine' for personal work queue and 'issue query' for
structured retrieval with optional full-text search via --search.
Keep 'issue list' as a separate backwards-compatible command.
Remove standalone 'issue search' registration in favor of query --search.

query supports multi-team filtering, --all-teams, --json output,
--search-comments, and verifies GraphQL variables in tests.
2026-04-03 18:22:51 +00:00
Peter Schilling aba660998e refactor: preserve GraphQL payload shape in project update list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling 8d11f4b6fa refactor: preserve GraphQL connection shape in project list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling ab1f64fb7a refactor: preserve GraphQL mutation shape in project create JSON 2026-04-02 15:15:00 -07:00
Peter Schilling 4691061aad refactor: preserve GraphQL connection shape in label list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling d73884d9aa test: cover raw GraphQL JSON output in agent session view 2026-04-02 15:15:00 -07:00
Peter Schilling 8f1e406fee refactor: preserve GraphQL connection shape in agent session list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling 2d2208ffd5 refactor: preserve GraphQL connection shape in issue comment list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling 03a12b06bf refactor: preserve GraphQL payload shape in initiative update list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling ef925984dc refactor: preserve GraphQL payload shape in initiative view JSON 2026-04-02 15:15:00 -07:00
Peter Schilling 11487b6097 refactor: preserve GraphQL connection shape in initiative list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling f460007a5f refactor: preserve GraphQL connection shape in document list JSON 2026-04-02 15:15:00 -07:00
Peter Schilling 7c7ad2ac1c docs: codify GraphQL-shaped JSON output policy 2026-04-02 15:15:00 -07:00
Peter Schilling f86356d435 fix: show issue documents in issue view
Fixes #183
2026-04-02 11:49:05 -07:00
Peter Schilling c4feb0866b fix: accept alphanumeric Linear issue team keys 2026-04-02 09:30:13 -07:00
Peter Schilling fb329435f3 fix: remove -w short flag from --workspace to resolve collision with --web
Also skip keyring integration test when D-Bus secrets service is unavailable
2026-04-02 09:07:13 -07:00
Peter Schilling c53feef022 docs: include full command tree in linear skill 2026-04-02 08:46:00 -07:00
Peter Schilling b4aea366f6 feat: add issue search command 2026-04-02 04:58:17 +00:00
schpetbot e23e9ff856 feat: show resolved thread metadata in issue view (breaking change) (#199)
## Summary
- include resolved-thread metadata and derived `threadId` in `linear
issue view --json`
- hide resolved threads by default in human-readable `issue view`, with
`--show-resolved-threads` to reveal them
- show root thread ids in rendered output and use OSC-8 hyperlinks for
them when terminal hyperlinks are enabled

## Testing
- deno check src/main.ts
- deno lint
- deno task test
- manual QA against CLI-team issues for default view,
`--show-resolved-threads`, JSON output, no-comments JSON, open-only
threads, OSC-8 behavior, and reply creation from printed thread ids

Co-authored-by: Peter Schilling <code@schpet.com>
2026-04-01 18:44:30 +00:00
Peter Schilling 1e51d2adbd test: disable colors in issue list assertion 2026-04-01 14:59:12 +00:00
Peter Schilling 713a6c2acd style: format issue list test for CI 2026-04-01 14:59:12 +00:00
Peter Schilling 4113c4d4fc test: make issue list output deterministic 2026-04-01 14:59:12 +00:00
Evan Jacobson 6fdd1e0da2 upgrade dependencies (#194) 2026-03-31 20:36:06 -07:00
Paymahn Moghadasian 4ac13293c0 feat: add agent-session list and view commands (#192) 2026-03-31 05:59:48 +00:00
Jeffrey Holm 08fcf6ce96 feat: add --created-after and --updated-after filters to issue list (#191) 2026-03-31 05:47:31 +00:00
Jeffrey Holm f9519f7807 feat: show assignee and priority in issue view (#190)
## Summary
- Add **assignee** and **priority** fields to the `issue view` command's
metadata line
- Priority uses the existing `getPriorityDisplay` function (same visual
format as `issue list`)
- Assignee shows `@displayName` or `Unassigned` when null
- Both GraphQL queries (`GetIssueDetailsWithComments` and
`GetIssueDetails`) updated with `assignee { name displayName }` and
`priority`

## Motivation
These are critical fields for triaging issues. Previously, `issue view`
showed project, milestone, and cycle but not who owns the issue or how
urgent it is.

## Example output
```
# ENG-123: Fix authentication bug

**Priority:** ▄▆█ | **Assignee:** @Jane Smith | **Project:** Platform Infrastructure Q1
```

## Test plan
- [x] Updated all 10 issue-view snapshot tests with mock data covering:
unassigned/assigned, all priority levels (0-4)
- [x] `deno check src/main.ts` passes
- [x] `deno lint` passes
- [x] All issue-view tests pass (`deno test --allow-all --filter "Issue
View"`)

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

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 05:28:52 +00:00
Mihai Chiorean e7851e3cb5 feat: add --label filter to issue list (#180)
## Summary

Adds `-l, --label <label>` flag to `issue list` for filtering issues by
label name. The flag is repeatable — when multiple labels are specified,
only issues matching **all** labels are returned.

- Uses `eqIgnoreCase` for case-insensitive label name matching
- Single label: `filter.labels = { some: { name: { eqIgnoreCase: "Bug" }
} }`
- Multiple labels: `filter.labels = { and: [{ some: { name: {
eqIgnoreCase: "Bug" } } }, ...] }`

### Usage

```bash
# Single label
linear issue list --label Bug

# Multiple labels (AND logic)
linear issue list --label Bug --label "High Priority"

# Combined with other filters
linear issue list --label Bug --state started --cycle active
```

## Test plan

- [x] Added snapshot test for `issue list --label Bug` with mock server
- [x] Updated help text snapshot with new `--label` flag
- [x] `deno fmt` clean
- [x] `deno lint` clean
- [x] All tests pass, existing tests unaffected

---------

Co-authored-by: Peter Schilling <code@schpet.com>
Co-authored-by: Mihai Chiorean <mihai-chiorean@users.noreply.github.com>
2026-03-31 05:04:45 +00:00
Mihai Chiorean 16ae8ae9ce feat: add --json flag to issue list, issue create, and cycle list (#179)
## Summary

Adds `--json` / `-j` flag to three commands that were missing structured
output support:

- **`issue list --json`** — outputs issues as a JSON array with `id`,
`identifier`, `title`, `priority`, `estimate`, `state`, `labels`,
`assignee`, and `updatedAt`
- **`issue create --json`** — outputs the created issue's `id`,
`identifier`, `url`, and `team` as JSON (non-interactive path only)
- **`cycle list --json`** — outputs cycles as a JSON array with `id`,
`number`, `name`, `startsAt`, `endsAt`, `completedAt`, `isActive`,
`isFuture`, `isPast`, and `status`

When `--json` is set, the spinner is suppressed and empty results output
`[]` instead of human-readable messages.

This is particularly useful for AI agents and automation that need to
parse CLI output programmatically. The `linear api` raw GraphQL command
works as a workaround today, but first-class `--json` support on
list/create commands is much more ergonomic.

Related: #127 (requests `--json` on project commands — this PR covers
issue and cycle commands using the same pattern)

## Test plan

- [x] Added snapshot test for `issue list --json` with mock server
- [x] Added snapshot test for `issue create --json` with mock server
- [x] Added snapshot test for `cycle list --json` with mock server
- [x] Updated help text snapshots for all three commands
- [x] `deno fmt` clean
- [x] `deno lint` clean
- [x] All new tests pass, existing tests unaffected
2026-03-31 04:35:22 +00:00
Al Johri 3ec5c08978 chore: regenerate skill docs for --project-label flag 2026-03-31 04:27:57 +00:00
Al Johri 16ebdfc69d feat: add --project-label flag to issue list command
Filter issues by project label name, showing issues from all projects
that have a given label. Uses Linear's native GraphQL project label
filtering rather than a two-step query.
2026-03-31 04:27:57 +00:00
c-99-e cb749d3dbd skill: improve SKILL.md with bunx fallback, required flags, and --no-pager caveat (#182)
A few practical improvements based on real usage friction:

- **Prerequisites**: Added `bunx linear` as a zero-install fallback for
when `linear` isn't on PATH
- **Discovering Options**: Added a note about commands with non-obvious
required flags — specifically that `issue list` requires `--sort` (valid
values: `manual`, `priority`) and `--team`, and that `--no-pager` is
only supported on `issue list`
2026-03-25 08:47:31 -07:00
Luc Leray a8ee13e999 regenerate skill docs for issue link command 2026-03-25 08:46:56 -07:00
Luc Leray 1b510720c5 style: fix deno fmt formatting in test 2026-03-25 08:46:56 -07:00
Luc Leray e38fc08ef2 feat: add issue link command to attach URLs to issues 2026-03-25 08:46:56 -07:00
Hyunsu Lim a7c4f75b5e feat: display issue state in issue view command
Show the issue state (e.g., Todo, In Progress, Done) in the metadata
line of `linear issue view`, positioned before Project/Milestone/Cycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:30:06 -07:00
Peter Schilling 91866c0e7d chore: strip version from generated skill docs
Removes version strings from all generated documentation to avoid
unnecessary churn in PRs when cutting a release. Adds a stripVersion
helper that filters "Version: X.Y.Z" lines from CLI help output, and
removes the "Generated from linear CLI vX.Y.Z" line from the template
and index.
2026-03-10 22:22:26 -07:00
Peter Schilling 691df87116 fix: add suggestion to auth migrate keyring error message 2026-03-10 22:12:08 -07:00
Ben Drucker b8a7e54854 feat: store API keys in the system keyring (#136)
Move API key storage from plaintext TOML to OS-native keyrings (macOS
Keychain, Linux `libsecret`, Windows Credential Manager). The
credentials file retains only workspace metadata. Keys are loaded into
an in-memory cache at startup so all downstream reads remain synchronous
— no changes needed to any command files.

## Changes

### Keyring (`src/keyring/`)

- Platform-detecting wrapper with `getPassword`, `setPassword`,
`deletePassword` exports
- macOS: `/usr/bin/security` (exit 44 = not found)
- Linux: `secret-tool` via stdin for writes (exit 1 = not found)
- Windows: `Deno.dlopen("advapi32.dll")` FFI calling
`CredReadW`/`CredWriteW`/`CredDeleteW` directly
- `_setBackend()` test seam for injecting an in-memory `Map` backend

### Windows Credential Manager via FFI

The Windows backend calls `advapi32.dll` directly via Deno's FFI
(`Deno.dlopen`) rather than shelling out to PowerShell. This matches the
standard approach taken by every comparable credential tool:

-
[`danieljoos/wincred`](https://github.com/danieljoos/wincred/blob/623325312d3224d48d131159187b93e906216563/sys.go)
— Go library calling `advapi32.dll` via `windows.NewLazySystemDLL`, used
by:
-
[`docker-credential-helpers`](https://github.com/docker/docker-credential-helpers/blob/2b4e08bca3dbdb8e6c6e28790042742d0c0fc48f/wincred/wincred.go)
- [`gh`
CLI](https://github.com/cli/cli/blob/2c54a0d36a2f3c9c1f1b869a64120837c3a1e6f5/internal/keyring/keyring.go)
(via
[`zalando/go-keyring`](https://github.com/zalando/go-keyring/blob/5c6f7e0ba54d20daa8ea4e03f7ce0a27c075bfb6/keyring_windows.go))
-
[`aws-vault`](https://github.com/99designs/aws-vault/blob/70522e8f0b8f9c5b4e2e4e1e1e1cc4e3e5c3f04c/go.mod)
(via `99designs/keyring`)
-
[`node-keytar`](https://github.com/atom/node-keytar/blob/deae59a488789f2cd4a8dba6c7e58665795804fe/src/keytar_win.cc)
— C++ N-API addon, `#include <wincred.h>`
-
[`jaraco/keyring`](https://github.com/jaraco/keyring/blob/38c040133559682902f25fe96496756ee6849820/keyring/backends/Windows.py)
— Python, `win32cred` (pywin32-ctypes wrapping advapi32 via ctypes)

The implementation packs the 80-byte `CREDENTIALW` struct manually via
`DataView`, encodes strings as UTF-16LE for the `W`-suffix APIs, and
uses `GetLastError` from `kernel32.dll` to distinguish "not found"
(`ERROR_NOT_FOUND` = 1168) from real failures. DLLs are lazy-loaded so
the module import doesn't fail on macOS/Linux.

### Credentials (`src/credentials.ts`)

- `Credentials` interface changed from index signature to `{ default?:
string; workspaces: string[] }`
- `apiKeyCache` `Map` populated at startup, keeping
`getCredentialApiKey()` sync
- `addCredential`/`removeCredential` write to keyring first, only mutate
local state on success
- `parseInlineCredentials` / `parseKeyringCredentials` /
`populateKeyringCache` extracted from `loadCredentials`
- Parallel keyring lookups via `Promise.all`
- Malformed TOML parse errors caught with recovery guidance
- Warnings for: missing keyring entries, dangling default workspace,
inline format detected

### Backward Compatibility

- Inline-format TOML files (keys stored as `workspace = "lin_api_..."`)
are detected by `hasInlineKeys` and served from the file directly
- `addCredential` on an inline-format installation rewrites the file to
keyring format

### Auth List (`src/commands/auth/auth-list.ts`)

- Replaces removed `getAllCredentials()` with `getApiKeyForWorkspace()`
- Distinguishes auth errors (401/403) from network/other failures
instead of labeling everything "invalid credentials"

### CI

- Added `keyring-integration` job on `macos-latest` and `windows-latest`
for real credential round-trip testing

## Testing

- Subprocess isolation via `deno eval` for credential tests (required by
top-level `await loadCredentials()`)
- Mock keyring backend injected via `_setBackend` — covers happy paths,
error propagation, and cache consistency
- Integration test (`test/keyring.integration.test.ts`) exercises the
real macOS Keychain and Windows Credential Manager lifecycle
- Edge cases covered: keyring write/delete failures leave state
unchanged, null keyring returns warn but don't crash, dangling default
dropped on load, inline→keyring format transition on `addCredential`

## References

Closes #130

---------

Co-authored-by: Peter Schilling <code@schpet.com>
2026-03-10 22:03:52 -07:00
Peter Schilling ab21736a1c docs: add npm install instructions to README 2026-03-07 17:59:28 +00:00
Peter Schilling 4007ac76cb chore: Release linear-cli version 1.11.1 v1.11.1 2026-03-06 22:13:11 +00:00
Peter Schilling dbebd16319 feat: add npm installer and publish job for @schpet/linear-cli 2026-03-06 21:39:27 +00:00
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
Peter Schilling 47f69b1e5e fix attribution on changelog 2026-03-05 05:36:04 +00:00