Deploy the five oh-my-opencode-slim bundled skills (clonedeps, codemap, deepwork, oh-my-opencode-slim, simplify) by symlinking them from the image path into ~/.agents/skills/ on every container start, instead of the installer copying them into the persistent config volume on first run only. Image-sourced links mean 'docker compose pull' + recreate refreshes the skills with no installer run and no config reset; the old copy-on-first-run froze them in the volume forever. - entrypoint-user.sh: new non-fatal OMOS bundled-skills reconcile block (runs after skillset deploy so OMOS wins the simplify collision; absolute symlinks; gated by OMOS_SKILLS, now independent of ENABLE_OMOS). Both installer calls now pass --skills=no. One-time migration backs up (never deletes) frozen real copies in ~/.config/opencode/skills/ to .bak.<epoch>. - scripts/smoke-test.sh: assert the bundled-skills source path on omos. - Bump OPENCODE_VERSION 1.17.4 -> 1.17.5. - Versioning: document the move to independent image semver (v2.0.0 was the decouple point), mirroring pi-devbox. README/AGENTS/.env.example/CHANGELOG updated; new docs/omos-skills.md.
5.3 KiB
OMOS bundled skills
How the five skills bundled with oh-my-opencode-slim (OMOS) are deployed in this image, why the mechanism changed, and how to keep them up to date.
TL;DR
- OMOS bundles five skills:
clonedeps,codemap,deepwork,oh-my-opencode-slim,simplify. - They are symlinked from the image into
~/.agents/skills/on every container start byentrypoint-user.sh(gated byOMOS_SKILLS, defaulttrue). - To update them, pull a newer image and recreate the container — no
installer run, no config reset:
docker compose pull docker compose up -d --force-recreate
Why it works this way
The skills ship inside the OMOS npm package, baked into the image at
/usr/lib/node_modules/oh-my-opencode-slim/src/skills/<name>/. On start the
entrypoint creates one absolute symlink per skill into ~/.agents/skills/ —
the same flat directory the skillset deploy uses
and which opencode scans (directly and via the ~/.claude/skills pointer).
Because the symlink target lives in the image, not in a volume, the skill
content tracks whatever image you run. Pull a newer *-omos image and the
skills update on the next container start. ~/.agents/skills/ is itself an
ephemeral container-layer directory rebuilt from scratch on every start, so the
reconcile is idempotent and self-healing.
The symlinks are absolute (unlike skillset's relative links): the target is
always inside the container at a fixed /usr path, so there is no host/container
path divergence to guard against.
The old mechanism (and the trap it created)
Previously the OMOS installer (oh-my-opencode-slim install --skills=yes)
copied the skills into ~/.config/opencode/skills/ — but only on the very
first container start, gated by the absence of oh-my-opencode-slim.json. That
directory is the persistent devbox-opencode-config named volume.
The consequence: once the config existed, the installer was skipped forever, so
the copied skills froze at whatever the image shipped on first run. Pulling
a newer image did nothing (the copies lived in the volume, not the image). The
only refresh path was OMOS_RESET=true, which runs install --reset and
also overwrites your hand-tuned opencode.jsonc (model choices, agent
config). Updating skills meant clobbering unrelated config — a bad trade.
The installer has no skills-only refresh flag (--skills=yes|no is all-or-
nothing within a full install; --reset overwrites everything), so the fix was
to stop using the installer for skills entirely. The two install invocations
in entrypoint-user.sh now pass --skills=no; the installer manages only the
agent config (oh-my-opencode-slim.json).
One-time migration of frozen copies
Existing volumes still contain the old frozen real directories under
~/.config/opencode/skills/. Because opencode prefers a name found there over
the same name in ~/.agents/skills/, those stale copies would shadow the
fresh image-sourced symlinks. On the first start after upgrading, the entrypoint
backs each of them up — never deletes — to
~/.config/opencode/skills/<name>.bak.<epoch> and writes a marker at
~/.config/opencode/.omos-skills-migrated so the migration runs exactly once.
Only real directories are touched; any symlink in that directory is left alone.
If everything looks right after a few sessions, the backups are safe to remove:
rm -rf ~/.config/opencode/skills/*.bak.*
Relationship to skillset
The skillset repo deploys its own
version-controlled skills into ~/.agents/skills/ via
deploy-skills.sh --bootstrap --prune-stale, which the entrypoint runs on every
start — before the OMOS reconcile. If a skill name exists in both, OMOS
wins: the reconcile uses ln -sfn, which replaces any existing symlink. Today
the only overlap is simplify (the OMOS copy is richer — it bundles
codemap.md and a README.md), so simplify was removed from the skillset
repo and the image copy owns the name.
Configuration
| Variable | Default | Effect |
|---|---|---|
OMOS_SKILLS |
true |
Symlink the bundled skills into ~/.agents/skills/ on each start. Set false to deploy no skills from the image. |
OMOS_SKILLS is independent of ENABLE_OMOS: the skills are useful to plain
opencode even when the multi-agent orchestration config is not enabled. The
reconcile is additionally gated on the bundled-skills source being present, so
it is automatically a no-op on the non-OMOS (base) image variant.
Troubleshooting
- A skill didn't update after
docker compose pull. Make sure you recreated the container (docker compose up -d --force-recreate); a plain restart reuses the old container layer. Confirm the link target —readlink ~/.agents/skills/deepworkshould point under/usr/lib/node_modules/oh-my-opencode-slim/src/skills/. - A skill disappeared. If OMOS upstream restructured its package the symlink
target may no longer exist. The build-time smoke test asserts the source path,
so this should be caught in CI; if you hit it at runtime, look for a dangling
link in
ls -l ~/.agents/skills/. - I want a frozen copy back. It's at
~/.config/opencode/skills/<name>.bak.<epoch>until you delete it.