Environment Configuration Skill (One-Time)
Goal: Figure out exactly where these tools are on this machine, write a path contract, and then retire gracefully.
This skill has a 'use once and discard' lifecycle. Do not keep it resident — the wrap-up must go through the confirmation process in §7.
0. Three Hard Rules (Read First)
- Detection phase is read-only.
scripts/detect.pynever creates/modifies/deletes any system files. It only useswhich/stat/ version queries / directory listing. Any writes must happen ininstall.sh(§4), and each step must be logged in the manifest. - Never write to user disks. Don't touch
/mnt/c,/mnt/d, or Windows drives. All output and temporary files go into the current workspace or~/.config/ideaform/. - Don't try sudo. Sandboxed processes will never get root (kernel
NoNewPrivs=1); trying is a waste of time. Jobs requiring root must be handed off to the user to run in their own terminal, with the exact command provided. All tools in this project are designed for user-level installation (extracting AppImages, venv packages, local fonts) that doesn't need root.
1. Contract File (This Skill's Only Output)
Location (fixed, a third location outside the two skills):
$VW_CONFIG_ROOT/toolchain.json # default ~/.config/ideaform/
$VW_CONFIG_ROOT/env.sh # shell export script that can be sourced
$VW_CONFIG_ROOT/install-manifest.jsonl # what was installed, for rollback
$VW_CONFIG_ROOT/logs/
$VW_CONFIG_ROOT/backup/ # backups of any original files before overwriting
$VW_CONFIG_ROOT defaults to ~/.config/ideaform and can be overridden via environment variable.
The contract file is deliberately placed outside the skill directory — so even after this skill is deleted, workflow skills can still read it.
schema_version 1 fields (workflow skills use these keys):
{
"schema_version": 1,
"generated_at": "ISO8601",
"generated_by": "[email protected]",
"verified_at": "ISO8601 | null", // stamped after smoke test passes
"host": { "os": "linux", "distro": "...", "arch": "x86_64", "in_wsl": true },
"config_root": "/abs/path",
"tmpdir": "/abs/path/to/big/disk/tmp", // ★ must point to a large disk, not 10MB /tmp
"tools": {
"node": { "path": "/abs", "version": "22.x", "status": "ok|missing|degraded" },
"python": { "path": "/abs", "version": "3.13.x", "status": "..." },
"venv": { "path": "/abs", "python": "/abs/bin/python", "pip": "/abs/bin/pip" },
"ffmpeg": { "path": "/abs", "version": "...", "flavor": "full|remotion-minimal", "status": "..." },
"ffprobe": { "path": "/abs", "status": "..." },
"remotion": { "project": "/abs", "version": "4.x", "status": "..." },
"lmms": { "apprun": "/abs", "root": "/abs", "version": "1.2.2",
"stkdir": "/abs", "status": "..." },
"fonts": { "cjk_families": ["Noto Sans CJK SC"], "status": "..." }
},
"env_file": "/abs/env.sh",
"manifest": "/abs/install-manifest.jsonl"
}
When workflow skills start, they check schema_version and verified_at: if the version doesn't match, they ask to re-run this skill; if verified_at is null, they warn "smoke test not passed."
2. Execution Order (Follow, Don't Skip)
Step 1: Read-Only Detection
python3 skills/ideaform-setup/scripts/detect.py # human-readable report
python3 skills/ideaform-setup/scripts/detect.py --json # machine-readable
Cross-check each item against references/toolchain-matrix.md.
Each item's status is ok / missing / degraded (present but incomplete, e.g., ffmpeg is Remotion-minimal).
Step 2: Show Plan, Ask User
Organize the detection results into a table for the user: which are ok, which are missing, which are degraded, and for each missing item, how it will be installed, where, and how much disk space is needed. Wait for user confirmation before proceeding. Don't install anything on your own.
Step 3: Install (Only After User Confirmation)
bash skills/ideaform-setup/scripts/install.sh --only <tool1,tool2>
Without --only, installs all missing items. The script:
- Backs up any existing files that will be overwritten to
$VW_CONFIG_ROOT/backup/<timestamp>/ - Appends a record to
install-manifest.jsonlfor each completed step - Installs everything to user-level paths, no root needed
If a step requires root (very rare), the script stops and prints the command, then asks the user to run it in their own terminal.
Step 4: Write the Contract
python3 skills/ideaform-setup/scripts/detect.py --write
Writes the analysis results to toolchain.json + env.sh. At this point, verified_at remains null.
Step 5: Harvest Community Skills (Borrowing)
Once the contract is written, the tools in the chain are determined. Don't rush to rely on your own limited knowledge — first, grab the mature skills from the community that have already been battle-tested:
python3 skills/ideaform-setup/scripts/harvest-skills.py --from-contract # harvest one by one for each tool in the chain
python3 skills/ideaform-setup/scripts/harvest-skills.py --from-contract --dry-run # preview candidate list before deciding
For each tool, the script: searches GitHub for filename:SKILL.md → scores by stars/license/freshness → security scans (entries matching dangerous patterns go into _quarantine/ quarantine, next candidate tried) → saves to ~/.workbuddy/skills/<name>/ (includes _PROVENANCE.md source proof) → logs in manifest.
- No qualified candidate found = this tool really needs you to write a skill — that's exactly why this repo's
skills/ideaform*exists. - Saved skills are yours to evolve. The script has fork protection (
_harvest.jsonwith per-file hash): local modifications are not overwritten by default;--forceonly upgrades unmodified ones; upstream changes for forked skills go into_upstream/for manual merge. Seereferences/skill-harvest.md§4.1. - Full protocol (scoring details / security scan modes / limits) is in
references/skill-harvest.md.
This step is not only for initial setup. Whenever you introduce a new open-source tool during production (e.g., you need to draw chemical structures and think of RDKit), the first step is
harvest-skills.py rdkit— harvest first, then start working.
Step 6: End-to-End Smoke Test (Mandatory, Don't Skip)
python3 skills/ideaform-setup/scripts/verify.py
Actually runs a minimal closed loop; only stamps verified_at if all four pass:
★ Acceptance Criteria: After running this step, re-run it in a zero environment variable context —
env -u TMPDIR -u VW_TMPDIR -u VW_CHROME python3 scripts/verify.py— and it must still pass completely. That's the only way to prove the contract is truly self-consistent (toolchains, TMPDIR, chrome path all read from the contract). If it only passes with manualexport, the contract has gaps, and the workflow skill will fail on another machine.
| Check | What It Does | Pass Criterion |
|---|---|---|
| ① TTS | Synthesize one Chinese sentence | Output audio > 2 KB with RMS > threshold |
| ② Video | Render 1 still frame with Remotion | PNG dimensions correct, file > 20 KB |
| ③ Audio Render | Render a 1-second project with LMMS | WAV peak > 1000 and not silent |
| ④ Audio-Video Mux | Use ffmpeg to combine silent video + audio track | Output audio bitrate > 64000 bps |
All pass → stamp verified_at into toolchain.json.
Any fail → stop and report which item and why, fix then re-run. Don't stamp.
Step 7: Handoff Confirmation + Wrap-Up
See §7.
3. How to Find Each Tool (Summary)
Full table in references/toolchain-matrix.md. Key points:
- Node / Python: Prefer managed version paths on the host (
~/.workbuddy/binaries/...), then fall back toPATH. - ffmpeg / ffprobe: Usually not on the system. Remotion comes with a minimal version inside its package (
node_modules/@remotion/compositor-linux-x64-gnu/ffmpeg) — sufficient but with fewer filters (novolumedetect/acompressor,loudnormhas latency). Mark asdegradedif found, and noteflavorin the contract. - Remotion project: Prefer
$VW_REMOTION_PROJECT, then~/tools/remotion-app, then scan workspace forremotion.config.ts. If none found, use the starter template inassets/templates/remotion-starter/shipped with this skill. - LMMS: Look for
squashfs-root/AppRun(the run entry point after AppImage extraction). Note:stkdirin~/.lmmsrc.xmlmust point torawwaves/inside that extracted directory, otherwise silent output with no errors — this is the most expensive pitfall in this workflow, andverify.py③ is specifically designed to catch it. - CJK Fonts: Use
fc-listto check forNoto Sans CJK SCand similar. If missing, install user-level fonts to~/.local/share/fonts/.
4. Installation Target Paths
| Tool | Installed To | Method |
|---|---|---|
| Node / Python | Only install if missing | Prefer existing managed versions on the machine; otherwise prompt user |
edge-tts / soundfile / numpy | venv | <venv>/bin/pip install, must export TMPDIR=<large disk> |
| ffmpeg full version | ~/.local/bin/ | Download static package from mirror, extract, no root needed (optional; skip if minimal version is sufficient) |
| LMMS | $VW_CONFIG_ROOT/lmms/ | Download AppImage via proxy → --appimage-extract to unpack |
| Remotion dependencies | Project directory | npm install, point TMPDIR to large disk |
| CJK fonts | ~/.local/share/fonts/ | Extract .ttc → fc-cache -f |
⚠️ Every download must be verified: byte size / SHA256 / ability to run after extraction. If download fails, retry; never leave a half-written file.
5. Rollback
install-manifest.jsonl is the single source of truth. Format:
{ "entries": [
{ "ts": "...", "kind": "pip-install", "target": "<venv>", "detail": "edge-tts==7.3.1",
"undo": "<venv>/bin/pip uninstall -y edge-tts" },
{ "ts": "...", "kind": "mkdir", "target": "$VW_CONFIG_ROOT/lmms", "undo": "rm -rf ..." },
{ "ts": "...", "kind": "backup-file", "target": "~/.lmmsrc.xml",
"backup": "$VW_CONFIG_ROOT/backup/<ts>/lmmsrc.xml", "undo": "cp backup back to original position" }
] }
bash skills/ideaform-setup/scripts/rollback.sh --list # preview what will be undone
bash skills/ideaform-setup/scripts/rollback.sh --dry-run # simulate, no action
bash skills/ideaform-setup/scripts/rollback.sh --yes # actual rollback (reverse order)
Must back up user's existing files before overwriting — especially ~/.lmmsrc.xml.
By default, rollback does not delete the contract file (workflow skills need it), unless the user explicitly requests --purge-contract.
7. ★ Wrap-Up: Disable / Archive / Delete (Must Let User Choose)
After smoke tests pass, don't automatically delete yourself. Follow this procedure:
① Report First
Explain to the user:
- Environment is configured,
toolchain.jsonis ready (provide path) - Smoke test results for all four items
- Workflow skills do not need this skill to be present to work (because the contract file is outside the skill)
② Offer Three Options, Let User Choose
| Option | What It Does | Reversibility | Use Case |
|---|---|---|---|
| A. Disable (recommended) | Change disable: false to true in this SKILL.md's frontmatter | Re-enable by changing back to false | Want to keep it for re-running on a different machine or changed environment |
| B. Archive | Move entire skill directory to $VW_CONFIG_ROOT/archive/ideaform-setup-<ts>/ | Restore by moving it back | Don't want it in the skill list, but keep as backup |
| C. Delete | Actually delete the directory | Undo via automatic backup | Certain you won't need it again |
Recommend A: Disabling is safest, with lowest cost, and preserves the ability to "re-run if environment changes."
③ Iron Rule Before Executing
Whichever option, backup first, then act, then confirm:
- Backup:
cp -r <skill directory> $VW_CONFIG_ROOT/backup/skill-ideaform-setup-<ts>/ - List: Show the user every path that will be deleted or modified
- Second confirmation: Wait for the user to explicitly say "go ahead" or equivalent; don't use defaults or inference in place of confirmation
- Execute: Use
mvto backup then delete; never userm -rfdirectly - Verify: Confirm that workflow skills can still read
toolchain.jsonand start normally
④ Post-Delete Self-Check
test -f "$VW_CONFIG_ROOT/toolchain.json" && echo "Contract still present ✓"
Contract present → workflow unaffected. Contract missing → accidental deletion; restore from backup.
When a user asks "can I just delete it?", answer by explaining the three options and their trade-offs, not just "yes."
8. Common Errors
| Symptom | Root Cause | Fix |
|---|---|---|
| LMMS renders completely silent, no error in logs | stkdir in ~/.lmmsrc.xml doesn't point to rawwaves/ inside the extracted directory | Fix stkdir, then re-run verify.py ③ |
npm install / pip install fails with ENOSPC | TMPDIR is on a tiny 10MB /tmp tmpfs | export TMPDIR=<large disk>; the tmpdir field in the contract is for this purpose |
| Remotion render times out or page freezes mid-render | Too many concurrent processes maxing out memory (4×1080p pages) | Lower --concurrency, render long videos in segments |
| AppImage won't run | Sandbox lacks /dev/fuse | Use --appimage-extract to unpack, then run AppRun |
| LMMS refuses to start | id shows root inside sandbox | Add --allowroot |
edge-tts reports WSServerHandshakeError 403 | Version too old (not a network issue) | pip install --upgrade edge-tts, then sync system clock |
More in docs/05-Troubleshooting.md.
9. Handoff To Whom
After configuration is complete, the next step is the workflow skill:
skills/ideaform/SKILL.md
It will first read the toolchain.json file written by this skill. Handoff message:
Environment configured and verified. Contract at
<path>. Now switch to the workflow skill to start production.