diff --git a/.github/mkdocs/hooks.py b/.github/mkdocs/hooks.py
index 9a31e3c..eef7574 100644
--- a/.github/mkdocs/hooks.py
+++ b/.github/mkdocs/hooks.py
@@ -65,6 +65,10 @@ def _rewrite(target, page, config):
site = _site_path(resolved)
if site is not None:
return posixpath.relpath(site, posixpath.dirname(page.file.src_uri) or ".") + fragment
+ # Files under docs/ are published with the site, not served from GitHub.
+ if resolved.startswith("docs/") and (ROOT / resolved).is_file():
+ asset = resolved[len("docs/"):]
+ return posixpath.relpath(asset, posixpath.dirname(page.file.src_uri) or ".") + fragment
branch = "blob" if (ROOT / resolved).is_file() else "tree"
return f"{config['repo_url'].rstrip('/')}/{branch}/main/{resolved}{fragment}"
diff --git a/README.md b/README.md
index faffc06..b678c75 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,8 @@ OpenCode runs every tool call in its server, not in the TUI, so each agent
gets two sandboxes: a **server sandbox** (OpenCode's private server and every
tool it runs) and a **client sandbox** (the TUI).
+
+
| | Server sandbox: server and tools | Client sandbox: TUI |
| --- | --- | --- |
| Project files | Read-write: the worktree or git repository of the focused pane | Same |
diff --git a/docs/design.md b/docs/design.md
index 8061b58..77f5232 100644
--- a/docs/design.md
+++ b/docs/design.md
@@ -1,5 +1,17 @@
# Design
+## Launch and verification
+
+The action runs briefly under Herdr; the bridge stays in the agent pane for
+the lifetime of the session. The server and client run in separate nono
+sandboxes, while verification and the pane mapping stay outside both.
+
+
+
+The client can reach only its private server port; the server runs tools and
+uses nono's proxy for allowed provider hosts. See [Security](security.md) for
+the network and trust boundaries.
+
## Two plugin processes
Herdr runs plugin actions as short-lived processes without a terminal, so
diff --git a/docs/images/launch.svg b/docs/images/launch.svg
new file mode 100644
index 0000000..15f086d
--- /dev/null
+++ b/docs/images/launch.svg
@@ -0,0 +1,59 @@
+
diff --git a/docs/images/security-boundary.svg b/docs/images/security-boundary.svg
new file mode 100644
index 0000000..a3a8471
--- /dev/null
+++ b/docs/images/security-boundary.svg
@@ -0,0 +1,44 @@
+
diff --git a/docs/security.md b/docs/security.md
index ff9d29a..b19e0ec 100644
--- a/docs/security.md
+++ b/docs/security.md
@@ -19,19 +19,7 @@ The plugin picks the port `P` and a fresh password (`OPENCODE_PASSWORD`) on
every launch; the server rejects requests without it. `--server` is a required
argument that configuration cannot replace.
-```mermaid
-flowchart LR
- subgraph client["client sandbox: network blocked"]
- CLIENT["opencode --server http://127.0.0.1:P (TUI)"]
- end
- subgraph server["server sandbox: provider hosts via nono proxy"]
- SERVER["opencode serve --port P"] --> TOOLS["tools: bash, edits, ..."]
- end
- SVC["OpenCode host service 127.0.0.1:4096 (unsandboxed)"]
- CLIENT -->|"port P + password"| SERVER
- SERVER --> PROXY["nono proxy"] --> NET(("GitHub Copilot"))
- TOOLS -. "denied, directly and via the proxy" .-> SVC
-```
+
## What each sandbox can reach