You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
orch supports querying issues and runs using SQL with an in-memory SQLite database. This enables powerful analysis and custom reporting.
Quick Start
# List open issues
orch query "SELECT * FROM issues WHERE status = 'open'"# Alias: orch q
orch q "SELECT id, title FROM issues"# Output formats
orch q "SELECT * FROM runs" --format json
orch q "SELECT * FROM runs" --format tsv
Database Schema
Tables
issues
Column
Type
Description
id
TEXT
Issue ID (primary key)
title
TEXT
Issue title
status
TEXT
Issue status (open, closed, etc.)
path
TEXT
File path
created
TEXT
Created timestamp
updated
TEXT
Updated timestamp
runs
Column
Type
Description
issue_id
TEXT
Parent issue ID
run_id
TEXT
Run ID (timestamp)
hex_id
TEXT
Short hex ID (6 chars)
agent
TEXT
Agent type
status
TEXT
Run status
worktree
TEXT
Worktree path
branch
TEXT
Git branch
session_name
TEXT
Multiplexer session name
pr_url
TEXT
Pull request URL
created
TEXT
Created timestamp
updated
TEXT
Updated timestamp
issue_tags
Column
Type
Description
issue_id
TEXT
Issue ID
tag
TEXT
Tag value
events (with --with-events)
Column
Type
Description
run_id
TEXT
Parent run ID
timestamp
TEXT
Event timestamp
type
TEXT
Event type
name
TEXT
Event name
data
TEXT
Additional data (JSON)
Views
issues_v
Extended issues view with computed columns:
Column
Description
(all from issues)
Base issue columns
run_count
Number of runs for this issue
tags
Comma-separated tags
runs_v
Extended runs view with issue info:
Column
Description
(all from runs)
Base run columns
issue_title
Parent issue title
issue_status
Parent issue status
event_count
Number of events
Common Queries
Issue Queries
-- All open issuesSELECT id, title, status
FROM issues
WHERE status ='open';
-- Issues with specific tagSELECT i.*FROM issues i
JOIN issue_tags t ONi.id=t.issue_idWHEREt.tag='bug';
-- Issues without runsSELECT i.*FROM issues i
LEFT JOIN runs r ONi.id=r.issue_idWHEREr.run_id IS NULL;
-- Issues with active runsSELECT DISTINCT i.*FROM issues i
JOIN runs r ONi.id=r.issue_idWHEREr.statusIN ('running', 'waiting', 'booting');
-- Issue summary with run countsSELECT
id,
title,
status,
run_count
FROM issues_v
ORDER BY run_count DESC;
Run Queries
-- Currently runningSELECT issue_id, run_id, agent, status
FROM runs
WHERE status ='running';
-- Waiting runs needing attentionSELECT
issue_id,
run_id,
hex_id,
updated
FROM runs
WHERE status IN ('waiting', 'rate_limited')
ORDER BY updated DESC;
-- Runs with PRsSELECT
issue_id,
run_id,
pr_url,
status
FROM runs
WHERE pr_url IS NOT NULL;
-- Run history for an issueSELECT
run_id,
agent,
status,
created,
updated
FROM runs
WHERE issue_id ='my-issue'ORDER BY created DESC;
-- Status distributionSELECT
status,
COUNT(*) as count
FROM runs
GROUP BY status
ORDER BY count DESC;
Analytics Queries
-- Agent usageSELECT
agent,
COUNT(*) as runs,
SUM(CASE WHEN status ='done' THEN 1 ELSE 0 END) as successful
FROM runs
GROUP BY agent;
-- Daily run countsSELECTDATE(created) as day,
COUNT(*) as runs,
SUM(CASE WHEN status ='done' THEN 1 ELSE 0 END) as completed
FROM runs
GROUP BYDATE(created)
ORDER BY day DESCLIMIT14;
-- Average runs per issueSELECTAVG(run_count) as avg_runs
FROM (
SELECT issue_id, COUNT(*) as run_count
FROM runs
GROUP BY issue_id
);
-- Issues with most runsSELECT
issue_id,
COUNT(*) as run_count,
SUM(CASE WHEN status ='done' THEN 1 ELSE 0 END) as done_count
FROM runs
GROUP BY issue_id
ORDER BY run_count DESCLIMIT10;
Event Queries
Events require the --with-events flag (slower query):
orch q "SELECT * FROM events" --with-events
-- Events for a specific runSELECT*FROM events
WHERE run_id ='20260120-163000'ORDER BYtimestamp;
-- Status transitionsSELECT
run_id,
timestamp,
name as status
FROM events
WHERE type ='status'ORDER BY run_id, timestamp;
-- Time in each phaseSELECT
run_id,
name as phase,
timestampFROM events
WHERE type ='phase'ORDER BY run_id, timestamp;
-- PRs createdSELECTe.run_id,
r.issue_id,
e.timestamp,
e.dataFROM events e
JOIN runs r ONe.run_id=r.run_idWHEREe.type='artifact'ANDe.name='pr';
Output Formats
Table (default)
orch q "SELECT id, status FROM issues"
ID STATUS
my-issue open
other-task closed
JSON
orch q "SELECT id, status FROM issues" --format json
orch q "SELECT id, status FROM issues" --format tsv
my-issue open
other-task closed
Integration Examples
Shell scripts
# Get running run IDs
RUNNING=$(orch q "SELECT hex_id FROM runs WHERE status='running'" --format tsv)# Iterate over waiting runs
orch q "SELECT hex_id FROM runs WHERE status='waiting'" --format tsv |whileread id;doecho"Run $id is waiting"done
jq integration
# Get PR URLs
orch q "SELECT pr_url FROM runs WHERE pr_url IS NOT NULL" --format json | \
jq -r '.[].pr_url'# Count by status
orch q "SELECT status, COUNT(*) as n FROM runs GROUP BY status" --format json | \
jq -r '.[] | "\(.status): \(.n)"'
Export to CSV
# Using tsv + sed
orch q "SELECT * FROM issues" --format tsv | sed 's/\t/,/g'> issues.csv
Tips
Performance
Use --with-events only when needed (loads all events into memory)
Limit results for large datasets: LIMIT 100
Use specific columns instead of SELECT *
Debugging queries
# See schema
orch schema
# Test query structure
orch q "SELECT * FROM issues LIMIT 1" --format json
Common patterns
-- COALESCE for null handlingSELECT COALESCE(pr_url, 'no PR') FROM runs;
-- Date filteringSELECT*FROM runs
WHERE created > datetime('now', '-7 days');
-- Pattern matchingSELECT*FROM issues
WHERE title LIKE'%bug%';