Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions md/design/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,29 @@ The agent name is stored in `[agent] name` in either the user or project config.
For each agent, `cargo agents` needs to know how to:

1. **Register hooks** — write the hook configuration so the agent calls `cargo-agents hook` on the right events.
2. **Install extensions** — place skill files (and eventually workflow/MCP definitions) where the agent expects them.
2. **Install extensions** — hand each agent the plugins that apply, as a [compiled plugin directory](./module-structure.md#agentsplugin_installrs--handing-a-directory-to-an-agent) where the agent has such a unit, and as individual skill files where it does not.

Where these files go depends on whether the agent is configured at the user level or the project level (see [`sync --agent`](./sync-agent-flow.md)).

## Extension locations

When installing skills, `cargo agents` prefers vendor-neutral paths where possible:
### Plugin directories

An agent with a plugin unit receives a compiled directory instead of loose skill files. Only Claude Code can scope one to a project; for the others a project-scoped plugin falls back to the per-skill paths below.

| Agent | How it is given the directory | Project scope |
|-------|-------------------------------|---------------|
| Claude Code | marketplace registration in user settings plus `known_marketplaces.json`; enabled via `enabledPlugins` | yes |
| Codex CLI | `[marketplaces.*]` in `config.toml`, plus a copy in `plugins/cache/` | no |
| GitHub Copilot | `extraKnownMarketplaces` in `~/.copilot/settings.json`, plus a copy in `installed-plugins/` | no |
| Gemini CLI | a copy in `~/.gemini/extensions/` — no configuration at all | no |
| Kiro, OpenCode, Goose | *(no plugin unit)* | n/a |

A skill delivered inside a plugin is namespaced by the agent as `<plugin>:<skill>`.

### Skill paths

When installing individual skills, `cargo agents` prefers vendor-neutral paths where possible:

| Scope | Path | Supported by |
|-------|------|-------------|
Expand Down
23 changes: 23 additions & 0 deletions md/design/important-flows.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,29 @@ The consent prompt and the `use` / `search` / `status` commands that record deci

The key code paths are in `discovery.rs`, `config.rs` (`PluginsConfig`, `UseEntry`), `pm/cargo/mod.rs` (`active_plugins`, `load_plugin`), `plugins.rs` (`Plugin::requires_use`), `predicate.rs` (`PredicateContext::is_used`), and `skills.rs` (`active_plugins`, `record_active`).

## Compilation and delivery of agent plugin directories

Every `cargo agents sync` compiles the plugins that apply into the unit agents consume, then hands each directory to the agents that can take it. It runs after skills are resolved, so it never re-evaluates a gate. Outside a Rust workspace only the global half happens.

1. `agent_plugin::compile` groups applicable skills by their plugin's `canonical` id and builds one `CompiledPlugin` each: a slugged name, a version, the description, and one entry per distinct skill origin. Directory names and skill names are disambiguated with the same origin-hash suffix rule that governs skill installs.
2. `Scope::of` sends each to `<project root>/.symposium/plugins/` or `<config dir>/installed/` — see [key modules](./module-structure.md#agent_plugin--compiling-an-agent-plugin-directory) for what global requires and why. A scope no configured agent can take is not compiled.
3. `agent_plugin::write` stages into a tempdir and syncs it in through `sync::sync_managed_dir`, so an unchanged plugin is not recopied. `write_marketplace` writes `.claude-plugin/marketplace.json` at each staging root, and removes it when the root empties.
4. For each configured agent and each scope it accepts, `Agent::install_plugins` writes that agent's configuration and, where the agent loads only from its own tree, copies the directory there. Plugins an agent received are recorded, so their skills are skipped in the per-skill loop and nothing arrives twice.
5. `agent_plugin::reap_to_depth` removes marked directories this sync did not write, under both staging roots and every known agent's plugin tree. Reaping the global root from a project sync is sound only because step 2 keeps the global set a function of user config alone. Steps 4 and 5 are skipped entirely when a trusted source was unreadable, so a transient registry failure cannot be read as an uninstall.

The key code paths are in `agent_plugin/mod.rs`, `agent_plugin/manifest.rs`, `agents/plugin_install.rs`, `predicate.rs` (`is_workspace_independent`), and `sync.rs`.

## Reading an externally authored package

A directory holding a `plugin.json` loads as an ordinary symposium plugin, so compilation, delivery and `status` treat it like any other.

1. `pm::layout::classify` returns `EntryKind::AgentPlugin`. Precedence runs `SYMPOSIUM.toml`, `plugin.json`, `SKILL.md`. A claimed directory is not descended into, so a package cannot nest another; a source root that is itself a package is an error.
2. `agent_plugin::read::load` parses the manifest, reports unknown fields and an unsupported `mcp.json`, reads the gate from `extensions["dev.symposium"]`, and returns a `Plugin` with one `skills/` group limited to immediate children.
3. The three positions call it: `plugins::load_entry` (registry, dormancy applies), `workspace_plugin_for_dir` (member), and `CargoPm::build_from_fetched` (dependency) — the latter two gated by position. `embedded_plugin_kind` counts a `plugin.json`, so a dependency carrying one is offered for consent.
4. Containment is per unit: a bad manifest rejects that package alone, an unknown field is ignored, a broken skill is skipped, and a skill resolving outside the package is refused.

The key code paths are in `agent_plugin/read.rs`, `pm/layout.rs`, `plugins.rs` (`load_entry`, `workspace_plugin_for_dir`, `apply_sibling_identity`, `dormant_without_gate`), and `skills.rs` (`discover_skills`, `SkillDepth`).

## Help rendering

`cargo agents --help` (and `-h`, the bare `help` keyword, or no subcommand) is rendered by `help_render`, not by clap's default help.
Expand Down
Loading