A local AI DevOps agent powered by Pi coding agent + Unsloth Studio. Anubis runs a full development cycle — plan, code, review, test, audit, PR draft — entirely on local hardware using your Unsloth-served model.
Judge of code. Guardian of the pipeline. Weigher of diffs.
anubis/
├── .env.example # copy to .env and fill in
├── pyproject.toml # project metadata + dev deps (pytest)
├── prompt-collection/
│ ├── prompt_library.md # full reusable prompt library
│ ├── pi_prompts.md # Pi slash-command templates (/ci, /review, etc.)
│ └── core-coder-claude-config.md # CoreCoder system prompt + helper prompts
└── agent_src/
├── modules/
│ ├── unsloth_client.py # OpenAI-compat client for Unsloth Studio
│ ├── prompt_loader.py # load/fill prompt templates from prompt-collection/
│ └── devops_loop.py # all 6 devops cycle stages
├── scripts/
│ ├── run_cycle.py # CLI entry point — manual and --auto mode
│ └── setup_pi.py # one-time Pi config generator
└── utilities/
├── config.py # env/dotenv config loader
├── git_helpers.py # diff, log, fetch, pull, changed_files wrappers
├── file_writer.py # parses LLM code blocks and writes files to disk
├── pr_creator.py # opens GitHub PRs via REST API
└── test_runner.py # runs pytest and returns pass/fail + output
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux / Mac
source .venv/bin/activate
pip install -e ".[dev]"cp .env.example .env
# edit .env and fill in:
# UNSLOTH_API_KEY=sk-unsloth-XXXX... (from Unsloth Studio on startup)
# GITHUB_TOKEN=ghp_XXXX... (PAT with repo scope — needed for --auto)npm install -g @earendil-works/pi-coding-agent
pi --versionunsloth studio run --model ~/qwen-models/Qwen3.6-27B-UD-Q4_K_XL.gguf -p 8888Copy the API key it prints and put it in your .env.
python agent_src/scripts/setup_pi.pyAuto-detects the loaded model and writes ~/.pi/agent/models.json,
~/.pi/agent/settings.json, and copies the Pi prompt templates.
Verify:
pi --list-models | grep unsloth
pi --print "reply only: pong"Manual (inspect output before anything is committed):
python agent_src/scripts/run_cycle.py \
--task "add rate limiting to the login endpoint" \
--repo /path/to/your/repoAuto (branch → code → write → commit → pytest → review → audit → push → open PR):
python agent_src/scripts/run_cycle.py \
--task "add rate limiting to the login endpoint" \
--repo /path/to/your/repo \
--autoOpen as a draft PR:
--auto --draftRun one stage at a time:
python agent_src/scripts/run_cycle.py --task "..." --stage plan
python agent_src/scripts/run_cycle.py --task "..." --stage review| Stage | What it does |
|---|---|
| plan | Produces a numbered implementation plan, identifies files to change |
| code | Implements the plan against the current file contents |
| review | Reviews the real git diff main...HEAD for bugs, security issues, and quality |
| test | Runs pytest against the repo — result reported in PR body either way |
| audit | Full security + quality audit of the real diff — hardcoded secrets, silent failures, etc. |
| pr_draft | Drafts the PR title, summary, breaking changes, and testing checklist |
After setup, cd into any repo and run pi. Then use the slash commands:
| Command | What it does |
|---|---|
/ci |
Run CI checks and report failures |
/pr-draft |
Draft a PR description for the current branch |
/review |
Review the branch against main |
/issue |
Draft a GitHub issue |
/sync |
Check and pull remote changes |
/audit |
Security and quality audit of all changes |
/deps-check |
Check dependencies against a compromised package list |
/bloat |
Find dead code and over-engineering |
- Unsloth prints a new API key every restart. Re-run
setup_pi.pyor just update.envand~/.pi/agent/models.json— Pi reloads the file without a restart. - The model id in
models.jsonmust exactly match whatGET /v1/modelsreturns.setup_pi.pyhandles this automatically. - All LLM calls use
temperature=0.1–0.2for precision. Raise it for creative tasks. - In
--automode, pytest runs after the commit and the result is reported in the PR body — pass or fail, the PR always opens. - Anubis never merges. It opens PRs only. Merging is always a human decision.
- Branch names are auto-generated as
anubis/<slugified-task>. Override with--branch.
