Running a single task through an AI agent. This is the core feature of OpenLinear.
- Clone -- shallow clone (
git clone --depth 1) of the active repository into{REPOS_DIR}/{repoName}/{taskId} - Branch -- create and checkout
openlinear/{taskId} - Session -- create an OpenCode session scoped to the cloned directory via
client.session.create() - Prompt -- send the task's title + description + labels as a text prompt via
client.session.prompt() - Stream -- subscribe to OpenCode events and relay progress to the UI in real time
- Commit -- when the agent finishes, run
git add -A && git commit - Push --
git push -u origin {branch} - PR -- create a pull request via the GitHub API (or return a compare URL if no token)
Sidecar: POST /api/tasks/:id/execute
This endpoint is served by the local sidecar (apps/sidecar), not the cloud API. The sidecar fetches task metadata from the cloud API, then handles execution entirely on the host machine.
The endpoint checks:
- Task is not already running
- Active executions have not reached the
parallelLimitsetting - An active repository is selected
If any check fails, returns a 400 error.
The execution broadcasts progress updates via SSE (execution:progress):
| Stage | Description |
|---|---|
cloning |
Shallow-cloning the repository |
executing |
Agent is working (thinking, running tools, editing files) |
committing |
Staging and committing changes |
creating_pr |
Pushing branch and creating pull request |
done |
Execution complete |
error |
Execution failed |
cancelled |
Execution cancelled by user |
Every significant event is recorded as a log entry and broadcast via execution:log:
| Type | Icon | Examples |
|---|---|---|
info |
arrow | "Repository cloned", "Branch created", "Task prompt sent" |
agent |
robot | "Agent is thinking..." |
tool |
wrench | "Running: file_edit", "Starting: bash" |
success |
check | "Completed: file_edit", "Pull request created" |
error |
x | "Failed: bash", "Execution failed" |
Logs are persisted to the database (executionLogs JSON column) when execution completes.
While the agent is working, progress is estimated from three signals:
- Tools executed (5% each, up to 40%)
- Files changed (10% each, up to 30%)
- Elapsed time (3% per minute, up to 20%)
Maximum estimated progress is capped at 95%. It jumps to 100% only on completion.
Each task has a 30-minute timeout. If the agent hasn't finished by then, the task is automatically cancelled.
Sidecar: POST /api/tasks/:id/cancel
Cancelling a task:
- Calls
client.session.abort()to stop the OpenCode session - Marks the task as
cancelledin the database - Persists any collected logs
- Cleans up the execution state
On completion with changes:
- If a GitHub access token is available, creates a real PR via
POST https://api.github.com/repos/:owner/:repo/pulls - If no token or the API call fails, returns a GitHub compare URL for manual PR creation
Refresh PR: POST /api/tasks/:id/refresh-pr (sidecar) -- checks if a PR has been created for a compare-URL branch and updates the task's prUrl if found.
The UI shows a slide-out drawer with:
- Current execution stage
- Live scrolling log entries with colored icons
- Elapsed time
- PR link on completion
After execution completes, the system generates a brief outcome summary stored on the task. The outcome is a short description of what happened:
- If there were code changes:
"{N} file(s) changed, {M} tools executed" - If there were no changes:
"Completed with no changes"
The outcome is displayed in the task detail view, giving a quick summary of what the AI agent accomplished without opening the full log.
Task execution runs on the host machine via the local sidecar (apps/sidecar). The sidecar connects to the cloud API for task metadata, then runs OpenCode directly on your machine. Each task is isolated in its own git worktree with an independent branch and working directory. Provider credentials are configured per-user through the OpenCode instance managed by the sidecar. See OpenCode Integration for details.