sync-tools
$
npx mdskill add doodledood/manifest-dev/sync-toolsGenerate distribution packages for OpenCode and Codex CLI from the Claude Code plugin.
SKILL.md
.github/skills/sync-toolsView on GitHub ↗
---
name: sync-tools
description: 'Generate multi-CLI distribution packages from the Claude Code plugin. Converts skills, agents, and hooks for OpenCode and Codex CLI under dist/. Run after changing plugin components to keep distributions in sync.'
user-invocable: true
---
# /sync-tools — Multi-CLI Distribution Generator
Generate distribution packages for OpenCode and Codex CLI from the Claude Code plugin.
**Input**: `$ARGUMENTS` — optional CLI name (opencode, codex) to sync one target. Empty = both.
## Paths
| Role | Path |
|------|------|
| Sources (read-only) | `claude-plugins/manifest-dev/` and `claude-plugins/manifest-dev-tools/` |
| Output | `dist/{opencode,codex}/` |
| Conversion rules | `.claude/skills/sync-tools/references/{cli}-cli.md` |
| Per-CLI sync state | `dist/{cli}/.sync-meta.json` (records last-synced source SHA — drives diff-first workflow) |
| Per-CLI namespace metadata | `dist/{cli}/component-namespaces.json` (component name → install suffix) |
| GitHub repo | `doodledood/manifest-dev` |
## Scope
Sync only these source payloads:
- `claude-plugins/manifest-dev/` — core workflow skills, agents, hooks, context.
- `claude-plugins/manifest-dev-tools/` — tools skills (`skills/`) and tools agents (`agents/`); no hooks/context.
Never sync other plugins (e.g., `manifest-dev-collab` — uses Agent Teams/Slack, inherently incompatible). Never modify source files. Skip `sync-tools` skill from output (meta-tool).
Each generated component must carry plugin ownership in `component-namespaces.json`. Install-time namespacing comes from that metadata, not from a single global suffix:
- `manifest-dev` components install with `-manifest-dev`
- `manifest-dev-tools` components install with `-manifest-dev-tools`
Regenerate `component-namespaces.json` on every sync from the discovered source components; never hand-maintain it. The file is part of the generated dist contract and must include every distributed skill, agent, and command. If a component exists under `dist/{cli}/skills`, `agents`, or `commands` and is missing from metadata, the sync is incomplete.
## Per-CLI Processing
For each target CLI, read its reference file first. The reference file is **the single source of truth** for conversion rules — tool name mappings, frontmatter format, hook protocol, directory structure, and limitations. Do not duplicate conversion logic here; follow the reference.
### Diff-first sync (preferred)
Each `dist/{cli}/.sync-meta.json` records the source commit that dist was last synced from:
```json
{
"source_commit": "<sha>",
"source_path": "claude-plugins/manifest-dev",
"source_paths": [
"claude-plugins/manifest-dev",
"claude-plugins/manifest-dev-tools"
],
"synced_at": "<ISO 8601 UTC>"
}
```
On invocation, prefer a delta sync over a full re-sync:
1. Read `dist/{cli}/.sync-meta.json`. If missing, malformed, or the recorded SHA is unreachable from `HEAD` (e.g., rebased away, force-pushed branch), **fall back to full sync** for that CLI.
2. **Force full sync** if any of the following changed between recorded SHA and `HEAD` (these define the substitution rules — any change can affect every dist file):
- `.claude/skills/sync-tools/SKILL.md`
- `.claude/skills/sync-tools/references/{cli}-cli.md`
3. Otherwise compute `git diff --name-status <recorded-sha>..HEAD -- claude-plugins/manifest-dev/ claude-plugins/manifest-dev-tools/` and process each entry:
- **Added / Modified**: re-apply per-CLI substitutions, write to dist counterpart
- **Deleted**: remove dist counterpart (and parent dir if now empty)
- **Renamed**: handle as delete-old + add-new
4. Recompute README component tables and the CLI's context file (`AGENTS.md`) only if the set of skills/agents changed (added/removed/renamed). Body-only edits don't require regenerating these.
5. Regenerate `dist/{cli}/component-namespaces.json` from the current dist component set and source ownership map.
6. After all writes succeed, overwrite `dist/{cli}/.sync-meta.json` with the new HEAD sha and a fresh `synced_at` UTC timestamp. Keep the file even when the diff was empty — the timestamp records "we checked".
The metadata is an **optimization, not a correctness anchor**. When in doubt — unreachable commit, ambiguous rename, mid-rebase repo state, suspicious dist drift — fall back to full sync rather than trusting the recorded SHA.
### Per-component goals
| Component | Goal |
|-----------|------|
| **Skills** | Copy unchanged (Agent Skills Open Standard = universal) from both source payloads. Include all subdirectories. Replace operational CLAUDE.md references (e.g., "write to CLAUDE.md") with CLI context file name per reference file. Replace operational tool-name references in skill body prose with the target CLI's names (e.g., "use the Read tool" → OpenCode `read`, → Codex `read_file`; "run Bash" → OpenCode `bash`, → Codex `shell_command`) — see each reference file's tool-name lookup table. Leave research/reference content unchanged (teaching documents in `references/*.md` that explain Claude Code conventions stay Claude-Code-centric; only operational instructions remap). **Exception 1**: files in `references/execution-modes/` — replace Claude-specific model names (haiku, sonnet, opus) with `inherit`. Model tier routing is Claude Code-only; other CLIs use session model for all tiers. **Exception 2**: lines that surface a session-file path to the user (e.g. `Session: ~/.claude/projects/<dir>/${CLAUDE_SESSION_ID}.jsonl`, "Session JSONL files live at ...") — retarget per the reference file's "Session File Adaptation" section. If the target CLI has no per-session file the agent can locate at runtime, omit the line. |
| **Agents** | Convert frontmatter per reference file — including remapping the `tools:` list to the target CLI's tool keys (see each reference file's tool-name lookup table). Keep prompt body as identical as possible to Claude Code original — categories, actionability filters, severity guidelines, output formats, out-of-scope sections are the core value. Allowed body changes: tool-name references in prose remapped to the target CLI's names (e.g., *"use the Read tool"* → OpenCode `read`, → Codex `read_file`; *"run Bash"* → OpenCode `bash`, → Codex `shell_command`). See each reference file's "Prompt Body Adaptation" / "Phase 2 (LLM)" section for the per-CLI vocabulary. Other allowed changes: namespace suffix, context file name (CLAUDE.md → CLI name per reference file), genuinely unsupported features (document as limitation, don't remove). |
| **Hooks** | Adapt to the target hook protocol per reference file. Generate complete, installable hook/plugin payloads. Document unavoidable runtime gaps, but do not ship stubs or require manual post-install wiring. |
| **Commands** | Generate command files from user-invocable skills (`user-invocable: true`, the default) in both source payloads. Per reference file. |
| **Context file** | Workflow overview + agent descriptions in the CLI's native context format per reference file. |
| **README** | Component table, install instructions, feature parity table, required config, link to GitHub repo. |
| **Install script** | `install.sh` and `install_helpers.py` are **infrastructure files** — update incrementally, never regenerate. They contain logic not derivable from source (piped execution detection, temp dir cloning, cleanup traps, argument parsing, settings merging). Only modify sections that reflect changed components (step counts, file lists, component names). |
| **CLI extras** | Extension manifests, plugin configs, execution rules — per reference file. |
| **Namespace metadata** | Regenerate `component-namespaces.json` from source ownership every run. Every distributed component must appear exactly once under its component type with the suffix for its owning plugin. |
### README install section
Remote install (no clone needed) must be the primary method. Use the repo from the Paths table with the standard skills installer (`npx skills add`). Include CLI-native install methods from the reference file as alternatives. Full distribution install via `install.sh` as secondary.
### Install script constraints
- **Incremental updates only**: `install.sh` and `install_helpers.py` are maintained infrastructure — read existing content, modify only what changed. Never rewrite from scratch. Regression risk: infrastructure logic (piped `curl | bash` support, trap handlers, argument parsing) is invisible to component-level sync and will be lost on regeneration.
- Idempotent (safe to re-run for updates)
- Never overwrite user-owned shared entrypoints or config files; merge shared config additively
- Only replace installer-managed namespaced files or extension-private files owned by this distribution
- Full setup must complete from `install.sh` alone; no required manual follow-up steps
- Install scripts namespace components at install time via `install_helpers.py` using `component-namespaces.json`; never assume a single global suffix.
- Installer helpers must discover skills, agents, and commands from `dist/{cli}/` at runtime. Do not maintain hardcoded component-name lists or hardcoded installed counts; add/remove/rename in `dist/` must be enough for the installer to pick up the change.
- Selective cleanup before install is a full-state sync for metadata-owned suffixes (`*-manifest-dev*`, `*-manifest-dev-tools*`): removed components disappear, changed components are overwritten from dist, and newly added components appear. Never delete shared directories or unrelated user files.
- `dist/` keeps original names; namespacing is an install-time concern
## Constraints
| Constraint | Why |
|-----------|-----|
| `install.sh` and `install_helpers.py` are infrastructure — update incrementally, never regenerate | These contain manually-added logic (piped execution, traps, arg parsing) not derivable from source. Regeneration causes silent regressions. |
| Frontmatter conversion must work in both bash and zsh | macOS default shell is zsh; bash-only constructs break |
| Reference files are authoritative for conversion rules | Avoids two sources of truth — update one place |
| Unmapped agent tools pass through unchanged | Target CLI ignores unknown tools gracefully |
| Empty component sets skip gracefully | Codex has no hooks — note in README, don't error |
| Agent/skill prompt bodies stay faithful to Claude Code originals | Prompts are carefully crafted — don't simplify, rewrite, or truncate for other CLIs |
| Always update `dist/{cli}/.sync-meta.json` at end of run | The recorded SHA is what next run's diff-first path keys on. Skipping the update silently degrades future syncs to full re-syncs. |
## Progress Log
Write to `/tmp/sync-tools-{timestamp}.md` after each CLI: counts, warnings, what was generated. Read the full log before writing the final summary.
## Output
Summary table after all CLIs processed:
| CLI | Skills | Agents | Hooks | Commands | Status |
|-----|--------|--------|-------|----------|--------|
| OpenCode | N | N converted | N adapted | N | Complete |
| Codex | N | AGENTS.md + N TOML | none | — | Complete |
More from doodledood/manifest-dev
- autoEnd-to-end autonomous execution: figure-out → define → do, chained without manual approval gates. Use when you want to define and execute without intervention during planning, when the user asks for autonomous or end-to-end work, says just build it, or asks to tend or babysit a PR.
- auto-optimize-promptIteratively auto-optimize a prompt until no issues remain. Uses prompt-reviewer in a loop, asks user for ambiguities, applies fixes via prompt-engineering skill. Runs until converged.
- compress-promptCompresses prompts/skills into minimal goal-focused instructions. Trusts the model, drops what it already knows, maximizes action space. Use when asked to compress, condense, or minimize a prompt.
- defineManifest builder. Turns shared understanding into a verifiable Manifest with Deliverables, Acceptance Criteria, Global Invariants, and Approach. Use when planning features, scoping refactors, debugging complex issues, or when the user asks to define, scope, plan, spec out, make a manifest, or break down a task.
- doneCompletion marker for the /do workflow. Outputs a plain-prose summary of what was built. Called by /do after every Acceptance Criterion and Global Invariant verifies PASS, when the manifest is complete, all criteria pass, or the workflow needs to wrap up with a completion summary.
- escalateStructured escalation when /do hits an unrecoverable blocker. Surfaces what was tried, why it failed, and what the user can decide. Called by /do when work is blocked, cannot proceed, hits an unrecoverable failure, needs a user decision, or gets stuck.
- exampleAnalyzes the current project structure and tech stack. Use when asked to explore, understand, or summarize a project. Trigger terms: project overview, analyze codebase, what is this project.
- figure-outFigure things out together — any topic, problem, or idea. Presses relentlessly until shared understanding is reached. Use when you need to understand before acting, when figuring it out is the goal, or when the user asks to think through a decision, dig deeper, press an assumption, investigate why something is happening, or work through a problem.
- figure-out-teamDrive a multi-party deliberation in a Slack channel or thread. The agent is an involved orchestrator — presses rigorously, brings evidence, names trade-offs, surfaces disagreements, advances when answers cohere; owner-by-Slack-handle overrules. Use when the people involved cannot all sit in one chat, when deliberation has to happen in Slack, or when the user asks to figure out with the team, press a group asynchronously, or get the team aligned.
- harden-task-fileHarden /define task guidance files for one-shot quality. Iterates: orthogonality gap analysis, user-approved additions, prompt review, fix, converge. Use when a task file needs comprehensive coverage or "harden task file".