2026-09-19 23:33:24 +02:00
2026-09-19 23:33:24 +02:00
2026-09-19 23:33:24 +02:00
2026-09-19 23:33:24 +02:00
2026-09-19 23:33:24 +02:00

lodge

sync for files not meant to be in git

Runs in Docker, locally the same way as in production. Each part in backend/, frontend/ brings its own docker-compose.yml, included from the root one. COMPOSE_PROFILES in .env selects the services that run on this machine. docker-compose.override.yml in each part holds what differs between machines: published ports and the aliases on the external caddy network.

make env
make recreate

make env creates .env from the examples of every part and copies each docker-compose.override.yml.example. make recreate starts the selected profiles, make rebuild builds the images first, make logs, make restart and make down do what they say.

To deploy, git pull && make deploy. It runs make pre-deploy in every part, which builds images only when their inputs changed and applies migrations, then docker compose up -d, then make post-deploy, which restarts the services whose mounted code changed. A deploy system with its own up step calls the two hooks around it. What was built and started is remembered as refs/deploy/* in the clone.

make fmt, make check and make build run in every part. Part-specific targets live in the part's own Makefile: make -C backend ....

How it works

backend/ is one Go module with two binaries. lodge-server stores everything in a single SQLite file under backend/storage/, serves the API, the built frontend from frontend/build and the client binaries it was built together with, so a client always matches its server. lodge is the client: a CLI and a daemon in one.

A repository is identified by the hash of its root commit, so nothing is registered by hand. Files are content-addressed blobs; history is a log of revisions, each carrying the branch and the commit of the main repository at that moment. Every repository has a shared space and one space per branch. Which path goes where is set in .lodge at the repository root, which is synced like any other file:

shared docs/agents
shared CLAUDE.local.md
branch .agent

Synced paths are hidden through .git/info/exclude; .gitignore is never touched, and files tracked by git are never synced. When two machines edit the same file, the later edit wins and the other version stays in history.

Adding a machine

Set ADMIN_TOKEN in .env, sign in to the admin with it, open Machines and press "Connect a machine". The same one-time install command, valid for ten minutes, is available without a browser:

curl -X POST -H "Authorization: Bearer $ADMIN_TOKEN" https://lodge.example.com/api/codes

Running the returned curl ... | sh on a Mac or a Linux machine downloads the client, logs it in, starts the daemon under launchd or systemd, installs a post-checkout hook through init.templateDir so that fresh clones receive their files, and drops a skill for coding agents into ~/.claude/skills and ~/.agents/skills. Repositories cloned before that are picked up with lodge add. Where no daemon can run, set LODGE_URL and LODGE_TOKEN and call lodge sync.

make -C backend dev runs the server without Docker, make -C backend client builds the client into backend/bin.

The admin

The server serves the admin from frontend/build. History is drawn as a borehole log: every revision is a bed, newest on top, hatched by the machine that wrote it and labelled with the branch and commit of the main repository. Dragging along the column, or the arrow keys, shows the notes as they were at that revision, and every depth, file and view is a link. A file can be compared with its previous version and put back on the surface; a repository can be deleted with its history, which leaves the files on the machines alone. Machines are listed with their hatch and can be revoked.

make -C frontend dev runs the admin against a server on localhost:8080.

S
Description
sync for files not meant to be in git
Readme
399 KiB
0 Stars 2 Watchers 0 Forks
Languages
Go 53.8%
Svelte 34.3%
TypeScript 4.7%
CSS 4.1%
Makefile 1.6%
Other 1.5%