salvacybersec 2120b7b48c feat: feynman target + interactive target picker + fzf preview fix
- Add feynman as third target (~/.feynman/agent/agents) alongside opencode
  and claude. Default targets now: opencode,claude,feynman. Each target
  gets its own parked source dir (formats differ: opencode permission/mode,
  claude PascalCase tools, feynman lowercase tools + thinking/output).
- Fix fzf {} preview shell-escape bug: {} in fzf is shell-escaped, so
  "$PARKED/{}.md" embedded literal quotes into the path and broke preview.
  Switched to "$PARKED"/{}.md across all 8 preview lines.
- pick: union-of-parked across all 3 targets for category list (so a
  feynman-only agent like researcher is reachable). After agent multi-select
  (rows annotated [oc,cl,fy] showing parked-in targets), prompt target
  picker (all / opencode / claude / feynman, TAB for multi).
- disable-pick: rewritten to show union of actives across all 3 targets
  with [oc,cl,fy] indicators, then target picker for which to disable from.
- cmd_status: 3-target counts (parked + active) with all-3 intersection.
- reindex: tracks parked.{opencode,claude,feynman} + active list across 3.
- New env vars: OPC_AGENTS_FEYNMAN_PARKED, OPC_AGENTS_FEYNMAN_ACTIVE.
2026-05-01 13:14:06 +03:00
2026-04-30 21:52:24 +03:00

opc-agents

Multi-target agent manager for opencode + Claude Code + Feynman. Per-target parked sources (different formats), shared CLI surface. Companion to opc-skills.

Why

opencode injects every agent's frontmatter into the calling agent's tool registry. With 100+ agents the registry alone burns ~280K tokens of context before the user types a prompt. Park the ones you don't need this week.

opencode, Claude Code, and Feynman use three different agent frontmatter formats:

target tools field extra fields
opencode permission: { edit, bash, webfetch, … } mode: (primary/subagent), temperature:
claude tools: Read, Glob, Grep, … (PascalCase) color:
feynman tools: read, write, grep, … (lowercase) thinking:, output:, defaultProgress:, inheritProjectContext:

opc-agents keeps a separate parked source per target and copies the appropriate format for each --target selection. The upstream personas/build.py pipeline can produce all three formats from one persona definition, so a --target all enable can deliver the same persona to all three platforms in their native format.

Install

ln -s ~/Documents/opc-agents/bin/opc-agents ~/.local/bin/opc-agents

Ensure ~/.local/bin is on your PATH.

Layout it expects

~/Documents/personas/agents-opencode-archive/   # parked, opencode format
  <name>.md       (frontmatter: mode, permission, …)
  INDEX.json + INDEX.md (canonical index — also tracks claude+feynman parked/active)

~/Documents/personas/agents-claude-archive/     # parked, claude format
  <name>.md       (frontmatter: tools: Read, Glob, …)

~/Documents/personas/agents-feynman-archive/    # parked, feynman format
  <name>.md       (frontmatter: tools: read,write,…  thinking, output, defaultProgress)

~/.config/opencode/agents/                      # active, opencode target
~/.claude/agents/                               # active, claude target
~/.feynman/agent/agents/                        # active, feynman target

(~/Documents/opencode-agents-parked is symlinked to personas/agents-opencode-archive for backward compat.)

Override via env:

  • OPC_AGENTS_PARKED — opencode parked source (default personas/agents-opencode-archive)
  • OPC_AGENTS_CLAUDE_PARKED — claude parked source (default personas/agents-claude-archive)
  • OPC_AGENTS_FEYNMAN_PARKED — feynman parked source (default personas/agents-feynman-archive)
  • OPC_AGENTS_ACTIVE — opencode active dir (default ~/.config/opencode/agents)
  • OPC_AGENTS_CLAUDE_ACTIVE — claude active dir (default ~/.claude/agents)
  • OPC_AGENTS_FEYNMAN_ACTIVE — feynman active dir (default ~/.feynman/agent/agents)
  • OPC_AGENTS_TARGETS — comma-separated default targets (default opencode,claude,feynman)

Targets

enable, disable, and disable-all accept --target / -t (opencode, claude, feynman, all, or comma-separated subset). Default is opencode,claude,feynman. both is preserved as a legacy alias for opencode,claude (no feynman).

An agent missing in a target's parked source is skipped with a clear message — there is no automatic format conversion at the opc-agents layer. Cross-format conversion happens upstream in personas/build.py.

Commands

Inspection

status counts of active vs parked across all 3 targets + opencode primary/subagent breakdown
list {active|parked|all} list agent names
categories / cats prefix-based base-persona counts (PARKED)
variants / vars suffix-based variant counts (PARKED) — eg. salva, iran

Single-agent operations

enable [--target T] <name> enable single agent (copy parked → active) in selected targets
disable [--target T] <name> disable single agent (remove from active; keep parked)
disable-all [--target T] [-y|--yes] [--keep-primary] disable every active agent (asks for confirmation)

Bulk by axis

enable-category <prefix> / disable-category <prefix> fzf multi-pick by base persona prefix (eg. frodo, marshal)
enable-variant <suffix> / disable-variant <suffix> bulk by variant suffix (eg. salva, iran, russian-doctrine)
enable-domain <domain> / disable-domain <domain> bulk by Domain: value in description (live scan)
pick fzf: union-parked category → multi-select agents → target picker → enable
disable-pick fzf: union-of-actives → category → multi-select → target picker → disable
search [query] / disable-search fzf fuzzy search across name + mode + domain + variant + description
reindex rebuild INDEX.json / INDEX.md (extracts persona/variant/domain from frontmatter; tracks all 3 targets)

fzf is required for the interactive pickers; jq for the search variants; python3 for reindex.

pick flow

  1. Choose a category from the union of parked agents across all 3 targets (so a feynman-only agent like researcher is reachable via pick)
  2. Multi-select agents — each row shows [parked-in:oc,cl,fy] indicators
  3. Target picker appears: all / opencode / claude / feynmanTAB for multi-select; ENTER on highlighted all (default) sends to all three
  4. cmd_enable copies the appropriate parked file per target; targets without that agent in their parked dir are skipped with [t] not parked message

disable-pick flow

Lists the union of all active agents across the three targets, with each entry annotated [oc,cl,fy] showing where it's currently active. After multi-select, the target picker decides which target(s) to remove from.

Notes

  • Each agent is a single <name>.md file with YAML frontmatter; format depends on target (see table above).
  • disable* commands never delete data — they remove the active copy and keep (or restore) the parked copy. Re-enable with opc-agents enable <name>.
  • --keep-primary on disable-all skips agents with mode: primary (opencode-format only — claude and feynman don't have a mode: field).
  • Common agent prefixes seen in personas: frodo-, marshal-, sentinel-, bastion-, neo-, oracle-, warden-, polyglot-, etc.

Implementation notes

  • fzf placeholder {} is shell-escaped automatically — preview commands use "$PARKED"/{}.md (variable quoted, {} unquoted) so bash concatenation produces a clean path.

Differences from opc-skills

opc-skills opc-agents
Unit directory containing SKILL.md single <name>.md file
Frontmatter fields used name, description, domain, subdomain, tags description, mode, tools, permission
Format per target identical (folder + SKILL.md) different per target (oc / claude / feynman)
Parked source-of-truth one (skills-archive) three (one per target format)
Shared refs sync yes (_platform-mapping.md) n/a
disable-all flags -y -y, --keep-primary
Status breakdown active/parked + opencode primary/subagent counts
Description
Opencode agent enable/disable manager — companion to opc-skills
Readme 77 KiB
Languages
Shell 100%