Skip to content

Latest commit

 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

AI Coding Automation

A minimal automation system: a Bash worker that picks up Linear issues assigned to you, has OpenCode implement them autonomously, runs the tests, opens a pull request, and moves the issue to In Review — across all of your repositories, from a single installation.

No framework, no database, no containers. Just Bash, Git, GitHub CLI, the Linear API, and the OpenCode CLI.

How it works

┌────────────┐  assigned Linear issue   ┌──────────────┐
│ loop start │ ───────────────────────► │ Linear API   │
│  (worker)  │ ◄─────────────────────── │              │
└─────┬──────┘   issue: title, body     └──────────────┘
      │  resolve repo (team name → repos.yaml)
      ▼
 1. checkout repo base branch, create branch ai/<KEY>-<slug>
 2. opencode run <coding prompt> --dir <repo path> --auto
 3. commit changes
 4. run tests (npm test / cargo test / go test / pytest)
 5. git push, gh pr create
 6. move Linear issue to "In Review"
      │
      └──► repeat until stop/pause

Quick start

cd automation
./install.sh               # checks tools, creates config.env + repos.yaml, installs `loop`
vim config.env             # set LINEAR_API_KEY, GITHUB_TOKEN
vim repos.yaml             # register your repositories
loop start
loop status
loop logs
loop pause
loop resume
loop stop
loop run LIN-123
loop run LIN-123 --repo loopengineering

See INSTALL.md for full setup instructions.

Commands

Command What it does
loop start Starts the worker in the background (refuses if already running).
loop stop Stops the worker gracefully — after the current issue (or immediately if idle).
loop pause Pauses after the current issue finishes; no new issues are started.
loop resume Clears the pause request.
loop run KEY Runs the full pipeline for one issue, in the foreground. Refuses while the worker is running.
loop run KEY --repo NAME As above, forcing the repository (overrides auto-detection).
loop status Shows running/stopped, paused, current issue + repo, current step, last completed issue, last PR.
loop logs [-e|-o] [N] Worker log (default, last 50 lines), -e error log, -o opencode log.
loop repos Lists the repositories registered in repos.yaml.

The individual scripts (start.sh, run-issue.sh, ...) still work directly; loop is just a thin CLI over them.

Configuration (config.env)

Variable Purpose
LINEAR_API_KEY Linear personal API key (https://linear.app/settings/api).
GITHUB_TOKEN GitHub token used by gh (exported to the worker).
OPENCODE_COMMAND OpenCode invocation, e.g. opencode run or opencode run -m provider/model.
CHECK_INTERVAL Seconds the worker waits between iterations when idle.

Repository registry (repos.yaml)

All your repositories live in one registry file. Adding a project is a new entry — the automation code never changes:

repositories:
  hermes:
    path: ~/Projects/Hermes

  loopengineering:
    path: ~/Projects/LoopEngineering
    branch: develop        # optional, defaults to main

  ielts-journey:
    path: ~/Projects/IELTS-Journey
    aliases: [engineering, ieltsjourney]   # optional: Linear team/project names

How the repository is chosen for an issue

  1. From the Linear issue: the issue's Linear team name (or, failing that, its project name) is matched against the registry. Matching is loose — "Loop Engineering" finds an entry named loopengineering or loop-engineering, "IELTS Journey" finds ielts-journey. Names listed under aliases: also match, which is what you need when the Linear team is called something generic like "Engineering".
  2. Single-repo fallback: if exactly one repository is registered, it is used when nothing else matches (unambiguous by definition).
  3. --repo <name> override: loop run LIN-123 --repo hermes forces a repository when detection is not possible or you want to override it.

State files (state/)

Plain text files, no database:

File Meaning
worker.pid PID of the running worker.
current_issue Linear identifier currently being processed (ABC-123).
current_repo Repository currently being worked on.
current_step Current pipeline stage: branch, coding, commit, testing, pushing, pr, linear, idle, paused.
last_issue Identifier and title of the last completed issue.
last_pr URL of the last pull request created.
pause.flag Present while a pause is requested.
stop.flag Present while a stop is requested.
prompt.md Scratch: the prompt handed to OpenCode for the current issue.

Logs (logs/)

File Contents
worker.log Timestamped progress of the worker and the pipeline (each line is prefixed with the repo name).
error.log Errors only.
opencode.log Full output of each OpenCode run.

Behavior notes

  • Issue selection: the worker takes the most recently updated issue assigned to you that is in an unstarted or started workflow state — across all registered repositories. Completed and canceled issues are skipped.
  • Branches: named ai/<KEY>-<slug>, cut from the repo's base branch (from repos.yaml, default main). If the branch already exists (e.g. after a crash), it is reused instead of failing.
  • Tests: detected automatically (npm/cargo/go/pytest). If tests fail, the PR is still created and an error is logged — review it.
  • Linear updates: the issue is moved to a workflow state named In Review. Your Linear team must have a state with exactly that name.
  • No changes: if OpenCode produces no diff, no PR is created and the issue is moved to In Review.
  • Unresolvable issue: if no registry entry matches the issue's team/project name, the worker logs an error and moves on; use loop run KEY --repo NAME to process it manually.
  • Stopping: loop stop sends SIGTERM; a running OpenCode session is allowed to finish before the worker exits.
  • Prompt: edit prompts/coding.md to change how OpenCode works on issues.

Troubleshooting

  • error.log says "could not resolve Linear user id" — LINEAR_API_KEY is invalid or unset.
  • error.log says "could not resolve a repository" — the issue's Linear team name matches no entry in repos.yaml. Add an entry (or use --repo).
  • status.sh shows the wrong state — stale pid file is detected and reported as "Stopped".
  • PR creation fails — check GITHUB_TOKEN scopes (repo, pull_request) and that gh is authenticated.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages