linear

The linear extension bidirectionally syncs Linear issues with the Thurbox task list : your issues show up as tasks, and marking a task done moves the issue to a completed state. A linear-tick automation (every 15 min, cron:*/15 * * * * ) runs a deterministic Exec command — {home}/scripts/sync.sh — that reconciles the teams in trackers.md with the task list. There is no agent, no LLM, no tokens : Thurbox's scheduler runs the script (TUI or headless heartbeat) and records its output in the automation run history. The script only calls thurbox-cli and the Linear GraphQL API. Linear has no CLI , so all calls hit https://api.linear.app/graphql via curl ; no Linear bot, no webhook.

Experimental. linear is new and under active testing — its sync scripts and manifest may change between releases.

Overview #

Pull is the default direction: Linear issues become Thurbox tasks. Linear is authoritative for an issue's title, URL, and open-vs-done state ; your local todoin_progress distinction is preserved. Linear's richer states map faithfully: unstarted / backlog / triagetodo , startedin_progress , completed / canceleddone . Imported tasks carry source=linear and external_id="<issue identifier>" (e.g. ENG-7 ), so re-syncing never duplicates them — dedup is by (source, external_id) .

Requirements #

  • thurbox-cli ≥ 0.141 on PATH — the sync uses the task --source/--external-id/--external-url flags added there (check with thurbox-cli version ).
  • curl and jq on PATH .

Get a Linear API key #

In Linear, go to Settings → Security & access → Personal API keys → New key . Because the automation runs headless (the scheduler fires it with no inherited shell environment), hand it the key via a credentials.env file in the install home — sync.sh sources it before running:

$ mkdir -p ~/.config/thurbox/extensions/linear
$ printf 'LINEAR_API_KEY=lin_api_xxxxxxxx\n' > ~/.config/thurbox/extensions/linear/credentials.env
$ chmod 600 ~/.config/thurbox/extensions/linear/credentials.env

(Exporting LINEAR_API_KEY from your shell profile is an alternative, but it only reaches the sync if the scheduler inherits your profile — so credentials.env is recommended.) The key is sent verbatim in the Authorization header — Linear personal API keys are not prefixed with Bearer . Also note your team key (the prefix on issue ids, e.g. ENG in ENG-7 ).

Install #

linear is a Thurbox extension (a declarative extension.toml manifest):

$ thurbox-cli extension install linear       # or ./extensions/linear
$ thurbox-cli extension uninstall linear     # --purge also deletes ~/.config/thurbox/extensions/linear

Installing lays down the ~/.config/thurbox/extensions/linear/ home (override with --home ; it holds scripts/sync.sh + helpers and the seeded trackers.md ) and activates the linear-tick automation — self-healed by Thurbox if deleted.

Configure trackers.md #

Edit ~/.config/thurbox/extensions/linear/trackers.md — one row per Linear team. The query is a Linear team key (e.g. ENG ): the whole cell is the team key, and all of that team's issues are synced. Keep push_back = no for the first run.

| name    | query | push_back |
|---------|-------|-----------|
| backend | ENG   | no        |
| web     | WEB   | no        |

First sync & verify #

The automation fires every 15 min. To run it now, trigger it from the Automations pane ( Ctrl+P → select linear-tickr ) or headless:

$ thurbox-cli automation run <id>     # id from: thurbox-cli automation list
$ ~/.config/thurbox/extensions/linear/scripts/sync.sh     # or run the script directly

Then inspect the imported tasks:

$ thurbox-cli task list --json | jq -c '.[] | select(.source=="linear") | {id,status,external_id,title}'

States map as above ( unstarted / backlog / triagetodo , startedin_progress , completed / canceleddone ). Re-running is idempotent — dedup by (source, external_id) leaves unchanged issues alone, and the source=linear tag keeps these tasks distinct from any other tracker's. The run's output (created/updated/unchanged counts) shows in the automation run history.

Two-way sync #

Once the pull looks right, set push_back = yes on a tracker row. Now marking an imported task done moves its Linear issue to a completed state, and moving it back to todo moves it to an unstarted state — only the open↔done axis is pushed. The sync runs push-then-pull ( push-status.sh then per-tracker fetch.sh | upsert.sh ), so your local change reaches Linear before the pull reads state back. Push acts only on push_back=yes rows.

Files #

See extensions/linear for the extension.toml manifest, the seeded trackers.md , the README.md , and the sync scripts ( scripts/sync.sh , scripts/fetch.sh , scripts/upsert.sh , scripts/push-status.sh ).