Compare commits

..

2 Commits

Author SHA1 Message Date
0b308ed8be fix(install_opencode): emit all variants, spec-compliant frontmatter
Agent emission was only writing general.json for each persona (29 files),
skipping 82 variants. Non-general variants now install as:
  <codename>-<variant>.md  with  mode: subagent + hidden: true

Key changes to install_opencode agent-emission half:
- Loop every *.json in each persona dir, not just general.json
- Enforce opencode identifier regex ^[a-z0-9]+(-[a-z0-9]+)*$ with sanitizer
- Non-general variants are always subagent (hidden:true is undefined on
  mode:primary per opencode docs); permission tier still follows domain
- Add permission.task block gating subagent dispatch
- Wrap description in double quotes with backslash/quote escaping so any
  special chars (&, :, quotes) can't corrupt the YAML frontmatter
- Variant identity surfaced in both description ("Variant: x") and body
  header "[x]" so prompts self-identify

Stale-agent cleanup via sidecar manifest (.personas-manifest.json):
prior emission list is tracked so re-runs prune removed variants without
touching any hand-authored agents in agents/.

Result: 29 -> 111 agents installed, 9 primary + 102 subagent, all
picker-clean (Tab cycles 9 canonical offensive personas; variants reach
via @codename-variant or task dispatch).

Skills-install half intentionally untouched — direct-to-active remains
the correct default for users who don't layer opc-skills on top.
2026-04-18 19:12:11 +03:00
salvacybersec
f2f90abf13 docs: update README + CLAUDE.md for OpenCode + InternalAllTheThings
- Add OpenCode as 7th install target with topic filter docs
- Add InternalAllTheThings (168 AD/red team docs) to shared library listing
- Update skill count 795→796, community-skills 701→703
- Add OpenCode integration section with CLI examples
- Add build output rows for OpenCode agents/skills
- Platform count 6→7

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 11:44:58 +03:00
3 changed files with 166 additions and 71 deletions

View File

