Compare commits
2 Commits
448d1cdcd9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b308ed8be | |||
|
|
f2f90abf13 |
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## What This Is
|
## What This Is
|
||||||
|
|
||||||
A platform-agnostic system prompt library for LLM agents. 29 personas across 10 domains, 111 variants, 59,712 words. Includes 795 shared skills, 58 brand design systems, 23 company agents, and auto-install to 7 platforms (Claude, Antigravity, Gemini, OpenClaw, OpenCode, Paperclip, raw).
|
A platform-agnostic system prompt library for LLM agents. 29 personas across 10 domains, 111 variants, 59,712 words. Includes 796 shared skills, 58 brand design systems, 23 company agents, 168 AD/red team attack docs (InternalAllTheThings), and auto-install to 7 platforms (Claude, Antigravity, Gemini, OpenClaw, OpenCode, Paperclip, raw).
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ Optional: `cp config.example.yaml config.yaml` for dynamic variable injection. B
|
|||||||
**Shared library** (`personas/_shared/`): Reusable knowledge bases (skipped during persona build, indexed into outputs):
|
**Shared library** (`personas/_shared/`): Reusable knowledge bases (skipped during persona build, indexed into outputs):
|
||||||
- `skills/` — 42 shared skills from OpenClaw/kali-claw (SKILL.md + references per skill)
|
- `skills/` — 42 shared skills from OpenClaw/kali-claw (SKILL.md + references per skill)
|
||||||
- `paperclip-skills/` — 52 skills from paperclip-docs (ceo-advisor, coding-agent, security-review, etc.)
|
- `paperclip-skills/` — 52 skills from paperclip-docs (ceo-advisor, coding-agent, security-review, etc.)
|
||||||
- `community-skills/` — 701 skills from skills.sh marketplace (shadcn, vercel, marketing, expo, obsidian, impeccable, browser-use, stitch, firecrawl, github, neon, azure, etc.)
|
- `community-skills/` — 703 skills from skills.sh marketplace (shadcn, vercel, olla, expo, etc.) (shadcn, vercel, marketing, expo, obsidian, impeccable, browser-use, stitch, firecrawl, github, neon, azure, etc.)
|
||||||
- `design-md/` — 58 brand DESIGN.md files (Stripe, Claude, Linear, Apple, Vercel, etc.)
|
- `design-md/` — 58 brand DESIGN.md files (Stripe, Claude, Linear, Apple, Vercel, etc.)
|
||||||
- `ui-ux-pro-max/` — BM25 search engine + 14 CSV data files (67 styles, 161 products, 57 fonts)
|
- `ui-ux-pro-max/` — BM25 search engine + 14 CSV data files (67 styles, 161 products, 57 fonts)
|
||||||
- `paperclip-agents/` — 23 company agents (Odin/CEO, Thor/CTO, Freya/CMO, Frigg/COO + 19 team members)
|
- `paperclip-agents/` — 23 company agents (Odin/CEO, Thor/CTO, Freya/CMO, Frigg/COO + 19 team members)
|
||||||
@@ -44,6 +44,7 @@ Optional: `cp config.example.yaml config.yaml` for dynamic variable injection. B
|
|||||||
- `openclaw-personas/` — Original 6 OpenClaw persona definitions + SOUL.md + IDENTITY.md + TOOLS.md
|
- `openclaw-personas/` — Original 6 OpenClaw persona definitions + SOUL.md + IDENTITY.md + TOOLS.md
|
||||||
- `osint-sources/` — OSINT master reference and investigation templates
|
- `osint-sources/` — OSINT master reference and investigation templates
|
||||||
- `ad-attack-tools/` — Active Directory attack chain references
|
- `ad-attack-tools/` — Active Directory attack chain references
|
||||||
|
- `internal-allthethings/` — 168 InternalAllTheThings docs (swisskyrepo): AD attacks (ADCS ESC1-15, Kerberos, NTLM relay, coerce, delegation), red team (access, escalation, evasion, persistence, pivoting), cloud (AWS/Azure/IBM), C2 (Cobalt Strike, Metasploit, Mythic), containers, databases, DevOps CI/CD
|
||||||
|
|
||||||
**Build outputs** (`generated/_index/`):
|
**Build outputs** (`generated/_index/`):
|
||||||
- `escalation_graph.json` — cross-persona handoff map extracted from Boundaries sections
|
- `escalation_graph.json` — cross-persona handoff map extracted from Boundaries sections
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> Platform-agnostic system prompt library for LLM agents.
|
> Platform-agnostic system prompt library for LLM agents.
|
||||||
> 29 personas. 10 domains. 111 variants. 60,000+ words of production-grade prompts.
|
> 29 personas. 10 domains. 111 variants. 60,000+ words of production-grade prompts.
|
||||||
> 795 skills. 58 brand design systems. 16 Kali tool references. Multi-platform auto-install.
|
> 796 skills. 58 brand design systems. 16 Kali tool references. 168 AD/red team attack docs. Multi-platform auto-install.
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─ Neo ─── Phantom ─── Cipher ─── Specter ─── Bastion ─── Vortex ─── Sentinel
|
┌─ Neo ─── Phantom ─── Cipher ─── Specter ─── Bastion ─── Vortex ─── Sentinel
|
||||||
@@ -47,8 +47,8 @@
|
|||||||
│ └─ Heimd (Product Manager)
|
│ └─ Heimd (Product Manager)
|
||||||
│
|
│
|
||||||
└──── SHARED LIBRARY ────────────────────────────────────
|
└──── SHARED LIBRARY ────────────────────────────────────
|
||||||
795 skills │ 58 brand designs │ 16 kali-tools
|
796 skills │ 58 brand designs │ 16 kali-tools │ 168 AD/redteam docs
|
||||||
Auto-install: Claude · Antigravity · Gemini · OpenClaw · Paperclip
|
Auto-install: Claude · Antigravity · Gemini · OpenClaw · OpenCode · Paperclip
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
@@ -190,7 +190,8 @@ personas/
|
|||||||
├── _shared/ # Shared knowledge bases (skipped in persona build)
|
├── _shared/ # Shared knowledge bases (skipped in persona build)
|
||||||
│ ├── skills/ (42) # OpenClaw + kali-claw shared skills
|
│ ├── skills/ (42) # OpenClaw + kali-claw shared skills
|
||||||
│ ├── paperclip-skills/(52) # Paperclip company skills (CEO, coding, devops...)
|
│ ├── paperclip-skills/(52) # Paperclip company skills (CEO, coding, devops...)
|
||||||
│ ├── community-skills/(701)# skills.sh marketplace (shadcn, vercel, marketing...)
|
│ ├── community-skills/(703)# skills.sh marketplace (shadcn, vercel, olla, marketing...)
|
||||||
|
│ ├── internal-allthethings/ # InternalAllTheThings — 168 AD/red team attack docs (swisskyrepo)
|
||||||
│ ├── design-md/ (58) # Brand DESIGN.md files (Stripe, Claude, Linear...)
|
│ ├── design-md/ (58) # Brand DESIGN.md files (Stripe, Claude, Linear...)
|
||||||
│ ├── ui-ux-pro-max/ # BM25 search engine + 14 CSV data files
|
│ ├── ui-ux-pro-max/ # BM25 search engine + 14 CSV data files
|
||||||
│ ├── paperclip-agents/(23) # Company agents (Odin/CEO, Thor/CTO, Freya/CMO...)
|
│ ├── paperclip-agents/(23) # Company agents (Odin/CEO, Thor/CTO, Freya/CMO...)
|
||||||
@@ -276,10 +277,12 @@ Escalation paths to other personas
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 build.py # build all → generated/
|
python3 build.py # build all → generated/
|
||||||
python3 build.py --install claude # deploy as Claude Code slash commands
|
python3 build.py --install claude # deploy as Claude Code slash commands + agents
|
||||||
|
python3 build.py --install claude-skills # deploy shared skills to ~/.claude/skills/
|
||||||
python3 build.py --install antigravity # deploy to Antigravity IDE
|
python3 build.py --install antigravity # deploy to Antigravity IDE
|
||||||
python3 build.py --install gemini # deploy as Gemini Gems
|
python3 build.py --install gemini # deploy as Gemini Gems
|
||||||
python3 build.py --install openclaw # deploy to OpenClaw format
|
python3 build.py --install openclaw # deploy to OpenClaw format
|
||||||
|
python3 build.py --install opencode # deploy 29 agents + 1011 skills to OpenCode
|
||||||
python3 build.py --install paperclip # deploy to Paperclip (52 agents + 73 skills)
|
python3 build.py --install paperclip # deploy to Paperclip (52 agents + 73 skills)
|
||||||
python3 build.py --install all # deploy to all platforms
|
python3 build.py --install all # deploy to all platforms
|
||||||
```
|
```
|
||||||
@@ -303,6 +306,8 @@ Reads `config.yaml` (if present) and generates three formats per variant:
|
|||||||
| Gemini Gems | `generated/_gems/` | Google AI Studio format |
|
| Gemini Gems | `generated/_gems/` | Google AI Studio format |
|
||||||
| OpenClaw | `generated/_openclaw/` | IDENTITY.md + individual personas |
|
| OpenClaw | `generated/_openclaw/` | IDENTITY.md + individual personas |
|
||||||
| Paperclip | `generated/_paperclip/` | 52 agents + 73 skills (Hermes format) |
|
| Paperclip | `generated/_paperclip/` | 52 agents + 73 skills (Hermes format) |
|
||||||
|
| OpenCode agents | `~/.config/opencode/agents/` | 29 native subagents (md + YAML frontmatter) |
|
||||||
|
| OpenCode skills | `~/.config/opencode/skills/` | 1011 skills (topic-filtered, no marketing/biz) |
|
||||||
|
|
||||||
### Config-Driven Customization
|
### Config-Driven Customization
|
||||||
|
|
||||||
@@ -329,6 +334,20 @@ Persona files can reference config values:
|
|||||||
|
|
||||||
Without `config.yaml`, personas build with their static content — no config required.
|
Without `config.yaml`, personas build with their static content — no config required.
|
||||||
|
|
||||||
|
### OpenCode Integration
|
||||||
|
|
||||||
|
OpenCode (`opencode-ai`) gets 29 agents and 1011 topic-filtered skills:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 build.py --install opencode # default: security + dev + AI + ops
|
||||||
|
python3 build.py --install opencode --opencode-topics all # everything (1530)
|
||||||
|
python3 build.py --install opencode --opencode-topics security-offensive,security-defensive,ai-llm-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
**Topics**: security-offensive, security-defensive, security-cloud, security-specialized, security-iam, security-network, security-general, ai-llm-dev, coding-backend, coding-frontend, coding-tools, cloud-infra, database, browser-scrape, ops-sysadmin, osint-intel, marketing-content, business-pm, uncategorized.
|
||||||
|
|
||||||
|
Default drops marketing/business-pm/uncategorized (~514 skills). Agents use OpenCode's markdown+YAML format with `mode: primary|subagent` and `permission:` blocks. OpenCode also reads `~/.claude/skills/` natively.
|
||||||
|
|
||||||
## Integration
|
## Integration
|
||||||
|
|
||||||
### Raw System Prompt
|
### Raw System Prompt
|
||||||
@@ -435,7 +454,8 @@ The `_shared/` directory contains reusable knowledge bases from multiple sources
|
|||||||
|--------|---------|-------|
|
|--------|---------|-------|
|
||||||
| **OpenClaw + kali-claw** | Security/intelligence skills (pentest, OSINT, CTI) | 42 skills |
|
| **OpenClaw + kali-claw** | Security/intelligence skills (pentest, OSINT, CTI) | 42 skills |
|
||||||
| **Paperclip (Born2beRoot)** | Company management skills (CEO, coding, devops) | 52 skills |
|
| **Paperclip (Born2beRoot)** | Company management skills (CEO, coding, devops) | 52 skills |
|
||||||
| **skills.sh marketplace** | Community skills (shadcn, vercel, marketing, expo) | 701 skills |
|
| **skills.sh marketplace** | Community skills (shadcn, vercel, olla, expo) | 703 skills |
|
||||||
|
| **InternalAllTheThings** | AD attacks, red team, ADCS, Kerberos, NTLM relay (swisskyrepo) | 168 docs |
|
||||||
| **awesome-design-md** | Brand design systems (Stripe, Claude, Linear, Apple) | 58 brands |
|
| **awesome-design-md** | Brand design systems (Stripe, Claude, Linear, Apple) | 58 brands |
|
||||||
| **ui-ux-pro-max** | BM25 search engine for UI/UX decisions | 14 data files |
|
| **ui-ux-pro-max** | BM25 search engine for UI/UX decisions | 14 data files |
|
||||||
| **Kali Linux** | Tool reference docs (nmap, hashcat, AD, wireless) | 16 docs |
|
| **Kali Linux** | Tool reference docs (nmap, hashcat, AD, wireless) | 16 docs |
|
||||||
@@ -449,11 +469,12 @@ Skills are auto-mapped to personas during build. Each persona's JSON/YAML output
|
|||||||
| Personas | 29 |
|
| Personas | 29 |
|
||||||
| Total variants | 111 |
|
| Total variants | 111 |
|
||||||
| Prompt content | 59,712 words |
|
| Prompt content | 59,712 words |
|
||||||
| Shared skills | 795 |
|
| Shared skills | 796 |
|
||||||
| Design brands | 58 |
|
| Design brands | 58 |
|
||||||
| Kali tool docs | 16 |
|
| Kali tool docs | 16 |
|
||||||
|
| AD/Red team docs | 168 (InternalAllTheThings) |
|
||||||
| Paperclip agents | 23 |
|
| Paperclip agents | 23 |
|
||||||
| Target platforms | 6 (Claude, Antigravity, Gemini, OpenClaw, Paperclip, raw) |
|
| Target platforms | 7 (Claude, Antigravity, Gemini, OpenClaw, OpenCode, Paperclip, raw) |
|
||||||
| Output formats | 3 (.prompt.md, .yaml, .json) + platform-specific |
|
| Output formats | 3 (.prompt.md, .yaml, .json) + platform-specific |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|||||||
195
build.py
195
build.py
@@ -1394,79 +1394,152 @@ def install_opencode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
agent_count = 0
|
agent_count = 0
|
||||||
|
emitted_agents: set[str] = set()
|
||||||
|
ident_re = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$")
|
||||||
|
|
||||||
|
# Emit one agent file per variant. General → <codename>.md (picker-visible).
|
||||||
|
# Non-general → <codename>-<variant>.md with hidden:true so it's
|
||||||
|
# task-dispatchable by name without cluttering the picker.
|
||||||
for persona_dir in sorted(output_dir.iterdir()):
|
for persona_dir in sorted(output_dir.iterdir()):
|
||||||
if not persona_dir.is_dir() or persona_dir.name.startswith("_"):
|
if not persona_dir.is_dir() or persona_dir.name.startswith("_"):
|
||||||
continue
|
continue
|
||||||
general_json = persona_dir / "general.json"
|
|
||||||
if not general_json.exists():
|
|
||||||
continue
|
|
||||||
|
|
||||||
data = json.loads(general_json.read_text(encoding="utf-8"))
|
for variant_json in sorted(persona_dir.glob("*.json")):
|
||||||
codename = data.get("codename", persona_dir.name)
|
try:
|
||||||
name = data.get("name", codename.title())
|
data = json.loads(variant_json.read_text(encoding="utf-8"))
|
||||||
role = data.get("role", "Specialist")
|
except json.JSONDecodeError:
|
||||||
domain = data.get("domain", "")
|
continue
|
||||||
tone = data.get("tone", "")
|
if not data.get("codename"):
|
||||||
address_to = data.get("address_to", "")
|
continue
|
||||||
quote = data.get("quote", "")
|
|
||||||
skills = data.get("skills", [])
|
|
||||||
|
|
||||||
soul = data.get("sections", {}).get("soul", "")
|
codename = data["codename"]
|
||||||
methodology = data.get("sections", {}).get("methodology", "")
|
variant = data.get("variant") or "general"
|
||||||
behavior = data.get("sections", {}).get("behavior_rules", "")
|
name = data.get("name", codename.title())
|
||||||
|
role = data.get("role", "Specialist")
|
||||||
|
domain = data.get("domain", "")
|
||||||
|
tone = data.get("tone", "")
|
||||||
|
address_to = data.get("address_to", "")
|
||||||
|
quote = data.get("quote", "")
|
||||||
|
skills = data.get("skills", [])
|
||||||
|
|
||||||
body = f"You are **{name}** ({address_to}) — {role}.\n\n"
|
# opencode agent identifier: ^[a-z0-9]+(-[a-z0-9]+)*$
|
||||||
body += f"Domain: {domain} | Tone: {tone}\n\n"
|
agent_ident = codename if variant == "general" else f"{codename}-{variant}"
|
||||||
if quote:
|
agent_ident = agent_ident.lower()
|
||||||
body += f'> "{quote}"\n\n'
|
if not ident_re.match(agent_ident):
|
||||||
if soul:
|
sanitized = re.sub(r"[^a-z0-9]+", "-", agent_ident).strip("-")
|
||||||
body += "## Soul\n" + soul.strip() + "\n\n"
|
if not ident_re.match(sanitized):
|
||||||
if methodology:
|
print(f" WARN skipping {codename}/{variant}: cannot sanitize identifier")
|
||||||
body += "## Methodology\n" + methodology.strip() + "\n\n"
|
continue
|
||||||
if behavior:
|
agent_ident = sanitized
|
||||||
body += "## Behavior\n" + behavior.strip() + "\n\n"
|
|
||||||
if skills:
|
|
||||||
body += "## Mapped Skills\n" + ", ".join(skills) + "\n"
|
|
||||||
|
|
||||||
is_offensive = domain in OFFENSIVE_DOMAINS
|
soul = data.get("sections", {}).get("soul", "")
|
||||||
mode = "primary" if is_offensive else "subagent"
|
methodology = data.get("sections", {}).get("methodology", "")
|
||||||
color = DOMAIN_COLOR.get(domain, "primary")
|
behavior = data.get("sections", {}).get("behavior_rules", "")
|
||||||
|
|
||||||
# Permission block differs for offensive vs analytical personas.
|
header = f"You are **{name}** ({address_to}) — {role}"
|
||||||
if is_offensive:
|
if variant != "general":
|
||||||
permission_block = (
|
header += f" [{variant}]"
|
||||||
"permission:\n"
|
body = header + ".\n\n"
|
||||||
" edit: allow\n"
|
body += f"Domain: {domain} | Tone: {tone}\n\n"
|
||||||
" bash:\n"
|
if quote:
|
||||||
' "*": allow\n'
|
body += f'> "{quote}"\n\n'
|
||||||
" webfetch: allow\n"
|
if soul:
|
||||||
)
|
body += "## Soul\n" + soul.strip() + "\n\n"
|
||||||
else:
|
if methodology:
|
||||||
permission_block = (
|
body += "## Methodology\n" + methodology.strip() + "\n\n"
|
||||||
"permission:\n"
|
if behavior:
|
||||||
" edit: ask\n"
|
body += "## Behavior\n" + behavior.strip() + "\n\n"
|
||||||
" bash:\n"
|
if skills:
|
||||||
' "*": ask\n'
|
body += "## Mapped Skills\n" + ", ".join(skills) + "\n"
|
||||||
" webfetch: allow\n"
|
|
||||||
|
is_offensive = domain in OFFENSIVE_DOMAINS
|
||||||
|
# Only general variants can be primary (Tab-cycled, top-level).
|
||||||
|
# All non-general variants are subagents so hidden:true is defined
|
||||||
|
# per opencode spec ("only applies to mode: subagent") and the Tab
|
||||||
|
# cycle stays restricted to canonical personas.
|
||||||
|
if variant == "general" and is_offensive:
|
||||||
|
mode = "primary"
|
||||||
|
else:
|
||||||
|
mode = "subagent"
|
||||||
|
color = DOMAIN_COLOR.get(domain, "primary")
|
||||||
|
|
||||||
|
# Tier-based permissions. task:"*" gates subagent dispatch so a
|
||||||
|
# compromised subagent can't silently escalate into another.
|
||||||
|
if is_offensive:
|
||||||
|
permission_block = (
|
||||||
|
"permission:\n"
|
||||||
|
" edit: allow\n"
|
||||||
|
" bash:\n"
|
||||||
|
' "*": allow\n'
|
||||||
|
" webfetch: allow\n"
|
||||||
|
" task:\n"
|
||||||
|
' "*": allow\n'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
permission_block = (
|
||||||
|
"permission:\n"
|
||||||
|
" edit: ask\n"
|
||||||
|
" bash:\n"
|
||||||
|
' "*": ask\n'
|
||||||
|
" webfetch: allow\n"
|
||||||
|
" task:\n"
|
||||||
|
' "*": ask\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
if variant == "general":
|
||||||
|
desc_raw = f"{name} ({address_to}) — {role}. Domain: {domain}."
|
||||||
|
else:
|
||||||
|
desc_raw = (
|
||||||
|
f"{name} ({address_to}) — {role}. "
|
||||||
|
f"Variant: {variant}. Domain: {domain}."
|
||||||
|
)
|
||||||
|
desc_safe = desc_raw.replace("\n", " ").replace("\r", " ")
|
||||||
|
desc_escaped = desc_safe.replace("\\", "\\\\").replace('"', '\\"')
|
||||||
|
|
||||||
|
hidden_line = "hidden: true\n" if variant != "general" else ""
|
||||||
|
|
||||||
|
frontmatter = (
|
||||||
|
"---\n"
|
||||||
|
f'description: "{desc_escaped}"\n'
|
||||||
|
f"mode: {mode}\n"
|
||||||
|
f"{hidden_line}"
|
||||||
|
"temperature: 0.3\n"
|
||||||
|
f"color: {color}\n"
|
||||||
|
f"{permission_block}"
|
||||||
|
"---\n\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
desc = f"{name} ({address_to}) — {role}. Domain: {domain}.".replace(
|
agent_filename = f"{agent_ident}.md"
|
||||||
"\n", " "
|
(agents_dir / agent_filename).write_text(
|
||||||
)
|
frontmatter + body, encoding="utf-8"
|
||||||
|
)
|
||||||
|
emitted_agents.add(agent_filename)
|
||||||
|
agent_count += 1
|
||||||
|
|
||||||
frontmatter = (
|
# Remove stale agents we emitted on a previous run but not this one. Track
|
||||||
"---\n"
|
# via sidecar manifest so hand-authored files in agents/ are never touched.
|
||||||
f"description: {desc}\n"
|
manifest_path = agents_dir / ".personas-manifest.json"
|
||||||
f"mode: {mode}\n"
|
previously_emitted: set[str] = set()
|
||||||
"temperature: 0.3\n"
|
if manifest_path.exists():
|
||||||
f"color: {color}\n"
|
try:
|
||||||
f"{permission_block}"
|
previously_emitted = set(
|
||||||
"---\n\n"
|
json.loads(manifest_path.read_text(encoding="utf-8")).get("agents", [])
|
||||||
)
|
)
|
||||||
agent_file = agents_dir / f"{codename}.md"
|
except Exception:
|
||||||
agent_file.write_text(frontmatter + body, encoding="utf-8")
|
previously_emitted = set()
|
||||||
agent_count += 1
|
stale = sorted(previously_emitted - emitted_agents)
|
||||||
|
for name_ in stale:
|
||||||
|
stale_path = agents_dir / name_
|
||||||
|
if stale_path.exists():
|
||||||
|
stale_path.unlink()
|
||||||
|
manifest_path.write_text(
|
||||||
|
json.dumps(
|
||||||
|
{"agents": sorted(emitted_agents)}, indent=2, ensure_ascii=False
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
if stale:
|
||||||
|
print(f" OpenCode: pruned {len(stale)} stale agent file(s)")
|
||||||
|
|
||||||
# Install shared skills with topic filter. OpenCode reads SKILL.md with
|
# Install shared skills with topic filter. OpenCode reads SKILL.md with
|
||||||
# name+description frontmatter (same as Claude).
|
# name+description frontmatter (same as Claude).
|
||||||
|
|||||||
Reference in New Issue
Block a user