Releases: pouriamrt/claude-mesh
Release list
v0.1.5 — hard delete + 30-day inactive auto-purge
Cleans up accumulated user cruft, automatically and on demand.
What's new
mesh admin delete-user <handle> — hard delete. Removes the human row, all its tokens, and pending paircodes in one transaction. Handle becomes immediately reusable without --force. Use this when you want a row gone, not just tombstoned.
mesh admin purge-inactive [--days 30] — on-demand sweep of every user whose last_active_at is older than N days. Users holding an active admin-tier token are never purged (guard against deleting the team's sole admin).
Background sweeper — the relay runs the inactivity sweep every hour. Configurable via MESH_INACTIVE_DAYS (default 30; set to 0 to disable). Logged as purge.sweep when it deletes anything.
Schema migration
Schema v2 adds human.last_active_at. Fresh databases get the column from schema.sql; existing v1 databases are migrated in place on startup (ALTER TABLE, backfill from created_at). No manual step needed.
Activity tracking
last_active_at updates on:
- every authenticated request (bearerAuth middleware)
- successful
mesh pair(token creation) - new user creation via
initoradd-user
Upgrade
docker pull ghcr.io/pouriamrt/claude-mesh/relay:v0.1.5
docker stop mesh-relay && docker rm mesh-relay
docker run -d --name mesh-relay --restart unless-stopped \
-p 8443:8443 -v mesh-data:/data \
ghcr.io/pouriamrt/claude-mesh/relay:v0.1.5Data survives. The migration runs on the first startup of the new image.
Cleanup example
# List what's there
mesh admin audit
# Nuke specific orphans (frees the handles for re-use)
mesh admin delete-user Pouria
mesh admin delete-user pouria
mesh admin delete-user old-test-user
# Or sweep everything older than 7 days in one go
mesh admin purge-inactive --days 7v0.1.3 — add-user --force for idempotent user creation
Adds --force to mesh admin add-user. Lets you re-use an existing handle (including disabled ones) instead of hitting 409 handle_taken and ending up with dozens of unusable rows during setup.
What --force does
When the handle already exists:
- Revokes every active token for that user (old paired devices stop sending)
- Deletes pending paircodes for the handle (old unconsumed codes become dead)
- Clears
disabled_atif tombstoned (re-enables a disabled user) - Updates
display_namein place - Mints a fresh paircode
Response is 200 OK with reset: true; fresh creates still return 201. Audit event user.reset.
Usage
# Clean up an existing mess without draining the DB
mesh admin add-user --handle mesh-admin --tier admin --display-name "Pouria" --force
# → OK Reset "mesh-admin" (admin)
# Old tokens revoked, unconsumed paircodes invalidated.
# OK Pair code: MESH-XXXX-XXXX-XXXX (expires ...)
mesh pair <NEW-PAIRCODE> --label "my-laptop"Upgrade
docker pull ghcr.io/pouriamrt/claude-mesh/relay:v0.1.3
docker stop mesh-relay && docker rm mesh-relay
docker run -d --name mesh-relay --restart unless-stopped -p 8443:8443 -v mesh-data:/data ghcr.io/pouriamrt/claude-mesh/relay:v0.1.3Data survives. :latest tag also updated.
v0.1.2 — reject invalid admin handle at init
Patch release that prevents a foot-gun at relay init.
What was wrong
If you typed a capitalized handle at the Admin handle: prompt (e.g. Pouria), init happily wrote it to the DB. Everything superficially worked — mesh admin add-user succeeded, list_peers returned the entry — but every outbound message from that user hit invalid_message at the relay because HANDLE_REGEX (used by EnvelopeSchema on the from field) only allows ^[a-z][a-z0-9_-]{0,31}$.
Users on v0.1.0/v0.1.1 who created a capitalized admin will still see this. The fix prevents new installs from ending up in that state.
Fix
initTeam() now validates admin_handle against HANDLE_REGEX up front. Bad handle → clear error naming the rule, no partial DB writes.
Upgrade
docker pull ghcr.io/pouriamrt/claude-mesh/relay:v0.1.2
docker stop mesh-relay && docker rm mesh-relay
docker run -d --name mesh-relay --restart unless-stopped -p 8443:8443 -v mesh-data:/data ghcr.io/pouriamrt/claude-mesh/relay:v0.1.2Data survives in the mesh-data volume.
If you already hit this on v0.1.0/v0.1.1
Your DB has an invalid handle row. Add a new lowercase admin and re-pair:
mesh admin add-user --handle mesh-admin --display-name "<your name>" --tier admin
mesh pair <paircode> --label "my-laptop"
# optionally: mesh admin disable-user <old-capitalized-handle>
claude --dangerously-load-development-channels server:claude-mesh-peersv0.1.1 — docker volume permissions fix
Patch release fixing a container-permissions bug in v0.1.0.
What broke in v0.1.0
docker run ghcr.io/pouriamrt/claude-mesh/relay:v0.1.0 init failed with `SqliteError: unable to open database file (SQLITE_CANTOPEN)` on a fresh named volume. Root cause: the distroless nonroot user (UID 65532) couldn't write to `/data` because a freshly-initialized named volume inherited root:root ownership.
Fix
Dockerfile now stages a pre-chowned `/seed-data` directory in the build stage and COPYs it into `/data` in the final image. Docker's volume-initialization semantics mean fresh named volumes now inherit nonroot ownership on first use, so better-sqlite3 can open the DB.
Upgrade
docker pull ghcr.io/pouriamrt/claude-mesh/relay:v0.1.1
docker stop mesh-relay && docker rm mesh-relay
docker run -d --name mesh-relay --restart unless-stopped \
-p 8443:8443 -v mesh-data:/data \
ghcr.io/pouriamrt/claude-mesh/relay:v0.1.1If you previously used the `--user 0:0` workaround from the bug thread, drop that flag on the new image.
Workaround for anyone stuck on v0.1.0
Run with `--user 0:0` for both the init and the long-running server (loses the nonroot hardening but unblocks the database create):
docker run --rm -it --user 0:0 -v mesh-data:/data \
ghcr.io/pouriamrt/claude-mesh/relay:v0.1.0 init
docker run -d --name mesh-relay --user 0:0 -p 8443:8443 \
-v mesh-data:/data ghcr.io/pouriamrt/claude-mesh/relay:v0.1.0v0.1.0 — first release
First tagged release of claude-mesh.
What's in it
- Self-hosted HTTP relay (Hono + SQLite WAL) with SSE fan-out and idempotency
- Per-user peer-agent (MCP channel bridge) exposing `send_to_peer`, `list_peers`, `set_summary` tools
- ULID-ordered envelope pipeline with `?since=` resume cursor
- Permission-relay plumbing (verdict path working; outbound request path pending — see Caveats in README)
- 100% coverage on `@claude-mesh/shared`, 80%+ on relay and peer-agent business logic
Verified end-to-end
Inbound `<channel source="peers" ...>` tag delivery from peer → relay → SSE → peer-agent → Claude Code context was tested on real Claude Code v2.1.80+ (Windows 11, with the `--dangerously-load-development-channels server:claude-mesh-peers` launch flag).
Docker image
Published to GitHub Container Registry:
```bash
docker pull ghcr.io/pouriamrt/claude-mesh/relay:v0.1.0
docker pull ghcr.io/pouriamrt/claude-mesh/relay:latest
```
Once you flip the package to public visibility (see package settings), anyone can pull without auth.
Getting started
See the Quickstart for the 2-minute single-machine demo, or the Tailscale recipe for cross-laptop setup.
Known gaps
See Caveats — outbound permission-request flow, L3 scenario tests gated behind `CLAUDE_DRIVER=cli`, docker image not yet tested as a pulled artifact, peer-agent coverage thresholds relaxed pending a follow-up sweep.