A local-first free-form task inbox daemon for concurrent coding agents, Git worktrees, and maintainer-style integration.
Project description
Alluvium
Alluvium is a local-first task inbox daemon for running commodity coding agents concurrently.
The primary CLI is named alluvium. The PyPI distribution is alluvium-swarm because the bare alluvium package name is already taken on PyPI.
The public API is intentionally tiny:
Drop a folder or a bare file into
tasks/inbox/. The daemon claims it, assigns a unique task ID, gives it an isolated Git worktree/branch, runs an agent, stores outputs under.agent/, and serially integrates any repository changes.
It is designed for workflows like:
- incoming files that should be summarized or ingested into long-term knowledge,
- mail/upload/folder watchers that dump task folders into a local inbox,
- concurrent coding-agent tasks in isolated worktrees,
- self-improving durable repositories containing code, docs, knowledge, skills, tests, or any other project state.
Status
Alpha. The core filesystem/Git orchestration is implemented. The default worker is a deterministic built-in inventory agent; configure [agent].command to use your preferred coding agent.
Concepts
agent-system/
tasks/
inbox/ # public drop zone: folders or bare files
running/ # currently being worked
needs_revision/ # integrator returned task to worker for amendment
needs_human/ # blocked on clarification/approval/manual intervention
done/ # worker finished; integration status is in .agent/integration.json
failed/ # worker failed
dead_letter/ # reserved for invalid/repeatedly failed tasks
repo/ # long-term Git repo: code, docs, knowledge, skills, tests, etc.
worktrees/ # one worktree per task
config.toml
A dropped item named acme-contract becomes a unique internal task like:
tasks/running/20260516T101530Z-acme-contract-a8f2c1/
A bare file works too:
tasks/inbox/report.pdf
becomes:
tasks/running/20260516T101530Z-report.pdf-c771aa/
report.pdf
.agent/
Every task gets:
- a reserved
.agent/subtree, - a Git branch
task/<task-id>, - a Git worktree
worktrees/<task-id>.
The daemon does not pre-classify tasks. The agent infers meaning from the free-form folder.
Installation with uv
After PyPI publication:
uv tool install alluvium-swarm
# or without installing permanently:
uvx --from alluvium-swarm alluvium --help
From GitHub before PyPI publication:
uv tool install git+https://github.com/spoj/alluvium
Development with uv
git clone https://github.com/spoj/alluvium
cd alluvium
uv sync --dev
uv run alluvium --help
uv run pytest
Publishing to PyPI
The intended PyPI distribution name is alluvium-swarm. The installed command is alluvium.
Build locally:
uv build
Publish with a PyPI token:
UV_PUBLISH_TOKEN=... uv publish
A GitHub Actions trusted-publishing workflow can also be used once the PyPI project is configured for trusted publishing.
Quick start
Initialize a system root in the current directory:
mkdir agent-system
cd agent-system
alluvium init
Or initialize a specific path:
alluvium init ~/agent-system
cd ~/agent-system
Drop a bare file into the inbox:
echo "Please summarize this." > tasks/inbox/request.txt
Run once:
alluvium run-once --ignore-settle
Or run as a daemon:
alluvium daemon
Check status:
alluvium status
Using a real coding agent
Edit config.toml:
[agent]
# Placeholders: {task_id}, {task_dir}, {agent_dir}, {worktree}, {branch}, {prompt_file}
command = ["your-coding-agent", "--cwd", "{worktree}", "--prompt-file", "{prompt_file}"]
timeout_seconds = 3600
The daemon provides environment variables too:
ALLUVIUM_TASK_ID
ALLUVIUM_TASK_DIR
ALLUVIUM_AGENT_DIR
ALLUVIUM_WORKTREE
ALLUVIUM_BRANCH
ALLUVIUM_PROMPT_FILE
The generated prompt asks the worker to:
- inspect the free-form task folder,
- write
.agent/understanding.md,.agent/plan.md,.agent/result.md, and.agent/result.json, - put artifacts under
.agent/outputs/, - commit useful repo changes directly on the task branch,
- request human help by writing
.agent/needs_human.md, - address integrator feedback from
.agent/revision_request.mdwhen returned, - log external effects under
.agent/effects/ledger.jsonl.
Integration model
Workers run concurrently. Integration into main is serial.
After a worker exits, the task is moved to tasks/done/ if it succeeded. The daemon writes:
.agent/integration.json
If the task branch has no changes:
{"status": "noop", "has_repo_changes": false}
If it has changes:
{"status": "pending", "has_repo_changes": true, "branch": "task/..."}
The integrator loop scans tasks/done/ for pending integrations, performs a squash merge into main, runs configured tests, and updates the integration status to merged, noop, needs_revision, or blocked.
If a merge conflict or integration test failure is likely fixable by the worker, the integrator writes:
.agent/revision_request.md
and moves the task to:
tasks/needs_revision/
The coordinator then re-runs a worker on the same task ID, branch, and worktree so it can amend the branch. After the worker finishes, the task returns to done/ and integration is attempted again. After max_revision_rounds, or for unrevisionable problems, the task is moved to needs_human/.
Durable repo conventions
Alluvium does not impose a special knowledge/proposal topology. The durable repo is just a Git repository. It may contain code, docs, knowledge, skills, tests, generated assets, or anything else your project needs.
Workers are expected to make the branch correct as a whole. The integrator acts like a repo maintainer: it serially reviews, tests, merges, or sends the task back for amendment.
Project-specific conventions should live in repo/AGENTS.md.
Inbox publishing safety
The daemon supports human-friendly dropping. It waits for inbox items to be unchanged for inbox_settle_seconds before claiming them.
For producer programs, the safest pattern is atomic publish:
tasks/inbox/.some-task.tmp/
files...
↓ rename when complete
tasks/inbox/some-task/
Bare files are also supported:
tasks/inbox/report.pdf
The daemon wraps the file into a unique task folder when claiming it.
systemd user service example
[Unit]
Description=Alluvium Daemon
After=network.target
[Service]
Type=simple
WorkingDirectory=/home/me/agent-system
ExecStart=/home/me/.local/bin/alluvium daemon --config /home/me/agent-system/config.toml
Restart=always
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=60
[Install]
WantedBy=default.target
Then:
systemctl --user daemon-reload
systemctl --user enable alluvium
systemctl --user start alluvium
journalctl --user -u alluvium -f
Design tradeoffs
- The inbox is free-form;
.agent/is the only reserved task subtree. - Every task gets a branch/worktree, even if no repo changes are ultimately made.
done/means the worker finished. Integration status is separate and stored inside.agent/integration.json.needs_revision/is the send-back primitive: the same task branch is re-run and amended.- Workers may run concurrently;
mainintegration is serialized. - The default crash recovery is conservative: interrupted
running/tasks move tofailed/on daemon restart.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file alluvium_swarm-0.2.0.tar.gz.
File metadata
- Download URL: alluvium_swarm-0.2.0.tar.gz
- Upload date:
- Size: 21.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab522ad50ed0a49cee23561db5a2998abd6b99d2c38b3669df8c8127cc5c6155
|
|
| MD5 |
9b8f3e30ed6ec35f8ac88c4aafca3da5
|
|
| BLAKE2b-256 |
7504cb49f6a2a7330519986d510704d1a01daf7b2ccc98f7228e2e13b19df18b
|
File details
Details for the file alluvium_swarm-0.2.0-py3-none-any.whl.
File metadata
- Download URL: alluvium_swarm-0.2.0-py3-none-any.whl
- Upload date:
- Size: 25.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9269bba7b4801acf264434a8399ca99ed9a1fe0a791a77bd957fd94691032a54
|
|
| MD5 |
4ef7b5f1bd0862f59e78bc1238ae1d7d
|
|
| BLAKE2b-256 |
32bc08d069c95709e730041bba94a26d004a0a10a54ae180905399e71d637198
|