Skip to content

Add OpenCode sandbox workflows#3

Draft
christestet wants to merge 2 commits into
mainfrom
feat/cleanup-hook
Draft

Add OpenCode sandbox workflows#3
christestet wants to merge 2 commits into
mainfrom
feat/cleanup-hook

Conversation

@christestet
Copy link
Copy Markdown
Collaborator

What changed

This adds a more reliable OpenCode sandbox workflow setup for local vLLM-backed usage:

  • Added global sandbox rules in config/AGENTS.md.
  • Added reusable OpenCode commands:
    • /refactor-audit <target> for read-only refactor analysis.
    • /refactor-apply <approved scope> for focused refactors with verification and WORKLOG.md updates.
    • /git-commit for reviewed Conventional Commit workflows.
  • Updated the write-worklog skill so it is an on-demand formatting helper rather than a second global rule source.
  • Kept HOME=/home/opencode and changed the entrypoint to start OpenCode from /home/opencode/workspace without moving the home directory.
  • Simplified Compose mounts for global commands, skills, and rules.
  • Added ripgrep and tzdata to the image so OpenCode search tooling and Europe/Berlin timestamps work without runtime downloads or UTC fallback.
  • Updated README documentation to match the current Qwen/vLLM config, mount layout, command behavior, and sandbox expectations.

Why

The previous setup mixed persistent rules, skills, and command behavior in ways that were harder for local models to follow reliably. In testing, broad AGENTS.md instructions were useful for orientation, but repeatable workflow requirements were followed more consistently when embedded directly in slash commands.

This keeps the layers clearer:

  • AGENTS.md provides short global sandbox orientation.
  • Commands define repeatable workflows and required worklog behavior.
  • Skills provide on-demand reusable formatting and detailed procedures.
  • Docker/Compose provide the actual filesystem and runtime boundary.

Validation

Configuration and syntax checks:

jq empty config/opencode.json config/opencode-with-vllm-side.json
docker compose config
bash -n entrypoint.sh start.sh

Container/runtime checks performed:

docker compose build
docker compose run --rm opencode --version
docker compose run --rm --entrypoint bash opencode -lc 'rg --version | head -n 1; TZ=Europe/Berlin date "+%d.%m.%Y, %H:%M (%Z)"'

Observed results:

  • OpenCode started successfully and reported 1.15.10.
  • ripgrep 15.1.0 was available in the container.
  • Europe/Berlin timestamp resolved correctly as CEST.

Workflow smoke test performed in a temporary workspace project:

docker compose run --rm opencode run \
  --dir /home/opencode/workspace/opencode-agent-follow-test \
  --command refactor-apply \
  "In calc.py, extract the duplicated label normalization steps from normalize_user_label and normalize_project_label into a private helper named _normalize_label. Keep behavior unchanged. Do not touch any other code." \
  --format default

Observed result:

  • calc.py was refactored as requested.
  • WORKLOG.md was updated with the changed file, findings, CEST timestamp, and pending state.

A normal non-command OpenCode run was also tested with a small file edit and updated WORKLOG.md as expected.

Notes

/refactor-audit was recognized as the plan agent and remained read-only, but the local model stalled during one audit smoke test. The command wiring was correct; the stall appears related to local model/tool-loop behavior rather than configuration.

@christestet
Copy link
Copy Markdown
Collaborator Author

christestet commented May 23, 2026

here is calc.py

def normalize_user_label(label):
      value = label.strip()
      value = value.lower()
      value = value.replace(" ", "-")
      return value

      return value


  def format_status(name, enabled):
      if enabled:
          status = "enabled"
      else:
          status = "disabled"

      return f"{normalize_user_label(name)}:{status}"

@christestet christestet requested a review from jammsen May 23, 2026 14:28
1. Findings ordered by impact
2. Exact files and symbols involved
3. Suggested refactor steps
4. Behavioral risks and verification needed
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security risks is missing

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.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The 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

Comment thread config/AGENTS.md

When starting work in an existing project directory, check whether `WORKLOG.md` exists and read it for prior context. Commands that change files define their own required worklog steps; follow the command workflow exactly.

Create a new subdirectory under `/home/opencode/workspace` only when the user asks for a new standalone task or project and no suitable project directory already exists.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"no suitable project directory already exists."

Dangerous choice of words, this could generate another node-gamedig-app inside the existing node-gamedig-app diretory. Had this happening already twice, llms arent that creative all the time 😅

Better choice, if something is found ask the user to confirm if the code should go there and always recommend a naming for the project while asking.

Comment thread config/AGENTS.md

Create a new subdirectory under `/home/opencode/workspace` only when the user asks for a new standalone task or project and no suitable project directory already exists.

Prefer focused changes over broad rewrites. Before large refactors, first produce a short audit and wait for the user to choose what should be changed.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically open-close-principle

Comment thread config/AGENTS.md

Use the mounted sandbox commands for repeatable workflows when they fit the task:

- `/refactor-audit <target>`: inspect a target for refactor opportunities without editing files.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a target? Does the LLM know that? Im confused

Comment thread README.md
# A hardened Docker sandbox setup for opencode

With OpenCode + vLLM (Gemma 4 26B MoE) configs
With OpenCode + vLLM local model configs
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The 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.

Comment thread README.md
curl http://10.0.0.13:8000/v1/models
```

You should see your model ID in the response (e.g. `gemma4-26b-a4b`).
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment thread README.md
You should see your model ID in the response (e.g. `gemma4-26b-a4b`).
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`.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment thread README.md
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`
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice, the previous part should be named just like that.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean "Qwen3.6 35B A3B"

Comment thread README.md
```

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.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove "so they survive the HOME override that redirects opencode's session state to the mounted workspace."?

Comment thread config/opencode.json
"agent": {
"build": {
"prompt": "All project are located under /home/opencode/workspace, you will only work there and create a new subdirectory for each task or project, NO EXCEPTIONS. You must maintain a file called WORKLOG.md in the current project working directory at all times.\\n\\nRules:\\n- Before starting any task, check if WORKLOG.md exists and read it to understand prior context.\\n- After completing EACH task, immediately update WORKLOG.md with: what was done (specific files changed, exact lines modified), what was found (exact issues, not vague summaries), and what still needs doing with current date and time in german timezone. Do NOT proceed to the next task until WORKLOG.md has been updated.\\n- If WORKLOG.md does not exist, create it before doing anything else.",
"prompt": "Follow the sandbox rules from /home/opencode/.config/opencode/AGENTS.md. Before finishing any task that changes files, read WORKLOG.md if present and append a concise entry with the current Europe/Berlin timestamp from `TZ=Europe/Berlin date \"+%d.%m.%Y, %H:%M (%Z)\"`, changed files, concrete findings, and pending follow-ups.",
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be kept

"All project are located under /home/opencode/workspace, you will only work there and create a new subdirectory for each task or project, NO EXCEPTIONS."

Comment thread scripts/cleanup.sh
This cannot be undone.
EOF

read -r -p "Do you want to proceed? [y/N] " answer
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Linux is stopping you from doing a dangerous action by demanding you type exactly Yes, do as I say! (including the exclamation mark), it is trying to protect your operating system from breaking.

we should add this instead or y/Y and the yes variants its a major destructive workflow and Linux has a "prompt" already for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants