|
| 1 | +# Community Agent Adapters |
| 2 | + |
| 3 | +ZCF uses an adapter-based architecture to support different coding agent CLIs. Built-in adapters are shipped with the package (`claude-code`, `codex`, `opencode`), but you can also write and load your own adapter without modifying ZCF. |
| 4 | + |
| 5 | +## Adapter Interface |
| 6 | + |
| 7 | +A community adapter must implement the `AgentAdapter` interface exported by `zcf`: |
| 8 | + |
| 9 | +```ts |
| 10 | +import type { AgentAdapter, AgentConfigFile, AgentContext, AgentSkillSpec, InstallOptions, UninstallOptions, UpdateOptions } from 'zcf' |
| 11 | + |
| 12 | +export default { |
| 13 | + id: 'my-agent', |
| 14 | + displayName: 'My Agent', |
| 15 | + aliases: ['ma'], |
| 16 | + homeDir: '/home/user/.my-agent', |
| 17 | + templateDir: 'templates/my-agent', |
| 18 | + configFiles: [ |
| 19 | + { id: 'settings', path: '/home/user/.my-agent/settings.json', format: 'json', mergeStrategy: 'merge' }, |
| 20 | + ], |
| 21 | + skillSpec: { |
| 22 | + skillsDir: '/home/user/.my-agent/skills', |
| 23 | + manifestName: 'SKILL.md', |
| 24 | + scopes: ['global', 'project'], |
| 25 | + }, |
| 26 | + |
| 27 | + async isInstalled() { /* ... */ }, |
| 28 | + async install(options: InstallOptions, ctx: AgentContext) { /* ... */ }, |
| 29 | + async update(options: UpdateOptions, ctx: AgentContext) { /* ... */ }, |
| 30 | + async uninstall(options: UninstallOptions, ctx: AgentContext) { /* ... */ }, |
| 31 | + async backup(file: AgentConfigFile) { /* ... */ }, |
| 32 | +} satisfies AgentAdapter |
| 33 | +``` |
| 34 | + |
| 35 | +Key methods: |
| 36 | + |
| 37 | +- `isInstalled` — detect whether the target CLI is available. |
| 38 | +- `install` — render templates, write configuration, install skills. |
| 39 | +- `update` — refresh templates and skills without a full reinstall. |
| 40 | +- `uninstall` — remove ZCF-managed files and skills. |
| 41 | +- `backup` — create a timestamped backup before overwriting a config file. |
| 42 | + |
| 43 | +Use the `TemplateEngine` class from `zcf/core/template-engine` to render templates and skills consistently. |
| 44 | + |
| 45 | +## Loading from a Local TOML Manifest |
| 46 | + |
| 47 | +Place a TOML manifest in `~/.ufomiao/zcf/adapters/<id>.toml`: |
| 48 | + |
| 49 | +```toml |
| 50 | +id = "my-agent" |
| 51 | +displayName = "My Agent" |
| 52 | +aliases = ["ma"] |
| 53 | +main = "my-agent/adapter.mjs" |
| 54 | +``` |
| 55 | + |
| 56 | +The `main` path is relative to `~/.ufomiao/zcf/adapters/`. The referenced module must export a valid `AgentAdapter` as its default export. You can also use a factory export: |
| 57 | + |
| 58 | +```toml |
| 59 | +id = "my-agent" |
| 60 | +displayName = "My Agent" |
| 61 | +main = "my-agent/adapter.mjs" |
| 62 | +export = "createAdapter" |
| 63 | +``` |
| 64 | + |
| 65 | +```ts |
| 66 | +// my-agent/adapter.mjs |
| 67 | +export function createAdapter(manifest) { |
| 68 | + return { |
| 69 | + id: manifest.id, |
| 70 | + // ... |
| 71 | + } |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +ZCF loads external adapters on startup. A broken adapter is logged and skipped so it cannot break the CLI. |
| 76 | + |
| 77 | +## Loading from an NPM Package |
| 78 | + |
| 79 | +Reference an NPM package in the manifest: |
| 80 | + |
| 81 | +```toml |
| 82 | +id = "my-agent" |
| 83 | +displayName = "My Agent" |
| 84 | +package = "zcf-adapter-my-agent" |
| 85 | +export = "adapter" |
| 86 | +``` |
| 87 | + |
| 88 | +The package must be resolvable by Node (install it globally or in a parent project). The adapter is loaded via dynamic import. |
| 89 | + |
| 90 | +## Best Practices |
| 91 | + |
| 92 | +1. **Preserve user customizations** — use `mergeStrategy: 'merge'` for JSON/TOML files and back up before writing. |
| 93 | +2. **Scope skills** — put user-facing skills under `templates/<agent>/skills/user/` and project-internal skills under `templates/<agent>/skills/zcf/`. |
| 94 | +3. **Manual-only skills** — if a skill should only be triggered by the user, add `disable-model-invocation: true` to its `SKILL.md` frontmatter. |
| 95 | +4. **Use the template engine** — `renderConfigFile`, `renderCommon`, and `renderSkill` handle merge strategies, backups, and i18n-friendly rendering. |
| 96 | +5. **Test coverage** — adapters must have unit tests covering installation, update, uninstall, and edge cases. Maintain ≥80% coverage. |
| 97 | + |
| 98 | +## Example `SKILL.md` |
| 99 | + |
| 100 | +```markdown |
| 101 | +--- |
| 102 | +name: my-skill |
| 103 | +description: A custom skill for my agent |
| 104 | +version: 1.0.0 |
| 105 | +namespace: user |
| 106 | +disable-model-invocation: true |
| 107 | +--- |
| 108 | + |
| 109 | +# My Skill |
| 110 | + |
| 111 | +Instructions for the agent when this skill is invoked. |
| 112 | +``` |
| 113 | + |
| 114 | +## Troubleshooting |
| 115 | + |
| 116 | +- **Adapter not appearing in `zcf --help`**: check the manifest ID/aliases are unique and the module exports a valid adapter. |
| 117 | +- **`isInstalled` always false**: ensure the executable is on the user's `PATH`. |
| 118 | +- **Template not rendered**: verify `templateDir` points to a directory containing the expected files and `renderCommon` is called for shared resources. |
0 commit comments