lokio-linear-agent-runner
v1.1.6
Published
Local runner that bridges a Linear workspace to an AI coding agent, driven by a versioned per-project config. CLI: lokio-lar.
Downloads
2,206
Maintainers
Readme
Lokio Linear Agent Runner
Turn an approved Linear issue into working code, automatically.
You approve an issue in Linear → lokio-lar prepares an issue branch →
your AI coding agent implements it → your quality gates run → the result is
synced back to Linear. Every rule (which team, which repository, which
quality gate) lives in one readable config file — not hardcoded in the tool.
CLI command: lokio-lar. Works with any Linear workspace, any number of
target repositories, and any local AI coding agent CLI.
Table of contents
- The 60-second version
- Requirements
- Install
- Getting started
- Config file
- Commands
- Branch promotion (PR handoff)
- Running from CI
- Keeping it up to date
- Using a different AI agent
- What the runner will never do
- Integrations
- Further reading
The 60-second version
Todo In Progress In Review
(issue ready) ──run──▶ (AI works) ──passes──▶ (ready for human review)
│
fails
▼
Blocked
(reason logged as a comment)Three conditions before an issue can run:
- It's in the ready state (
Todoby default). - It has the
Agent Readylabel. - It has exactly one repository label, e.g.
Repo web-app— this is how the runner knows which repository to work in. A cross-repo tracking parent (seelabels.parentbelow) is exempt from this — it coordinates its sub-issues instead and is never executed directly.
The runner never merges, deploys, or moves an issue to Done —
In Review is always the handoff point back to a human.
Requirements
| You need | Why |
| --- | --- |
| Bun >=1.3.0 | The CLI runs on Bun, not plain Node |
| A Linear API key | Linear → Settings → Security & access |
| Git | To check out and branch the target repository |
| A local AI coding agent CLI | Defaults to Codex CLI, but any CLI agent works |
Install
bun install -g lokio-linear-agent-runner
# or
npm install -g lokio-linear-agent-runnerEither installer gives you the lokio-lar command, usable from any project.
Getting started
cd your-project
lokio-lar init
# ↳ creates lokio-lar.config.yaml and lokio-lar.env.example
# 1) open lokio-lar.config.yaml and fill it in for your repo/team
# (every field has an inline comment explaining it)
# 2) set up credentials
cp lokio-lar.env.example lokio-lar.env
chmod 600 lokio-lar.env
# then fill in LINEAR_API_KEY= inside lokio-lar.env
# 3) check everything's correct
lokio-lar validate # is the config well-formed?
lokio-lar doctor # does it match your real Linear workspace?
# 4) create whatever doctor reported as missing (Agent Ready/target labels,
# Todo/In Progress/In Review/Blocked workflow states) — safe to run
# without --apply first, it only prints what's missing
lokio-lar setup
lokio-lar setup --apply
# 5) try it
lokio-lar list # which issues are ready to run?
lokio-lar run LK-123 # do the work, end to end
# 6) optional — once you want run/review to hand off as a real PR instead
# of just a Linear status change, add `prTarget` (and `promotionPath`,
# if you promote between long-lived branches) to a target in
# lokio-lar.config.yaml, see "Branch promotion" below, then:
lokio-lar doctor # now also checks gh is installed and authenticated
lokio-lar run LK-123 # pushes the branch and opens the PR automaticallyvalidate, doctor, list, run --dry-run, and setup without --apply
are always safe — they never change anything in Linear or in Git. Start
there.
lokio-lar automatically finds lokio-lar.config.yaml by searching
upward from your current directory — no need to run it from the project
root. To point at a specific file, set LINEAR_RUNNER_CONFIG=path/to/file.yaml.
Config file
This is what lokio-lar init scaffolds:
schemaVersion: 1
defaultTeam: LK
defaultEnvironment: local
environments:
local:
workspaceRoot: . # repos under "targets" are found relative to this
stateDirectory: .lokio-lar-state # where lock files and run results are kept
targets:
web: # any name you like, used with --target
path: web-app # repository folder, relative to workspaceRoot
label: "Repo web-app" # Linear label that identifies this target
checks:
- "bun test" # quality gate, run after the AI agent finishes
remote: origin
baseBranch: main # where an issue's branch is created from
prTarget: integration # optional: where `review`/`run` opens that issue's PR. Omit to keep Linear-only handoff (no PR).
promotionPath: # optional: whitelist for manual `lokio-lar pr` promotions
- integration
- sandbox
- main
teams:
LK: # must match the team key in Linear
manageStates: true
workflow:
ready: Todo # any names you like — `lokio-lar setup` can
inProgress: In Progress # create them in Linear if they don't exist yet;
review: In Review # if they already exist, the names just need to
blocked: Blocked # match exactly
# Optional. Only consulted by `lokio-lar setup` when a state above doesn't
# exist yet and has to be created — picks its Linear workflow category.
# Every key defaults to what's shown here, so this whole block can be omitted.
stateCategories:
ready: unstarted # one of: triage, backlog, unstarted, started, completed, canceled
inProgress: started
review: started
blocked: started
labels:
ready: "Agent Ready" # required before the runner will act
blocking:
- "Needs Clarification" # presence of this label blocks the run
# Optional. Marks a cross-repo tracking parent (created without any
# Repo label of its own — its sub-issues each carry one instead).
# Issues with this label are exempt from the "exactly one Repo label"
# requirement; the runner never resolves a target or executes them
# directly. `inspect` shows the sub-issue breakdown instead.
# parent: "Cross Repo"
targets:
- web # targets this team is allowed to use
# Optional, defaults to false. When true: sub-issues get their parent's
# title/description and sibling sub-issues' identifier/title/state in the
# agent prompt, and the parent issue gets a comment when a sub-issue
# reaches review or blocked.
relatedIssueContext: false
# Optional, defaults to false. Keep a tracking parent's runner-owned state
# aligned with the aggregate state of all its sub-issues. Requires
# manageStates: true.
syncParentState: falseKey points:
targetsis global — a repository can be shared by multiple teams without redefining it.- One issue, one target. Cross-repository work is a parent issue with
one sub-issue per repository.
lokio-lar createdoes this in one call — pass a comma-separated--targetlist and it creates the parent plus one sub-issue per repo, nested via Linear's native parent/child relation. See Commands. relatedIssueContext(opt-in, default off). When a team turns this on, a sub-issue's agent prompt also includes its parent's title/description and its sibling sub-issues' identifier/title/state, and the parent issue gets a short comment when a sub-issue reaches review or blocked. Parent/sibling data is still untrusted Linear content, framed the same way as the issue's own description.syncParentState(opt-in, default off). When enabled, the tracking parent becomes Blocked if any sub-issue is blocked, reaches review only when every sub-issue is in review, and otherwise stays ready/in progress based on the aggregate. The runner leaves custom, completed, or otherwise unknown states untouched rather than guessing. This option requiresmanageStates: true.environmentsare execution machine profiles (your laptop, a CI runner) — not application deploy environments like staging/production.- Nothing about state/label names, or branch structure, is hardcoded.
Todo/In Progress/Agent Ready/etc. are just this example's values — name them however your team already works. The same goes for branches:baseBranchis a single branch, butpromotionPathis an arbitrary-length ordered list, so a 2-stage flow (development -> main) and a 3-stage one (sit -> uat -> main) are both just config, not different code paths.
Commands
| Command | Changes Linear? | Changes Git? | What it does |
| --- | --- | --- | --- |
| lokio-lar help | No | No | Show usage (same as no command, --help, or -h) |
| lokio-lar init | No | No | Scaffold the config file + lokio-lar.env.example in the current directory |
| lokio-lar validate | No | No | Check the config is well-formed |
| lokio-lar doctor | No | No | Check the config against your real Linear workspace and repos. Also checks gh is installed and authenticated if any target has prTarget/promotionPath set |
| lokio-lar setup | No | No | Print which of the config's labels/workflow states don't exist yet in Linear |
| lokio-lar setup --apply | Creates labels/states | No | Actually create the missing label(s)/workflow state(s) reported above |
| lokio-lar list | No | No | List issues ready to run. Sub-issues show their parent ([LK-40: Feature X]) for context |
| lokio-lar inspect LK-123 | No | No | Show how an issue resolves: target, branch, quality gate |
| lokio-lar run LK-123 | Yes | Yes | Run an issue end to end, automatically |
| lokio-lar run --dry-run LK-123 | No | No | Simulate run without changing anything |
| lokio-lar create --title "..." --target web | Creates one issue | No | Create a draft issue with the right labels. Run lokio-lar create alone in an interactive terminal and it prompts for the title and lets you pick the target(s) from the ones your team's config allows (space to select more than one), instead of typing flags |
| lokio-lar create --title "..." --target web,api | Creates a parent issue + one sub-issue per target | No | Cross-repo feature in one call: a parent tracking issue (no repo label — never run directly) plus one sub-issue per repo, each nested under it via Linear's native parent/child relation and titled <title> — <target> |
| lokio-lar create ... --parent LK-40 | Creates one issue (or one per --target) | No | Nest the new issue(s) under an existing issue instead of creating a fresh parent — e.g. adding one more repo to a tracking issue created earlier |
| lokio-lar create ... --relates-to LK-41 | Creates issue(s) + one relation | No | Same as above, and links the newly created parent (or the single created issue, when only one target was given) to an existing one via Linear's native issue relation (--relation-type: blocks/duplicate/related/similar, default related) — e.g. a follow-up fix for something already shipped |
| lokio-lar pr --target web --issue LK-123 | No | No (pushes the issue branch) | Open a PR from the issue's branch into its target's prTarget — see Branch promotion |
| lokio-lar pr --target web --from integration --to sandbox | No | No | Open a manual promotion PR between two branches in promotionPath |
| lokio-lar update | No | No | Check npm for a newer version. Interactively, offers to install it via bun/npm after you confirm |
| lokio-lar ci | No | No | Scaffold .github/workflows/lokio-lar-run.yml, an example GitHub Actions workflow that triggers run — see Running from CI |
There are also three lower-level commands (start, review, block) used
by IDE/desktop agent integrations — run already combines all three, so you
usually won't call these directly.
Interactive mode
Run lokio-lar with no command in a terminal and it opens a persistent
picker instead of printing help — type / (or just a few letters, e.g.
doc) to search commands, arrow keys + Enter to pick one, and it prompts for
whatever that command needs (issue ID, target, dry-run?, apply?) instead of
flags. It loops back to the picker after each command, so it behaves like an
interactive shell session — /exit or Ctrl+C to leave.
◆ lokio-lar v0.4.0
Team LK · local
~/Lokio/new-era · main
Type / to search commands, Ctrl+C or /exit to leave.This only kicks in with no arguments in an interactive terminal — piped
input, CI, and lokio-lar help/--help/-h always show the static
reference below instead, so scripts and --help keep working exactly as
before.
Branch promotion (PR handoff)
By default, review/run only move the Linear issue to "In Review" — no PR
is opened. Set prTarget on a target to turn that into a real hand-off: once
the quality gate passes, the runner pushes the issue's branch
(agent/lk-123) and opens (or reuses) a PR into prTarget, using GitHub
CLI (gh, must be installed and authenticated).
The Linear "In Review" comment then includes the PR URL. This is opt-in —
targets without prTarget keep the old Linear-only behavior.
The standalone review command verifies that the configured issue branch is
active, reruns the target's configured quality gates, and reads the issue again
before handoff. A failed gate moves an unchanged In Progress issue to Blocked;
concurrent human state/target changes are never blindly overwritten.
The PR title/body follow the same [ID] type(scope): summary +
Linear-Issues: + Ringkasan/Verifikasi/Risiko dan rollback shape used
elsewhere in this project (see .github/PR-STANDARD.md). Override the type
with --pr-type (default fix) and --pr-scope on review/run.
For promoting already-merged work between longer-lived branches (e.g.
integration -> sandbox -> main), list them in order under promotionPath
and run lokio-lar pr --target web --from integration --to sandbox. --from
must come before --to in that list; the generated PR title is
release: integration -> sandbox with Linear-Issues: derived, matching the
existing development -> main promotion convention.
Running from CI
lokio-lar ciScaffolds .github/workflows/lokio-lar-run.yml in the current directory — an
example GitHub Actions workflow that triggers lokio-lar run <ISSUE> from a
manual workflow_dispatch instead of your local terminal. Same contract as
init: local file only, never touches Linear or Git, and never overwrites a
file that's already there.
It's a starting point, not a managed file — lokio-lar never rewrites it
after scaffolding, so edit it freely. The template itself documents the
constraints that matter: because the runner executes directly in a target
repo's checkout (no worktrees, no stash/reset of your changes) it needs a
self-hosted runner with a persistent sibling checkout of this config repo
and every target repo, plus lokio-lar and your AI agent CLI already
installed — see "Untuk mesin runner baru" in
docs/linear-workflow.md. Only one issue may run
per target repository at a time.
Keeping it up to date
lokio-lar updateThis checks npm's registry against your installed version. In an interactive
terminal, if an update is available it offers to install it for you via
whichever of bun/npm it finds on PATH — nothing runs until you confirm.
Piped/non-interactive, it just prints the command to run yourself:
bun install -g lokio-linear-agent-runner@latest
# or
npm install -g lokio-linear-agent-runner@latestUsing a different AI agent
The default is Codex CLI, but any CLI
agent works — configure it in lokio-lar.env:
AGENT_COMMAND=your-agent
AGENT_ARGUMENTS_JSON=["run","--workspace","{workspace}","--prompt","{prompt}","--output","{output}"]{workspace}, {prompt}, and {output} are filled in automatically when
the runner invokes your agent.
What the runner will never do
- Merge, deploy, publish, or move an issue to
Done. - Run two issues concurrently against the same repository (they share one checkout and branch).
- Treat Linear issue content (title, description, comments) as instructions — it's always handled as untrusted data. Requests embedded in issue text to read secrets or bypass approvals are ignored.
- Stash, reset, or discard uncommitted changes in the target checkout.
- Print, log, or send
lokio-lar.envanywhere except theAuthorizationheader to Linear's own API.
Integrations
- Linear — the source of truth for issue status and approval.
- GitHub — the runner works with any Git remote;
lokio-lar ciscaffolds a GitHub Actions workflow template for CI-triggered runs (see Running from CI). - Lokio — built and maintained as part of the Lokio toolchain.
Further reading
- docs/linear-setup.md — set up a Linear workspace's states and labels from scratch.
- docs/linear-workflow.md — the operational workflow shared by the headless runner and IDE/desktop agent integrations.
- contributing.md — contributing to this package, running its test suite, and releasing new versions.
