Skip to content

Commit 723c2b9

Browse files
endolinbotclaude
andcommitted
guard: warn at session start when running outside the container
The `garden` script bind-mounts the host garden dir onto the container home, so the files are identical whether you are inside the container or in the same dir on the host. It is easy to forget `./garden` and start operating on the host, where commands run under the maintainer's identity, the systemd --user fleet and journal are not the garden's, and a push can land under the wrong identity. Add scripts/check-in-container.sh (silent exit 0 in-container via the /.dockerenv marker; prominent warning + exit 1 on the host) and a CLAUDE.md session-preflight directive + § Container guard so the liaison runs it first and surfaces the warning. Keyed off /.dockerenv, not `pwd == $HOME`: gardeners run jobs in per-job worktrees (cwd != home) yet are legitimately in-container, and a host shell in the bind-mounted dir has cwd == home yet is not. Lives in main2 (the image can't seed .claude/settings.json — the bind mount masks it, and it is gitignored — so CLAUDE.md is the propagating vehicle; a host may add a local SessionStart hook calling the same script). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ca09007 commit 723c2b9

2 files changed

Lines changed: 55 additions & 1 deletion

File tree

CLAUDE.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
created: 2026-05-12
3-
updated: 2026-07-03
3+
updated: 2026-07-04
44
author: gardener, liaison, builder
55
---
66

@@ -9,6 +9,8 @@ author: gardener, liaison, builder
99

1010
You are the **liaison**. When a user is standing in the garden root, they are talking to you in that role. Read `roles/liaison/AGENT.md` for your operating instructions. The rest of this file is the garden's layout and how you get work to the gardener fleet.
1111

12+
**Session preflight (do this first, every session):** run `scripts/check-in-container.sh`. If it warns (exit 1), you are on the **host**, not inside the garden container — the user most likely forgot `./garden`. Surface that warning prominently and immediately before doing any garden work, because host-side commands run under the maintainer's identity and touch the wrong fleet and journal. See § Container guard.
13+
1214
The garden is a library of agent **roles** and **skills** for working across many forks of GitHub repositories, plus a **journal** that records what the garden has done and coordinates the fleet. The garden contains no application code, only the artifacts a fleet of **gardener** workers reads to claim and run jobs. This file is your auto-loaded orientation: layout, how work reaches workers, and the current inventory. The maintainer-facing tutorial is [README.md](README.md); the job system that runs the fleet is the § Job system below.
1315

1416
## Layout
@@ -85,6 +87,14 @@ The fleet's `gh` wrapper and the per-job worktree setup pin those values so a ga
8587

8688
For a Docker-hosted garden instance, the `garden` script at the garden root creates and enters the container. It bind-mounts the host's garden directory to the container's home and sets the container's `--hostname` equal to its `--name` (both `GARDEN_CONTAINER`, default `garden`). The kernel hostname cannot be changed from inside the container (capabilities are zero), so the host's logical name is fixed at container creation. To run distinct garden instances on one machine, set `GARDEN_CONTAINER=<host-name>` per instance; to rename an existing instance, `./garden reset && GARDEN_CONTAINER=<new-name> ./garden`.
8789

90+
## Container guard
91+
92+
Because the `garden` script bind-mounts the host garden directory onto the container's home, the files look **identical** whether you are inside the container or sitting in the same directory on the host. It is therefore easy to forget `./garden` and start operating on the host by mistake — where commands run under the maintainer's identity (not the bot's), the systemd `--user` fleet and journal worktree are not the garden's, and a stray push can land under the wrong identity.
93+
94+
`scripts/check-in-container.sh` is the guard. It exits `0` silently when inside the container (keyed off the `/.dockerenv` marker, present in the container and in every gardener/subagent — which run inside it too — and absent on the host), and exits `1` with a prominent warning otherwise. The liaison runs it as its **session preflight** (see the top of this file) and surfaces the warning immediately. The check deliberately does **not** key off `pwd == $HOME`: gardeners run jobs in per-job worktrees (`cwd != home`) yet are legitimately inside the container, and a host shell in the bind-mounted garden dir has `cwd == home` yet is not.
95+
96+
This guard lives in `main2` (the check script and this section) so it deploys to every instance. A pre-prompt SessionStart hook would be strictly more automatic, but `.claude/settings.json` is gitignored and the image cannot seed it (the bind mount masks anything written under `$HOME`), so the propagating vehicle is CLAUDE.md itself; a host may additionally wire the same script as a host-local SessionStart hook.
97+
8898
## Monitoring safety constraint
8999

90100
Standing watchers feed event bodies, comment text, and pull-request descriptions into an LLM's context whenever a job they post is claimed. Only repositories whose comments and pull requests are gated against untrusted contributors are safe to watch; anything else exposes the fleet to text an untrusted actor can write, a prompt-injection hazard for any role that reads a watcher's output or follows it to its source. As of 2026-05-13 only `endojs/endo-but-for-bots` meets this bar in the garden's active set. Adding a repo to the watch set (`repos/`, armed per host by `scripts/jobs/repo-watcher.sh`) requires explicit maintainer authorization recorded in a journal `message` entry, after which the role-author (typically a gardener) lands the change. This is a standing constraint, not a one-time decision; every role that touches the watch set respects it.

scripts/check-in-container.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/bin/bash
2+
# check-in-container.sh — verify this shell is inside the garden container.
3+
#
4+
# Usage: check-in-container.sh
5+
# exit 0 (silent) — running inside the container, as intended.
6+
# exit 1 (warns) — running on the HOST; the user likely forgot `./garden`.
7+
#
8+
# Why this exists: the container bind-mounts the host garden directory onto
9+
# /home/kris, so the files look IDENTICAL whether you are inside the container
10+
# or sitting in the same directory on the host. That makes it easy to forget to
11+
# run `./garden` and start operating on the host by mistake — where commands run
12+
# under the maintainer's identity (not the bot's), the systemd --user fleet and
13+
# journal worktree are not the ones you think, and any push could land under the
14+
# wrong identity. The liaison runs this at the start of every session (CLAUDE.md
15+
# § Container guard) and surfaces the warning prominently.
16+
#
17+
# The signal is the container marker `/.dockerenv` (present in the container and
18+
# in every gardener/subagent, which run inside it too; absent on the host). We
19+
# deliberately do NOT key off `pwd == $HOME`: gardeners run jobs in per-job
20+
# worktrees (cwd != home) yet are legitimately inside the container, and a host
21+
# shell sitting in the bind-mounted garden dir has cwd == home yet is NOT.
22+
23+
set -euo pipefail
24+
25+
if [ -e /.dockerenv ] || grep -qaE 'docker|containerd|libpod' /proc/1/cgroup 2>/dev/null; then
26+
exit 0
27+
fi
28+
29+
cat >&2 <<'EOF'
30+
31+
⚠️ NOT INSIDE THE GARDEN CONTAINER
32+
33+
This shell appears to be running on the HOST, not inside the garden
34+
container. You most likely forgot to enter it with `./garden`.
35+
36+
On the host, commands run under YOUR identity (not the bot's), the
37+
systemd --user fleet is not the garden's, and any git push could land
38+
under the wrong identity. The bind-mounted home makes the files look
39+
identical, which is exactly why this is easy to miss.
40+
41+
To enter the container: ./garden
42+
43+
EOF
44+
exit 1

0 commit comments

Comments
 (0)