|

Container manager for software repositories that leverage AI agents

Clone
hg clone ssh://hg@leafscale.isurus.dev:2222/leafscale/repoman hg clone https://leafscale.isurus.dev/leafscale/repoman
a879806fe0a3 cli: cmd_new bind repo with shift=true so host uid maps into container; bump 0.4.2
Chris Tusa <chris.tusa@leafscale.com> 16 days ago

repoman

Per-project Incus containers + opinionated NFS/ZFS backup. v0.1.

Build

reefc build

Produces ./build/repoman.

Test

for t in tests/test_*.reef; do
    echo "== $t =="
    reefc run "$t" || exit 1
done

Install

System-wide via Makefile (uses reefc build under the hood):

make
sudo make install        # installs to /usr/local/bin/repoman

Quickstart

# First run creates ~/.config/repoman/repoman.toml with sane defaults.
repoman --help
repoman new isurus --repo isurus-project
repoman sync --dry-run
repoman list

Subcommands

Subcommand Description
new <name> [--repo <dirname>] [--image <image>] Launch an Incus container and bind a local repo into it. (Use repoman setup --with-llm first if you want LLM stack wiring.)
sync [name] [--no-delete] [--dry-run] Mirror local repos to NFS backup via rsync.
list Print a table of all registered projects (read-only).
status [name] Show project state from registry + live incus query.
remove <name> --yes [--keep-incus] Delete the incus container and registry entry. --yes required.
shell <name> [--cwd <path>] Open a bash login shell inside the project's container (replaces repoman).
--help / -h / help Show usage and subcommand list.
--version / -V Print version string.

Setup wizard

First-time host bootstrap (idempotent — safe to re-run):

repoman setup                     # interactive
repoman setup --non-interactive   # accept defaults

The wizard creates the Incus project repoman, detects your host LAN IP (used by
profiles that wire containers to host services), and writes the initial registry.

After setup, install the vendor profile library:

repoman profile install --all

Profile library

repoman ships a vendor profile library at /usr/local/share/repoman/profiles/.
v0.4 includes three profiles:

  • claude-share — bind ~/.claude and ~/.local/bin/claude into containers
    so they share the host's Claude CLI auth, history, and plugins.
  • llm-share — bind /usr/local/bin/ollama and ~/.ollama into containers,
    set OLLAMA_HOST=http://<host-lan-ip>:11434 so containers reach the host's
    ollama daemon over LAN.
  • dotfiles — bind ~/.gitconfig and ~/.hgrc (extend with your own).

Manage profiles via repoman profile:

repoman profile list
repoman profile install <name>
repoman profile install --all
repoman profile diff <name>            # show drift between file and incus state
repoman profile show <name>            # print rendered YAML
repoman profile remove <name>          # remove from incus (file untouched)

Customizing profiles

To override a vendor profile, copy it to your user dir and edit:

cp /usr/local/share/repoman/profiles/dotfiles.yml ~/.config/repoman/profiles.d/
$EDITOR ~/.config/repoman/profiles.d/dotfiles.yml
repoman profile install dotfiles       # applies the user version (shadows vendor)

User profiles in ~/.config/repoman/profiles.d/ always win over vendor profiles
of the same name. repoman profile list shows the active source for each.

Migrating from v0.3

If you ran repoman setup --with-llm on v0.3, your registry is at schema 2 and
includes a [defaults.llm] block. v0.4 reads that block on first load, extracts
the ollama_url's host portion into [host].lan_ip, and writes the registry as
schema 3 on the next save. No action required — the migration is automatic and
lossless for the one fact that's still useful.

The --hermes / --no-hermes / --purge-hermes flags are gone (those were
already reverted in v0.3 before tagging). Hermes (and similar agents that need
per-container installs) is the user's responsibility: shell into the container
with repoman shell <name> and run the install yourself.

Smoke test (requires Incus + NFS)

# In an existing repo dir under ~/repos:
repoman new test-foo
repoman sync test-foo --dry-run
incus delete --project repoman test-foo

Output and logging

By default repoman runs quietly — only its own ==> ... markers and any errors reach the terminal. Subprocess probes (e.g. incus project show, stat /nfs/repos, findmnt) have their stdout/stderr suppressed to /dev/null. The actual user-facing operations (launch, rsync) pass their stdio through.

To see the suppressed probe output for troubleshooting, run with --verbose (or -v). Pass --quiet (or -q) to force quiet mode if your config defaults to verbose.

Every invocation also writes a log file at <logdir>/<project>-<verb>.log, truncated each run. So if a repoman new veemarker fails, the log lives at ~/.local/state/repoman/veemarker-new.log until the next run with the same name+verb. Whole-tree sync uses all-sync.log.

Configuration

Central registry: ~/.config/repoman/repoman.toml (managed; do not edit while repoman is running).

Tool-level settings under [repoman]:

Field Values Default Effect
output "quiet" | "verbose" "quiet" Default output mode (CLI flags override).

Defaults under [defaults]:

Field Default Effect
repos_root ~/repos Local NVMe canonical location.
backup_root /nfs/repos NFS-mounted backup destination.
logdir ~/.local/state/repoman Per-invocation log files written here.
incus_project repoman Incus project containers are created in.
default_image images:ubuntu/26.04/cloud Image used when no --image flag and no override.
profiles ["default", "claude-share"] Profiles applied when creating containers.

Per-project overrides: ~/.config/repoman/repos.d/<container-name>.toml (user-authored). Example:

[container]
image    = "images:debian/12/cloud"
profiles = ["default", "claude-share", "node-dev"]

[[mount]]
source = "~/.npm"
path   = "/home/ctusa/.npm"

[env]
NODE_ENV = "development"

For the agent-friendly setup repoman is built around, create a shared profile that exposes the user's Claude state:

# (one-time)
incus profile create claude-share
incus profile edit claude-share  # add your bind-mounts for ~/.claude, etc.

repoman uses profiles default and claude-share by default; override per-project in repos.d/<name>.toml.

License
CDDL-1.0
Languages
Markdown 70%
Reef 29%
YAML 0%
Makefile 0%
plaintext 0%
Activity
138 commits
Updated 2 hours ago