Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/onenot8/issueLoop/llms.txt

Use this file to discover all available pages before exploring further.

The batch workflow is the core IssueLoop pipeline: point it at a repository, let it run your test suite, hand the raw output to an LLM for triage, and then drain the resulting queue of independent tickets one at a time. Use it whenever you want a repeatable, fully-automated sweep — after a merge, on a schedule, or as a gate before deploying. Unlike the live monitor, the batch workflow runs synchronously and exits when the test suite finishes.

The test_manifest.json

IssueLoop reads data/test_manifest.json to know which commands to run for each repository and how to prioritize them. Create this file in the root of your IssueLoop working directory before your first run.
{
  "repos": [
    {
      "name": "myrepo",
      "local_path": "repos/myrepo",
      "test_types": [
        {
          "id": "unit",
          "command": "pytest tests/unit -v",
          "blocking": true,
          "priority": 1
        },
        {
          "id": "integration",
          "command": "pytest tests/integration -v",
          "blocking": false,
          "priority": 2
        }
      ]
    }
  ]
}
name
string
required
The short identifier for the repo. Used everywhere in the API — run_tests("myrepo"), get_top_error("myrepo"), etc.
local_path
string
required
Path to the repo on disk, relative to the IssueLoop working directory. The test runner changes into this directory before executing each command.
test_types[].id
string
required
A stable identifier for this test suite. Stored on every ticket so run_single_test can re-run exactly that suite when verifying a fix.
test_types[].command
string
required
The shell command to run. Executed with shell=True inside local_path. Both stdout and stderr are captured.
test_types[].blocking
boolean
required
Whether a failure here should be treated as blocking. Blocking failures receive the highest-priority blocking ticket tier and can halt the rest of the run when stop_on_first_blocking_failure=True.
test_types[].priority
integer
required
Execution order within the repo. Lower numbers run first. Tests with the same priority are run in the order they appear in the list.

Step-by-step batch run

1

Configure IssueLoop

Call issueloop.use() once at the top of your script to set the database backend and LLM provider. Both are optional — defaults are local SQLite and Ollama.
import issueloop

issueloop.use(
    database="local",
    database_path="data/issueloop.db",
    llm={"provider": "ollama", "model": "qwen2.5-coder:7b"},
)
2

Scan the repository

scan_repo walks the repository and writes a file inventory to data/logs/<repo>_files.json. This gives the LLM context about the project structure when it triages failures.
issueloop.scan_repo("repos/myrepo")
3

Run the test suite

run_tests executes every entry in test_manifest.json for the named repo, in priority order. Results are appended to data/logs/run_<repo>.jsonl.
results = issueloop.run_tests("myrepo")

for r in results:
    status = "OK" if r["exit_code"] == 0 else "FAIL"
    print(f"[{status}] {r['test_id']}")
4

Create tickets from failures

create_tickets reads the JSONL log, sends each failure block to the LLM, and writes the resulting tickets to the database. Duplicate summaries are de-duplicated automatically.
tickets = issueloop.create_tickets("myrepo")
print(f"Created {len(tickets)} tickets")
5

Drain the ticket queue

get_top_error claims the highest-priority pending ticket and marks it in_progress. Call resolve when the fix is confirmed. Loop until the queue is empty.
while True:
    ticket = issueloop.get_top_error("myrepo")
    if ticket is None:
        print("Queue empty — all done.")
        break

    print(f"[{ticket['priority']}] {ticket['error_summary']}")

    # ... apply your fix here ...

    issueloop.resolve(ticket["id"])

CLI equivalent

The same four steps are available as CLI commands, making the batch workflow trivially scriptable.
# 1. Configure (uses config files / env vars — no explicit step needed)

# 2. Scan the repo
issueloop scan repos/myrepo

# 3. Run tests
issueloop test myrepo

# 4. Create tickets from the run log
issueloop tickets myrepo

# 5. Claim and work the next ticket
issueloop next myrepo
Run issueloop next myrepo in a loop, or hand it to an agent that fixes and re-runs until the queue is drained.

stop_on_first_blocking_failure

Pass stop_on_first_blocking_failure=True to test_runner.run_tests to abort the run as soon as a test marked "blocking": true fails. This is useful when later test suites depend on earlier ones passing — there is no point running integration tests if unit tests are already broken.
from issueloop import test_runner

results = test_runner.run_tests("myrepo", stop_on_first_blocking_failure=True)
When this flag is set and a blocking test fails, the remaining test types in the manifest are skipped. Only the results collected so far are returned and written to the log. Tests are run in ascending priority order, so place your fastest, most fundamental suites at priority 1.
Running as a CI step — add the four commands to a post-merge hook or a nightly cron job to keep the ticket queue continuously up to date. Because each run appends to the JSONL log and IssueLoop deduplicates on summary text, re-running on a green suite is safe and produces no spurious tickets.
# GitHub Actions example
- name: IssueLoop triage
  run: |
    issueloop scan repos/myrepo
    issueloop test myrepo
    issueloop tickets myrepo

Build docs developers (and LLMs) love