From 26ce9aa490a335c96cf7b4e468a636a035d80c08 Mon Sep 17 00:00:00 2001 From: Joakim Persson Date: Sat, 2 May 2026 22:21:57 +0000 Subject: [PATCH] Auto-deploy skillset on container start for portable skill resolution Add entrypoint logic to detect and run the skillset deploy script on container start. Detection order: SKILLSET_CONTAINER_PATH env var, then ~/skillset dedicated mount, then /workspace/skillset fallback. The deploy script (from the skillset repo) creates relative symlinks that resolve inside the container regardless of the host path layout. Also adds SKILLSET_PATH volume mount option to docker-compose files and documents SKILLSET_CONTAINER_PATH in .env.example for hosts where the skillset lives in a workspace subdirectory. --- .env.example | 25 +++++++++++++++++++++++++ docker-compose.shared.yml | 6 ++++++ docker-compose.yml | 6 ++++++ entrypoint-user.sh | 22 ++++++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/.env.example b/.env.example index bc285e8..084a488 100644 --- a/.env.example +++ b/.env.example @@ -31,6 +31,31 @@ WORKSPACE_PATH=~/projects # Path to SSH keys on host SSH_KEY_PATH=~/.ssh +# ── Skillset (agent skills and instructions) ───────────────────────── +# If you have a skillset repo, the entrypoint auto-deploys skills and +# instructions on container start using relative symlinks (portable +# across host/container). +# +# Detection is automatic if the skillset lives directly at the workspace +# root (i.e. WORKSPACE_PATH/skillset → /workspace/skillset in container). +# +# If the skillset lives in a subdirectory of your workspace, set +# SKILLSET_CONTAINER_PATH to its location *inside the container*. This +# is determined by the workspace mount: whatever is at +# WORKSPACE_PATH/ on the host becomes /workspace/ +# in the container. +# +# Examples: +# Host skillset at ~/projects/skillset → already at /workspace/skillset (auto-detected, no config needed) +# Host skillset at ~/projects/tools/skillset → SKILLSET_CONTAINER_PATH=/workspace/tools/skillset +# Host skillset at ~/projects/local/skillset → SKILLSET_CONTAINER_PATH=/workspace/local/skillset +# +# Alternatively, mount the skillset repo at a dedicated path using the +# SKILLSET_PATH volume in docker-compose.yml (see comments there). In +# that case the entrypoint finds it at ~/skillset automatically. +# +# SKILLSET_CONTAINER_PATH= + # ── Locale (defaults to en_US.UTF-8) ───────────────────────────────── # LANG=sv_SE.UTF-8 # LANGUAGE=sv_SE:sv diff --git a/docker-compose.shared.yml b/docker-compose.shared.yml index bf5074e..904b175 100644 --- a/docker-compose.shared.yml +++ b/docker-compose.shared.yml @@ -45,6 +45,12 @@ services: # SSH keys — user-specific if available, else shared - ${SSH_KEY_PATH:-~/.ssh}:/home/developer/.ssh:ro + # Optional: mount skillset repo for automatic skill/instruction deployment. + # The entrypoint runs deploy-skills.sh --bootstrap on start, creating + # relative symlinks that resolve inside the container regardless of + # where the repo lives on the host. Set SKILLSET_PATH in .env. + # - ${SKILLSET_PATH}:/home/developer/skillset + # Opencode config — per-user (persists settings across restarts) - ${HOME}/${SIGNUM}/.config/opencode:/home/developer/.config/opencode diff --git a/docker-compose.yml b/docker-compose.yml index e8ec1a1..6398209 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,12 @@ services: # SSH keys (read-only) — for git push/pull - ${SSH_KEY_PATH:-~/.ssh}:/home/developer/.ssh:ro + # Optional: mount skillset repo for automatic skill/instruction deployment. + # The entrypoint runs deploy-skills.sh --bootstrap on start, creating + # relative symlinks that resolve inside the container regardless of + # where the repo lives on the host. Set SKILLSET_PATH in .env. + # - ${SKILLSET_PATH}:/home/developer/skillset + # Optional: mount opencode config directory (persists config changes across restarts) # Includes opencode.json, oh-my-opencode-slim.json, skills, etc. # When mounted, OPENCODE_PROVIDER auto-config is skipped if opencode.json exists. diff --git a/entrypoint-user.sh b/entrypoint-user.sh index ee2bef7..914368f 100644 --- a/entrypoint-user.sh +++ b/entrypoint-user.sh @@ -44,6 +44,28 @@ fi # generated) and no-ops if OPENCODE_PROVIDER is unset. python3 /usr/local/lib/opencode-devbox/generate-config.py +# ── Skillset: deploy skills/instructions from mounted skillset repo ── +# When the skillset repo is mounted (at $HOME/skillset or /workspace/skillset), +# run the deploy script to create relative symlinks for skills and instructions. +# This ensures skills resolve correctly inside the container regardless of +# where the repo lives on the host. Idempotent — second run is a no-op. +# +# Detection order: +# 1. SKILLSET_CONTAINER_PATH env var (explicit, for non-standard layouts) +# 2. $HOME/skillset (dedicated volume mount via SKILLSET_PATH in compose) +# 3. /workspace/skillset (skillset is directly inside workspace root) +SKILLSET_DEPLOY="" +if [ -n "${SKILLSET_CONTAINER_PATH:-}" ] && [ -x "${SKILLSET_CONTAINER_PATH}/deploy-skills.sh" ]; then + SKILLSET_DEPLOY="${SKILLSET_CONTAINER_PATH}/deploy-skills.sh" +elif [ -x "$HOME/skillset/deploy-skills.sh" ]; then + SKILLSET_DEPLOY="$HOME/skillset/deploy-skills.sh" +elif [ -x /workspace/skillset/deploy-skills.sh ]; then + SKILLSET_DEPLOY="/workspace/skillset/deploy-skills.sh" +fi +if [ -n "$SKILLSET_DEPLOY" ]; then + "$SKILLSET_DEPLOY" --bootstrap --prune-stale >/dev/null 2>&1 || true +fi + CONFIG_DIR="$HOME/.config/opencode" OMOS_CONFIG="$CONFIG_DIR/oh-my-opencode-slim.json"