Skip to main content

IssueLoop

Finds failing tests (batch or live). Splits failures into independent tickets via an LLM, with automatic priority fallback across providers. Stores them. Hands them out one at a time. Optionally proposes and applies fixes under an explicit, auditable permission allowlist.

license python status


Why this exists

Bugs sit unfixed because someone has to notice them first. IssueLoop reads the test suite directly — a failing test is the bug report. It can also watch a live-running process or log file, for bugs that only show up outside a test run. No human has to spot it, and no human has to manually triage which failures are actually distinct problems.

Install

Not yet on PyPI — install from git:

python3 -m venv .venv
source .venv/bin/activate
pip install "git+https://github.com/onenot8/issueLoop@phase-2"

Or for local development:

git clone https://github.com/onenot8/issueLoop
cd issueLoop
pip install -e ".[dev]"

Local SQLite backend, zero setup. No database account, no API key required to try it.

Quickstart

import issueloop

issueloop.use(
    database="local",                     # or "supabase" for a hosted backup
    llm={"providers": [                   # priority list — falls back automatically
        {"provider": "anthropic", "model": "claude-sonnet-4-6", "api_key": "sk-..."},
        {"provider": "ollama", "model": "qwen2.5-coder:7b"},   # free, local, default if omitted
    ]},
    notify={"webhook": "https://your-endpoint"},   # fires if IssueLoop itself breaks
)

issueloop.scan_repo("repos/myrepo")
issueloop.run_tests("myrepo")
issueloop.create_tickets("myrepo")

ticket = issueloop.get_top_error("myrepo")   # claims one, marks in_progress
issueloop.resolve(ticket["id"])              # your side fixed it

Live monitoring

Watch a process IssueLoop spawns itself, or tail a log file an already-running process writes to:

from issueloop import watch_process, watch_log_file, stop_watch

handle = watch_process("myrepo", "python3 main.py", cwd="/path/to/repo", debounce_seconds=3.0)
# ...
stop_watch(handle)

Or from the CLI, in the foreground:

issueloop watch myrepo --command "python3 main.py" --cwd /path/to/repo --debounce 3.0
issueloop watch myrepo --log-file /path/to/app.log --debounce 3.0

Errors are debounced (default 3s of quiet) so a single multi-line traceback becomes one ticket, not dozens. Detected errors land in the same log format the batch test runner uses — issueloop tickets picks them up with no extra steps.

Fix-apply layer

Off by default — every command needs an explicit allowlist entry:

# config/permission.yaml
per_repo:
  myrepo:
    allowed_patterns:
      - 'sed -i .* somefile\.py'
issueloop.propose_fix(ticket_id, "sed -i 's/old/new/' somefile.py")
result = issueloop.apply_fix(ticket_id)
# {"status": "resolved" | "retry" | "escalated" | "denied", ...}

apply_fix re-runs the ticket's associated test after applying the fix and only resolves it if the test actually passes. Failures retry up to a configurable limit, then escalate to needs_human. Every permission decision is audited — issueloop.get_permission_audit_log().

Use it from the CLI

issueloop check-env
issueloop scan repos/myrepo
issueloop test myrepo
issueloop tickets myrepo
issueloop next myrepo
issueloop watch myrepo --command "..." | --log-file ...
issueloop cleanup --days 30

Use it from Node, Go, or anything else

issueloop serve --port 8787
const r = await fetch("http://localhost:8787/errors/top?repo=myrepo");
const ticket = await r.json();

serve is localhost-only, no auth — put it behind your own gateway if you ever expose it further.

Full API

Bug query — get_all_bugs, get_unresolved_bugs, get_resolved_bugs, get_failed_bugs, get_bugs_needing_human, get_bugs_by_status, get_bugs_by_priority, get_bug, get_bug_count, get_bug_count_by_status, search_bugs, get_oldest_bug, get_newest_bug

Lifecycle — get_top_error, get_all_errors, resolve, fail, escalate, reassign, retry_bug, get_bug_attempts, bulk_resolve

Fix-apply — propose_fix, apply_fix, check_permission, get_permission_audit_log

Scan / test — scan_repo, get_file_inventory, run_tests, run_single_test, create_tickets

Live monitoring — watch_process, watch_log_file, stop_watch, list_active_watchers

LLM / tokens — get_token_consumption, get_token_consumption_by_provider, get_llm_call_history, get_llm_provider_status

Database — cleanup, purge_repo, get_database_stats, export_bugs, reap_stale_bugs, rotate_logs

Notifications — get_crash_log, get_notification_config

Config / utility — use, get_config, list_repos, health_check

Config — every option

Field Values Default
database "local", "supabase" "local"
database_path any path data/issueloop.db
retention_days int 30
llm.providers list of provider dicts, priority order single ollama default
llm.provider "ollama", "anthropic", "openai" "ollama"
llm.apiKey string none (required for anthropic/openai)
llm.tokenSize int 1024
notify.webhook URL none

Both apiKey/api_key and tokenSize/token_size work — camelCase or snake_case, your call. A single llm={...} dict still works exactly as before; wrap multiple in llm={"providers": [...]} for automatic fallback.

Config files (config/permission.yaml, config/provider_config.yaml) resolve in this order: an explicit env var (ISSUELOOP_PERMISSION_PATH / ISSUELOOP_PROVIDER_CONFIG_PATH) → ./config/ relative to your current directory → config/ in the IssueLoop checkout → bundled package defaults. This means a real pip install (not just -e .) still works correctly even without a project-local config/ directory.

Why trust this

  • Every module has a test, and the tests run against real behavior — a real SQLite file, a real HTTP server on a real socket — not just mocks pretending things work.
  • Real bugs were caught and fixed by actually running this code, not by reading it — including a prompt that only ever sent stderr to the LLM triage step while pytest (and most test runners) report failures on stdout, and a config-bundling gap that made the permission system silently deny everything under a real (non-editable) install. Both have regression coverage now.
  • Local-first by default. Nothing phones home, nothing requires an account to try.
  • Read the code — it's small enough to actually read. That's on purpose. File-by-file build order: BUILD_ORDER.md.

Testing

pytest tests/ -v

Full walkthrough, including live monitoring and the fix-apply layer: TESTING.md.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

issueloop-0.2.0.tar.gz (24.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

issueloop-0.2.0-py3-none-any.whl (25.0 kB view details)

Uploaded Python 3

File details

Details for the file issueloop-0.2.0.tar.gz.

File metadata

  • Download URL: issueloop-0.2.0.tar.gz
  • Upload date:
  • Size: 24.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for issueloop-0.2.0.tar.gz
Algorithm Hash digest
SHA256 858ef99ce2d3dc696c6b863937c703405bca7c996e49d968b8a6f91d48c269d9
MD5 546af7d344bb698ff8dd9e2ea6ded9d9
BLAKE2b-256 bdaf68c848234db10778865d73bbaf2f249e44d831bc29d650ba870d05e1410d

See more details on using hashes here.

File details

Details for the file issueloop-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: issueloop-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 25.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for issueloop-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5060806f2a45ecd3f57d5669db1ed4e5410164e0aa2af48c216c0c0a06319abe
MD5 05e098da7b1cb2c3a5e008ff4d23274f
BLAKE2b-256 1116c5a4674c96e0813299c3c7e7efe64c73d1f4947a358baba8f7b546984a87

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.0

2 files

0.2.1

2 files

This release

0.2.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page