-
Notifications
You must be signed in to change notification settings - Fork 0
Add OpenCode sandbox workflows #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| --- | ||
| description: Review, document, and commit approved changes using Conventional Commits | ||
| agent: build | ||
| subtask: true | ||
| --- | ||
|
|
||
| Commit the current approved changes using Conventional Commits. | ||
|
|
||
| Workflow: | ||
|
|
||
| 1. Review `git status --short`. | ||
| 2. Inspect the staged and unstaged diff for the files that will be committed. | ||
| 3. Do not commit credentials, secrets, generated caches, local editor files, or unrelated changes. | ||
| 4. If unrelated changes are present, ask the user whether to include or exclude them before committing. | ||
| 5. If `CHANGELOG.md` already exists and the change is user-facing, update it before committing. Do not create a new changelog unless the user explicitly asks for one. | ||
| 6. Read `WORKLOG.md` if it exists. | ||
| 7. Run the smallest useful verification command available in the project. If no verification command exists, say that explicitly. | ||
| 8. Append a concise entry to `WORKLOG.md` before committing. | ||
| 9. Stage only approved files. | ||
| 10. Use a concise Conventional Commit message, for example `feat: add sandbox commands` or `fix: preserve opencode home path`. | ||
| 11. After committing, show the commit hash and final `git status --short`. | ||
|
|
||
| Use this exact timestamp command for the worklog: | ||
|
|
||
| ```bash | ||
| TZ=Europe/Berlin date "+%d.%m.%Y, %H:%M (%Z)" | ||
| ``` | ||
|
|
||
| Append this shape to `WORKLOG.md`: | ||
|
|
||
| ```markdown | ||
| --- | ||
|
|
||
| ## Commit: <short description> | ||
|
|
||
| **Status:** Done | ||
| **Date:** <timestamp> | ||
|
|
||
| ### What Changed | ||
|
|
||
| - File: `<path>` — <specific changes included in the commit> | ||
|
|
||
| ### Findings | ||
|
|
||
| - Verification: <command and result, or "No verification command available"> | ||
| - Commit: `<hash>` <subject> | ||
|
|
||
| ### Pending | ||
|
|
||
| - <remaining follow-up, or "None"> | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| --- | ||
| description: Apply one approved refactor, verify it, and update WORKLOG.md | ||
| agent: build | ||
| subtask: true | ||
| --- | ||
|
|
||
| Apply only the refactor requested in `$ARGUMENTS`. | ||
|
|
||
| If `$ARGUMENTS` is empty or the requested scope is unclear, ask the user to name the approved refactor before editing files. | ||
|
|
||
| Workflow: | ||
|
|
||
| 1. Read `WORKLOG.md` if it exists. | ||
| 2. Identify the smallest file/symbol scope needed for `$ARGUMENTS`. | ||
| 3. Keep behavior unchanged. | ||
| 4. Keep changes focused to the approved files or symbols. | ||
| 5. Do not include unrelated cleanup. | ||
| 6. Run the smallest useful verification command available in the project. If none exists, say that explicitly. | ||
| 7. Append a concise entry to `WORKLOG.md` before finishing. | ||
| 8. Summarize changed files and verification results. | ||
|
|
||
| Use this exact timestamp command for the worklog: | ||
|
|
||
| ```bash | ||
| TZ=Europe/Berlin date "+%d.%m.%Y, %H:%M (%Z)" | ||
| ``` | ||
|
|
||
| Append this shape to `WORKLOG.md`: | ||
|
|
||
| ```markdown | ||
| --- | ||
|
|
||
| ## Refactor: <short description> | ||
|
|
||
| **Status:** Done | ||
| **Date:** <timestamp> | ||
|
|
||
| ### What Changed | ||
|
|
||
| - File: `<path>` — <specific changes> | ||
|
|
||
| ### Findings | ||
|
|
||
| - <concrete findings or observations> | ||
| - Verification: <command and result, or "No verification command available"> | ||
|
|
||
| ### Pending | ||
|
|
||
| - <remaining follow-up, or "None"> | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| --- | ||
| description: Audit refactor opportunities without editing files | ||
| agent: plan | ||
| subtask: true | ||
| --- | ||
|
|
||
| Analyze the target given in `$ARGUMENTS` for code smells, duplicate code, unnecessary complexity, and technical debt. | ||
|
|
||
| If `$ARGUMENTS` is empty, inspect the current git diff first and then the smallest relevant surrounding files. | ||
|
|
||
| Do not edit files. Do not update `WORKLOG.md`; this is a read-only planning command unless the user explicitly asks you to document the audit. | ||
|
|
||
| Produce a concise audit with: | ||
|
|
||
| 1. Findings ordered by impact | ||
| 2. Exact files and symbols involved | ||
| 3. Suggested refactor steps | ||
| 4. Behavioral risks and verification needed | ||
|
|
||
| Ask the user which items should be implemented before making changes. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,27 @@ | ||
| --- | ||
| name: write-worklog | ||
| description: Maintain a WORKLOG.md file in the project directory to track task progress, decisions, and outcomes. Use when completing tasks, making file changes, or working on multi-step project work. | ||
| description: Append structured WORKLOG.md entries for task progress, decisions, and outcomes. Use when a project requires a detailed worklog entry or the user asks for one. | ||
| --- | ||
|
|
||
| # Write Worklog | ||
|
|
||
| Maintain a file called `WORKLOG.md` in the current project working directory at all times. This logs every task you complete, keeping context available for later sessions. | ||
| Append structured entries to `WORKLOG.md` in the current project working directory. This keeps concrete task context available for later sessions. | ||
|
|
||
| ## Core rules | ||
|
|
||
| ### Before starting a task | ||
|
|
||
| 1. Read `WORKLOG.md` to understand prior context and what is still pending. | ||
| 2. If the file does not exist, create it before doing anything else. | ||
| 1. Read `WORKLOG.md` if it exists to understand prior context and pending work. | ||
| 2. If the file does not exist, create it when a worklog entry is required. | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "create it in the project directory" i had that already, it created random entries in the "root dirs worklog" was fucking weird xD |
||
|
|
||
| ### After completing a task | ||
|
|
||
| 1. Append a new entry to `WORKLOG.md` immediately. | ||
| 2. Do NOT proceed to the next task until the entry is written. | ||
| 1. Append a new entry to `WORKLOG.md`. | ||
| 2. Keep the entry concise and specific. | ||
|
|
||
| ### Workflow checklist | ||
|
|
||
| Copy this checklist and track progress before moving on: | ||
| Use this checklist: | ||
|
|
||
| ``` | ||
| Worklog: | ||
|
|
@@ -30,19 +30,25 @@ Worklog: | |
| - [ ] Include files changed and exact lines modified | ||
| - [ ] Add concrete findings, not vague summaries | ||
| - [ ] List pending items | ||
| - [ ] Verify entry is written before continuing | ||
| - [ ] Verify entry is written | ||
| ``` | ||
|
|
||
| ## Entry format | ||
|
|
||
| Each entry MUST include all of the following: | ||
|
|
||
| - Task heading (descriptive summary) | ||
| - **Status** and **Date** (DD.MM.YYYY, HH:MM - CET/CEZ, Europe/Berlin) | ||
| - **Status** and **Date** (DD.MM.YYYY, HH:MM - CET/CEST, Europe/Berlin) | ||
| - **What was done** (files changed, exact lines modified) | ||
| - **What was found** (issues, bugs, observations with concrete specifics) | ||
| - **Pending** (outstanding items or follow-ups) | ||
|
|
||
| For the timestamp, use: | ||
|
|
||
| ```bash | ||
| TZ=Europe/Berlin date "+%d.%m.%Y, %H:%M (%Z)" | ||
| ``` | ||
|
|
||
| Use this structure: | ||
|
|
||
| ```markdown | ||
|
|
@@ -51,15 +57,15 @@ Use this structure: | |
| ## <task-description> | ||
|
|
||
| **Status:** Done | In Progress | Pending | ||
| **Date:** DD.MM.YYYY, HH:MM (CET/CEZ) | ||
| **Date:** DD.MM.YYYY, HH:MM (CET/CEST) | ||
|
|
||
| ### What was done | ||
| ### What Changed | ||
|
|
||
| - File: `path/to/file` — changed / created / removed | ||
| - Specific detail of what was modified | ||
| - Exact lines or sections if applicable | ||
|
|
||
| ### What was found | ||
| ### Findings | ||
|
|
||
| - Concrete issues, bugs, or observations | ||
| - Specific file paths and line numbers | ||
|
|
@@ -70,9 +76,7 @@ Use this structure: | |
| - Any blockers or follow-ups | ||
| ``` | ||
|
|
||
| ## Do not | ||
| ## Avoid | ||
|
|
||
| - Do NOT proceed to the next task without updating the worklog. | ||
| - Do NOT write vague summaries — include exact details. | ||
| - Do NOT skip entries, even for small tasks. | ||
| - Do NOT use relative time references without timestamps. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| FROM ubuntu:26.04@sha256:f3d28607ddd78734bb7f71f117f3c6706c666b8b76cbff7c9ff6e5718d46ff64 | ||
|
|
||
| ARG ENABLE_NODEJS=true | ||
| ARG ENABLE_NODEJS=false | ||
| ARG ENABLE_PYTHON=false | ||
| ARG ENABLE_RUST=false | ||
| ARG PYTHON_VERSION=3.13 | ||
|
|
@@ -14,7 +14,7 @@ ENV DEBIAN_FRONTEND=noninteractive \ | |
| ENABLE_PYTHON=${ENABLE_PYTHON} \ | ||
| ENABLE_RUST=${ENABLE_RUST} \ | ||
| PYTHON_VERSION=${PYTHON_VERSION} \ | ||
| # Pin tool data dirs explicitly — survives the HOME override in entrypoint.sh | ||
| # Pin tool data dirs explicitly so subprocesses find language toolchains reliably | ||
| CARGO_HOME=/home/opencode/.cargo \ | ||
| RUSTUP_HOME=/home/opencode/.rustup \ | ||
| # All user tool bins in PATH — inherited by every subprocess after exec gosu | ||
|
|
@@ -27,6 +27,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| ca-certificates \ | ||
| git \ | ||
| gosu \ | ||
| ripgrep \ | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Baaaaaaaaaah alphabetical order! Heresy! |
||
| tzdata \ | ||
| openssh-client \ | ||
| && apt-get autoremove -y \ | ||
| && apt-get clean \ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,14 @@ | ||
| # A hardend Docker sandbox setup for opencode | ||
| # A hardened Docker sandbox setup for opencode | ||
|
|
||
| With OpenCode + vLLM (Gemma 4 26B MoE) configs | ||
| With OpenCode + vLLM local model configs | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name the model (qwen3.6-35b) is more descriptive for people cloning the repo, then hiding it inside the config inside a nested directory. |
||
|
|
||
| Run OpenCode as a sandboxed, hardenend non-root Docker container connected to a self-hosted vLLM inference server. No cloud API keys required. | ||
| Run OpenCode as a sandboxed, hardened non-root Docker container connected to a self-hosted vLLM inference server. No cloud API keys required. | ||
|
|
||
| --- | ||
|
|
||
| ## Table of Contents | ||
|
|
||
| - [A hardend Docker sandbox setup for opencode](#a-hardend-docker-sandbox-setup-for-opencode) | ||
| - [A hardened Docker sandbox setup for opencode](#a-hardened-docker-sandbox-setup-for-opencode) | ||
| - [Table of Contents](#table-of-contents) | ||
| - [Prerequisites](#prerequisites) | ||
| - [Directory Structure](#directory-structure) | ||
|
|
@@ -22,6 +22,7 @@ Run OpenCode as a sandboxed, hardenend non-root Docker container connected to a | |
| - [Security Notes](#security-notes) | ||
| - [Feature Toggles](#feature-toggles) | ||
| - [Using Tools and Skills](#using-tools-and-skills) | ||
| - [Commands](#commands) | ||
| - [Skills](#skills) | ||
|
|
||
|
|
||
|
|
@@ -37,9 +38,9 @@ Verify your vLLM is reachable before starting: | |
| curl http://10.0.0.13:8000/v1/models | ||
| ``` | ||
|
|
||
| You should see your model ID in the response (e.g. `gemma4-26b-a4b`). | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| You should see your model ID in the response (e.g. `qwen3.6-35b`). | ||
|
|
||
| Use the exact `"id"` value from the response — e.g. `gemma4-26b-a4b`. | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| Use the exact `"id"` value from the response — e.g. `qwen3.6-35b`. | ||
|
|
||
| **Finding your context size:** | ||
| The `max_model_len` field in the `/v1/models` response is your context limit. Use that value for `"context"`. | ||
|
|
@@ -57,9 +58,10 @@ opencode-sandbox/ | |
| ├── start.sh | ||
| ├── config/ | ||
| │ ├── opencode.json | ||
| │ ├── AGENTS.md ← global sandbox rules (mounted read-only) | ||
| │ └── auth.json ← provider auth tokens (mounted read-only) | ||
| ├── data/ ← opencode session state, persisted across runs | ||
| ├── .opencode/ ← skills and agent config (optional) | ||
| ├── .opencode/ ← global sandbox commands and skills (mounted read-only) | ||
| └── workspace/ ← put your code projects here | ||
| ``` | ||
|
|
||
|
|
@@ -88,7 +90,7 @@ Inside the TUI: | |
|
|
||
| 1. Press `/model` — your model should appear under your provider name with an orange dot | ||
| 2. Type `hello, what model are you?` — the response should mention your model ID | ||
| 3. Check the status bar at the bottom — it should show `Gemma 4 26B MoE · vLLM (Gemma4 local)` | ||
| 3. Check the status bar at the bottom — it should show your configured model, for example `Qwen3.6 35B A3B · vLLM` | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. very nice, the previous part should be named just like that.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean "Qwen3.6 35B A3B" |
||
| 4. Check the right panel — `$0.00 spent` confirms no cloud API is being used | ||
|
|
||
| --- | ||
|
|
@@ -97,7 +99,7 @@ Inside the TUI: | |
|
|
||
| ### Working with files | ||
|
|
||
| Drop files into `./workspace/` on your host. They appear at `~/workspace/` inside the container. OpenCode operates within this directory and cannot access anything outside it. | ||
| Drop files into `./workspace/` on your host. They appear at `/home/opencode/workspace/` inside the container. OpenCode starts in this directory; the global config still lives under `/home/opencode/.config/opencode/`. | ||
|
|
||
| ```bash | ||
| # Copy a project into the sandbox | ||
|
|
@@ -146,7 +148,7 @@ If this fails, your vLLM IP is unreachable from the container. Use the actual ho | |
|
|
||
| **Tool calling loops or model halts mid-task** | ||
|
|
||
| This is a known Gemma 4 behavior with agentic tool use. Mitigations: | ||
| Some local models can struggle with long agentic tool-use loops. Mitigations: | ||
|
|
||
| - Prefer **Ask mode** for questions and code review that don't require file editing | ||
| - For Build mode, give explicit step-by-step instructions rather than open-ended goals | ||
|
|
@@ -165,7 +167,7 @@ The container starts as root to handle setup (creating the user, fixing file own | |
| - **`cap_add: CHOWN, SETUID, SETGID, DAC_OVERRIDE`** — only the four capabilities the entrypoint actually needs for its setup phase are added back. Once `gosu` drops to the non-root user, the kernel automatically clears the effective capability set on the UID transition, and `no-new-privileges` blocks any path to reclaiming them. | ||
| - **`PUID` / `PGID`** — the in-container user is created at runtime with the same UID/GID as your host user. This ensures bind-mounted files in `./workspace` and `./data` have correct ownership on both sides of the mount. | ||
| - Bridge networking only — isolated from the host network | ||
| - Filesystem access limited to `./workspace` and `./data` on the host | ||
| - Writable filesystem access is limited to `./workspace` and `./data` on the host. Config, commands, skills, and auth are mounted read-only. | ||
|
|
||
| The model runs entirely on your local vLLM server. No data leaves your network. | ||
|
|
||
|
|
@@ -187,18 +189,34 @@ docker compose build --build-arg ENABLE_PYTHON=true --build-arg PYTHON_VERSION=3 | |
| ./start.sh --no-cache # rebuild with new toggles | ||
| ``` | ||
|
|
||
| All runtimes are installed at **build time** under the `opencode` user, so the container starts instantly with no network downloads at runtime. The tool binaries are on `PATH` and their data directories (`CARGO_HOME`, `RUSTUP_HOME`) are pinned via environment variables so they survive the `HOME` override that redirects opencode's session state to the mounted workspace. | ||
| All runtimes are installed at **build time** under the `opencode` user, so the container starts instantly with no language runtime downloads at startup. Base tooling includes `ripgrep` for OpenCode search tools and `tzdata` for correct Europe/Berlin timestamps. The tool binaries are on `PATH` and their data directories (`CARGO_HOME`, `RUSTUP_HOME`) are pinned via environment variables. | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why remove "so they survive the |
||
|
|
||
| --- | ||
|
|
||
| ## Using Tools and Skills | ||
|
|
||
| ### Commands | ||
|
|
||
| Sandbox-wide commands and skills are mounted globally: | ||
|
|
||
| ```yaml | ||
| - ./config/AGENTS.md:/home/opencode/.config/opencode/AGENTS.md:ro | ||
| - ./.opencode/commands:/home/opencode/.config/opencode/commands:ro | ||
| - ./.opencode/skills:/home/opencode/.config/opencode/skills:ro | ||
| ``` | ||
|
|
||
| This makes the commands available regardless of which project under `./workspace/` you open. Project-specific commands, skills, and `AGENTS.md` files can still live inside the project directory. | ||
|
|
||
| `AGENTS.md` is intentionally short: it gives global orientation. Repeatable process requirements live directly in the commands, because local models follow concrete command workflows more reliably than broad standing instructions. | ||
|
|
||
| Available sandbox commands: | ||
|
|
||
| - `/refactor-audit <target>` — analyze refactor opportunities without editing files | ||
| - `/refactor-apply <approved scope>` — apply one focused approved refactor, verify it, and update `WORKLOG.md` | ||
| - `/git-commit` — review, document, and commit approved changes using Conventional Commits | ||
|
|
||
| ### Skills | ||
|
|
||
| Skills a special capabilities for an Agent that tells him how to do things or how to handle tools. | ||
| They have a specific Format and a SKILL.md file is mandatory. | ||
| Read more about Skills here https://agentskills.io/home | ||
| Skills are reusable on-demand capabilities for an agent. They use one directory per skill with a mandatory `SKILL.md`. | ||
|
|
||
| You have 2 options to use them | ||
| - just copy over the `.opencode` folder into your workspace. Opencode will then recognize them | ||
| - just add them to the worklog example skill in the `compose.yml` | ||
| The included `write-worklog` skill provides a structured `WORKLOG.md` entry format for ad-hoc tasks. Command-driven workflows inline their own worklog format so they do not depend on automatic skill selection. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security risks is missing