docs: Updated documentation on bundles

2026-08-21 19:50:44 -06:00
parent 9f8186ebc4
commit 4413fc61f2
4 changed files with 363 additions and 84 deletions
+1 -1
@@ -23,7 +23,7 @@ Coming from [AIChat](https://github.com/sigoden/aichat)? Follow the [migration g
* [AIChat Migration Guide](AIChat-Migration): Coming from AIChat? Follow the migration guide to get started.
* [Installation](Installation): Install Coyote
* [Getting Started](Getting-Started): Get started with Coyote by doing first-run setup steps, and learn the basics.
* [Sharing Configurations](Sharing-Configurations): Install bundles of agents, roles, macros, tools, and MCP servers from any git repo, and share your own.
* [Sharing Configurations](Sharing-Configurations): Install bundles of agents, roles, macros, tools, and MCP servers from any git repo, and share your own. Bundles are Coyote's equivalent of plugins in other CLI agents.
* [REPL](REPL): Interactive Read-Eval-Print Loop for conversational interactions with LLMs and Coyote.
* [Custom REPL Prompt](REPL-Prompt): Customize the REPL prompt to provide useful contextual information.
* [Vault](Vault): Securely store and manage sensitive information such as API keys and credentials.
+33 -11
@@ -398,6 +398,7 @@ The `.list` command lists the assets of a given kind, making them discoverable w
| `.list agents` | List installed agents, with their descriptions when available |
| `.list rags` | List all RAGs |
| `.list macros` | List all macros |
| `.list bundles` | List installed bundles with their source, version, ref pin, and drift status (see [Sharing Configurations](Sharing-Configurations)) |
| `.list skills` | List skills available in this context, with descriptions and a `(loaded)` marker for active skills |
| `.list tools` | List the tools that can be enabled/disabled via `.tool [enable\|disable] <name>` (excludes internal tools; in an agent context, lists the agent's tool pool) |
| `.list mcp-servers` | List the MCP servers that can be enabled/disabled via `.mcp [enable\|disable] <name>` (configured servers plus mapping aliases) |
@@ -418,7 +419,8 @@ when an update ships improved built-ins you want to adopt.
| `.install functions` | Reinstall the built-in tool functions (leaves your `mcp.json` alone) |
| `.install mcp_config` | Merge new bundled MCP servers into `mcp.json` (existing servers are preserved) |
The same operation is available from the command line: `coyote --install <category>` (e.g. `coyote --install agents`).
The same operation is available from the command line: `coyote --install-builtins <category>` (e.g.
`coyote --install-builtins agents`).
`.install` prompts for confirmation before overwriting anything. Assets you created yourself are never touched. Only
Coyote's own bundled assets are replaced.
@@ -427,23 +429,43 @@ Coyote's own bundled assets are replaced.
present in your file are added; your existing servers and any custom secret references are left untouched. This
behaves consistently with the other install categories, which also leave your own customizations alone.
## `.install remote` - Install assets from a git repository
## `.install <source>` - Install and update bundles
The `.install remote` command installs agents, roles, macros, tools, and MCP servers from any git repository whose
layout mirrors Coyote's user config directory. This is the primary mechanism for sharing and reusing Coyote configurations.
Besides category names, `.install` accepts a git source or an installed bundle's name. It installs agents, roles,
skills, macros, tools, and MCP servers from any git repository whose layout mirrors Coyote's user config directory.
This is the primary mechanism for sharing and reusing Coyote configurations; an installed repo is tracked as a
**bundle** you can list, update, and uninstall.
| Command | Description |
|-------------------------------------------------|-------------------------------------------------------------------------------------|
| `.install remote <git-url>` | Install everything the repo provides |
| `.install remote <git-url>#<ref>` | Pin to a tag, branch, or commit (e.g. `#v1.0.0`, `#main`) |
| `.install remote <git-url> --filter <category>` | Restrict to one of `agents`, `roles`, `skills`, `macros`, `functions`, `mcp_config` |
| `.install remote <git-url> --force` | Skip all conflict prompts; overwrite local files unconditionally |
| Command | Description |
|------------------------------------------|-------------------------------------------------------------------------------------|
| `.install <git-url>` | Install everything the repo provides |
| `.install <owner>/<repo>` | Shorthand; expands to `https://github.com/<owner>/<repo>` |
| `.install <owner>/<repo> --git-host <h>` | Expand the shorthand against a different git host |
| `.install <source>#<ref>` | Pin to a tag, branch, or commit (e.g. `#v1.0.0`, `#main`) |
| `.install <source> --filter <category>` | Restrict to one of `agents`, `roles`, `skills`, `macros`, `functions`, `mcp_config` |
| `.install <source> --force` | Skip all conflict prompts; overwrite local files unconditionally |
| `.install <bundle-name>` | Update an installed bundle from its recorded source |
The CLI equivalent is `coyote --install-from <git-url>` (with `--filter` and `--install-force` accepting the same values).
The CLI equivalent is `coyote --install <source-or-name>` (with `--git-host`, `--filter`, and `--install-force`
accepting the same values). Use `.list bundles` to see what's installed and `.uninstall <name>` to remove a bundle.
See [Sharing Configurations](Sharing-Configurations) for the expected repo layout, conflict resolution, secret handling,
and the [coyote-config-template](https://github.com/Dark-Alex-17/coyote-config-template) starter you can fork.
## `.uninstall` - Uninstall a bundle
The `.uninstall` command removes a bundle installed with `.install`: it deletes the files the bundle owns, removes the
`mcp.json` entries it added, and drops its record. Files you've modified locally are kept unless you confirm their
deletion, and anything the bundle never owned is left untouched.
| Command | Description |
|----------------------------|------------------------------------------------------------------------------|
| `.uninstall <name>` | Uninstall by bundle name (see `.list bundles`) |
| `.uninstall <source-url>` | Uninstall by the source URL the bundle was installed from |
| `.uninstall <owner>/<repo>`| Match against recorded sources; multiple matches show an interactive selector |
The CLI equivalent is `coyote --uninstall <name>` (add `--yes` to skip confirmation prompts).
## `.update` - Update Coyote
The `.update` command updates the Coyote binary itself to the latest release,
+324 -67
@@ -1,18 +1,24 @@
Coyote ships with a built-in mechanism for installing and sharing configurations (i.e. agents, roles, macros, tools, and
MCP servers) directly from any git repository. This makes it easy to:
Coyote ships with a built-in mechanism for installing and sharing configurations (i.e. agents, roles, skills, macros,
tools, and MCP servers) directly from any git repository. A shareable repository is called a **bundle**; bundles are
Coyote's equivalent of plugins in other CLI agents. Bundles make it easy to:
- Sync your Coyote setup across multiple machines.
- Share your work with teammates or the community.
- Bootstrap a new install with a curated set of assets.
- Pin to specific versions for reproducibility.
The relevant commands:
Coyote tracks every bundle it installs, so bundles have a full lifecycle:
- CLI: `coyote --install-from <git-url>`
- REPL: `.install remote <git-url>`
| Action | CLI | REPL |
|-----------------------|-----------------------------------------|----------------------|
| Install or update | `coyote --install <source-or-name>` | `.install <value>` |
| List installed | `coyote --list-bundles` | `.list bundles` |
| Update from source | `coyote --update-bundle <name>` | |
| Uninstall | `coyote --uninstall <name> [--yes]` | `.uninstall <name>` |
| Reinstall built-ins | `coyote --install-builtins <category>` | `.install <category>`|
This page covers the expected repository layout, command-line flags, conflict resolution, secrets handling, and how to
publish your own shareable bundle.
This page covers the expected repository layout, bundle identity, provenance tracking, conflict resolution, secrets
handling, and how to publish your own bundle.
To see a template repository with all recognized categories, see the
[coyote-config-template](https://github.com/Dark-Alex-17/coyote-config-template) repository.
@@ -21,21 +27,29 @@ To see a template repository with all recognized categories, see the
## Quick start
Install everything from a remote repo:
Install everything from a GitHub repo using `owner/repo` shorthand:
```sh
coyote --install-from https://github.com/Dark-Alex-17/coyote-config-template
coyote --install someuser/oh-my-coyote
```
Coyote expands the shorthand against `github.com` (printing `Resolved 'someuser/oh-my-coyote' to
'https://github.com/someuser/oh-my-coyote'`), clones the repo to a temp directory, scans for recognized asset
categories, and installs each into the matching subdirectory of your user config. The temp clone is removed on
completion, and the install is recorded in the bundle store so you can list, update, and uninstall it later.
Full URLs work everywhere shorthand does:
```sh
coyote --install https://github.com/someuser/oh-my-coyote
```
or from inside the Coyote REPL:
```
.install remote https://github.com/Dark-Alex-17/coyote-config-template
.install someuser/oh-my-coyote
```
That's it. Coyote clones the repo to a temp directory, scans for recognized asset categories, and installs each into the
matching subdirectory of your user config. The temp clone is removed on completion.
> ⚠️ **Heads up: Sandbox implications.** If you use [Sandbox mode](Sandboxes) and the bundle includes any
> `sbx-mixin.yaml` files, installing it grants those mixins network access and install privileges inside your
> sandboxes the next time you `coyote --sandbox`. See [Sandbox Implications](#sandbox-implications) at the bottom of
@@ -43,12 +57,100 @@ matching subdirectory of your user config. The temp clone is removed on completi
---
## Install sources
`--install` accepts one value that Coyote classifies automatically:
| Value shape | Interpretation |
|--------------------------------------|-----------------------------------------------------------------------|
| `https://...`, `git@host:path`, `file://...`, `./dir`, `/abs`, `~/dir` | A remote source; cloned and installed. |
| `owner/repo` (two or more segments) | Shorthand; expanded to `https://<git-host>/owner/repo` and installed. |
| An installed bundle's name | The bundle is [updated](#updating-a-bundle) from its recorded source. |
| An asset category (`agents`, ...) | An error pointing you at `--install-builtins <category>` instead. |
| Anything else | An error listing your installed bundles. |
Bare names never trigger a clone, so a typo'd bundle name can't silently install something from the network.
### `owner/repo` shorthand and `--git-host`
The shorthand defaults to `github.com`. To install from a different host, pass `--git-host`:
```sh
coyote --install someuser/oh-my-coyote # github.com
coyote --install --git-host git.somedomain.com someuser/oh-my-coyote # self-hosted
coyote --install --git-host gitlab.com group/subgroup/repo # nested groups work
```
Details:
- Shorthand takes **two or more** path segments, so GitLab-style nested subgroups expand correctly.
- Expansion always uses `https://`. For private repos you authenticate over SSH, use the full
`git@host:owner/repo.git` URL instead (see [Git authentication](#git-authentication)).
- `--git-host` requires `--install`, only accepts shorthand values (passing it with a full URL is an error), and
**forces the value to be treated as a source** even if it happens to match an installed bundle's name.
- [Ref pinning](#ref-pinning) works on shorthand: `coyote --install someuser/repo#v1.2.0`.
- The REPL form accepts the same flag: `.install someuser/repo --git-host git.somedomain.com`.
### Ref pinning
Pin the install to a specific tag, branch, or commit by appending `#<ref>` to the URL or shorthand.
```sh
coyote --install someuser/repo#v1.2.3
coyote --install https://github.com/<owner>/<repo>#main
coyote --install https://github.com/<owner>/<repo>#abc1234
```
How Coyote resolves the ref:
- **Branch or tag names** are passed as `--branch <ref>` to a shallow `git clone --depth 1`.
- **Commit SHAs** (4-40 hex characters) trigger a full clone followed by `git checkout <ref>`.
Validation: refs must match `[A-Za-z0-9._/+-]`, must not start with `-`, and must not contain `..`. These rules prevent
the ref from being interpreted as a CLI flag or escaping the repo via path traversal.
The pin is recorded with the bundle, and `--update-bundle <name>#<new-ref>` moves it later.
### Filtering by category
Restrict an install to a single asset category with `--filter`:
| Filter | Installs |
|--------------|------------------------------------------------------------------------------------------------|
| *(omitted)* | `agents/`, `roles/`, `skills/`, `macros/`, `functions/tools/`, and merges `functions/mcp.json` |
| `agents` | `agents/` only |
| `roles` | `roles/` only |
| `skills` | `skills/` only |
| `macros` | `macros/` only |
| `functions` | `functions/tools/` only (does **not** include `mcp.json`) |
| `mcp_config` | `functions/mcp.json` only (merged) |
```sh
coyote --install <source> --filter agents
coyote --install <source> --filter mcp_config
```
REPL form:
```
.install <source> --filter agents
```
Note that `--filter functions` is intentionally narrow. It installs the global tools under `functions/tools/` and
**not** `mcp.json`. To install just the MCP config, use `--filter mcp_config`. To install both, use no filter.
Repeated filtered installs of the same bundle merge into a single bundle record, and a later
[update](#updating-a-bundle) always processes the whole remote, including categories a filtered install excluded.
---
## Expected repository layout
Coyote recognizes these top-level directories. Anything outside them is ignored.
```
<repo>/
├── coyote-bundle.yaml # Optional bundle manifest (identity only)
├── agents/
│ └── <agent-name>/ # One subdirectory per agent
│ ├── config.yaml # LLM-loop agent
@@ -71,7 +173,7 @@ Coyote recognizes these top-level directories. Anything outside them is ignored.
A few things to note:
- **Missing categories are skipped silently.** A repo that only contains `agents/` installs only agents. This means you
- **Missing categories are skipped silently.** A repo that only contains `agents/` installs only agents. This means you
do not need to use `--filter` for partial repos.
- **`.git/` is excluded** from the scan automatically.
- **Symlinks are rejected** by the install walker as a defense-in-depth measure.
@@ -80,53 +182,142 @@ A few things to note:
---
## Ref pinning
## Bundle identity and the manifest
Pin the install to a specific tag, branch, or commit by appending `#<ref>` to the URL.
Every installed bundle has a name. By default it's the repository name (the last URL segment, without `.git`), so
`https://github.com/someuser/oh-my-coyote` installs as `oh-my-coyote`.
```sh
coyote --install-from https://github.com/<owner>/<repo>#v1.2.3
coyote --install-from https://github.com/<owner>/<repo>#main
coyote --install-from https://github.com/<owner>/<repo>#abc1234
Bundle authors can override this by adding a `coyote-bundle.yaml` manifest to the repository root:
```yaml
name: oh-my-coyote # required; the bundle's identity
version: "1.4.0" # optional; shown in --list-bundles
description: Opinionated roles, macros, and skills for Coyote
homepage: https://github.com/example/oh-my-coyote # optional
```
How Coyote resolves the ref:
The manifest is **identity only**. It never declares the bundle's contents; those are always discovered by scanning
the repository, exactly as for a manifest-less repo.
- **Branch or tag names** are passed as `--branch <ref>` to a shallow `git clone --depth 1`.
- **Commit SHAs** (4-40 hex characters) trigger a full clone followed by `git checkout <ref>`.
How names are kept unambiguous:
Validation: refs must match `[A-Za-z0-9._/+-]`, must not start with `-`, and must not contain `..`. These rules prevent
the ref from being interpreted as a CLI flag or escaping the repo via path traversal.
- **One source, one record.** Installing the same repository again (by any URL spelling, or via shorthand) updates the
existing record instead of creating a second one. If the repo's manifest name changed since the last install, the
record migrates to the new name and Coyote prints a notice.
- **Cross-source collisions are owner-qualified.** If you install two different repositories that both want the name
`oh-my-coyote`, the second is recorded as `<owner>/oh-my-coyote` and Coyote prints a notice. Lifecycle commands
accept the qualified name.
---
## Filtering by category
## Provenance and ownership
Restrict the install to a single asset category with `--filter`:
Coyote records everything an install writes in `installed-bundles.yaml` in your config directory. For each bundle it
tracks the source URL, ref pin, resolved commit, manifest metadata, timestamps, every file written (with its content
hash and category), and every `mcp.json` server entry the merge added, replaced, or renamed (with the hash of the
entry as written).
| Filter | Installs |
|--------------|------------------------------------------------------------------------------------------------|
| *(omitted)* | `agents/`, `roles/`, `skills/`, `macros/`, `functions/tools/`, and merges `functions/mcp.json` |
| `agents` | `agents/` only |
| `roles` | `roles/` only |
| `skills` | `skills/` only |
| `macros` | `macros/` only |
| `functions` | `functions/tools/` only (does **not** include `mcp.json`) |
| `mcp_config` | `functions/mcp.json` only (merged) |
This record is what powers the rest of the lifecycle:
- **Ownership.** A file belongs to the bundle that wrote its current content. If a later install overwrites a file
another bundle owned, ownership transfers. Files you chose to *keep* during conflict prompts are never claimed.
- **Abort safety.** Provenance is recorded as files are written, so aborting mid-install (e.g. at a conflict prompt)
leaves everything already on disk tracked and uninstallable.
- **Drift detection.** The recorded hashes let `--list-bundles` tell you which files you've modified since install,
and let update/uninstall treat your modified files more carefully than pristine ones.
- **No secrets.** Recorded hashes cover the content as written, and MCP entries are written with their
`{{SECRET}}` placeholders intact, so the store never contains secret material.
The store is plain YAML and safe to read, but hand-editing it will make Coyote's view of ownership drift from
reality. If it becomes corrupt, Coyote refuses to treat it as empty (that would let a reinstall re-claim files you've
since modified) and reports the parse error instead.
---
## Listing bundles and drift
```sh
coyote --install-from <git-url> --filter agents
coyote --install-from <git-url> --filter mcp_config
coyote --list-bundles
```
REPL form:
or `.list bundles` in the REPL. Output is a table:
```
.install remote <git-url> --filter agents
| Column | Meaning |
|-------------|-------------------------------------------------------------------------------------|
| `name` | The bundle's identity (manifest name, repo name, or owner-qualified name). |
| `version` | The manifest `version`, or the short commit hash if the manifest doesn't set one. |
| `source` | The recorded source URL updates are pulled from. |
| `ref` | The `#<ref>` pin, or `-` if the install tracked the default branch. |
| `installed` | When the bundle was first installed. |
| `files` | Per-category counts of owned files (e.g. `macros: 3, roles: 2`). |
| `drift` | File status vs. the recorded hashes: `intact`, `modified locally`, and `missing`. |
Drift statuses:
- **intact**: the file on disk still matches the content the bundle installed.
- **modified locally**: you've edited the file since install (or it can't be read).
- **missing**: the file was deleted from disk.
---
## Updating a bundle
```sh
coyote --update-bundle <name> # update from the recorded source
coyote --update-bundle <name>#<ref> # also move the ref pin
coyote --install <name> # same thing; installed names dispatch to update
```
Note that `--filter functions` is intentionally narrow. It installs the global tools under `functions/tools/` and
**not** `mcp.json`. To install just the MCP config, use `--filter mcp_config`. To install both, use no filter.
An update re-clones the recorded source (at the recorded pin unless you move it) and re-runs the install with
provenance-aware conflict handling:
- **Files the bundle owns that you haven't touched** (hash still matches) are refreshed without prompting. The bundle
wrote that content; bringing it up to date is not a conflict.
- **Files you've modified locally**, and files owned by other bundles, get the normal
[conflict prompts](#conflict-resolution).
- **The whole remote is processed**, including categories a previous `--filter` excluded.
- **Files the remote no longer ships** are reconciled: a file already deleted from disk just drops out of the record;
a file still present is kept by default (you may rely on it) and only deleted if you confirm. Kept files stay in
the record so a later uninstall still offers to remove them.
`--filter` and `--install-force` do not apply to updates by name; they are flags for remote installs.
---
## Uninstalling a bundle
```sh
coyote --uninstall <name>
coyote --uninstall <name> --yes # skip confirmation prompts
```
or `.uninstall <name>` in the REPL. The spec can be the bundle name, its source URL, or `owner/repo` shorthand.
What gets removed:
- **Owned files whose content still matches the recorded hash** are deleted, and directories left empty by the
deletions are pruned.
- **Owned files you've modified locally** are kept unless you explicitly confirm their deletion at a prompt
(`--yes` does *not* delete them; it only skips confirmations).
- **`mcp.json` entries the bundle added** are removed if unmodified; modified entries prompt like files. Entries that
existed before the bundle replaced them, and keys the bundle never owned, are never touched.
- **The bundle's record** is dropped once nothing it owned remains. If items were kept or a deletion failed, the
record keeps them and re-running `--uninstall` offers them again.
Not removed: vault secrets the bundle's servers referenced, `enabled_*` config lists that mention its assets, and
compiled tool binaries under `functions/bin/` (those linger until the next `--build-tools` prune; Coyote prints a
note when this applies).
Uninstalling is confirmation-gated: in a terminal you're shown what the bundle owns and asked to proceed;
non-interactive runs (CI, piped) require `--yes`.
### Ambiguous `owner/repo` specs
`--uninstall someuser/oh-my-coyote` resolves in strict priority order: exact bundle name, then exact source URL, then
a match against the recorded sources' trailing path segments. If several bundles were installed from different hosts
under the same `owner/repo` path, Coyote shows an interactive selector listing each candidate as `name (source)` so
you choose exactly which one to remove. There is no auto-picking: non-interactive runs bail and list the candidates
(re-run with the exact bundle name or source URL), and `--yes` never selects on your behalf.
---
@@ -134,7 +325,7 @@ Note that `--filter functions` is intentionally narrow. It installs the global t
When an install file would overwrite an existing local file with different contents, you have several options.
### Plain files (agents, roles, macros, tools)
### Plain files (agents, roles, skills, macros, tools)
In a terminal (TTY), Coyote prompts per conflicting file:
@@ -144,12 +335,15 @@ In a terminal (TTY), Coyote prompts per conflicting file:
| `replace` | Overwrite with the remote file. |
| `keep-all` | Skip this file and all remaining conflicts in this install. |
| `replace-all` | Overwrite this file and all remaining conflicts in this install. |
| `abort` | Stop the install. Files already written stay; they are not rolled back. |
| `abort` | Stop the install. Files already written stay; they are not rolled back (and remain tracked in the bundle's record). |
To skip prompts and replace everything, pass `--install-force` on the CLI or `--force` in the REPL form. In non-TTY
mode (CI, piped, redirected stdin), the install will **abort** rather than silently overwrite. To overwrite
non-interactively, you must pass `--install-force`.
During [updates](#updating-a-bundle), files the bundle owns and you haven't modified skip these prompts entirely and
are refreshed in place.
### Identical content is not a conflict
If a remote file's bytes match your local copy exactly, Coyote silently treats it as `identical` and skips it. Re-running
@@ -183,6 +377,10 @@ Coyote **merges** the remote `mcp.json` into your existing one.
With `--install-force`, every conflict is resolved by taking the remote entry. In non-TTY mode without
`--install-force`, the merge aborts before writing.
Entries the merge adds, replaces, or renames are recorded as owned by the bundle (with the hash of the entry as
written), which is how [uninstall](#uninstalling-a-bundle) knows what it may safely remove later. Entries you kept
local are not claimed.
### Validation
Each added, replaced, or renamed entry is validated against the MCP server schema (e.g., `stdio` servers must have a
@@ -202,7 +400,7 @@ MCP server entries (and other config files) can reference vault secrets with `{{
install completes, Coyote scans the resulting `mcp.json` for placeholders that are not yet in your vault and either:
- **In a TTY:** prompts you, one secret at a time, whether to add it to the vault now. On the first "Yes", Coyote
initializes the vault (if needed; for the Local provider, this just means creating the password file). On "No", the
initializes the vault (if needed; for the Local provider, this just means creating the password file). On "No", the
secret is deferred and reported at the end.
- **In a non-TTY environment:** skips prompts entirely; lists every missing secret in a final reminder block, with the
commands you can run later (`coyote --add-secret <NAME>` or `.vault add <NAME>`).
@@ -222,13 +420,28 @@ authentication setup** with no additional configuration:
Linux, the GitHub CLI's helper).
- **Public HTTPS URLs** require no auth.
Note that `owner/repo` shorthand always expands to an HTTPS URL. If your access to a private repo only works over
SSH, install with the full SSH URL instead.
If `git` is not on your `PATH`, you'll get a clear error message on the first install attempt.
---
## Built-ins are not bundles
`coyote --install-builtins <category>` (REPL: `.install <category>`) reinstalls the assets that ship inside the
Coyote binary for one category (`agents`, `roles`, `skills`, `macros`, `functions`, `themes`), **overwriting any local
changes** to those files. Built-in assets are not tracked in the bundle store, don't appear in `--list-bundles`, and
can't be uninstalled; they're part of Coyote itself.
Passing a category name to `--install` never reinstalls built-ins by accident; it errors and points you at
`--install-builtins` (and, if you also have a bundle by that name, at `--update-bundle`).
---
## Publishing your own bundle
To share your Coyote configuration, structure a git repo like the template above and push it to GitHub, GitLab, your
To share your Coyote configuration, structure a git repo like the layout above and push it to GitHub, GitLab, your
self-hosted Forgejo instance, etc.
The easiest way to start is to **fork the official template repo**:
@@ -237,23 +450,27 @@ asset type plus a `README` describing the customization workflow.
### Best practices
1. **Pin to tagged releases** so consumers can install with `#<tag>` for reproducibility.
2. **Keep per-agent logic in `agents/<name>/`**. Only put global tools in `functions/tools/`.
3. **Use `{{SECRET}}` placeholders** for any sensitive value in `mcp.json`. Never commit a real API key.
4. **Document expected secrets** in your repo's `README` so users know which vault entries to add.
5. **Avoid name collisions** with Coyote's bundled assets (`agents/code-reviewer`, `agents/sql`, etc.) unless you
1. **Add a `coyote-bundle.yaml`** with a stable `name` and a `version` you bump on releases. This keeps your bundle's
identity stable even if the repo is renamed or forked, and gives installers a meaningful version in
`--list-bundles`.
2. **Pin to tagged releases** so consumers can install with `#<tag>` for reproducibility, and move pins deliberately
with `--update-bundle <name>#<tag>`.
3. **Keep per-agent logic in `agents/<name>/`**. Only put global tools in `functions/tools/`.
4. **Use `{{SECRET}}` placeholders** for any sensitive value in `mcp.json`. Never commit a real API key.
5. **Document expected secrets** in your repo's `README` so users know which vault entries to add.
6. **Avoid name collisions** with Coyote's bundled assets (`agents/code-reviewer`, `agents/sql`, etc.) unless you
specifically want to replace them. Pick distinctive names for your shared assets.
6. **Test installs against a clean `COYOTE_CONFIG_DIR`** before publishing. You can use:
7. **Test installs against a clean `COYOTE_CONFIG_DIR`** before publishing. You can use:
```sh
COYOTE_CONFIG_DIR=$(mktemp -d) coyote --install-from file:///path/to/your/clone --install-force
COYOTE_CONFIG_DIR=$(mktemp -d) coyote --install file:///path/to/your/clone --install-force
```
---
## What is not shared
The following are **intentionally** outside the install-remote feature's scope:
The following are **intentionally** outside the bundle feature's scope:
- **`config.yaml`** (the global Coyote config). It holds user-specific things like editor preference, secrets provider
configuration, client API keys, OAuth tokens, and similar. Merging a shared `config.yaml` would risk breaking auth or routing
@@ -264,54 +481,76 @@ The following are **intentionally** outside the install-remote feature's scope:
- **`functions/utils/`:** Utility scripts intentionally not part of the share contract.
If a team really needs synced global settings, the recommended approach is dotfiles-style symlinks or a sync tool.
Those are designed for that problem and not for `coyote --install-from`.
Those are designed for that problem and not for `coyote --install`.
---
## Examples
### Install everything from a public repo
### Install from GitHub with shorthand
```sh
coyote --install-from https://github.com/Dark-Alex-17/coyote-config-template
coyote --install someuser/oh-my-coyote
```
### Install from a self-hosted git server
```sh
coyote --install --git-host git.somedomain.com someuser/oh-my-coyote
```
### Pin to a release tag
```sh
coyote --install-from https://github.com/your-org/coyote-config#v2.4.0
coyote --install your-org/coyote-config#v2.4.0
```
### Install only the agents from a fork
```sh
coyote --install-from https://github.com/your-org/coyote-config --filter agents
coyote --install https://github.com/your-org/coyote-config --filter agents
```
### Install only the MCP servers, force-replace conflicts
```sh
coyote --install-from https://github.com/your-org/coyote-config --filter mcp_config --install-force
coyote --install https://github.com/your-org/coyote-config --filter mcp_config --install-force
```
### See what you have installed, then update one bundle
```sh
coyote --list-bundles
coyote --update-bundle oh-my-coyote
coyote --update-bundle coyote-config#v2.5.0 # move the pin
```
### Uninstall a bundle non-interactively
```sh
coyote --uninstall oh-my-coyote --yes
```
### From the REPL
```
.install remote https://github.com/your-org/coyote-config
.install remote https://github.com/your-org/coyote-config#main --filter agents
.install remote https://github.com/your-org/coyote-config --force
.install your-org/coyote-config
.install https://github.com/your-org/coyote-config#main --filter agents
.install someuser/repo --git-host git.somedomain.com
.list bundles
.uninstall oh-my-coyote
```
### From a private SSH URL
```sh
coyote --install-from git@github.com:your-org/private-coyote-config.git#v1.0.0
coyote --install git@github.com:your-org/private-coyote-config.git#v1.0.0
```
### From a local file:// URL (testing your own template)
```sh
coyote --install-from file:///home/you/code/my-coyote-config
coyote --install file:///home/you/code/my-coyote-config
```
---
@@ -323,10 +562,28 @@ coyote --install-from file:///home/you/code/my-coyote-config
The remote clone failed. Coyote passes git's stderr through verbatim. The most common causes:
- **Authentication required**: `fatal: could not read username/password` or `Permission denied (publickey)`. Verify
your git credentials work for the same URL outside Coyote by running `git clone <url>` manually.
your git credentials work for the same URL outside Coyote by running `git clone <url>` manually. Remember that
`owner/repo` shorthand expands to HTTPS; use the full SSH URL for SSH-only private repos.
- **Network failure**: `Could not resolve host` or similar. Check connectivity.
- **Invalid ref**: `couldn't find remote ref <ref>`. Verify the tag/branch/commit exists in the remote.
### "'agents' is an asset category, not a bundle"
You passed a category name to `--install`. Use `coyote --install-builtins agents` to reinstall Coyote's built-in
assets for that category, or `--update-bundle <name>` if you meant a bundle that happens to share the name.
### "no bundle named '`<value>`' is installed"
The value didn't match an installed bundle, and it isn't shaped like a source (git URL, `owner/repo` shorthand,
scp-style `host:path`, or an explicit local path). Check `--list-bundles` for the exact bundle name, or pass a full
source to install something new.
### "'`<owner>/<repo>`' matches multiple installed bundles"
You uninstalled by `owner/repo` shorthand in a non-interactive run and more than one installed bundle matches that
path on different hosts. Re-run with the exact bundle name or source URL (both shown in the error and in
`--list-bundles`), or run interactively to get a selector.
### "No recognized assets found in `<url>`"
The cloned repo has none of the recognized top-level directories. Make sure the repo's layout matches the
+5 -5
@@ -147,7 +147,7 @@ your current context with git knowledge, frontend conventions, or any other modu
| `.skill <name>` | Open the skill in `$EDITOR`. Creates a scaffolded `SKILL.md` if missing. |
| `.delete skill` | Interactive prompt to choose installed skills to delete. |
| `.install skills` | Reinstall all bundled built-in skills, overwriting existing copies after confirmation. |
| `.install remote <git-url> --filter skills` | Install only `skills/` from a remote repo. See [Sharing Configurations](Sharing-Configurations). |
| `.install <git-url> --filter skills` | Install only `skills/` from a remote repo. See [Sharing Configurations](Sharing-Configurations). |
| `.set skills_enabled <true\|false\|null>` | Flip the master switch at runtime. Inside a session this sets the session override; otherwise it updates the global default (`null` restores the default `true`). |
| `.set enabled_skills <csv\|null>` | Replace the global default-active skill list at runtime, e.g. `.set enabled_skills git-master,ai-slop-remover`. Use `null` to clear. |
@@ -158,8 +158,8 @@ your current context with git knowledge, frontend conventions, or any other modu
| `coyote --list-skills` | Print installed skill names, one per line. |
| `coyote --skill <NAME>` | If the skill exists, load it and proceed to REPL or one-shot. If missing, scaffold + edit. |
| `coyote --skill <A> --skill <B> [...]` | Pre-load multiple skills in argument order. All must exist; fails fast if any is missing. |
| `coyote --install skills` | Reinstall all bundled built-in skills. |
| `coyote --install-from <url> --filter skills` | Install only `skills/` from a remote repo. |
| `coyote --install-builtins skills` | Reinstall all bundled built-in skills. |
| `coyote --install <url> --filter skills` | Install only `skills/` from a remote repo. |
`coyote --skill <name>` composes naturally with `--role`, `--agent`, and a one-shot prompt:
@@ -431,9 +431,9 @@ laid out as:
installs with:
```shell
coyote --install-from https://github.com/<owner>/<repo>
coyote --install <owner>/<repo>
# or just the skills/:
coyote --install-from https://github.com/<owner>/<repo> --filter skills
coyote --install <owner>/<repo> --filter skills
```
See [Sharing Configurations](Sharing-Configurations) for the full layout, ref pinning, conflict resolution, and secrets