- 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.
133 lines
7.3 KiB
Markdown
133 lines
7.3 KiB
Markdown
# opc-agents
|
|
|
|
**Multi-target** agent manager for **opencode** + **Claude Code** + **Feynman**. Per-target parked sources (different formats), shared CLI surface. Companion to [`opc-skills`](https://gitea.taygun.net.tr/salvacybersec/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
|
|
|
|
```bash
|
|
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) |
|
|
|
|
### Interactive / search
|
|
|
|
| | |
|
|
|---|---|
|
|
| `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` / `feynman` — `TAB` 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 |
|