Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ ecluse/
│ ├── env.rs .env.ecluse generation
│ ├── compose.rs compose parse + overlay generation
│ ├── docker.rs docker shell-outs
│ ├── postgres.rs psql shell-outs
│ ├── process.rs tmux/nohup service spawning
│ ├── sync.rs external process/container discovery
│ ├── hooks.rs lifecycle hook execution
│ ├── validate.rs config validation + port probing
│ ├── whose_pid.rs PID → session reverse lookup
│ ├── log.rs console step output
│ ├── detect.rs mode detection signals
│ ├── error.rs EcluseError enum
│ └── modes/ container / host / hybrid handlers
Expand All @@ -36,11 +41,10 @@ The `rust-toolchain.toml` pins to stable. Do not add nightly features.

## Key invariants — do not break these

- **State is always consistent.** `state.json` is written atomically (write `.json.tmp`, then rename). The lock at `state.lock` is held for the entire duration of `up` and `down`.
- **State is always consistent.** `state.json` is written atomically (write `.json.tmp`, then rename) and only ever mutated while holding the `state.lock` file lock via `StateGuard`.
- **Mode is per-repo, not per-session.** Stored in `.ecluse.toml`. `up` never reads `--mode` from CLI.
- **Rollback on failure.** Every `bring_up` in `modes/*.rs` must roll back any partially-created resources (worktree, containers, database) if it returns an error before `state_guard.commit()`.
- **Rollback on failure.** Every `bring_up` in `modes/*.rs` must roll back any partially-created resources (worktree, containers, database) if it returns an error before the session is committed to state.
- **Same CLI surface across all modes.** No mode-specific subcommands or flags. If you find yourself adding `--container-only-flag`, stop and reconsider.
- **LoC budget: 2500 lines of Rust** (`src/**/*.rs`). Check with `find src -name '*.rs' | xargs wc -l`.

## Skills are in `skills/`, not `src/`

Expand Down
13 changes: 11 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ ecluse shutdown # tear down ALL active sessions (--keep-worktrees to leave wor
ecluse ls # list active sessions
ecluse env # print session env vars as JSON
ecluse shell # drop into worktree with env loaded (interactive use only)
ecluse status # per-service health for a session
ecluse sync # register externally-started processes as a session
ecluse whose-pid # reverse-map a PID to the owning session
ecluse flush # hard-reset: tear down everything ecluse knows about
ecluse validate # validate .ecluse.toml port ranges and service gaps
```

Expand Down Expand Up @@ -66,7 +70,7 @@ Not every change touches all five — a slot-allocation bug fix probably touches

```
src/
├── main.rs command handlers (init/up/down/ls/shell/env)
├── main.rs command handlers
├── cli.rs clap CLI definitions
├── config.rs .ecluse.toml parsing, Config struct, Mode enum
├── slot.rs slot allocation (first free in 1..max_slots)
Expand All @@ -75,7 +79,12 @@ src/
├── error.rs EcluseError variants with actionable messages
├── detect.rs mode auto-detection via signal scoring
├── worktree.rs git worktree create/remove wrappers
├── hooks.rs on_up/on_down lifecycle hook execution
├── hooks.rs lifecycle hook execution (pre_up/pre_spawn/post_up/pre_down/post_down)
├── process.rs native service spawning (tmux/nohup) + global config
├── sync.rs discovery of externally-started processes/containers
├── validate.rs config validation + free-port probing
├── whose_pid.rs PID → owning session reverse lookup
├── log.rs step/detail/warn console output
├── compose.rs docker-compose.yml parsing + overlay generation
├── docker.rs Docker CLI wrappers
└── modes/ ModeHandler trait + container/host/hybrid impls
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,13 @@ name = "postgres"
run = "docker"
base_port = 5432 # slot 1 → ECLUSE_POSTGRES_PORT=5433, slot 2 → 5434

# Optional: lifecycle hooks — run in the worktree with all env vars set
# Optional: lifecycle hooks — shell commands run in the worktree.
# Order: pre_up (nothing exists yet, no env) → pre_spawn (env written,
# services not started) → post_up (everything up) → pre_down (before
# teardown) → post_down (after teardown).
[hooks]
on_up = "npx prisma migrate deploy"
on_down = "npx prisma migrate reset --force"
post_up = "npx prisma migrate deploy" # full ECLUSE_* env available
pre_down = "npx prisma migrate reset --force"
```

`ecluse init` writes `~/.config/ecluse/config.toml` with the detected process manager (`tmux` if installed, otherwise `nohup`). Services with `command` are spawned on `ecluse up` and killed on `ecluse down`. Set `process_manager = "none"` to opt out.
Expand Down Expand Up @@ -248,7 +251,7 @@ compose = "services/worker/docker-compose.yml" # its own compose file

**Port collision handling** — by default ecluse searches for a free port if the nominal one is taken, trying `nominal + i × max_slots` to stay out of other slots' territory. Set `strict_port = true` to fail immediately instead. Run `ecluse validate` to check your config and preview the full port allocation table.

Hooks run as shell commands inside the worktree directory with all `.env.ecluse` variables pre-loaded. Use them for migrations, seeding, or teardown. ecluse doesn't manage databases directly — your app's own tooling handles that via `on_up`.
Hooks run as shell commands inside the worktree directory with all `.env.ecluse` variables pre-loaded (except `pre_up`, which runs before any env exists). Use them for migrations, seeding, or teardown. ecluse doesn't manage databases directly — your app's own tooling handles that via `post_up`. The old `on_up`/`on_down` names still work as deprecated aliases for `pre_up`/`pre_down`.

## Known limits

Expand Down
Loading