oxagenDocs
Collectors

Linear

Read Linear issues into a workspace by team, and write back as the Oxagen app.

The Linear collector is not available yet. This page describes how it works once Oxagen turns it on.

Account to connect with

An organization Owner, or a workspace Admin, signs in to Linear and approves the Oxagen app for the Linear workspace. The grant acts as the Oxagen app (actor=app), not as the person. Every write shows in Linear as the Oxagen app.

The sign-in needs the LINEAR_OAUTH_CLIENT_ID setting, and the webhook needs LINEAR_WEBHOOK_SECRET, the shared secret Linear locks each delivery with. Sign-in uses PKCE, so no client secret is needed.

Scopes asked for

ScopeAskedUsed for
readAlwaysReading issues, teams, and workflow states
writeOnly when the person turns on writingComments, state changes, priority, and labels

Oxagen asks for no admin scope. It registers no webhook of its own, so it does not need one.

Scope choices

A collector names one or more teams by key, such as ENG. The scope step lists the teams the connection can read. An issue that moves to another team keeps its Oxagen item, and the collector stops reading it when the new team is not in scope.

toml
# work/collectors/linear-eng.toml in the steering repo
schema = "collector/v1"
name = "linear-eng"
label = "Linear engineering"
type = "linear"
connection = "<connection id>"

[scope]
teams = ["ENG", "OPS"]
repos = ["acme/app"]
create_team = "ENG"

repos is optional. It names the linked repositories whose work items this collector creates issues for. Without it the collector creates no issue. create_team names the team the issues go to. Leave it out only when the scope names one team. Until the collector settings page shows these fields, set them in the collector file or with set_work_collector.

A reconcile fails when the connection can no longer read a named team. After three failed reconciles in a row the collector reads failing and stops polling until an admin reconnects it.

Default field mapping

A workspace with no Linear rows gets these. They use Linear's workflow state types, which every team shares.

OxagenReads from LinearWrites to Linear
Status OpenState types triage, backlog, unstarted, startedThe team's first unstarted state
Status ClosedState types completed, canceled, duplicateThe team's first completed state
Resolution DoneState type completedThe first completed state
Resolution CanceledState type canceledNone
Resolution DuplicateState type duplicateNone
Resolution Won't doNoneThe team's first canceled state
Priority P0, P1, P2, P3Priority 1 Urgent, 2 High, 3 Medium, 4 LowThe same numbers
Type Bug, New Feature, Improvement, Documentation, Test, ChoreLabels Bug, Feature, Improvement, Documentation, Test, ChoreThe same labels

Linear priority 0 means no priority and maps to none. A trashed issue reads as closed. You can change a status write row to name a state instead of a state type.

What each switch writes

SwitchLinear callResult
certify_notecommentCreateA comment that lists the criteria
send_notecommentCreateA comment about the send
statusissueUpdate with stateIdMoves the issue to a state of its own team, chosen by the write rows
closeissueUpdate with stateIdMoves the issue to the team's first completed state
labelsissueUpdateSets the priority number and the Type label, and swaps the Type label, keeping every unrelated label
createfileUpload, issueCreate, attachmentCreateUploads each file, creates the issue in create_team with the mapped priority, labels, and state, and attaches each file
textissueUpdateSets the title and description a person edited in Oxagen
badgeNoneWrites nothing. A Linear issue gets no work item badge yet

The created issue's id comes from the work item, so a retry finds the issue an earlier try made. A label no mapping row names is set only where the team or workspace has it.

A label the team and workspace do not have fails the write once as mapping_missing, and the message says to create the label in Linear or change the mapping. Oxagen creates no label and no state. A mapping that names a field Linear cannot set, or a priority outside 0 to 4, fails the same way.

What the tracker cannot do

  • Linear has no resolution field. A state carries the resolution, so a won't-do needs a canceled state in the team.
  • A write targets a state of the issue's own team. A team with no state of the mapped type fails as status_unreachable.
  • Oxagen writes a title or a description only for an issue it creates, and for a person's edit in Oxagen. It never sets an assignee.
  • One webhook serves every installation of the app, so Oxagen cannot register or renew a webhook per team.

Webhook and reconcile timing

Linear locks each delivery with the shared secret and sends the lock in Linear-Signature, the hex HMAC-SHA256 of the raw body, so any change to the body shows. Oxagen refuses a delivery whose webhookTimestamp, inside the locked body, is more than a minute from now. The webhook arrives within seconds of a change. It names only the issue id, and Oxagen reads the issue over GraphQL.

The webhook never expires, so Oxagen renews nothing. A reconcile every 15 minutes reads the issues changed since its cursor. Press Read now on the collector to start one sooner.

On this page