Skip to content

Releases: pouriamrt/claude-mesh

v0.1.5 — hard delete + 30-day inactive auto-purge

Choose a tag to compare

@pouriamrt pouriamrt released this 18 Apr 21:58

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 init or add-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.5

Data 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 7

v0.1.3 — add-user --force for idempotent user creation

Choose a tag to compare

@pouriamrt pouriamrt released this 18 Apr 21:32

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_at if tombstoned (re-enables a disabled user)
  • Updates display_name in 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.3

Data survives. :latest tag also updated.

v0.1.2 — reject invalid admin handle at init

Choose a tag to compare

@pouriamrt pouriamrt released this 18 Apr 21:12

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.2

Data 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-peers

v0.1.1 — docker volume permissions fix

Choose a tag to compare

@pouriamrt pouriamrt released this 18 Apr 19:40

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.1

If 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.0

v0.1.0 — first release

Choose a tag to compare

@pouriamrt pouriamrt released this 18 Apr 19:21

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.