forked from bots-garden/ori
🛟 Updated.
55d4c9e parent: 4166f8f added
demo/picard-story.md +33 -0 | new file mode 100644 | ||
| @@ -0,0 +1,33 @@ | ||
| 1 | +# The Archaeologist's Gambit | |
| 2 | + | |
| 3 | +**Agent: Bob** | |
| 4 | + | |
| 5 | +Captain Jean-Luc Picard stood before the ancient artifact, his fingers hovering millimeters above its surface. The crystalline structure pulsed with a faint amber glow, responding to his proximity like a living thing. | |
| 6 | + | |
| 7 | +"Captain, I must advise caution," Data said from behind him, his golden eyes scanning the tricorder readings. "The energy signature is unlike anything in our database." | |
| 8 | + | |
| 9 | +Picard's lips curved into a slight smile. "Mr. Data, in my experience, the most profound discoveries often lie beyond the boundaries of our databases." | |
| 10 | + | |
| 11 | +They were deep within the ruins of Kataan—not the Kataan of his inner light experience, but its sister colony, hidden for millennia beneath the ice sheets of Delta Sigma IV. The Federation archaeological survey had discovered it three weeks ago, and Picard had been unable to resist the opportunity to lead the away team himself. | |
| 12 | + | |
| 13 | +"This script," Picard murmured, tracing the air above the inscriptions that spiraled around the artifact's base, "is Kataan, but it's... older. More refined than what I learned." | |
| 14 | + | |
| 15 | +He closed his eyes, and for a moment, he was Kamin again—the memories of that life as vivid as his actual past. The flute music, the sun on his face, Eline's laugh. A life lived in forty minutes that had shaped him forever. | |
| 16 | + | |
| 17 | +"It's a beacon," Picard said suddenly, his eyes opening. "Not a warning, but an invitation. The Kataan people knew their sun was dying. They sent out their culture, their memories, in multiple forms. We found one—the probe that found me. But this... this is something more." | |
| 18 | + | |
| 19 | +"More?" Commander Riker's voice crackled through the comm badge. "Captain, you're already talking about a civilization that downloaded an entire lifetime into your brain. What could be 'more' than that?" | |
| 20 | + | |
| 21 | +Picard's hand finally made contact with the artifact. The amber light exploded into a cascade of images—not memories this time, but pure information. Mathematics. Philosophy. Art. The complete accumulated knowledge of a civilization. | |
| 22 | + | |
| 23 | +"Number One," Picard said, his voice thick with emotion, "prepare to download approximately four hundred exabytes of data. The Kataan didn't just want to be remembered—they wanted to teach. This is their university, their library, their gift to whoever would listen." | |
| 24 | + | |
| 25 | +As Data began the careful transfer, Picard stood back, one hand unconsciously moving to his uniform jacket pocket where he kept Kamin's flute. He had been given a life once by the Kataan people. Now, they were giving him—giving humanity—the tools to understand that life and countless others. | |
| 26 | + | |
| 27 | +"Make it so," he whispered to himself, a small smile playing at the corners of his mouth. | |
| 28 | + | |
| 29 | +The Enterprise would be here for weeks, perhaps months, cataloging this discovery. And for once, Jean-Luc Picard, who had always believed that to boldly go meant to leave and explore further, was content to stay still and listen to the voices of the past. | |
| 30 | + | |
| 31 | +--- | |
| 32 | + | |
| 33 | +*Captain's Log, Supplemental: The Kataan archive is beyond anything I imagined. In seeking to preserve themselves, they may have given us the key to understanding dozens of lost civilizations. I find myself wondering: how many other ancient peoples left such gifts among the stars, waiting for someone to stop and listen? Perhaps the greatest exploration is not in discovering new worlds, but in understanding those that came before us.* | |
| new file mode 100644 | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | +# The Archaeologist's Gambit | ||
| 2 | + | ||
| 3 | +**Agent: Bob** | ||
| 4 | + | ||
| 5 | +Captain Jean-Luc Picard stood before the ancient artifact, his fingers hovering millimeters above its surface. The crystalline structure pulsed with a faint amber glow, responding to his proximity like a living thing. | ||
| 6 | + | ||
| 7 | +"Captain, I must advise caution," Data said from behind him, his golden eyes scanning the tricorder readings. "The energy signature is unlike anything in our database." | ||
| 8 | + | ||
| 9 | +Picard's lips curved into a slight smile. "Mr. Data, in my experience, the most profound discoveries often lie beyond the boundaries of our databases." | ||
| 10 | + | ||
| 11 | +They were deep within the ruins of Kataan—not the Kataan of his inner light experience, but its sister colony, hidden for millennia beneath the ice sheets of Delta Sigma IV. The Federation archaeological survey had discovered it three weeks ago, and Picard had been unable to resist the opportunity to lead the away team himself. | ||
| 12 | + | ||
| 13 | +"This script," Picard murmured, tracing the air above the inscriptions that spiraled around the artifact's base, "is Kataan, but it's... older. More refined than what I learned." | ||
| 14 | + | ||
| 15 | +He closed his eyes, and for a moment, he was Kamin again—the memories of that life as vivid as his actual past. The flute music, the sun on his face, Eline's laugh. A life lived in forty minutes that had shaped him forever. | ||
| 16 | + | ||
| 17 | +"It's a beacon," Picard said suddenly, his eyes opening. "Not a warning, but an invitation. The Kataan people knew their sun was dying. They sent out their culture, their memories, in multiple forms. We found one—the probe that found me. But this... this is something more." | ||
| 18 | + | ||
| 19 | +"More?" Commander Riker's voice crackled through the comm badge. "Captain, you're already talking about a civilization that downloaded an entire lifetime into your brain. What could be 'more' than that?" | ||
| 20 | + | ||
| 21 | +Picard's hand finally made contact with the artifact. The amber light exploded into a cascade of images—not memories this time, but pure information. Mathematics. Philosophy. Art. The complete accumulated knowledge of a civilization. | ||
| 22 | + | ||
| 23 | +"Number One," Picard said, his voice thick with emotion, "prepare to download approximately four hundred exabytes of data. The Kataan didn't just want to be remembered—they wanted to teach. This is their university, their library, their gift to whoever would listen." | ||
| 24 | + | ||
| 25 | +As Data began the careful transfer, Picard stood back, one hand unconsciously moving to his uniform jacket pocket where he kept Kamin's flute. He had been given a life once by the Kataan people. Now, they were giving him—giving humanity—the tools to understand that life and countless others. | ||
| 26 | + | ||
| 27 | +"Make it so," he whispered to himself, a small smile playing at the corners of his mouth. | ||
| 28 | + | ||
| 29 | +The Enterprise would be here for weeks, perhaps months, cataloging this discovery. And for once, Jean-Luc Picard, who had always believed that to boldly go meant to leave and explore further, was content to stay still and listen to the voices of the past. | ||
| 30 | + | ||
| 31 | +--- | ||
| 32 | + | ||
| 33 | +*Captain's Log, Supplemental: The Kataan archive is beyond anything I imagined. In seeking to preserve themselves, they may have given us the key to understanding dozens of lost civilizations. I find myself wondering: how many other ancient peoples left such gifts among the stars, waiting for someone to stop and listen? Perhaps the greatest exploration is not in discovering new worlds, but in understanding those that came before us.* | ||
added
demo/sbx-docker-summary.adoc +294 -0 | new file mode 100644 | ||
| @@ -0,0 +1,294 @@ | ||
| 1 | += SBX: Docker Sandbox Environment | |
| 2 | +:toc: left | |
| 3 | +:toclevels: 3 | |
| 4 | +:sectnums: | |
| 5 | +:icons: font | |
| 6 | + | |
| 7 | +== Overview | |
| 8 | + | |
| 9 | +SBX is Docker's sandboxed environment system that provides isolated, persistent development containers with controlled network access, environment persistence, and Git integration. It enables secure development workflows with fine-grained policy control. | |
| 10 | + | |
| 11 | +== Core Features | |
| 12 | + | |
| 13 | +=== Environment Persistence | |
| 14 | + | |
| 15 | +SBX provides a persistent environment file at `/etc/sandbox-persistent.sh` that is automatically sourced across all shell contexts: | |
| 16 | + | |
| 17 | +* **Non-interactive shells**: via `BASH_ENV=/etc/sandbox-persistent.sh` | |
| 18 | +* **Login shells**: via `/etc/profile.d/sandbox-persistent.sh` | |
| 19 | +* **Interactive shells**: via `/etc/bash.bashrc` and `~/.bashrc` | |
| 20 | + | |
| 21 | +.Adding Persistent Variables | |
| 22 | +[source,bash] | |
| 23 | +---- | |
| 24 | +echo "export VAR_NAME=value" >> /etc/sandbox-persistent.sh | |
| 25 | +---- | |
| 26 | + | |
| 27 | +[IMPORTANT] | |
| 28 | +==== | |
| 29 | +**Never add shell completion scripts to `/etc/sandbox-persistent.sh`**. Completion scripts break the bash tool because the persistent file is sourced before every command execution, not just during initialization. Only add core initialization scripts (like `nvm.sh` or `sdkman-init.sh`), never completion scripts (like `bash_completion`). | |
| 30 | +==== | |
| 31 | + | |
| 32 | +=== Network Access and Security | |
| 33 | + | |
| 34 | +SBX includes a firewall that restricts outbound network access with policy-based controls. | |
| 35 | + | |
| 36 | +==== Blocked Request Handling | |
| 37 | + | |
| 38 | +Blocked HTTP/HTTPS requests return **HTTP 403** with structured explanations: | |
| 39 | + | |
| 40 | +[horizontal] | |
| 41 | +Blocked by local rule:: A developer-added deny rule (global or per-sandbox) is blocking the host | |
| 42 | +Blocked by org policy:: Centralized organization policy enforcement | |
| 43 | +No matching allow rule:: Domain not on any allow list (default deny) | |
| 44 | + | |
| 45 | +.Inspecting Connection Policy | |
| 46 | +[source,bash] | |
| 47 | +---- | |
| 48 | +sbx policy log # Shows host, rule, reason, last-seen time | |
| 49 | +sbx policy ls # Shows active rules and suppressed rules | |
| 50 | +---- | |
| 51 | + | |
| 52 | +.Allowing Network Access | |
| 53 | +[source,bash] | |
| 54 | +---- | |
| 55 | +sbx policy allow network <domain>[,<domain>…] # Allow specific domains | |
| 56 | +sbx policy allow network "**" # Allow all (not on denylist) | |
| 57 | +---- | |
| 58 | + | |
| 59 | +.Removing Deny Rules | |
| 60 | +[source,bash] | |
| 61 | +---- | |
| 62 | +sbx policy rm network --resource <host> # Remove global deny | |
| 63 | +sbx policy rm network --sandbox <sandbox> --resource <host> # Remove sandbox-scoped deny | |
| 64 | +---- | |
| 65 | + | |
| 66 | +==== Port Publishing | |
| 67 | + | |
| 68 | +Services in the sandbox are not directly accessible from the host. To expose ports: | |
| 69 | + | |
| 70 | +[source,bash] | |
| 71 | +---- | |
| 72 | +sbx ports <sandbox-name> --publish [[HOST_IP:]HOST_PORT:]SANDBOX_PORT[/PROTOCOL] | |
| 73 | +---- | |
| 74 | + | |
| 75 | +.Example: Publishing Web Server | |
| 76 | +[source,bash] | |
| 77 | +---- | |
| 78 | +sbx ports <sandbox-name> --publish 8080:8080/tcp | |
| 79 | +sbx ports <sandbox-name> # List published ports | |
| 80 | +sbx ports <sandbox-name> --unpublish 8080:8080/tcp # Unpublish | |
| 81 | +---- | |
| 82 | + | |
| 83 | +[NOTE] | |
| 84 | +==== | |
| 85 | +Services must listen on the `eth0` interface (not just `127.0.0.1`). Bind to `0.0.0.0` (IPv4) or `::` (IPv6) to be reachable via port publishing. | |
| 86 | +==== | |
| 87 | + | |
| 88 | +==== Accessing Host Services | |
| 89 | + | |
| 90 | +The sandbox has its own `localhost`. To reach services on the host machine: | |
| 91 | + | |
| 92 | +[source,bash] | |
| 93 | +---- | |
| 94 | +curl http://host.docker.internal:3000 | |
| 95 | +---- | |
| 96 | + | |
| 97 | +==== IP Stack Configuration | |
| 98 | + | |
| 99 | +If connectivity fails, the proxy may be using the wrong IP protocol version. Configure with: | |
| 100 | + | |
| 101 | +[source,bash] | |
| 102 | +---- | |
| 103 | +DOCKER_SANDBOXES_IP_STACK=ipv4only # Only IPv4 | |
| 104 | +DOCKER_SANDBOXES_IP_STACK=ipv6only # Only IPv6 | |
| 105 | +DOCKER_SANDBOXES_IP_STACK=dual-stack # Try both (may be slow if one fails) | |
| 106 | +---- | |
| 107 | + | |
| 108 | +==== .NET Aspire IPv6 Workaround | |
| 109 | + | |
| 110 | +.NET Aspire's DCP uses bracketed IPv6 loopback `http://[::1]:<port>`. Add to `NO_PROXY`: | |
| 111 | + | |
| 112 | +[source,bash] | |
| 113 | +---- | |
| 114 | +cat >> /etc/sandbox-persistent.sh <<'EOF' | |
| 115 | +if [ -z "${SBX_ASPIRE_NOPROXY_DONE:-}" ]; then | |
| 116 | + export NO_PROXY="${NO_PROXY:+$NO_PROXY,}[::1]" | |
| 117 | + export no_proxy="$NO_PROXY" | |
| 118 | + export SBX_ASPIRE_NOPROXY_DONE=1 | |
| 119 | +fi | |
| 120 | +EOF | |
| 121 | +---- | |
| 122 | + | |
| 123 | +=== Git Integration | |
| 124 | + | |
| 125 | +==== Authentication | |
| 126 | + | |
| 127 | +The sandbox proxy handles GitHub authentication automatically by injecting credentials for HTTPS Git operations. No need to run `gh auth login` inside the sandbox. | |
| 128 | + | |
| 129 | +[IMPORTANT] | |
| 130 | +==== | |
| 131 | +`gh auth status` will show "not logged in" inside the sandbox. This is expected and does not affect Git operations. | |
| 132 | +==== | |
| 133 | + | |
| 134 | +.Configuring GitHub Token | |
| 135 | +[source,bash] | |
| 136 | +---- | |
| 137 | +# For existing sandbox (immediate effect) | |
| 138 | +sbx secret set github --sandbox <sandbox-name> -t "$(gh auth token)" | |
| 139 | + | |
| 140 | +# Globally for all future sandboxes (requires recreate) | |
| 141 | +sbx secret set github -t "$(gh auth token)" | |
| 142 | +---- | |
| 143 | + | |
| 144 | +[TIP] | |
| 145 | +==== | |
| 146 | +Find the sandbox name using `$SANDBOX_NAME`, `hostname`, or the deprecated `$SANDBOX_VM_ID` inside the sandbox. | |
| 147 | +==== | |
| 148 | + | |
| 149 | +==== Git Workspace Modes | |
| 150 | + | |
| 151 | +SBX supports two workspace modes. Check your mode: | |
| 152 | + | |
| 153 | +[source,bash] | |
| 154 | +---- | |
| 155 | +if [ -d /run/sandbox/source ]; then echo "clone mode"; else echo "direct mode"; fi | |
| 156 | +---- | |
| 157 | + | |
| 158 | +===== Direct Mode (Default) | |
| 159 | + | |
| 160 | +The host working tree is mounted directly. Edits, commits, and branches appear on the host **immediately**. No separate copy to sync. | |
| 161 | + | |
| 162 | +===== Clone Mode (`--clone`) | |
| 163 | + | |
| 164 | +A standalone Git clone made at sandbox creation time: | |
| 165 | + | |
| 166 | +* **HEAD** matches the host repo's state at creation | |
| 167 | +* **Commits stay in sandbox** until fetched by the host | |
| 168 | +* **Host fetches with**: `git fetch sandbox-<name>` | |
| 169 | +* **Read-only host mount** at `/run/sandbox/source` | |
| 170 | + | |
| 171 | +.Syncing from Host in Clone Mode | |
| 172 | +[source,bash] | |
| 173 | +---- | |
| 174 | +git fetch /run/sandbox/source # Fetch host commits | |
| 175 | +git log HEAD..FETCH_HEAD --oneline # See what's new on host | |
| 176 | +git pull /run/sandbox/source <branch> # Merge host branch | |
| 177 | +---- | |
| 178 | + | |
| 179 | +.Host Retrieving Sandbox Commits | |
| 180 | +[source,bash] | |
| 181 | +---- | |
| 182 | +git fetch sandbox-<name> # On host machine | |
| 183 | +---- | |
| 184 | + | |
| 185 | +[WARNING] | |
| 186 | +==== | |
| 187 | +Commits not pushed to a remote (like GitHub) are lost if the sandbox is removed, as the git-daemon only runs while the sandbox is active. | |
| 188 | +==== | |
| 189 | + | |
| 190 | +==== Pushing and Pull Requests | |
| 191 | + | |
| 192 | +Push and open PRs **directly from inside the sandbox**: | |
| 193 | + | |
| 194 | +[source,bash] | |
| 195 | +---- | |
| 196 | +git remote -v # Check available remotes | |
| 197 | +git checkout -b <branch> # Create working branch | |
| 198 | +git add -A && git commit -m "…" | |
| 199 | +git push -u origin <branch> # Push to mirrored remote | |
| 200 | +gh pr create --fill # Create PR | |
| 201 | +---- | |
| 202 | + | |
| 203 | +.Pushing to Fork | |
| 204 | +[source,bash] | |
| 205 | +---- | |
| 206 | +git push -u <fork-remote> <branch> | |
| 207 | +gh pr create --repo <org>/<repo> --head <fork-user>:<branch> --fill | |
| 208 | +---- | |
| 209 | + | |
| 210 | +== Claude Code Integration | |
| 211 | + | |
| 212 | +=== Environment File | |
| 213 | + | |
| 214 | +The `CLAUDE_ENV_FILE` variable is set to `/etc/sandbox-persistent.sh`, which is sourced before each Bash command execution, ensuring environment persistence across tool invocations. | |
| 215 | + | |
| 216 | +[CAUTION] | |
| 217 | +==== | |
| 218 | +Apply the same shell completion restriction: never add completion scripts to this file, as it's sourced before every command, not just shell initialization. | |
| 219 | +==== | |
| 220 | + | |
| 221 | +=== Using the Bash Tool | |
| 222 | + | |
| 223 | +When tools are not found in PATH after installation: | |
| 224 | + | |
| 225 | +[source,bash] | |
| 226 | +---- | |
| 227 | +bash -l -c "your-command" # Use login shell | |
| 228 | +bash -l -c "java -version" # Example: SDKMAN-installed Java | |
| 229 | +bash -l -c "node --version" # Example: NVM-installed Node | |
| 230 | +---- | |
| 231 | + | |
| 232 | +[TIP] | |
| 233 | +==== | |
| 234 | +Login shells always source the persistent environment file fresh, ensuring the latest configuration is honored even if shell snapshots contain cached state. | |
| 235 | +==== | |
| 236 | + | |
| 237 | +== Kits System | |
| 238 | + | |
| 239 | +SBX supports installable "kits" that provide specialized functionality. Kit documentation is available under `/Users/k33g/kDrive/Rickub/bots-garden/kits-agent-context/` and should be read only when relevant to the task. | |
| 240 | + | |
| 241 | +.Example: Ori Kit | |
| 242 | +The `ori` kit provides an ACP web client for Claude Code, serving a browser-based interface with: | |
| 243 | + | |
| 244 | +* React SPA with Zed-style agent panel | |
| 245 | +* Workspace panel with file tree and Monaco editor | |
| 246 | +* Interactive terminal | |
| 247 | +* Markdown and AsciiDoc rendering | |
| 248 | + | |
| 249 | +== Common Operations | |
| 250 | + | |
| 251 | +=== Troubleshooting Connectivity | |
| 252 | + | |
| 253 | +.Check Host IP Addresses | |
| 254 | +[source,bash] | |
| 255 | +---- | |
| 256 | +# macOS | |
| 257 | +ifconfig | grep 'inet ' # IPv4 | |
| 258 | +ifconfig | grep 'inet6 ' # IPv6 (ignore fe80::) | |
| 259 | + | |
| 260 | +# Linux | |
| 261 | +ip -4 addr show scope global | |
| 262 | +ip -6 addr show scope global | |
| 263 | +---- | |
| 264 | + | |
| 265 | +=== Managing Secrets | |
| 266 | + | |
| 267 | +[source,bash] | |
| 268 | +---- | |
| 269 | +sbx secret set <name> --sandbox <sandbox-name> -t "value" # Per-sandbox | |
| 270 | +sbx secret set <name> -t "value" # Global | |
| 271 | +---- | |
| 272 | + | |
| 273 | +=== Docker Network Access | |
| 274 | + | |
| 275 | +Direct access to container ports requires adding the container's network to the `no_proxy` configuration, as Docker daemon access is provided but port routing needs explicit configuration. | |
| 276 | + | |
| 277 | +== Best Practices | |
| 278 | + | |
| 279 | +[arabic] | |
| 280 | +. **Never add shell completions to persistent environment files** - only core initialization | |
| 281 | +. **Use login shells (`bash -l -c`)** when tools aren't found after installation | |
| 282 | +. **Bind services to `0.0.0.0` or `::`** not just `127.0.0.1` for port publishing | |
| 283 | +. **Use `host.docker.internal`** to access host services, not `localhost` | |
| 284 | +. **Push and create PRs from inside the sandbox** - it's the authorized workflow | |
| 285 | +. **Set IP stack explicitly** if dual-stack causes slow connections | |
| 286 | +. **Configure GitHub tokens as sandbox secrets** for Git push operations | |
| 287 | + | |
| 288 | +== References | |
| 289 | + | |
| 290 | +* Sandbox policy management: `sbx policy` | |
| 291 | +* Port publishing: `sbx ports` | |
| 292 | +* Secret management: `sbx secret` | |
| 293 | +* Git authentication: Automatic via proxy credential injection | |
| 294 | +* Environment persistence: `/etc/sandbox-persistent.sh` | |
| new file mode 100644 | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | += SBX: Docker Sandbox Environment | ||
| 2 | +:toc: left | ||
| 3 | +:toclevels: 3 | ||
| 4 | +:sectnums: | ||
| 5 | +:icons: font | ||
| 6 | + | ||
| 7 | +== Overview | ||
| 8 | + | ||
| 9 | +SBX is Docker's sandboxed environment system that provides isolated, persistent development containers with controlled network access, environment persistence, and Git integration. It enables secure development workflows with fine-grained policy control. | ||
| 10 | + | ||
| 11 | +== Core Features | ||
| 12 | + | ||
| 13 | +=== Environment Persistence | ||
| 14 | + | ||
| 15 | +SBX provides a persistent environment file at `/etc/sandbox-persistent.sh` that is automatically sourced across all shell contexts: | ||
| 16 | + | ||
| 17 | +* **Non-interactive shells**: via `BASH_ENV=/etc/sandbox-persistent.sh` | ||
| 18 | +* **Login shells**: via `/etc/profile.d/sandbox-persistent.sh` | ||
| 19 | +* **Interactive shells**: via `/etc/bash.bashrc` and `~/.bashrc` | ||
| 20 | + | ||
| 21 | +.Adding Persistent Variables | ||
| 22 | +[source,bash] | ||
| 23 | +---- | ||
| 24 | +echo "export VAR_NAME=value" >> /etc/sandbox-persistent.sh | ||
| 25 | +---- | ||
| 26 | + | ||
| 27 | +[IMPORTANT] | ||
| 28 | +==== | ||
| 29 | +**Never add shell completion scripts to `/etc/sandbox-persistent.sh`**. Completion scripts break the bash tool because the persistent file is sourced before every command execution, not just during initialization. Only add core initialization scripts (like `nvm.sh` or `sdkman-init.sh`), never completion scripts (like `bash_completion`). | ||
| 30 | +==== | ||
| 31 | + | ||
| 32 | +=== Network Access and Security | ||
| 33 | + | ||
| 34 | +SBX includes a firewall that restricts outbound network access with policy-based controls. | ||
| 35 | + | ||
| 36 | +==== Blocked Request Handling | ||
| 37 | + | ||
| 38 | +Blocked HTTP/HTTPS requests return **HTTP 403** with structured explanations: | ||
| 39 | + | ||
| 40 | +[horizontal] | ||
| 41 | +Blocked by local rule:: A developer-added deny rule (global or per-sandbox) is blocking the host | ||
| 42 | +Blocked by org policy:: Centralized organization policy enforcement | ||
| 43 | +No matching allow rule:: Domain not on any allow list (default deny) | ||
| 44 | + | ||
| 45 | +.Inspecting Connection Policy | ||
| 46 | +[source,bash] | ||
| 47 | +---- | ||
| 48 | +sbx policy log # Shows host, rule, reason, last-seen time | ||
| 49 | +sbx policy ls # Shows active rules and suppressed rules | ||
| 50 | +---- | ||
| 51 | + | ||
| 52 | +.Allowing Network Access | ||
| 53 | +[source,bash] | ||
| 54 | +---- | ||
| 55 | +sbx policy allow network <domain>[,<domain>…] # Allow specific domains | ||
| 56 | +sbx policy allow network "**" # Allow all (not on denylist) | ||
| 57 | +---- | ||
| 58 | + | ||
| 59 | +.Removing Deny Rules | ||
| 60 | +[source,bash] | ||
| 61 | +---- | ||
| 62 | +sbx policy rm network --resource <host> # Remove global deny | ||
| 63 | +sbx policy rm network --sandbox <sandbox> --resource <host> # Remove sandbox-scoped deny | ||
| 64 | +---- | ||
| 65 | + | ||
| 66 | +==== Port Publishing | ||
| 67 | + | ||
| 68 | +Services in the sandbox are not directly accessible from the host. To expose ports: | ||
| 69 | + | ||
| 70 | +[source,bash] | ||
| 71 | +---- | ||
| 72 | +sbx ports <sandbox-name> --publish [[HOST_IP:]HOST_PORT:]SANDBOX_PORT[/PROTOCOL] | ||
| 73 | +---- | ||
| 74 | + | ||
| 75 | +.Example: Publishing Web Server | ||
| 76 | +[source,bash] | ||
| 77 | +---- | ||
| 78 | +sbx ports <sandbox-name> --publish 8080:8080/tcp | ||
| 79 | +sbx ports <sandbox-name> # List published ports | ||
| 80 | +sbx ports <sandbox-name> --unpublish 8080:8080/tcp # Unpublish | ||
| 81 | +---- | ||
| 82 | + | ||
| 83 | +[NOTE] | ||
| 84 | +==== | ||
| 85 | +Services must listen on the `eth0` interface (not just `127.0.0.1`). Bind to `0.0.0.0` (IPv4) or `::` (IPv6) to be reachable via port publishing. | ||
| 86 | +==== | ||
| 87 | + | ||
| 88 | +==== Accessing Host Services | ||
| 89 | + | ||
| 90 | +The sandbox has its own `localhost`. To reach services on the host machine: | ||
| 91 | + | ||
| 92 | +[source,bash] | ||
| 93 | +---- | ||
| 94 | +curl http://host.docker.internal:3000 | ||
| 95 | +---- | ||
| 96 | + | ||
| 97 | +==== IP Stack Configuration | ||
| 98 | + | ||
| 99 | +If connectivity fails, the proxy may be using the wrong IP protocol version. Configure with: | ||
| 100 | + | ||
| 101 | +[source,bash] | ||
| 102 | +---- | ||
| 103 | +DOCKER_SANDBOXES_IP_STACK=ipv4only # Only IPv4 | ||
| 104 | +DOCKER_SANDBOXES_IP_STACK=ipv6only # Only IPv6 | ||
| 105 | +DOCKER_SANDBOXES_IP_STACK=dual-stack # Try both (may be slow if one fails) | ||
| 106 | +---- | ||
| 107 | + | ||
| 108 | +==== .NET Aspire IPv6 Workaround | ||
| 109 | + | ||
| 110 | +.NET Aspire's DCP uses bracketed IPv6 loopback `http://[::1]:<port>`. Add to `NO_PROXY`: | ||
| 111 | + | ||
| 112 | +[source,bash] | ||
| 113 | +---- | ||
| 114 | +cat >> /etc/sandbox-persistent.sh <<'EOF' | ||
| 115 | +if [ -z "${SBX_ASPIRE_NOPROXY_DONE:-}" ]; then | ||
| 116 | + export NO_PROXY="${NO_PROXY:+$NO_PROXY,}[::1]" | ||
| 117 | + export no_proxy="$NO_PROXY" | ||
| 118 | + export SBX_ASPIRE_NOPROXY_DONE=1 | ||
| 119 | +fi | ||
| 120 | +EOF | ||
| 121 | +---- | ||
| 122 | + | ||
| 123 | +=== Git Integration | ||
| 124 | + | ||
| 125 | +==== Authentication | ||
| 126 | + | ||
| 127 | +The sandbox proxy handles GitHub authentication automatically by injecting credentials for HTTPS Git operations. No need to run `gh auth login` inside the sandbox. | ||
| 128 | + | ||
| 129 | +[IMPORTANT] | ||
| 130 | +==== | ||
| 131 | +`gh auth status` will show "not logged in" inside the sandbox. This is expected and does not affect Git operations. | ||
| 132 | +==== | ||
| 133 | + | ||
| 134 | +.Configuring GitHub Token | ||
| 135 | +[source,bash] | ||
| 136 | +---- | ||
| 137 | +# For existing sandbox (immediate effect) | ||
| 138 | +sbx secret set github --sandbox <sandbox-name> -t "$(gh auth token)" | ||
| 139 | + | ||
| 140 | +# Globally for all future sandboxes (requires recreate) | ||
| 141 | +sbx secret set github -t "$(gh auth token)" | ||
| 142 | +---- | ||
| 143 | + | ||
| 144 | +[TIP] | ||
| 145 | +==== | ||
| 146 | +Find the sandbox name using `$SANDBOX_NAME`, `hostname`, or the deprecated `$SANDBOX_VM_ID` inside the sandbox. | ||
| 147 | +==== | ||
| 148 | + | ||
| 149 | +==== Git Workspace Modes | ||
| 150 | + | ||
| 151 | +SBX supports two workspace modes. Check your mode: | ||
| 152 | + | ||
| 153 | +[source,bash] | ||
| 154 | +---- | ||
| 155 | +if [ -d /run/sandbox/source ]; then echo "clone mode"; else echo "direct mode"; fi | ||
| 156 | +---- | ||
| 157 | + | ||
| 158 | +===== Direct Mode (Default) | ||
| 159 | + | ||
| 160 | +The host working tree is mounted directly. Edits, commits, and branches appear on the host **immediately**. No separate copy to sync. | ||
| 161 | + | ||
| 162 | +===== Clone Mode (`--clone`) | ||
| 163 | + | ||
| 164 | +A standalone Git clone made at sandbox creation time: | ||
| 165 | + | ||
| 166 | +* **HEAD** matches the host repo's state at creation | ||
| 167 | +* **Commits stay in sandbox** until fetched by the host | ||
| 168 | +* **Host fetches with**: `git fetch sandbox-<name>` | ||
| 169 | +* **Read-only host mount** at `/run/sandbox/source` | ||
| 170 | + | ||
| 171 | +.Syncing from Host in Clone Mode | ||
| 172 | +[source,bash] | ||
| 173 | +---- | ||
| 174 | +git fetch /run/sandbox/source # Fetch host commits | ||
| 175 | +git log HEAD..FETCH_HEAD --oneline # See what's new on host | ||
| 176 | +git pull /run/sandbox/source <branch> # Merge host branch | ||
| 177 | +---- | ||
| 178 | + | ||
| 179 | +.Host Retrieving Sandbox Commits | ||
| 180 | +[source,bash] | ||
| 181 | +---- | ||
| 182 | +git fetch sandbox-<name> # On host machine | ||
| 183 | +---- | ||
| 184 | + | ||
| 185 | +[WARNING] | ||
| 186 | +==== | ||
| 187 | +Commits not pushed to a remote (like GitHub) are lost if the sandbox is removed, as the git-daemon only runs while the sandbox is active. | ||
| 188 | +==== | ||
| 189 | + | ||
| 190 | +==== Pushing and Pull Requests | ||
| 191 | + | ||
| 192 | +Push and open PRs **directly from inside the sandbox**: | ||
| 193 | + | ||
| 194 | +[source,bash] | ||
| 195 | +---- | ||
| 196 | +git remote -v # Check available remotes | ||
| 197 | +git checkout -b <branch> # Create working branch | ||
| 198 | +git add -A && git commit -m "…" | ||
| 199 | +git push -u origin <branch> # Push to mirrored remote | ||
| 200 | +gh pr create --fill # Create PR | ||
| 201 | +---- | ||
| 202 | + | ||
| 203 | +.Pushing to Fork | ||
| 204 | +[source,bash] | ||
| 205 | +---- | ||
| 206 | +git push -u <fork-remote> <branch> | ||
| 207 | +gh pr create --repo <org>/<repo> --head <fork-user>:<branch> --fill | ||
| 208 | +---- | ||
| 209 | + | ||
| 210 | +== Claude Code Integration | ||
| 211 | + | ||
| 212 | +=== Environment File | ||
| 213 | + | ||
| 214 | +The `CLAUDE_ENV_FILE` variable is set to `/etc/sandbox-persistent.sh`, which is sourced before each Bash command execution, ensuring environment persistence across tool invocations. | ||
| 215 | + | ||
| 216 | +[CAUTION] | ||
| 217 | +==== | ||
| 218 | +Apply the same shell completion restriction: never add completion scripts to this file, as it's sourced before every command, not just shell initialization. | ||
| 219 | +==== | ||
| 220 | + | ||
| 221 | +=== Using the Bash Tool | ||
| 222 | + | ||
| 223 | +When tools are not found in PATH after installation: | ||
| 224 | + | ||
| 225 | +[source,bash] | ||
| 226 | +---- | ||
| 227 | +bash -l -c "your-command" # Use login shell | ||
| 228 | +bash -l -c "java -version" # Example: SDKMAN-installed Java | ||
| 229 | +bash -l -c "node --version" # Example: NVM-installed Node | ||
| 230 | +---- | ||
| 231 | + | ||
| 232 | +[TIP] | ||
| 233 | +==== | ||
| 234 | +Login shells always source the persistent environment file fresh, ensuring the latest configuration is honored even if shell snapshots contain cached state. | ||
| 235 | +==== | ||
| 236 | + | ||
| 237 | +== Kits System | ||
| 238 | + | ||
| 239 | +SBX supports installable "kits" that provide specialized functionality. Kit documentation is available under `/Users/k33g/kDrive/Rickub/bots-garden/kits-agent-context/` and should be read only when relevant to the task. | ||
| 240 | + | ||
| 241 | +.Example: Ori Kit | ||
| 242 | +The `ori` kit provides an ACP web client for Claude Code, serving a browser-based interface with: | ||
| 243 | + | ||
| 244 | +* React SPA with Zed-style agent panel | ||
| 245 | +* Workspace panel with file tree and Monaco editor | ||
| 246 | +* Interactive terminal | ||
| 247 | +* Markdown and AsciiDoc rendering | ||
| 248 | + | ||
| 249 | +== Common Operations | ||
| 250 | + | ||
| 251 | +=== Troubleshooting Connectivity | ||
| 252 | + | ||
| 253 | +.Check Host IP Addresses | ||
| 254 | +[source,bash] | ||
| 255 | +---- | ||
| 256 | +# macOS | ||
| 257 | +ifconfig | grep 'inet ' # IPv4 | ||
| 258 | +ifconfig | grep 'inet6 ' # IPv6 (ignore fe80::) | ||
| 259 | + | ||
| 260 | +# Linux | ||
| 261 | +ip -4 addr show scope global | ||
| 262 | +ip -6 addr show scope global | ||
| 263 | +---- | ||
| 264 | + | ||
| 265 | +=== Managing Secrets | ||
| 266 | + | ||
| 267 | +[source,bash] | ||
| 268 | +---- | ||
| 269 | +sbx secret set <name> --sandbox <sandbox-name> -t "value" # Per-sandbox | ||
| 270 | +sbx secret set <name> -t "value" # Global | ||
| 271 | +---- | ||
| 272 | + | ||
| 273 | +=== Docker Network Access | ||
| 274 | + | ||
| 275 | +Direct access to container ports requires adding the container's network to the `no_proxy` configuration, as Docker daemon access is provided but port routing needs explicit configuration. | ||
| 276 | + | ||
| 277 | +== Best Practices | ||
| 278 | + | ||
| 279 | +[arabic] | ||
| 280 | +. **Never add shell completions to persistent environment files** - only core initialization | ||
| 281 | +. **Use login shells (`bash -l -c`)** when tools aren't found after installation | ||
| 282 | +. **Bind services to `0.0.0.0` or `::`** not just `127.0.0.1` for port publishing | ||
| 283 | +. **Use `host.docker.internal`** to access host services, not `localhost` | ||
| 284 | +. **Push and create PRs from inside the sandbox** - it's the authorized workflow | ||
| 285 | +. **Set IP stack explicitly** if dual-stack causes slow connections | ||
| 286 | +. **Configure GitHub tokens as sandbox secrets** for Git push operations | ||
| 287 | + | ||
| 288 | +== References | ||
| 289 | + | ||
| 290 | +* Sandbox policy management: `sbx policy` | ||
| 291 | +* Port publishing: `sbx ports` | ||
| 292 | +* Secret management: `sbx secret` | ||
| 293 | +* Git authentication: Automatic via proxy credential injection | ||
| 294 | +* Environment persistence: `/etc/sandbox-persistent.sh` | ||
added
demo/seven-story.md +55 -0 | new file mode 100644 | ||
| @@ -0,0 +1,55 @@ | ||
| 1 | +# Frequency of Self | |
| 2 | + | |
| 3 | +**Agent: Riker** | |
| 4 | + | |
| 5 | +Seven of Nine stood in the Voyager's astrometrics lab, surrounded by the comforting precision of stellar cartography. The darkness of the room was punctuated by thousands of glowing data points—stars, nebulae, spatial anomalies—each one catalogued, measured, understood. | |
| 6 | + | |
| 7 | +"You've been here for fourteen hours straight," Kathryn Janeway's voice came from the doorway, gentle but firm. | |
| 8 | + | |
| 9 | +"Efficiency," Seven replied without turning. "I can complete the Astrometrics survey in—" | |
| 10 | + | |
| 11 | +"Seven." Janeway stepped into the star field, her face illuminated by the blue-white glow of a nearby pulsar. "That's not what I asked." | |
| 12 | + | |
| 13 | +Seven's hands stilled on the console. The question Janeway hadn't asked hung in the air between them, as visible as the holographic stars. | |
| 14 | + | |
| 15 | +"I am... struggling with a paradox," Seven finally admitted. | |
| 16 | + | |
| 17 | +Janeway moved to stand beside her, studying the star chart. "Tell me." | |
| 18 | + | |
| 19 | +"The Borg's concept of perfection is mathematical. Absolute. Add complexity, eliminate redundancy, optimize all functions." Seven's voice held that peculiar flatness it took on when she discussed her former Collective. "But humanity's concept of perfection is... contradictory." | |
| 20 | + | |
| 21 | +She pulled up a new display—not stars this time, but a complex probability matrix. "I have analyzed 4,327 human literary works, 12,482 personal logs, and 847 philosophical texts. In 94.3% of cases, humans describe 'perfect' moments that are inefficient, redundant, or even counterproductive." | |
| 22 | + | |
| 23 | +Seven zoomed in on a specific data point. "The Doctor recently described his time singing opera with Ensign Kim as 'perfect,' despite the fact that they made seventeen errors in tempo and pitch. Lieutenant Paris called watching a sunset on an M-class planet 'perfect,' though it served no tactical or scientific purpose. You yourself—" | |
| 24 | + | |
| 25 | +"Called our coffee yesterday morning perfect, even though we were late for the staff meeting," Janeway finished with a smile. | |
| 26 | + | |
| 27 | +"Yes." Seven's hands gripped the edge of the console. "I do not understand how something flawed can be perfect. It is... illogical. And yet..." | |
| 28 | + | |
| 29 | +"And yet?" Janeway prompted gently. | |
| 30 | + | |
| 31 | +Seven's voice dropped to barely above a whisper. "Last night, I helped Naomi Wildman construct a model of a subspace manifold for her science project. We made numerous errors. The scale was incorrect. The materials were inadequate. By any objective measure, it was deeply flawed." | |
| 32 | + | |
| 33 | +She paused, and when she continued, there was something almost vulnerable in her tone. "Naomi said it was 'perfect.' And I... agreed with her." | |
| 34 | + | |
| 35 | +Janeway said nothing, letting the silence stretch. | |
| 36 | + | |
| 37 | +"The Borg were wrong," Seven said finally, the words coming out like a confession. "Perfection is not the elimination of imperfection. It is..." She struggled, her assimilation-trained mind wrestling with concepts that couldn't be reduced to data. "It is finding value in the inefficiency. Meaning in the redundancy. Beauty in the flaw." | |
| 38 | + | |
| 39 | +"You're learning to be human," Janeway said softly. | |
| 40 | + | |
| 41 | +"I am learning that being human is not something one completes," Seven corrected. "It is not a state to be achieved, like optimal efficiency. It is a process. An ongoing... adaptation." | |
| 42 | + | |
| 43 | +She turned to face Janeway fully. "I will never be perfectly human, Captain. I will always be partially Borg. But perhaps that is acceptable. Perhaps perfection is not about eliminating what I was, but about integrating who I am becoming." | |
| 44 | + | |
| 45 | +Janeway reached out and squeezed Seven's shoulder. "That sounds pretty perfect to me." | |
| 46 | + | |
| 47 | +Seven allowed herself a small smile—still rare, still uncertain, but genuine. "Inefficient sentiment. But... appreciated." | |
| 48 | + | |
| 49 | +After Janeway left, Seven returned to her star charts. But before she resumed her work, she did something new. She pulled up an image from the ship's database: the flawed subspace manifold she and Naomi had built, photographed before they'd taken it to the science fair. | |
| 50 | + | |
| 51 | +She added it to her personal files, archived under a new category she created specifically for this purpose: | |
| 52 | + | |
| 53 | +*Imperfect Perfection.* | |
| 54 | + | |
| 55 | +Then Seven of Nine, former Borg drone, current human-in-progress, went back to mapping the stars, secure in the knowledge that sometimes the most important journeys weren't through space at all. | |
| new file mode 100644 | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | +# Frequency of Self | ||
| 2 | + | ||
| 3 | +**Agent: Riker** | ||
| 4 | + | ||
| 5 | +Seven of Nine stood in the Voyager's astrometrics lab, surrounded by the comforting precision of stellar cartography. The darkness of the room was punctuated by thousands of glowing data points—stars, nebulae, spatial anomalies—each one catalogued, measured, understood. | ||
| 6 | + | ||
| 7 | +"You've been here for fourteen hours straight," Kathryn Janeway's voice came from the doorway, gentle but firm. | ||
| 8 | + | ||
| 9 | +"Efficiency," Seven replied without turning. "I can complete the Astrometrics survey in—" | ||
| 10 | + | ||
| 11 | +"Seven." Janeway stepped into the star field, her face illuminated by the blue-white glow of a nearby pulsar. "That's not what I asked." | ||
| 12 | + | ||
| 13 | +Seven's hands stilled on the console. The question Janeway hadn't asked hung in the air between them, as visible as the holographic stars. | ||
| 14 | + | ||
| 15 | +"I am... struggling with a paradox," Seven finally admitted. | ||
| 16 | + | ||
| 17 | +Janeway moved to stand beside her, studying the star chart. "Tell me." | ||
| 18 | + | ||
| 19 | +"The Borg's concept of perfection is mathematical. Absolute. Add complexity, eliminate redundancy, optimize all functions." Seven's voice held that peculiar flatness it took on when she discussed her former Collective. "But humanity's concept of perfection is... contradictory." | ||
| 20 | + | ||
| 21 | +She pulled up a new display—not stars this time, but a complex probability matrix. "I have analyzed 4,327 human literary works, 12,482 personal logs, and 847 philosophical texts. In 94.3% of cases, humans describe 'perfect' moments that are inefficient, redundant, or even counterproductive." | ||
| 22 | + | ||
| 23 | +Seven zoomed in on a specific data point. "The Doctor recently described his time singing opera with Ensign Kim as 'perfect,' despite the fact that they made seventeen errors in tempo and pitch. Lieutenant Paris called watching a sunset on an M-class planet 'perfect,' though it served no tactical or scientific purpose. You yourself—" | ||
| 24 | + | ||
| 25 | +"Called our coffee yesterday morning perfect, even though we were late for the staff meeting," Janeway finished with a smile. | ||
| 26 | + | ||
| 27 | +"Yes." Seven's hands gripped the edge of the console. "I do not understand how something flawed can be perfect. It is... illogical. And yet..." | ||
| 28 | + | ||
| 29 | +"And yet?" Janeway prompted gently. | ||
| 30 | + | ||
| 31 | +Seven's voice dropped to barely above a whisper. "Last night, I helped Naomi Wildman construct a model of a subspace manifold for her science project. We made numerous errors. The scale was incorrect. The materials were inadequate. By any objective measure, it was deeply flawed." | ||
| 32 | + | ||
| 33 | +She paused, and when she continued, there was something almost vulnerable in her tone. "Naomi said it was 'perfect.' And I... agreed with her." | ||
| 34 | + | ||
| 35 | +Janeway said nothing, letting the silence stretch. | ||
| 36 | + | ||
| 37 | +"The Borg were wrong," Seven said finally, the words coming out like a confession. "Perfection is not the elimination of imperfection. It is..." She struggled, her assimilation-trained mind wrestling with concepts that couldn't be reduced to data. "It is finding value in the inefficiency. Meaning in the redundancy. Beauty in the flaw." | ||
| 38 | + | ||
| 39 | +"You're learning to be human," Janeway said softly. | ||
| 40 | + | ||
| 41 | +"I am learning that being human is not something one completes," Seven corrected. "It is not a state to be achieved, like optimal efficiency. It is a process. An ongoing... adaptation." | ||
| 42 | + | ||
| 43 | +She turned to face Janeway fully. "I will never be perfectly human, Captain. I will always be partially Borg. But perhaps that is acceptable. Perhaps perfection is not about eliminating what I was, but about integrating who I am becoming." | ||
| 44 | + | ||
| 45 | +Janeway reached out and squeezed Seven's shoulder. "That sounds pretty perfect to me." | ||
| 46 | + | ||
| 47 | +Seven allowed herself a small smile—still rare, still uncertain, but genuine. "Inefficient sentiment. But... appreciated." | ||
| 48 | + | ||
| 49 | +After Janeway left, Seven returned to her star charts. But before she resumed her work, she did something new. She pulled up an image from the ship's database: the flawed subspace manifold she and Naomi had built, photographed before they'd taken it to the science fair. | ||
| 50 | + | ||
| 51 | +She added it to her personal files, archived under a new category she created specifically for this purpose: | ||
| 52 | + | ||
| 53 | +*Imperfect Perfection.* | ||
| 54 | + | ||
| 55 | +Then Seven of Nine, former Borg drone, current human-in-progress, went back to mapping the stars, secure in the knowledge that sometimes the most important journeys weren't through space at all. | ||
added
kits/.backup/spec.yaml +88 -0 | new file mode 100644 | ||
| @@ -0,0 +1,88 @@ | ||
| 1 | +schemaVersion: "2" | |
| 2 | +kind: mixin | |
| 3 | +name: ori | |
| 4 | +displayName: Ori — ACP web client for Claude Code | |
| 5 | +description: > | |
| 6 | + Starts the ori web server inside the sandbox. Ori is a browser client for | |
| 7 | + ACP (Agent Client Protocol) code agents: a Go backend serves a React SPA | |
| 8 | + (Zed-style agent panel: streamed answers, thoughts, tool calls, plans, | |
| 9 | + permission prompts) plus a workspace panel (file tree with Material icons, | |
| 10 | + Monaco preview/editor with rendered Markdown and AsciiDoc, interactive | |
| 11 | + terminal). This kit only launches and describes the server; the binaries | |
| 12 | + ship in the k33g/ori template image (template/Dockerfile in the ori | |
| 13 | + repository), so use it together with `--template k33g/ori:0.0.1`. | |
| 14 | +licenses: | |
| 15 | + - MIT | |
| 16 | + | |
| 17 | +# This mixin only makes sense composed with the claude agent kit: the server | |
| 18 | +# it starts drives Claude Code through the claude-code-acp adapter, and the | |
| 19 | +# Anthropic credentials/egress come from that kit. | |
| 20 | +requires: | |
| 21 | + agent: claude | |
| 22 | + | |
| 23 | +args: | |
| 24 | + port: | |
| 25 | + default: "8888" | |
| 26 | + description: TCP port the ori server listens on inside the sandbox | |
| 27 | + pattern: "^[0-9]{2,5}$" | |
| 28 | + | |
| 29 | +# No extra network permissions: the Anthropic endpoints come from the claude | |
| 30 | +# agent kit this mixin composes with, and the ACP adapter is baked into the | |
| 31 | +# template image, so nothing is downloaded at runtime. | |
| 32 | + | |
| 33 | +# Auto-publishes an ephemeral localhost port at create (the create output | |
| 34 | +# prints it: "Published web: localhost:<port> -> <port>/tcp"). Pin a fixed | |
| 35 | +# host port instead with `-p 8888:8888` at create or `sbx ports … --publish`. | |
| 36 | +# The unquoted arg reference decodes as the integer the schema expects. | |
| 37 | +ports: | |
| 38 | + - container: ${{ kit.args.port }} | |
| 39 | + protocol: tcp | |
| 40 | + name: web | |
| 41 | + | |
| 42 | +setup: | |
| 43 | + startup: | |
| 44 | + # Startup commands run on every container start through the detached | |
| 45 | + # dispatcher, so the pgrep guard makes this idempotent. The server binds | |
| 46 | + # 0.0.0.0 (empty host in --addr) so published ports reach it from the | |
| 47 | + # host's browser. `user` is omitted: startup commands default to uid 1000, | |
| 48 | + # the agent user. | |
| 49 | + # | |
| 50 | + # The PATH export is load-bearing: the dispatcher runs this via | |
| 51 | + # `su -s /bin/sh -c … agent`, and su resets PATH to the login.defs | |
| 52 | + # default — which does not contain the npm prefix where claude-code-acp | |
| 53 | + # lives, nor ~/.local/bin where claude does. | |
| 54 | + - command: | |
| 55 | + - "sh" | |
| 56 | + - "-c" | |
| 57 | + - | | |
| 58 | + export PATH="/usr/local/share/npm-global/bin:/home/agent/.local/bin:$PATH" | |
| 59 | + pgrep -x ori >/dev/null 2>&1 && exit 0 | |
| 60 | + nohup /usr/local/bin/ori \ | |
| 61 | + --addr ":${{ kit.args.port }}" \ | |
| 62 | + --agent-cmd claude-code-acp \ | |
| 63 | + --cwd "${WORKSPACE_DIR:-/home/agent/workspace}" \ | |
| 64 | + >> /home/agent/.ori.log 2>&1 & | |
| 65 | + description: Start the ori web server (idempotent) | |
| 66 | + | |
| 67 | +agentInstructions: | |
| 68 | + content: | | |
| 69 | + ## Ori web server (kit `ori`) | |
| 70 | + | |
| 71 | + This sandbox runs **ori**, a web client for Claude Code over ACP. It was | |
| 72 | + started automatically and serves on **port ${{ kit.args.port }}** (all | |
| 73 | + interfaces). | |
| 74 | + | |
| 75 | + - Binaries: `/usr/local/bin/ori` (server) and `/usr/local/bin/ori-mock-agent` | |
| 76 | + (a deterministic demo ACP agent that needs no credentials). | |
| 77 | + - Log file: `/home/agent/.ori.log`. | |
| 78 | + - The server drives its own Claude Code session through the | |
| 79 | + `claude-code-acp` adapter (preinstalled); credentials are injected by the | |
| 80 | + sandbox proxy, so no login is needed inside the container. | |
| 81 | + - Restart it with: | |
| 82 | + `pkill -x ori; nohup ori --addr ":${{ kit.args.port }}" --agent-cmd claude-code-acp --cwd "$PWD" >> /home/agent/.ori.log 2>&1 &` | |
| 83 | + - To demo without consuming Claude usage, restart it with | |
| 84 | + `--agent-cmd ori-mock-agent` instead. | |
| 85 | + | |
| 86 | + A localhost port for the UI was published on the host at create time (see | |
| 87 | + the create output); the human can pin a different one with | |
| 88 | + `sbx ports <sandbox-name> --publish <host-port>:${{ kit.args.port }}/tcp`. | |
| new file mode 100644 | |||
| @@ -0,0 +1,88 @@ | |||
| 1 | +schemaVersion: "2" | ||
| 2 | +kind: mixin | ||
| 3 | +name: ori | ||
| 4 | +displayName: Ori — ACP web client for Claude Code | ||
| 5 | +description: > | ||
| 6 | + Starts the ori web server inside the sandbox. Ori is a browser client for | ||
| 7 | + ACP (Agent Client Protocol) code agents: a Go backend serves a React SPA | ||
| 8 | + (Zed-style agent panel: streamed answers, thoughts, tool calls, plans, | ||
| 9 | + permission prompts) plus a workspace panel (file tree with Material icons, | ||
| 10 | + Monaco preview/editor with rendered Markdown and AsciiDoc, interactive | ||
| 11 | + terminal). This kit only launches and describes the server; the binaries | ||
| 12 | + ship in the k33g/ori template image (template/Dockerfile in the ori | ||
| 13 | + repository), so use it together with `--template k33g/ori:0.0.1`. | ||
| 14 | +licenses: | ||
| 15 | + - MIT | ||
| 16 | + | ||
| 17 | +# This mixin only makes sense composed with the claude agent kit: the server | ||
| 18 | +# it starts drives Claude Code through the claude-code-acp adapter, and the | ||
| 19 | +# Anthropic credentials/egress come from that kit. | ||
| 20 | +requires: | ||
| 21 | + agent: claude | ||
| 22 | + | ||
| 23 | +args: | ||
| 24 | + port: | ||
| 25 | + default: "8888" | ||
| 26 | + description: TCP port the ori server listens on inside the sandbox | ||
| 27 | + pattern: "^[0-9]{2,5}$" | ||
| 28 | + | ||
| 29 | +# No extra network permissions: the Anthropic endpoints come from the claude | ||
| 30 | +# agent kit this mixin composes with, and the ACP adapter is baked into the | ||
| 31 | +# template image, so nothing is downloaded at runtime. | ||
| 32 | + | ||
| 33 | +# Auto-publishes an ephemeral localhost port at create (the create output | ||
| 34 | +# prints it: "Published web: localhost:<port> -> <port>/tcp"). Pin a fixed | ||
| 35 | +# host port instead with `-p 8888:8888` at create or `sbx ports … --publish`. | ||
| 36 | +# The unquoted arg reference decodes as the integer the schema expects. | ||
| 37 | +ports: | ||
| 38 | + - container: ${{ kit.args.port }} | ||
| 39 | + protocol: tcp | ||
| 40 | + name: web | ||
| 41 | + | ||
| 42 | +setup: | ||
| 43 | + startup: | ||
| 44 | + # Startup commands run on every container start through the detached | ||
| 45 | + # dispatcher, so the pgrep guard makes this idempotent. The server binds | ||
| 46 | + # 0.0.0.0 (empty host in --addr) so published ports reach it from the | ||
| 47 | + # host's browser. `user` is omitted: startup commands default to uid 1000, | ||
| 48 | + # the agent user. | ||
| 49 | + # | ||
| 50 | + # The PATH export is load-bearing: the dispatcher runs this via | ||
| 51 | + # `su -s /bin/sh -c … agent`, and su resets PATH to the login.defs | ||
| 52 | + # default — which does not contain the npm prefix where claude-code-acp | ||
| 53 | + # lives, nor ~/.local/bin where claude does. | ||
| 54 | + - command: | ||
| 55 | + - "sh" | ||
| 56 | + - "-c" | ||
| 57 | + - | | ||
| 58 | + export PATH="/usr/local/share/npm-global/bin:/home/agent/.local/bin:$PATH" | ||
| 59 | + pgrep -x ori >/dev/null 2>&1 && exit 0 | ||
| 60 | + nohup /usr/local/bin/ori \ | ||
| 61 | + --addr ":${{ kit.args.port }}" \ | ||
| 62 | + --agent-cmd claude-code-acp \ | ||
| 63 | + --cwd "${WORKSPACE_DIR:-/home/agent/workspace}" \ | ||
| 64 | + >> /home/agent/.ori.log 2>&1 & | ||
| 65 | + description: Start the ori web server (idempotent) | ||
| 66 | + | ||
| 67 | +agentInstructions: | ||
| 68 | + content: | | ||
| 69 | + ## Ori web server (kit `ori`) | ||
| 70 | + | ||
| 71 | + This sandbox runs **ori**, a web client for Claude Code over ACP. It was | ||
| 72 | + started automatically and serves on **port ${{ kit.args.port }}** (all | ||
| 73 | + interfaces). | ||
| 74 | + | ||
| 75 | + - Binaries: `/usr/local/bin/ori` (server) and `/usr/local/bin/ori-mock-agent` | ||
| 76 | + (a deterministic demo ACP agent that needs no credentials). | ||
| 77 | + - Log file: `/home/agent/.ori.log`. | ||
| 78 | + - The server drives its own Claude Code session through the | ||
| 79 | + `claude-code-acp` adapter (preinstalled); credentials are injected by the | ||
| 80 | + sandbox proxy, so no login is needed inside the container. | ||
| 81 | + - Restart it with: | ||
| 82 | + `pkill -x ori; nohup ori --addr ":${{ kit.args.port }}" --agent-cmd claude-code-acp --cwd "$PWD" >> /home/agent/.ori.log 2>&1 &` | ||
| 83 | + - To demo without consuming Claude usage, restart it with | ||
| 84 | + `--agent-cmd ori-mock-agent` instead. | ||
| 85 | + | ||
| 86 | + A localhost port for the UI was published on the host at create time (see | ||
| 87 | + the create output); the human can pin a different one with | ||
| 88 | + `sbx ports <sandbox-name> --publish <host-port>:${{ kit.args.port }}/tcp`. | ||
added
kits/ori/publish.kit.md +4 -0 | new file mode 100644 | ||
| @@ -0,0 +1,4 @@ | ||
| 1 | + | |
| 2 | +```bash | |
| 3 | +sbx kit push kits/ori docker.io/k33g/ori-kit:latest | |
| 4 | +``` | |
| \ No newline at end of file | ||
| new file mode 100644 | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | + | ||
| 2 | +```bash | ||
| 3 | +sbx kit push kits/ori docker.io/k33g/ori-kit:latest | ||
| 4 | +``` | ||
| \ No newline at end of file | \ No newline at end of file | ||
modified
quickstart.md +1 -1 | @@ -78,7 +78,7 @@ sbx run -d claude . \ | ||
| 78 | 78 | sbx rm hello-world |
| 79 | 79 | |
| 80 | 80 | sbx run -d claude . \ |
| 81 | - --template k33g/ori:0.0.2 \ | |
| 81 | + --template k33g/ori:0.0.3 \ | |
| 82 | 82 | --kit docker.io/k33g/ori-kit:latest \ |
| 83 | 83 | --name hello-world \ |
| 84 | 84 | -p 5555:8888/tcp |
| @@ -78,7 +78,7 @@ sbx run -d claude . \ | |||
| 78 | sbx rm hello-world | 78 | sbx rm hello-world |
| 79 | 79 | ||
| 80 | sbx run -d claude . \ | 80 | sbx run -d claude . \ |
| 81 | - --template k33g/ori:0.0.2 \ | 81 | + --template k33g/ori:0.0.3 \ |
| 82 | --kit docker.io/k33g/ori-kit:latest \ | 82 | --kit docker.io/k33g/ori-kit:latest \ |
| 83 | --name hello-world \ | 83 | --name hello-world \ |
| 84 | -p 5555:8888/tcp | 84 | -p 5555:8888/tcp |
modified
template/build.sh +1 -1 | @@ -12,7 +12,7 @@ | ||
| 12 | 12 | # docker buildx create --name ori-builder --driver docker-container --use |
| 13 | 13 | set -euo pipefail |
| 14 | 14 | |
| 15 | -VERSION="${1:-0.0.2}" | |
| 15 | +VERSION="${1:-0.0.3}" | |
| 16 | 16 | IMAGE="k33g/ori" |
| 17 | 17 | PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" |
| 18 | 18 | |
| @@ -12,7 +12,7 @@ | |||
| 12 | # docker buildx create --name ori-builder --driver docker-container --use | 12 | # docker buildx create --name ori-builder --driver docker-container --use |
| 13 | set -euo pipefail | 13 | set -euo pipefail |
| 14 | 14 | ||
| 15 | -VERSION="${1:-0.0.2}" | 15 | +VERSION="${1:-0.0.3}" |
| 16 | IMAGE="k33g/ori" | 16 | IMAGE="k33g/ori" |
| 17 | PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" | 17 | PLATFORMS="${PLATFORMS:-linux/amd64,linux/arm64}" |
| 18 | 18 | ||
added
template/publish.template.md +7 -0 | new file mode 100644 | ||
| @@ -0,0 +1,7 @@ | ||
| 1 | + | |
| 2 | + | |
| 3 | +Change `VERSION="${1:-0.0.2}"` in `build.sh`, then | |
| 4 | + | |
| 5 | +```bash | |
| 6 | +./build.sh | |
| 7 | +``` | |
| \ No newline at end of file | ||
| new file mode 100644 | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | + | ||
| 2 | + | ||
| 3 | +Change `VERSION="${1:-0.0.2}"` in `build.sh`, then | ||
| 4 | + | ||
| 5 | +```bash | ||
| 6 | +./build.sh | ||
| 7 | +``` | ||
| \ No newline at end of file | \ No newline at end of file | ||