2026-03-15 18:08:52 +00:00
< div align = "center" >
2026-03-17 23:11:40 +01:00
< img src = "site/al76.jpg" alt = "A tiny robot commanding a mountain-eating machine" width = "600" >
2026-03-15 18:08:52 +00:00
< br > < br >
2026-03-12 12:44:15 +00:00
2026-03-15 18:08:52 +00:00
# Disinto
2026-03-15 17:57:12 +01:00
2026-03-15 18:08:52 +00:00
**Autonomous code factory** — [disinto.ai ](https://disinto.ai )
*A mining robot, lost and confused, builds a Disinto from scrap —< br >
a device so powerful it vaporizes three-quarters of a mountain on a single battery.*< br >
— Isaac Asimov, "Robot AL-76 Goes Astray" (1942)
< / div >
< br >
2026-03-14 13:38:38 +01:00
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
Point it at a git repo with a Woodpecker CI pipeline and it will pick up issues, implement them, review PRs, and keep the system healthy — all on its own.
2026-03-12 12:44:15 +00:00
## Architecture
```
2026-03-15 18:06:25 +01:00
cron (*/10) ──→ supervisor-poll.sh ← supervisor (bash checks, zero tokens)
2026-03-12 12:44:15 +00:00
├── all clear? → exit 0
2026-03-12 18:10:25 +00:00
└── problem? → claude -p (diagnose, fix, or escalate)
2026-03-12 12:44:15 +00:00
2026-03-14 13:38:38 +01:00
cron (*/10) ──→ dev-poll.sh ← pulls ready issues, spawns dev-agent
└── dev-agent.sh ← claude -p: implement → PR → CI → review → merge
cron (*/10) ──→ review-poll.sh ← finds unreviewed PRs, spawns review
└── review-pr.sh ← claude -p: review → approve/request changes
2026-03-12 12:44:15 +00:00
2026-03-14 13:38:38 +01:00
cron (daily) ──→ gardener-poll.sh ← backlog grooming (duplicates, stale, tech-debt)
└── claude -p: triage → promote/close/escalate
2026-03-14 16:25:33 +01:00
2026-03-19 00:35:45 +00:00
cron (weekly) ──→ planner-poll.sh ← gap-analyse VISION.md, create backlog issues
└── claude -p: update AGENTS.md → create issues
cron (*/30) ──→ vault-poll.sh ← safety gate for dangerous/irreversible actions
└── claude -p: classify → auto-approve/reject or escalate
2026-03-14 16:25:33 +01:00
systemd ──→ matrix_listener.sh ← long-poll daemon for human replies
2026-03-19 00:35:45 +00:00
└── dispatches thread replies → supervisor/gardener/dev/review/vault
2026-03-14 16:25:33 +01:00
all agents ──→ matrix_send() ← status updates, escalations, merge notifications
2026-03-12 12:44:15 +00:00
```
2026-03-14 13:38:38 +01:00
## Prerequisites
**Required:**
- [Claude CLI ](https://docs.anthropic.com/en/docs/claude-cli ) — `claude` in PATH, authenticated
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
- [Docker ](https://docker.com/ ) — for provisioning a local Forgejo instance (or a running Forgejo/Gitea instance)
- [Woodpecker CI ](https://woodpecker-ci.org/ ) — local instance connected to your forge; disinto monitors pipelines, retries failures, and queries the Woodpecker Postgres DB directly
2026-03-14 13:38:38 +01:00
- PostgreSQL client (`psql` ) — for Woodpecker DB queries (pipeline status, build counts)
- `jq` , `curl` , `git`
**Optional:**
2026-03-14 16:25:33 +01:00
- [Matrix ](https://matrix.org/ ) homeserver ([Dendrite ](https://github.com/matrix-org/dendrite ) or Synapse) — real-time notifications, escalation threads with human-in-the-loop replies
2026-03-14 13:38:38 +01:00
- [Foundry ](https://getfoundry.sh/ ) (`forge` , `cast` , `anvil` ) — only needed if your target project uses Solidity
- [Node.js ](https://nodejs.org/ ) — only needed if your target project uses Node
2026-03-12 12:44:15 +00:00
## Setup
```bash
# 1. Clone
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
git clone https://github.com/johba/disinto.git
2026-03-15 17:57:12 +01:00
cd disinto
2026-03-12 12:44:15 +00:00
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
# 2. Bootstrap a project (provisions local Forgejo, creates tokens, clones repo)
disinto init https://github.com/yourorg/yourproject
2026-03-14 13:38:38 +01:00
```
2026-03-12 12:44:15 +00:00
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
Or configure manually — edit `.env` with your values:
2026-03-14 13:38:38 +01:00
```bash
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
# Forge (auto-populated by disinto init)
FORGE_URL=http://localhost:3000 # local Forgejo instance
FORGE_TOKEN=... # dev-bot token
FORGE_REVIEW_TOKEN=... # review-bot token
2026-03-14 13:38:38 +01:00
# Woodpecker CI
WOODPECKER_SERVER=http://localhost:8000
WOODPECKER_TOKEN=...
WOODPECKER_DB_PASSWORD=...
WOODPECKER_DB_USER=woodpecker
WOODPECKER_DB_HOST=127.0.0.1
WOODPECKER_DB_NAME=woodpecker
# Tuning
CLAUDE_TIMEOUT=7200 # max seconds per Claude invocation (default: 2h)
```
```bash
# 3. Install cron (staggered to avoid overlap)
2026-03-12 12:44:15 +00:00
crontab -e
# Add:
2026-03-15 18:06:25 +01:00
# 0,10,20,30,40,50 * * * * /path/to/disinto/supervisor/supervisor-poll.sh
2026-03-15 17:57:12 +01:00
# 3,13,23,33,43,53 * * * * /path/to/disinto/review/review-poll.sh
# 6,16,26,36,46,56 * * * * /path/to/disinto/dev/dev-poll.sh
# 15 8 * * * /path/to/disinto/gardener/gardener-poll.sh
2026-03-19 00:35:45 +00:00
# 0,30 * * * * /path/to/disinto/vault/vault-poll.sh
# 0 9 * * 1 /path/to/disinto/planner/planner-poll.sh
2026-03-12 12:44:15 +00:00
# 4. Verify
2026-03-15 18:06:25 +01:00
bash supervisor/supervisor-poll.sh # should log "all clear"
2026-03-12 12:44:15 +00:00
```
## Directory Structure
```
2026-03-15 17:57:12 +01:00
disinto/
2026-03-14 13:38:38 +01:00
├── .env.example # Template — copy to .env, add secrets + project config
├── .gitignore # Excludes .env, logs, state files
2026-03-12 12:44:15 +00:00
├── lib/
2026-03-14 16:25:33 +01:00
│ ├── env.sh # Shared: load .env, PATH, API helpers, matrix_send()
│ ├── ci-debug.sh # Woodpecker CI log/failure helper
│ ├── matrix_listener.sh # Matrix long-poll daemon (dispatches replies)
│ └── matrix_listener.service # systemd unit for the listener
2026-03-12 12:44:15 +00:00
├── dev/
2026-03-14 13:38:38 +01:00
│ ├── dev-poll.sh # Cron entry: find ready issues
│ └── dev-agent.sh # Implementation agent (claude -p)
2026-03-12 12:44:15 +00:00
├── review/
2026-03-14 13:38:38 +01:00
│ ├── review-poll.sh # Cron entry: find unreviewed PRs
│ └── review-pr.sh # Review agent (claude -p)
├── gardener/
│ ├── gardener-poll.sh # Cron entry: backlog grooming
│ └── best-practices.md # Gardener knowledge base
2026-03-18 08:50:08 +00:00
├── planner/
│ ├── planner-poll.sh # Cron entry: weekly vision gap analysis
2026-03-20 09:00:56 +00:00
│ └── (formula-driven) # run-planner.toml executed by action-agent
2026-03-18 08:50:08 +00:00
├── vault/
│ ├── vault-poll.sh # Cron entry: process pending dangerous actions
│ ├── vault-agent.sh # Classifies and routes actions (claude -p)
│ ├── vault-fire.sh # Executes an approved action
│ ├── vault-reject.sh # Marks an action as rejected
│ └── PROMPT.md # System prompt for vault agent
2026-03-15 18:06:25 +01:00
└── supervisor/
├── supervisor-poll.sh # Supervisor: health checks + claude -p
2026-03-14 13:38:38 +01:00
├── PROMPT.md # Supervisor's system prompt
├── update-prompt.sh # Self-learning: append to best-practices
└── best-practices/ # Progressive disclosure knowledge base
2026-03-12 18:10:25 +00:00
├── memory.md
├── disk.md
├── ci.md
fix: Replace Codeberg dependency with local Forgejo instance (#611)
- Add setup_forge() to bin/disinto: provisions Forgejo via Docker,
creates admin + bot users (dev-bot, review-bot), generates API
tokens, creates repo, and pushes code — all automated
- Rename env vars: CODEBERG_TOKEN→FORGE_TOKEN, REVIEW_BOT_TOKEN→
FORGE_REVIEW_TOKEN, CODEBERG_REPO→FORGE_REPO, CODEBERG_API→
FORGE_API, CODEBERG_WEB→FORGE_WEB, CODEBERG_BOT_USERNAMES→
FORGE_BOT_USERNAMES (with backwards-compat fallbacks)
- Rename API helpers: codeberg_api()→forge_api(), codeberg_api_all()
→forge_api_all() (with compat aliases)
- Add forge_url field to project TOML; load-project.sh derives
FORGE_API/FORGE_WEB from forge_url + repo
- Update parse_repo_slug() to accept any host URL, not just codeberg
- Forgejo data stored under ~/.disinto/forgejo/ (not in factory repo)
- Update all 58 files: agent scripts, formulas, docs, site HTML
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:57:12 +00:00
├── forge.md
2026-03-12 18:10:25 +00:00
├── dev-agent.md
├── review-agent.md
└── git.md
2026-03-12 12:44:15 +00:00
```
2026-03-14 13:38:38 +01:00
## Agents
| Agent | Trigger | Job |
|-------|---------|-----|
2026-03-15 18:06:25 +01:00
| **Supervisor** | Every 10 min | Health checks (RAM, disk, CI, git). Calls Claude only when something is broken. Self-improving via `best-practices/` . |
2026-03-14 13:38:38 +01:00
| **Dev** | Every 10 min | Picks up `backlog` -labeled issues, creates a branch, implements, opens a PR, monitors CI, responds to review, merges. |
| **Review** | Every 10 min | Finds PRs without review, runs Claude-powered code review, approves or requests changes. |
| **Gardener** | Daily | Grooms the issue backlog: detects duplicates, promotes `tech-debt` to `backlog` , closes stale issues, escalates ambiguous items. |
2026-03-18 08:50:08 +00:00
| **Planner** | Weekly | Updates AGENTS.md documentation to reflect recent code changes, then gap-analyses VISION.md vs current state and creates up to 5 backlog issues for the highest-leverage gaps. |
| **Vault** | Every 30 min | Safety gate for dangerous or irreversible actions. Classifies pending actions via Claude: auto-approve, auto-reject, or escalate to a human via Matrix. |
2026-03-14 13:38:38 +01:00
2026-03-12 18:10:25 +00:00
## Design Principles
2026-03-14 13:38:38 +01:00
- **Bash for checks, AI for judgment** — polling and health checks are shell scripts; Claude is only invoked when something needs diagnosing or deciding
2026-03-12 18:10:25 +00:00
- **Pull over push** — dev-agent derives readiness from merged dependencies, not labels or manual assignment
- **Progressive disclosure** — the supervisor reads only the best-practices file relevant to the current problem, not all of them
2026-03-14 13:38:38 +01:00
- **Self-improving** — when Claude fixes something new, the lesson is appended to best-practices for next time
- **Project-agnostic** — all project-specific values (repo, paths, CI IDs) come from `.env` , not hardcoded scripts
2026-03-12 12:44:15 +00:00
2026-03-18 21:20:09 +00:00
### Runtime constraints
Disinto is intentionally opinionated about its own runtime. These are hard constraints, not preferences:
- **Debian + GNU userland** — all scripts target Debian with standard GNU tools (`bash` , `awk` , `sed` , `date` , `timeout` ). No portability shims for macOS or BSD.
2026-03-18 21:29:21 +00:00
- **Shell + a small set of runtimes** — every agent is a bash script. The only interpreted runtimes used by disinto core are `python3` (TOML parsing in `lib/load-project.sh` , JSON state tracking in `dev/dev-poll.sh` , recipe matching in `gardener/gardener-poll.sh` ) and `claude` (the AI CLI). No Ruby, Perl, or other runtimes. Do not add new runtime dependencies without a strong justification.
- **Few, powerful dependencies** — required non-standard tools: `jq` , `curl` , `git` , `tmux` , `psql` , and `python3` (≥ 3.11 for `tomllib` ; or install `tomli` for older Pythons). Adding anything beyond this list requires justification.
2026-03-18 21:20:09 +00:00
- **Node.js and Foundry are target-project dependencies** — if your target repo uses Node or Solidity, install those on the host. They are not part of disinto's core and must not be assumed present in disinto scripts.
The goal: any Debian machine with the prerequisites listed above can run disinto. Keep it that way.