← Commit history

Add adompkg installer files

Kyle Bergstedt ·67a0f68208 ·4mo ago ·parent 44ef3e5
5 files changed +192−1
README.md+1−1
@@ -162,4 +162,4 @@ Container Conduit registers with the Gallia auto-start system via `service.json` | Permission denied on `/opt/container-conduit` | Script not run with sudo | Use `sudo -E bash` to preserve env vars | | Dashboard shows 0 containers | API URL detection fails | Restart MCP server (it injects `__CONDUIT_API_BASE__`) | | PTY timeout on Connect | Agent running old code | Restart agent with updated `agent.js` |-| Shell tab WebSocket error | Port 8801 not reachable via proxy | Ensure `server.js` binds 8801 to `0.0.0.0` |\ No newline at end of file+| Shell tab WebSocket error | Port 8801 not reachable via proxy | Ensure `server.js` binds 8801 to `0.0.0.0` |
SKILL.mdadded+161
@@ -0,0 +1,161 @@+---+name: container-conduit+author: Noah+description: "Use when the user wants to manage remote containers via Container Conduit — connecting satellite containers, running commands remotely, transferring files, opening interactive PTY shells, viewing the Conduit dashboard, or installing the Conduit agent on new containers. Covers the WebSocket bridge between a main Gallia container and satellite Adom containers."+---++# Container Conduit++Container Conduit is a WebSocket bridge that connects a main Gallia container to one or more satellite Adom containers. It enables remote command execution, file transfer, system status queries, and interactive PTY terminal sessions — all from Claude Code or the Gallia Viewer dashboard.++## Architecture++```+Main Container (Gallia)                  Satellite Container(s)+  server.js (WS port 8800)  ←──WS──→  agent.js+  HTTP API  (port 8801)                   ↑+       ↑                              install.sh (bootstrap)+  MCP tools (mcp/server.js)+       ↑+  Claude Code / Dashboard+```++- **server.js** — WebSocket server on port 8800 that accepts agent connections, plus an HTTP API on port 8801 for MCP tools and the dashboard+- **agent.js** — Lightweight satellite agent that connects back to the main container and handles exec, file, status, and PTY commands+- **mcp/server.js** — MCP stdio server exposing Container Conduit tools to Claude Code+- **dashboard.html** — Interactive management dashboard displayed in Gallia Viewer with Shell (xterm.js), Terminal, and Prompts tabs++## Key Files++| File | Location | Purpose |+|------|----------|---------|+| `server.js` | `services/container-conduit/server.js` | Main WS+HTTP server |+| `agent.js` | `services/container-conduit/agent/agent.js` | Satellite agent |+| `install.sh` | `services/container-conduit/agent/install.sh` | One-line agent bootstrap |+| `mcp/server.js` | `services/container-conduit/mcp/server.js` | MCP tool definitions |+| `dashboard.html` | `services/container-conduit/dashboard.html` | GV management dashboard |+| `service.json` | `services/container-conduit/service.json` | Auto-start manifest |++## MCP Tools++All tools are prefixed `container_` in the MCP server:++| Tool | Description |+|------|-------------|+| `container_list` | List all connected satellite containers |+| `container_exec` | Execute a shell command on a specific container |+| `container_exec_all` | Execute a command on ALL connected containers |+| `container_file_read` | Read a file from a remote container (base64) |+| `container_file_write` | Write a file to a remote container (base64) |+| `container_file_list` | List directory contents on a remote container |+| `container_status` | Get system status (memory, disk, uptime) of a container |+| `container_kick` | Disconnect a container (it will auto-reconnect) |+| `container_shell_start` | Start a persistent interactive shell session (returns sessionId) |+| `container_shell_exec` | Run a command in a persistent shell (state persists across calls) |+| `container_shell_stop` | Stop a persistent shell session |+| `container_dashboard` | Display the Conduit dashboard in Gallia Viewer |+| `container_create` | Create a new Adom container (repo + curium + container) |+| `container_install_cmd` | Generate the one-liner install command for a satellite |++## Installing the Agent on a Satellite Container++### One-liner install (direct network)++```bash+curl -sL http://<MAIN_IP>:8800/agent/install | CC_NAME=my-service bash+```++### Proxy install (Coder proxy for cross-container communication)++```bash+curl -sL https://coder.<SLUG>.containers.adom.inc/proxy/8800/agent/install | \+  CC_BASE_URL=https://coder.<SLUG>.containers.adom.inc/proxy/8800 \+  CC_NAME=my-service sudo -E bash+```++The install script:+1. Creates `/opt/container-conduit/` owned by `adom`+2. Downloads `agent.js` and `package.json` from the main container+3. Runs `npm install`+4. Writes `config.json` with WebSocket URL and token+5. Starts the agent from `~/project`+6. Adds a cron `@reboot` entry for auto-start++### Environment variables++| Variable | Default | Description |+|----------|---------|-------------|+| `CC_HOST` | (required) | Main container IP |+| `CC_PORT` | `8800` | Main container WS port |+| `CC_TOKEN` | `adom-container-token-2025` | Authentication token |+| `CC_NAME` | `$(hostname)` | Container name shown in dashboard |+| `CC_BASE_URL` | `http://$CC_HOST:$CC_PORT` | Override download URL (for proxy setups) |+| `CC_WS_URL` | auto-detected | Override WebSocket URL (e.g. `wss://...`) |++## Dashboard (Gallia Viewer)++Open the dashboard via MCP tool:++```+container_dashboard()+```++The dashboard has three tabs:++1. **Shell** — Interactive xterm.js terminal connected to a remote container via PTY WebSocket relay. Supports full TTY (nano, vim, htop, etc.)+2. **Terminal** — Simple command execution with output display (non-interactive)+3. **Claude Prompts** — Pre-built prompts for common container management tasks++The left panel shows all connected containers with name, hostname, IP, capabilities, and connection age.++## Persistent Shell Sessions (MCP)++The `container_shell_*` tools give Claude Code a persistent interactive shell on any satellite container. Unlike `container_exec` (which spawns a new process per call), shell sessions preserve state:++```+container_shell_start("service-test1")  → sessionId+container_shell_exec(sessionId, "cd /tmp")+container_shell_exec(sessionId, "pwd")  → /tmp  (cwd persists!)+container_shell_exec(sessionId, "export FOO=bar")+container_shell_exec(sessionId, "echo $FOO")  → bar  (env vars persist!)+container_shell_stop(sessionId)+```++**How it works:** The server spawns a PTY on the agent, then wraps each command with SOH-byte sentinel markers to detect completion and extract output. Sessions auto-cleanup after 30 minutes of inactivity.++## PTY Terminal (Dashboard)++The Shell tab provides a full interactive terminal via:++```+Dashboard (xterm.js) → WS port 8801 /pty → server.js relay → agent.js → script -qfc 'bash -i' /dev/null+```++The agent uses `script` to allocate a real PTY without requiring `node-pty`. This supports curses-based applications (nano, vim, htop, etc.).++## Auto-Start++The `service.json` manifest registers Container Conduit with the gallia auto-start system:++```json+{+  "name": "container-conduit",+  "port": 8800,+  "health": "tcp",+  "start": "node server.js",+  "cwd": "."+}+```++Both `gallia-start.sh` and `gallia-watchdog.sh` auto-discover this manifest. The server starts on boot and restarts automatically if it crashes.++## Troubleshooting++| Symptom | Cause | Fix |+|---------|-------|-----|+| Agent can't connect | Internal hostname not routable between containers | Use `CC_BASE_URL` with the Coder proxy URL |+| `\r': command not found` during install | CRLF line endings in agent files | Run `sed -i 's/\r$//' /opt/container-conduit/agent.js` |+| Permission denied on `/opt/container-conduit` | Script not run with sudo | Use `sudo -E bash` to preserve env vars |+| Dashboard shows 0 containers | API URL detection fails in srcdoc iframe | MCP server injects `__CONDUIT_API_BASE__` — restart MCP if stale |+| PTY timeout on Connect | Agent running old code without PTY support | Restart agent with updated `agent.js` |+| Shell tab WebSocket error | Port 8801 not reachable via proxy | Ensure `server.js` binds 8801 to `0.0.0.0` |
install.shadded+15
@@ -0,0 +1,15 @@+#!/bin/bash+set -e+PKG_DIR="$(cd "$(dirname "$0")" && pwd)"+SKILLS_DIR="$HOME/.claude/skills"+mkdir -p "$SKILLS_DIR/container-conduit"+if [ -f "$PKG_DIR/SKILL.md" ]; then+  cp "$PKG_DIR/SKILL.md" "$SKILLS_DIR/container-conduit/SKILL.md"+fi+for skill_dir in "$PKG_DIR/skills"/*/; do+  [ -d "$skill_dir" ] || continue+  skill_name=$(basename "$skill_dir")+  mkdir -p "$SKILLS_DIR/$skill_name"+  cp -r "$skill_dir"* "$SKILLS_DIR/$skill_name/"+done+echo "Installed container-conduit"
package.jsonadded+11
@@ -0,0 +1,11 @@+{+  "slug": "container-conduit",+  "version": "1.0.0",+  "type": "skill",+  "description": "WebSocket bridge connecting a main Gallia container to satellite Adom containers — remote command execution, persistent shell sessions, file transfer, system monitoring, and an interactive terminal ",+  "dependencies": {},+  "scripts": {+    "install": "./install.sh",+    "uninstall": "./uninstall.sh"+  }+}
uninstall.shadded+4
@@ -0,0 +1,4 @@+#!/bin/bash+set -e+rm -rf "$HOME/.claude/skills/container-conduit"+echo "Uninstalled container-conduit"