@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## 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
@@ -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):
- `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.)
- `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.)
- `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)
@@ -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
- `osint-sources/` — OSINT master reference and investigation templates
- `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/`):
- `escalation_graph.json` — cross-persona handoff map extracted from Boundaries sections

View File

@@ -2,7 +2,7 @@
> Platform-agnostic system prompt library for LLM agents.
> 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
@@ -47,8 +47,8 @@
│ └─ Heimd (Product Manager)
└──── SHARED LIBRARY ────────────────────────────────────
795 skills │ 58 brand designs │ 16 kali-tools
Auto-install: Claude · Antigravity · Gemini · OpenClaw · Paperclip
796 skills │ 58 brand designs │ 16 kali-tools │ 168 AD/redteam docs
Auto-install: Claude · Antigravity · Gemini · OpenClaw · OpenCode · Paperclip
```
## Quick Start
@@ -190,7 +190,8 @@ personas/
├── _shared/ # Shared knowledge bases (skipped in persona build)
│ ├── skills/ (42) # OpenClaw + kali-claw shared skills
│ ├── 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...)
│ ├── ui-ux-pro-max/ # BM25 search engine + 14 CSV data files
│ ├── paperclip-agents/(23) # Company agents (Odin/CEO, Thor/CTO, Freya/CMO...)
@@ -276,10 +277,12 @@ Escalation paths to other personas
```bash
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 gemini # deploy as Gemini Gems
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 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 |
| OpenClaw | `generated/_openclaw/` | IDENTITY.md + individual personas |
| 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
@@ -329,6 +334,20 @@ Persona files can reference config values:
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
### 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 |
| **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 |
| **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 |
@@ -449,11 +469,12 @@ Skills are auto-mapped to personas during build. Each persona's JSON/YAML output
| Personas | 29 |
| Total variants | 111 |
| Prompt content | 59,712 words |
| Shared skills | 795 |
| Shared skills | 796 |
| Design brands | 58 |
| Kali tool docs | 16 |
| AD/Red team docs | 168 (InternalAllTheThings) |
| 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 |
## License

195
build.py
View File

@@ -1394,79 +1394,152 @@ def install_opencode(
}
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()):
if not persona_dir.is_dir() or persona_dir.name.startswith("_"):
continue
general_json = persona_dir / "general.json"
if not general_json.exists():
continue
data = json.loads(general_json.read_text(encoding="utf-8"))
codename = data.get("codename", persona_dir.name)
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", [])
for variant_json in sorted(persona_dir.glob("*.json")):
try:
data = json.loads(variant_json.read_text(encoding="utf-8"))
except json.JSONDecodeError:
continue
if not data.get("codename"):
continue
soul = data.get("sections", {}).get("soul", "")
methodology = data.get("sections", {}).get("methodology", "")
behavior = data.get("sections", {}).get("behavior_rules", "")
codename = data["codename"]
variant = data.get("variant") or "general"
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"
body += f"Domain: {domain} | Tone: {tone}\n\n"
if quote:
body += f'> "{quote}"\n\n'
if soul:
body += "## Soul\n" + soul.strip() + "\n\n"
if methodology:
body += "## Methodology\n" + methodology.strip() + "\n\n"
if behavior:
body += "## Behavior\n" + behavior.strip() + "\n\n"
if skills:
body += "## Mapped Skills\n" + ", ".join(skills) + "\n"
# opencode agent identifier: ^[a-z0-9]+(-[a-z0-9]+)*$
agent_ident = codename if variant == "general" else f"{codename}-{variant}"
agent_ident = agent_ident.lower()
if not ident_re.match(agent_ident):
sanitized = re.sub(r"[^a-z0-9]+", "-", agent_ident).strip("-")
if not ident_re.match(sanitized):
print(f" WARN skipping {codename}/{variant}: cannot sanitize identifier")
continue
agent_ident = sanitized
is_offensive = domain in OFFENSIVE_DOMAINS
mode = "primary" if is_offensive else "subagent"
color = DOMAIN_COLOR.get(domain, "primary")
soul = data.get("sections", {}).get("soul", "")
methodology = data.get("sections", {}).get("methodology", "")
behavior = data.get("sections", {}).get("behavior_rules", "")
# Permission block differs for offensive vs analytical personas.
if is_offensive:
permission_block = (
"permission:\n"
" edit: allow\n"
" bash:\n"
' "*": allow\n'
" webfetch: allow\n"
)
else:
permission_block = (
"permission:\n"
" edit: ask\n"
" bash:\n"
' "*": ask\n'
" webfetch: allow\n"
header = f"You are **{name}** ({address_to}) — {role}"
if variant != "general":
header += f" [{variant}]"
body = header + ".\n\n"
body += f"Domain: {domain} | Tone: {tone}\n\n"
if quote:
body += f'> "{quote}"\n\n'
if soul:
body += "## Soul\n" + soul.strip() + "\n\n"
if methodology:
body += "## Methodology\n" + methodology.strip() + "\n\n"
if behavior:
body += "## Behavior\n" + behavior.strip() + "\n\n"
if skills:
body += "## Mapped Skills\n" + ", ".join(skills) + "\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(
"\n", " "
)
agent_filename = f"{agent_ident}.md"
(agents_dir / agent_filename).write_text(
frontmatter + body, encoding="utf-8"
)
emitted_agents.add(agent_filename)
agent_count += 1
frontmatter = (
"---\n"
f"description: {desc}\n"
f"mode: {mode}\n"
"temperature: 0.3\n"
f"color: {color}\n"
f"{permission_block}"
"---\n\n"
)
agent_file = agents_dir / f"{codename}.md"
agent_file.write_text(frontmatter + body, encoding="utf-8")
agent_count += 1
# Remove stale agents we emitted on a previous run but not this one. Track
# via sidecar manifest so hand-authored files in agents/ are never touched.
manifest_path = agents_dir / ".personas-manifest.json"
previously_emitted: set[str] = set()
if manifest_path.exists():
try:
previously_emitted = set(
json.loads(manifest_path.read_text(encoding="utf-8")).get("agents", [])
)
except Exception:
previously_emitted = set()
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
# name+description frontmatter (same as Claude).