local/skills/local-spec/SKILL.md
MUST be invoked before any work involving: authoring `kind: local` templates, `local.yml` files, the inline `local:` map in `overthink.yml`, or the merge semantics between a `kind: local` template and a `target: local` deployment.
npx skillsauth add overthinkos/overthink-plugins local-specInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
kind: local declares a reusable layer-stack template that gets applied to a Linux filesystem (target:local deployments). Unlike kind: pod / kind: vm / kind: k8s which wrap an image, a kind: local is defined entirely by its layers + install_opts + env — there's no OCI artifact backing it. The convention file is local.yml; templates may also be authored inline in the local: map of overthink.yml.
Legacy kind: host projects migrate via ov migrate.
kind: local
name: dev-workstation
spec:
layers: # required (use [] for a placeholder; see below)
- ripgrep
- direnv
- uv
install_opts: # optional — defaults merged 3-tier (CLI > deployment > template)
with_services: false
allow_repo_changes: true
env: # optional
- EDITOR=vim
description: # optional — Gherkin-shaped self-description
feature: Standard developer workstation profile
tag: [working]
eval: # optional — deploy-scope checks
- {id: rg-version, scope: deploy, command: "rg --version"}
version: 2026.144.1443
local:
dev-workstation:
layers: [ripgrep, direnv]
install_opts: {with_services: false, allow_repo_changes: true}
env: [EDITOR=vim]
description: {feature: Dev workstation, tag: [working]}
ci-runner:
layers: [ripgrep, pixi, cargo-toolchain]
install_opts: {with_services: true, allow_root_tasks: true}
description: {feature: CI runner profile, tag: [working]}
ov-cachyos:
# Empty placeholder — `layers: []` is a load-time WARNING (allowed
# for staged template name reservation); a missing `layer:` field
# is a hard error.
layers: []
install_opts: {}
description: {feature: CachyOS DX (placeholder), tag: [testing]}
| Field | Required | Description |
|---|---|---|
| layers | Yes | Ordered layer stack. [] permitted as a placeholder (warning, not error). |
| install_opts | No | Default install gates. Deployment overrides merge on top. |
| env | No | Shell-profile env vars (KEY=VALUE). Deployment env wins on key collision. |
| description | No | Gherkin-shaped (Feature/Narrative/Tag/Scenario). Status word lives in tag: working/testing/broken. |
| eval | No | Deploy-scope checks; merged with deployment.eval. |
| deploy_eval | No | Same as eval but reserved for image-style deploy-tests propagation. |
There is no status: or info: field. Status lives in description.tag (one of working/testing/broken); the human-facing description lives in description.feature + description.narrative.
A kind: local deploy emits zero container-image fetch / build
steps. The deploy applies host packages + configs only. There is no
image: field; declaring one in legacy YAML hard-errors at
ov image validate time with a pointer to ov migrate.
Test-bed image preflight is the eval entry point's job, not the
deploy's. When ov eval run --on-host <name> resolves to a host
target, the runner walks the score's recipes, collects every distinct
scenario.pod value plus score.target_image, and ensures each
image is present in local podman storage (LocalImageExists →
ov image pull → fall back to ov image build for short names that
resolve via cfg.Images). Operators who never run ov eval run
never pay the image-fetch cost. See /ov-eval:eval "Image
preflight" and ov/eval_image_preflight.go.
This invariant — "deploy fetches NOTHING speculative" — is codified
as a CLAUDE.md Key Rule and enforced at the type level: the
LocalSpec Go struct has no Images field, so the surface is
unreachable from any new code. Migration: ov migrate
(idempotent; rewrites legacy image: blocks under local.<name>
to a dated comment fence).
kind: local template + kind: deployWhen a deployment carries local: <template-name>:
| Field | Template provides | Deployment overrides | CLI overrides | Effective value |
|---|---|---|---|---|
| layers | base list | — | — | template.Layers |
| add_layers | — | extra list | --add-layer | deployment.AddLayers ++ CLI.AddLayer |
| effective layer order | — | — | — | template.Layers ++ deployment.AddLayers ++ CLI.AddLayer |
| install_opts.* (bool) | default | wins over template | wins over both | CLI > deployment > template |
| install_opts.builder_image | default "" | wins | wins over both | CLI > deployment > template |
| env | base list | extends + overrides on key | — | template.Env merged with deployment.Env (deployment-wins on collision) |
| eval | base checks | extends list | — | template.Eval ++ deployment.Eval |
| deploy_eval | base checks | extends list | — | template.DeployEval ++ deployment.DeployEval |
The InstallOptsConfig.ApplyTo method is fill-empty — calling it on the deployment's opts first, then the template's, gives the priority chain automatically.
layers: [] is a placeholderA template with layers: [] is permitted as a stub for staged name reservation:
local:
ov-cachyos:
layers: []
install_opts: {}
description: {feature: CachyOS DX (placeholder), tag: [testing]}
ov image validate emits a WARNING but does not error. A missing layer: field entirely IS an error — the field's presence is the signal that the author intended a template.
/ov-local:local-deploy — the target: local deployment surface that consumes this template./ov-internals:local-infra — Go file map (local_spec.go, LocalSpec struct, findLocalSpec lookup)./ov-image:layer — layer authoring (the building blocks composed by templates)./ov-build:migrate — ov migrate migrates legacy kind: host/host.yml projects and splits overthink.yml's inline image: / vm: / pod: / k8s: / local: / deploy: maps into sibling per-kind files. The ov-cachyos deploy key + local.ov-cachyos template share a name — a concrete demonstration of cross-kind name reuse (a kind: local template and a kind: deploy entry can share a name).A kind: local template's name lives in the local: namespace, independent of layer / image / pod / vm / k8s / deploy. The canonical example is ov-cachyos — local.ov-cachyos is the template; deploy.ov-cachyos is the deployment entry that applies it; both share the name without conflict. Verbs disambiguate: ov update ov-cachyos resolves to the deploy entry; the template is referenced internally via the deploy's local: ov-cachyos field. See CLAUDE.md "Cross-kind name reuse is permitted and encouraged".
MUST be invoked when the task involves authoring or editing kind: local templates, local.yml files, the inline local: map, or the merge between a template and a deployment. Invoke this skill BEFORE reading Go source or launching Explore agents.
development
Claude Code multi-agent support in Overthink — sub-agents, dynamic workflows, and agent teams, and how each drives the existing `ov eval` disposable beds to test and verify. MUST be invoked before authoring or invoking an ov sub-agent / dynamic workflow / agent team, wiring agent-lifecycle hooks, or asking "which primitive should drive the R10 beds?".
tools
Mounts a virtiofs share tagged `workspace` at /workspace inside a VM guest via a systemd .mount unit. Use when a kind:vm entity shares a host directory into the guest and you need it auto-mounted (and re-mounted at every boot).
development
MUST be invoked before any work involving: the `kind: android` schema kind, a `target: android` deploy, the `apk:` layer package format (installing Android apps declaratively), AndroidDeployTarget, an in-pod emulator OR a remote/physical adb-endpoint device, or nested `pod → android` deployment. The first-class Android device + app surface that sits above `ov eval adb`/`appium`.
tools
Use when committing, branching, pushing, merging, tagging, creating PRs, or approving/merging PRs with gh — the feat/-branch, R10-gated, never-force-push landing workflow across the main repo + the plugins submodule + image/<distro> submodules. Covers sync-to-upstream, branch/worktree pruning, the fork+PR path for contributors without write access, and cross-repo @github landing order.