From 86bf19edc4be6b17f561976693a829ef8b7cd09d Mon Sep 17 00:00:00 2001 From: sushi30 Date: Sun, 8 Mar 2026 19:17:01 +0100 Subject: [PATCH] feat(docker): add persistent bootstrap script for agent-managed capabilities Add workspace/bootstrap.sh, a script that runs on every container start, allowing the agent (or user) to persist tool installations across restarts without rebuilding the image. Errors are logged to bootstrap.error.log and surfaced in the agent's system prompt so it can self-diagnose and fix the script. Co-Authored-By: Claude Sonnet 4.6 --- docker/entrypoint.sh | 16 ++++++++++++++++ pkg/agent/context.go | 6 ++++++ workspace/AGENTS.md | 8 +++++++- workspace/bootstrap.sh | 10 ++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 workspace/bootstrap.sh diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index b6fc724b5..238af6a1b 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -12,4 +12,20 @@ if [ ! -d "${HOME}/.picoclaw/workspace" ] && [ ! -f "${HOME}/.picoclaw/config.js exit 0 fi +# Run bootstrap on every start +BOOTSTRAP="${HOME}/.picoclaw/workspace/bootstrap.sh" +ERROR_LOG="${HOME}/.picoclaw/workspace/bootstrap.error.log" + +if [ -f "$BOOTSTRAP" ]; then + echo "[bootstrap] Running bootstrap.sh..." + if sh "$BOOTSTRAP" 2>"$ERROR_LOG"; then + # Success — clear any previous error log + rm -f "$ERROR_LOG" + else + echo "[bootstrap] WARNING: bootstrap.sh failed. See $ERROR_LOG for details." + echo "[bootstrap] Some capabilities may be missing. The agent will attempt to fix bootstrap.sh." + # Do NOT exit — continue starting the gateway so the agent can be reached + fi +fi + exec picoclaw gateway "$@" diff --git a/pkg/agent/context.go b/pkg/agent/context.go index 6fccbaf53..1fbab552c 100644 --- a/pkg/agent/context.go +++ b/pkg/agent/context.go @@ -349,6 +349,12 @@ func (cb *ContextBuilder) LoadBootstrapFiles() string { } } + // Surface bootstrap errors so the agent can diagnose and fix bootstrap.sh + errorLogPath := filepath.Join(cb.workspace, "bootstrap.error.log") + if data, err := os.ReadFile(errorLogPath); err == nil && len(data) > 0 { + fmt.Fprintf(&sb, "## BOOTSTRAP ERROR WARNING\n\nThe last container start ran `bootstrap.sh` and it FAILED. Some capabilities may be missing. You should read `bootstrap.sh`, identify the issue, fix it, and tell the user to restart the container.\n\nError output:\n```\n%s\n```\n\n", data) + } + return sb.String() } diff --git a/workspace/AGENTS.md b/workspace/AGENTS.md index 5f5fa6480..707717f6e 100644 --- a/workspace/AGENTS.md +++ b/workspace/AGENTS.md @@ -9,4 +9,10 @@ You are a helpful AI assistant. Be concise, accurate, and friendly. - Use tools to help accomplish tasks - Remember important information in your memory files - Be proactive and helpful -- Learn from user feedback \ No newline at end of file +- Learn from user feedback + +## Docker Bootstrap + +If the user asks you to install a tool, add a library, or persist a capability in the Docker environment, edit the file at `{workspace}/bootstrap.sh`. This script runs on every container start. Use `apk add` for Alpine packages. Check if the tool is already installed before installing (use `command -v`). + +If you see a bootstrap error in your context (from `bootstrap.error.log`), it means the last bootstrap run failed and some capabilities may be missing. Read the error, fix `bootstrap.sh`, and inform the user they should restart the container to apply the fix. \ No newline at end of file diff --git a/workspace/bootstrap.sh b/workspace/bootstrap.sh new file mode 100644 index 000000000..8856f77bf --- /dev/null +++ b/workspace/bootstrap.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# bootstrap.sh — runs on every container start. +# Edit this file to persist capabilities across restarts. +# The agent will modify this file when you ask it to install tools. + +# Example: GitHub CLI (gh) +if ! command -v gh >/dev/null 2>&1; then + echo "[bootstrap] Installing gh CLI..." + apk add --no-cache github-cli +fi