Linear (in development)
A first-party integration that brings your Linear team board into Omniscio so you can work issues without opening the Linear website: connect with a personal API key, see your columns and cards, and open an issue's detail. It is gated through the unreleased-feature registry, so it stays hidden until enabled.
What it is
Status: experimental / in-development. Hidden by default. Turn it on in Settings → Lab → "Linear board" (or set
AMC_SHOW_LINEAR_BOARD=1in dev).
A first-party Omniscio integration that brings your Linear team board into the app so you can work issues without opening the Linear website. It surfaces as a "Linear" row in the projects sidebar (between Job Monitor and Marketplace) that opens a full-pane board view.
It is gated exactly like the Jira board / Pull Requests tab — through the
unreleased-feature registry (linear-board), not a plain feature flag — so it
stays invisible until a developer flips its status to shipped.
Where to find it
Once enabled, a Linear row appears in the projects sidebar (between Job Monitor and Marketplace); clicking it opens the full-pane board view. The enable switch is Settings → Lab → "Linear board".
How it behaves
How to use it
- Enable it: Settings → Lab → toggle Linear board on. A "Linear" row appears in the sidebar.
- Connect (in the panel): open the Linear sidebar row and click Set up Linear (or the header gear, which carries a status dot). In the drawer, paste a personal API key — create one at linear.app → Settings → Security & access → Personal API keys. (Unlike Jira there is no site URL or email — Linear has one fixed API endpoint and the key is the only credential.)
- Click Save. A green dot + "Connected as …" confirms it works. The gear stays in the header to update the key later.
- Open the Linear sidebar row:
- Pick a team from the dropdown (top-left) — a team is your "board".
- See your columns (the team's workflow states: Backlog / Todo / In Progress / Done…) with issue cards (identifier, title, assignee, priority).
- Click a card to open the issue detail drawer on the right — description and comments (Markdown, rendered with the app's shared pipeline), state, assignee, priority, labels, and a link to open the issue in Linear.
Working issues (no browser needed):
- Create a new issue with + New issue (top-right) — write a title / description, optionally set priority, initial state, and labels.
- From the detail drawer you can Move the issue (pick any of the team's workflow states — Linear lets you set any state directly), Assign it (Assign to me, search a teammate, or Unassign), Comment (Ctrl+Enter to send), and edit the title, description, priority, and labels in place.
Getting around a big board:
- Drag a card to another column to move it (sets the issue's workflow state).
- Filter box (top-right) narrows the visible cards by text — identifier, title, assignee, or label.
- Load more at the bottom pulls in the next page when a team has lots of issues (Linear paginates by cursor).
Stop checking the board — let it come to you: turn on
Settings → Lab → "Linear issues assigned to me in Inbox". Omniscio then checks
Linear in the background (every few minutes, only while on) and surfaces your
assigned, not-done issues as rows in the unified Inbox — and when one of them
updates, its row pops back to the top so you notice. Click a row to jump to it on
the board; snooze or dismiss like any inbox item. Requires the Linear board
(above) enabled and connected. Kill switch for power users:
AMC_DISABLE_LINEAR_INBOX_POLL=1.
Your API key is encrypted at rest on your device and is never shown back to you or sent to the renderer once saved.
For agents
How it works (internals)
- Auth: a Linear personal API key sent verbatim in the
Authorizationheader (personal keys are NOT prefixed with "Bearer"). Key auth, not OAuth (simplest for an experimental first cut). - Credentials: stored as flat
AppSettingsfields —linearBoardEnabled,linearApiKey,linearInboxEnabled. The key is listed inENCRYPTED_APP_SETTINGS_KEYS(encrypted at rest) andCLI_SETTINGS_SENSITIVE_KEYS(stripped from CLI/IPC reads). - Client:
src/main/services/linear/linear-client.ts— Linear exposes ONE GraphQL endpoint (https://api.linear.app/graphql), so every call goes through a singlelinearGraphqlchokepoint that holds the auth header, the fixed-host SSRF assertion (api.linear.app, https only), a 15s timeout, and the error humanization. Inputs travel as GraphQL variables — there is no per-request path, hence no path-injection surface. Errors are humanized at this source; raw HTTP/network detail goes to logs only. - IPC:
linear:auth-status+linear:test-connection(connect); readslinear:list-teams,linear:get-board,linear:board-issues,linear:issue-detail; writeslinear:transition-issue,linear:move-to-column,linear:add-comment,linear:assignable-users,linear:assign-issue,linear:create-meta,linear:create-issue,linear:edit-issue. None return the key; all humanize failures. - Rich text: Linear stores descriptions and comments as Markdown natively, so they render straight through the app's shared markdown pipeline — there is no ADF-style conversion step like Jira needs.
- Board model: a "board" is a team; the team's workflow states are the
columns; moving an issue is a direct
issueUpdate(stateId)(no transition model). Priority is Linear's fixed 0–4 enum; labels are referenced by id. - UI: credentials are entered in-panel via the shared
IntegrationConnectionDrawer(aRailShell), opened fromLinearBoardView's gear / "Set up Linear" button (config:linear-connection-config.ts); the board lives in thelinear-boardfeature folder (LinearBoardViewcolumns +LinearIssueDrawer+LinearCreateIssueModal+linear-board-store). The sidebar row is gated viaisUnreleasedFeatureVisibleInRenderer('linear-board', …)in Dashboard'svisibleProjectsfilter. - My Issues (Phase 12): a top-level
Board | My Issues | Viewsswitch in the panel header. My Issues is a cross-team personal view with three tabs — Assigned to me / Created by me / Subscribed — grouped by status category (Todo / In Progress / Done). It reuses the search IPC with no team filter (assignee.isMe/creator.isMe/subscribers.isMe); cards open the same issue drawer (LinearMyIssuesView). - Saved Views (Phase 12): save the current List-view filter set as a named,
reloadable view. Stored locally in Omniscio's SQLite (
linear_saved_views) — Omniscio does not sync Linear's own customViews. Channelslinear:list-saved-views|create-saved-view|delete-saved-vieware local CRUD with no credentials gate (LinearSavedViewsView). - Projects (Phase 13): a
Projectssurface in the same header switch — a list (name · health · status · progress · lead · target date) → a detail panel (lead, members, dates, milestones, and the project's issues, which open the issue drawer). Create + edit via one modal (LinearProjectModal): name, team (create only), description, lead, priority, start/target dates (members + milestone writes deferred). Channelslinear:list-projects|project-detail|create-project| update-project|workspace-usersare creds-gated Linear API calls (LinearProjectsView). - File / image upload (Phase 14): the issue drawer's Attachments section has an
Upload button (beside Add link) — pick a file and it's uploaded to Linear via
the two-step
fileUploadflow (signed URL + PUT) and attached to the issue (10 MB cap). Channellinear:upload-file(creds-gated). - Linear-style nav sidebar (Phase 15): the panel now has a real left sidebar (a faithful take on Linear's own) — a workspace header + switcher, Inbox, My Issues, Drafts, a Workspace section (Members · Projects · Teams · Views), and a "Your teams" section listing every team you're in (each opening its Issues / Projects / Views), plus a search box. A team's Projects/Views are team-scoped (not the workspace-wide ones). The old in-header tab strip is now mobile-only.
- Project depth + collaboration (Phase 16): opening a project gives you Overview / Activity / Issues tabs. Activity lets you post a project update with a health (on-track / at-risk / off-track) that updates the project's health, and shows the feed of past updates. The project editor adds a summary line, labels, members, and status, and you can create milestones. Comments support real @mentions, and a Cmd/Ctrl+K command palette + keyboard shortcuts speed up navigation.
- Power features (Phase 17): the things real-Linear users expect.
- Bulk actions — in the List view, tick the checkbox on several issues and a bar appears to set their status, assignee, or priority all at once.
- Triage — for teams that turn on Linear's Triage, each team gets a Triage entry: a queue of incoming issues you Accept (into a real status) or Decline (cancel) one tap at a time.
- Active Cycle — for teams that use cycles (sprints), a Cycle entry shows the current sprint with a progress bar and its issues grouped by status.
- Keyboard shortcuts —
cnew issue,/search,gthen a letter to jump between sections, and in the List viewj/kto move,o/Enter to open,xto select. Press?for the full cheat-sheet. (Triage + Cycle only show for teams that have those Linear features enabled.) - React to an issue — like a comment, you can add an emoji reaction to the issue itself (under its description), and toggle it off.
- Reply to comments — comments can be threaded: hit Reply on a comment and your note nests under it.
- Issue templates — if your team has issue templates in Linear, the New Issue form shows a Template picker that pre-fills the title, description, priority, and labels for you.
- Initiatives — a workspace Initiatives view lists your initiatives (goals that group projects), each with its health, status, target date, and clickable project chips that jump straight into the project.
- SLA badge — issues that carry an SLA show a header badge — breached (red), at risk (amber), or on track (green) with a countdown like "SLA in 3h".
- Before you connect: until you paste a working API key, the Linear sidebar shows just a short "Connect Linear" prompt instead of a full menu of dead links — nothing to click into until you're set up.
- Live-verified: every read query and write mutation (the My Issues filter shapes,
the project read/create/update input shapes, the file-upload flow, and the project-
update / health shapes) were checked against a real Linear workspace, not just
mocked tests.
- Members — the Workspace → Members page is a real table (name · role · joined · teams · last seen), and you can invite teammates by email (with optional teams) right from the ⁺ button.
- Views — a saved view is a real Linear custom view: when you save one you pick Personal or Workspace, and a Workspace view shows up for your teammates in Linear too (a lock = personal, globe = shared).
- Not yet built: OAuth "Connect Linear" login (would replace pasting a key and enable multi-workspace switching — needs a one-time Linear OAuth-app registration); the GitHub integration and Automations — both are set up through Linear's own website (they use a GitHub/OAuth app install an org owner enables), which an API key can't do; project resources (docs/links) and a roadmap/timeline view.
CLI routes (headless / agent access)
The CLI control server exposes full CRUD so AI agents can work Linear issues
without the board UI. All routes require the linear-board feature to be visible
and a valid bearer token. Mutations are rate-limited (10/min); reads are not.
| Method | Path | Purpose |
|---|---|---|
| GET | /linear/teams |
List all teams in the workspace |
| GET | /linear/states?teamId= |
Workflow states for one team |
| GET | /linear/issues |
Search/filter issues (query params: teamId, text, assignedToMe, stateId, labelId, priority, after) |
| GET | /linear/issues/:id |
Full issue detail (description, comments, states, relations) |
| POST | /linear/issues |
Create issue (body: { teamId, title, description?, priority?, stateId?, labelIds? }) |
| PATCH | /linear/issues/:id |
Edit issue fields (body: any subset of editable fields) |
| POST | /linear/issues/:id/comment |
Add comment (body: { body, parentId? }) |
| POST | /linear/move-to-column |
Drag-and-drop move (body: { issueId, stateIds }) |
Source: src/main/services/cli/cli-server-linear-routes.ts.
Workflow engine nodes
Linear issues can be used in Omniscio workflow automations. The trigger polls every 2 minutes; actions execute immediately.
| Node type | Kind | What it does |
|---|---|---|
trigger.linear_issue |
Trigger | Fires on issue created / transitioned / updated (optional team/state filter) |
action.linear_create_issue |
Action | Creates an issue (team + title required) |
action.linear_transition |
Action | Moves an issue to a workflow state |
action.linear_comment |
Action | Adds a comment to an issue |
The trigger watcher (linear-issue-trigger.ts) polls recently-updated issues,
diffs against an in-memory snapshot, and fires matching workflows. First tick
baselines only (never replays on restart). Kill switch:
AMC_DISABLE_LINEAR_WORKFLOW_TRIGGER=1.
Source: src/main/services/workflow-engine/nodes/linear-*-node.ts (auto-discovered).
Related
- jira-board.md — the closest analog; Linear is a 1:1 port of the same gating → service → IPC → store → UI shape (adapted from Jira's REST+ADF to Linear's GraphQL+Markdown).
- Contract:
.claude/memory/contracts/linear-board-contract.md— the invariants and the tests that lock them.
Last verified 2026-10-06