diff --git a/build.py b/build.py index e0b6823..f11a3b1 100755 --- a/build.py +++ b/build.py @@ -1513,6 +1513,9 @@ def install_opencode( output_dir: Path, shared_dir: Path | None = None, topics: set[str] | None = None, + purge_skills: bool = True, + agents_dest: Path | None = None, + skills_dest: Path | None = None, ): """Install personas to OpenCode as agents + skills. @@ -1529,11 +1532,26 @@ def install_opencode( Args: topics: set of topics to install (see OPENCODE_TOPICS). Defaults to OPENCODE_DEFAULT_TOPICS which drops marketing/biz skills. + purge_skills: when True (default), wipe ~/.config/opencode/skills/ + before installing. Set False (via --no-purge) when this dir is also + managed by an external tool (e.g. opc-skills) — purge would otherwise + delete its work on every build. """ if topics is None: topics = OPENCODE_DEFAULT_TOPICS - agents_dir = Path.home() / ".config" / "opencode" / "agents" - skills_dir = Path.home() / ".config" / "opencode" / "skills" + # Archive mode: agents_dest / skills_dest override the live opencode dirs. + # Used by --install opencode-archive to regenerate the personas archive + # that opc-skills and opc-agents consume as source-of-truth. + if agents_dest is not None: + agents_dir = agents_dest + agents_dir.mkdir(parents=True, exist_ok=True) + else: + agents_dir = Path.home() / ".config" / "opencode" / "agents" + if skills_dest is not None: + skills_dir = skills_dest + skills_dir.mkdir(parents=True, exist_ok=True) + else: + skills_dir = Path.home() / ".config" / "opencode" / "skills" agents_dir.mkdir(parents=True, exist_ok=True) skills_dir.mkdir(parents=True, exist_ok=True) @@ -1719,12 +1737,16 @@ def install_opencode( skipped_topic = 0 # Purge existing skills dir so stale filtered-out skills are removed. - if skills_dir.exists(): + # Skipped when --no-purge is passed (so external tools like opc-skills + # that manage this directory don't get clobbered on every build). + if purge_skills and skills_dir.exists(): import shutil as _shutil for existing in skills_dir.iterdir(): if existing.is_dir(): _shutil.rmtree(existing) + elif not purge_skills: + print(f" OpenCode: --no-purge — preserving existing {skills_dir}/") if shared_dir: for skills_subdir in [ @@ -2107,12 +2129,16 @@ def main(): "gemini", "openclaw", "opencode", + "opencode-archive", "paperclip", "all", ], help="Install generated personas to a target platform. " "'claude' installs persona agents+commands; 'claude-skills' installs " - "shared skills to ~/.claude/skills/ with category filters.", + "shared skills to ~/.claude/skills/ with category filters; " + "'opencode-archive' writes opencode-format agents+skills to " + "personas/agents-opencode-archive/ + personas/skills-archive/ " + "(consumed by opc-skills/opc-agents) without touching ~/.config/opencode/.", ) # --- claude-skills filters -------------------------------------------- parser.add_argument( @@ -2171,6 +2197,13 @@ def main(): "business-pm, uncategorized. " "Default drops marketing/biz. Use 'all' for no filter.", ) + parser.add_argument( + "--no-purge", + action="store_true", + help="For --install opencode: do NOT wipe ~/.config/opencode/skills/ " + "before installing. Use when the directory is also managed by an " + "external tool (e.g. opc-skills) so its enabled skills are preserved.", + ) parser.add_argument( "--search", type=str, @@ -2325,7 +2358,7 @@ def main(): install_gemini(output_dir) elif target == "openclaw": install_openclaw(output_dir) - elif target == "opencode": + elif target in ("opencode", "opencode-archive"): if args.opencode_topics: if args.opencode_topics.strip().lower() == "all": oc_topics = OPENCODE_TOPICS @@ -2337,7 +2370,29 @@ def main(): } else: oc_topics = None # use default - install_opencode(output_dir, shared_dir, topics=oc_topics) + if target == "opencode-archive": + # Source-of-truth layout consumed by opc-skills + opc-agents: + # personas/skills-archive//SKILL.md ← opc-skills reads + # personas/agents-opencode-archive/.md ← opc-agents reads + install_opencode( + output_dir, + shared_dir, + topics=oc_topics, + purge_skills=False, + agents_dest=root / "agents-opencode-archive", + skills_dest=root / "skills-archive", + ) + print( + " opcode-archive: regenerated source-of-truth used by " + "opc-skills + opc-agents. Did NOT touch ~/.config/opencode/." + ) + else: + install_opencode( + output_dir, + shared_dir, + topics=oc_topics, + purge_skills=not args.no_purge, + ) elif target == "paperclip": install_paperclip(output_dir, personas_dir, shared_dir)