docs: Updated documentation on bundles
+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
|
||||
|
||||
Reference in New Issue
Block a user