Metadata-Version: 2.5
Name: nohalt
Version: 0.1.0
Summary: Autonomous coding agents that keep going until the forge says done.
Project-URL: Homepage, https://github.com/Seityl/nohalt
Project-URL: Issues, https://github.com/Seityl/nohalt/issues
Project-URL: Changelog, https://github.com/Seityl/nohalt/blob/main/CHANGELOG.md
Author: Jeriel Francis trading as Seityl
License-Expression: MIT
License-File: LICENSE
Keywords: agents,ai,autonomous,ci,claude-code,coding-agents,github,opencode,orchestration
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-cov>=5; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Requires-Dist: twine>=5; extra == 'dev'
Description-Content-Type: text/markdown

# nohalt

**Autonomous coding agents that keep going until the forge says done.**

[![CI](https://github.com/Seityl/nohalt/actions/workflows/ci.yml/badge.svg)](https://github.com/Seityl/nohalt/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)

nohalt supervises a fleet of AI coding agents ([opencode](https://opencode.ai), [Claude Code](https://www.claude.com/product/claude-code), or any CLI) working through a queue of GitHub or GitLab issues: one agent per issue, each in its own git worktree, until every issue is **closed** -- not until the agents *say* they are done.

An endpoint that raised `NameError` on every call once shipped with green CI and a confident agent summary, and stayed broken for two months. Agents report success they have not earned. So nohalt believes exactly one thing: the issue's state on the forge, and an issue closes only when a reviewed, green pull request merges.

Everything else in nohalt exists because something went wrong without it, while agents ran unattended through the night on three production projects. Those lessons -- around a hundred of them -- are written up in [**docs/LESSONS.md**](docs/LESSONS.md), and the ones nohalt enforces are pinned by tests.

## What it does

```
queue.txt ──► scheduler ──► agent in its own worktree ──► PR ──► CI ──► integrator ──► merged ──► issue CLOSED
 (deps)      slots, memory,     (opencode / claude-code)          │       (direct or         │
             a model that                │                         │        release train)    └─► pipeline watched;
             answers                     ▼                         ▼                              red → fix-forward
                               verify lock: one test env    red / conflicting → handed back      issue, merging stops
                               per slot, at this commit     to the agent with the failure
```

- **Dependency-ordered queue.** `14: 13` means #14 waits until #13 is closed. Order is preference; dependencies are law. Edit it while nohalt runs.
- **GitHub or GitLab.** gitlab.com or self-hosted: merge requests, pipeline jobs as checks, `glab` for agents. Subgroups are fine.
- **Parallel agents, isolated.** One worktree and branch per issue; guard shims on each agent's `PATH` refuse merging, closing issues, pushing to the base branch, `git stash` (worktrees share one stash stack), and machine-wide `pkill`.
- **A verification lock.** Agents edit in parallel but verify one at a time per test slot (`nohalt verify <worktree> -- '<cmd>'`), with the environment reset to the commit under test.
- **Failures classified, not counted blindly.** A model-endpoint outage is not an attempt on the issue. A time limit continues in the same worktree. A hung agent (no output, no command running) is restarted. A red PR goes back to an agent with the failing checks. Only real failures spend attempts; then the issue is labelled for a human and the rest of the queue carries on.
- **One merger.** Agents never merge. `direct` mode merges green PRs one at a time and stops everything if the pipeline on the base branch goes red; `train` mode batches green PRs into a versioned release branch, resolving bookkeeping conflicts (package.json, migration lists, schema JSON) mechanically and handing real code conflicts back.
- **Survives itself.** Agents run in their own sessions. Kill or restart the supervisor and it adopts the running agents from their records. `nohalt keepalive` in cron brings it back.
- **Model routing and a spend guard.** Route by label or title, pin per issue, gate premium models behind approval, fall over to a model that answers, and cap paid-API spend per issue and in total.
- **Stacks.** A `generic` stack (your own `up`/`reset`/`env` hooks for the test environment) and a `frappe` stack (a pool of agent test sites on a shared bench, worktree-first `PYTHONPATH`, migrate before test, DocType/fixture/patch merge drivers).

## Quick start

```bash
pip install nohalt          # Python 3.11+, Linux; needs git, plus gh (GitHub) or glab (GitLab)
cd your-repo
nohalt init                 # writes nohalt.toml and queue.txt (--stack frappe for Frappe apps)
$EDITOR nohalt.toml queue.txt
nohalt doctor --probe       # checks config, forge auth, branch protection, agent binaries, models
nohalt run --dry-run        # what would launch now, what waits on what
nohalt run                  # supervise; Ctrl-C leaves agents running, `nohalt run` adopts them again
nohalt status --watch       # one screen: agents, idle time, attempts, last line of each log
```

Keep it running without a terminal:

```cron
*/3 * * * * cd /path/to/your-repo && nohalt keepalive
```

Control while it runs: `nohalt stop` (between issues), `nohalt stop --now`, `nohalt pause`, `nohalt route <issue> <model>`, `nohalt unblock <issue>`, `nohalt queue --add 42 --after 41`, `nohalt prompt <issue>` (see exactly what an agent will be told).

## Before you run it

nohalt gives AI agents write access to your repository and, if you enable an integrator, lets nohalt merge and deploy. **Read [docs/SAFETY.md](docs/SAFETY.md).** In short: protect the base branch on the forge (the shims are speed bumps, protection is the wall), use a token scoped to the one repository, run agents as a user that cannot reach production, start with `integrate.mode = "none"`, and watch the first few issues end to end.

## Documentation

- [docs/CONFIGURATION.md](docs/CONFIGURATION.md) -- every key in `nohalt.toml`
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) -- the supervisor loop, issue lifecycle, state on disk
- [docs/STACKS.md](docs/STACKS.md) -- generic and Frappe test environments, writing your own
- [docs/SAFETY.md](docs/SAFETY.md) -- the threat model and the guardrails
- [docs/LESSONS.md](docs/LESSONS.md) -- what running agent fleets unattended taught us

## Status

Alpha. The mechanisms come from scripts that ran production agent fleets for weeks; this package is their consolidation into one tested, configurable tool, and it is younger than they are. Before the first release it was run end to end on both forges -- real agents (Claude Code on GitHub, opencode on a self-hosted GitLab), real CI, both `none` and `direct` integration, a supervisor `kill -9` mid-run -- and the bugs those runs found are fixed. Expect rough edges. Issues and pull requests are welcome: see [CONTRIBUTING.md](CONTRIBUTING.md).

## License

[MIT](LICENSE) © Jeriel Francis trading as Seityl, and the nohalt contributors.
