Compare commits

...
3 Commits
Author SHA1 Message Date
Dark-Alex-17 001b13de5a docs: rename to coyote-bundle-template and document the bundle lifecycle
Adds the identity manifest and rewrites the README around the current
install surface: --install with owner/repo shorthand and --git-host,
provenance-backed --list-bundles / --update-bundle / --uninstall, and
the update semantics for files and mcp entries.
2026-08-24 10:03:11 -06:00
Dark-Alex-17 9557e0ba3c feat: Added sbx-mixin.yaml templates and documentation on how sandbox integration works in Coyote 2026-06-18 09:52:46 -06:00
Alex Clarke 6ffe62cc3a Merge pull request #1 from Dark-Alex-17/skills
feat: Added skills support
2026-06-05 11:53:47 -06:00
4 changed files with 177 additions and 29 deletions
+122 -29
View File
@@ -1,39 +1,52 @@
# coyote-config-template # coyote-bundle-template
A starter template for sharing [Coyote](https://github.com/Dark-Alex-17/coyote) A starter template for [Coyote](https://github.com/Dark-Alex-17/coyote)
configurations via any Git repository. Repositories structured like this enable bundles: shareable configurations distributed via any Git repository.
users to share agents, roles, macros, tools, and MCP servers in Coyote easily. Repositories structured like this let users share agents, roles, skills,
macros, tools, and MCP servers in Coyote easily. Bundles are Coyote's
equivalent of plugins.
Fork this repo, customize the assets to your taste, then install your fork Fork this repo, customize the assets to your taste, then install your fork
into Coyote with a single command. into Coyote with a single command.
## Quick start ## Quick start
Install everything in this template into your local Coyote config: Install everything in this template into your local Coyote config using the
`owner/repo` shorthand (expanded against github.com by default):
```sh ```sh
coyote --install-from https://github.com/<you>/coyote-config-template coyote --install <you>/coyote-bundle-template
``` ```
or from within the Coyote REPL: or with a full Git URL, or from within the Coyote REPL:
```sh
coyote --install https://github.com/<you>/coyote-bundle-template
```
``` ```
.install remote https://github.com/<you>/coyote-config-template .install <you>/coyote-bundle-template
```
Hosting somewhere other than GitHub? Point the shorthand at your forge:
```sh
coyote --install <group>/<subgroup>/coyote-bundle-template --git-host gitlab.com
``` ```
Pin to a specific branch, tag, or commit by suffixing `#<ref>`: Pin to a specific branch, tag, or commit by suffixing `#<ref>`:
```sh ```sh
coyote --install-from https://github.com/<you>/coyote-config-template#v1.0.0 coyote --install <you>/coyote-bundle-template#v1.0.0
coyote --install-from https://github.com/<you>/coyote-config-template#main coyote --install <you>/coyote-bundle-template#main
coyote --install-from https://github.com/<you>/coyote-config-template#abc1234 coyote --install <you>/coyote-bundle-template#abc1234
``` ```
Restrict the install to a single asset category with `--filter`: Restrict the install to a single asset category with `--filter`:
```sh ```sh
coyote --install-from https://github.com/<you>/coyote-config-template --filter agents coyote --install <you>/coyote-bundle-template --filter agents
coyote --install-from https://github.com/<you>/coyote-config-template --filter mcp_config coyote --install <you>/coyote-bundle-template --filter mcp_config
``` ```
Valid filter values: `agents`, `roles`, `skills`, `macros`, `functions`, `mcp_config`. Valid filter values: `agents`, `roles`, `skills`, `macros`, `functions`, `mcp_config`.
@@ -41,16 +54,63 @@ Valid filter values: `agents`, `roles`, `skills`, `macros`, `functions`, `mcp_co
Skip per-file conflict prompts with `--install-force`: Skip per-file conflict prompts with `--install-force`:
```sh ```sh
coyote --install-from https://github.com/<you>/coyote-config-template --install-force coyote --install <you>/coyote-bundle-template --install-force
``` ```
## Managing the installed bundle
Coyote records everything a bundle install writes (file paths, MCP server
entries, and content hashes) in a provenance store, which powers the full
lifecycle:
```sh
coyote --list-bundles # name, version, source, drift
coyote --install <bundle-name> # update by installed name
coyote --update-bundle <bundle-name> # update from the recorded source
coyote --update-bundle <bundle-name>#<ref> # move a pin while updating
coyote --update-bundle <bundle-name> --yes # non-interactive: keep local edits, refresh the rest
coyote --uninstall <bundle-name> # remove owned files and MCP entries
coyote --uninstall <bundle-name> --yes # skip the confirmation prompt
```
The same operations are available in the REPL as `.list bundles`,
`.install <bundle-name>`, and `.uninstall <bundle-name> [--yes]`.
Updates and uninstalls never clobber your local edits: files you modified
after install are prompted for (and kept by default on uninstall), while
untouched files refresh or delete silently. See the
[Sharing Configurations wiki](https://github.com/Dark-Alex-17/coyote/wiki/Sharing-Configurations)
for the full ownership and drift model.
## The manifest (`coyote-bundle.yaml`)
The optional manifest at the repo root declares the bundle's identity, and
nothing else. Coyote discovers installable content by scanning the asset
directories; the manifest never lists files.
```yaml
name: coyote-bundle-template
version: "1.0.0"
description: Starter template for Coyote bundles
homepage: https://github.com/Dark-Alex-17/coyote-bundle-template
```
- `name` is how consumers refer to the bundle in `--update-bundle` and
`--uninstall`. Ship a manifest so your bundle keeps a stable name across
forks; without one, Coyote derives the name from the repository name.
- `version` shows up in `--list-bundles` (falls back to the short commit SHA).
- If your chosen name collides with another installed bundle or a built-in
asset category, Coyote qualifies it with the repo owner (`owner/name`)
instead of overwriting anything.
## Layout ## Layout
Coyote only reads these top-level directories. Anything else in the repo is Coyote only reads the manifest and these top-level directories. Anything
ignored. else in the repo is ignored.
``` ```
coyote-config-template/ coyote-bundle-template/
├── coyote-bundle.yaml # Optional identity manifest
├── agents/ ├── agents/
│ └── <agent-name>/ │ └── <agent-name>/
│ ├── config.yaml # LLM-loop agent │ ├── config.yaml # LLM-loop agent
@@ -74,17 +134,19 @@ coyote-config-template/
The `functions/mcp.json` file is **merged** into your existing local file The `functions/mcp.json` file is **merged** into your existing local file
on install (not overwritten). For conflicting server names, you'll be on install (not overwritten). For conflicting server names, you'll be
prompted to keep yours, take the remote's, or rename the remote entry. prompted to keep yours, take the remote's, or rename the remote entry.
On update, entries the bundle installed and you never edited take the
remote side automatically.
## What's in this template ## What's in this template
| Asset | File | What it is | | Asset | File | What it is |
|--------|-----------------------------------|---------------------------------------------------------| |-------|----------------------------------|---------------------------------------------------------|
| Agent | `agents/hello-agent/config.yaml` | Tiny LLM-loop agent that greets the user. | | Agent | `agents/hello-agent/config.yaml` | Tiny LLM-loop agent that greets the user. |
| Role | `roles/explainer.md` | Role that explains technical concepts simply. | | Role | `roles/explainer.md` | Role that explains technical concepts simply. |
| Skill | `skills/rust-fmt/SKILL.md` | Skill demonstrating `enabled_tools` + `auto_unload`. | | Skill | `skills/rust-fmt/SKILL.md` | Skill demonstrating `enabled_tools` + `auto_unload`. |
| Macro | `macros/greet.yaml` | Macro showing positional and rest-arg variables. | | Macro | `macros/greet.yaml` | Macro showing positional and rest-arg variables. |
| Tool | `functions/tools/greet.sh` | Bash tool using Coyote's argc-style annotations. | | Tool | `functions/tools/greet.sh` | Bash tool using Coyote's argc-style annotations. |
| MCP | `functions/mcp.json` | One vanilla server + one with a vault secret reference. | | MCP | `functions/mcp.json` | One vanilla server + one with a vault secret reference. |
Each sample is intentionally minimal. Replace it with your own work, or Each sample is intentionally minimal. Replace it with your own work, or
delete what you don't need. delete what you don't need.
@@ -128,10 +190,35 @@ Use `{{SECRET_NAME}}` placeholders for values you don't want to commit;
Coyote will detect missing secrets after the merge and prompt you to add Coyote will detect missing secrets after the merge and prompt you to add
them to the vault (or list them for you to add via `coyote --add-secret`). them to the vault (or list them for you to add via `coyote --add-secret`).
### (Optional) Sandbox mixins (`sbx-mixin.yaml`)
If consumers of your bundle run Coyote in [Sandbox mode](https://github.com/Dark-Alex-17/coyote/wiki/Sandboxes),
they'll need any external binaries and network domain allowances declared
in an `sbx-mixin.yaml` file. Coyote auto-discovers mixin files at known
locations on every `coyote --sandbox` invocation, no flags required.
This template ships two starter examples:
- **`agents/hello-agent/sbx-mixin.yaml`:** Per-agent mixin, applied when
the agent is installed and any `coyote --sandbox` runs.
- **`functions/sbx-mixin.yaml`:** Shared by all custom tools in this
bundle. For per-tool granularity, use `functions/<tool>/sbx-mixin.yaml`
instead.
Both starters are commented-out templates. Simply open them and fill in the
domains and install commands your assets actually need. Delete the files
if they're not needed.
> ⚠️ **Privilege grant.** Anyone installing your bundle is granting the
> mixins' install commands (passwordless sudo) and network domain
> allowances inside their sandboxes. Document any non-obvious entries in
> this README so they don't have to grep your YAML to find out what
> they're accepting. See the [Sharing Configurations - Sandbox Implications](https://github.com/Dark-Alex-17/coyote/wiki/Sharing-Configurations#sandbox-implications)
> wiki page for the full security model.
## Secrets workflow ## Secrets workflow
Anywhere you reference a secret in `mcp.json` (or in any installed file), Anywhere you reference a secret in `mcp.json` (or in any installed file),
use the `{{NAME}}` placeholder syntax. After `--install-from` completes: use the `{{NAME}}` placeholder syntax. After an install completes:
- **Interactive mode**: Coyote prompts you per-secret to add the value to - **Interactive mode**: Coyote prompts you per-secret to add the value to
the vault. On the first "Yes," it creates the vault password file if the vault. On the first "Yes," it creates the vault password file if
@@ -145,9 +232,15 @@ the full secrets workflow.
## Tips for forks ## Tips for forks
- Ship a `coyote-bundle.yaml` with your own `name` so your bundle keeps a
stable identity no matter what consumers or forks call the repository.
- Pin your fork to tagged releases so consumers can install with - Pin your fork to tagged releases so consumers can install with
`#<tag>` for reproducibility. `#<tag>` for reproducibility, and bump the manifest `version` alongside
your tags so `coyote --list-bundles` shows something meaningful.
- Keep agent-local logic in `agents/<name>/scripts/`. Global - Keep agent-local logic in `agents/<name>/scripts/`. Global
tools (in `functions/tools/`) are shared across every agent. tools (in `functions/tools/`) are shared across every agent.
- The `mcp.json` merge is *additive*. If you remove a server from your - Removing a file from your fork does propagate: on the next
fork, existing installs of that server are _not_ pruned. That's by design. `--update-bundle`, consumers are asked whether to keep or delete files
the bundle no longer ships. Removing an `mcp.json` server does not prune
existing installs of that entry; uninstalling the bundle removes the
entries it added (unless the user edited them).
+23
View File
@@ -0,0 +1,23 @@
schemaVersion: "1"
kind: mixin
name: agent-hello
description: >
Example sbx mixin for the hello-agent. Coyote auto-discovers and applies
any sbx-mixin.yaml co-located with an agent whenever you run
`coyote --sandbox`. Use this to declare any binaries the agent needs to
install inside the sandbox and any network domains it needs to reach.
Delete this file if your agent doesn't need extra sandbox setup.
network:
allowedDomains:
# Replace with the domains your agent actually hits.
# Example: an agent that calls api.example.com would add:
# - "api.example.com:443"
commands:
install:
# Replace with any binaries your agent depends on. Runs as the
# `agent` user (UID 1000) with passwordless sudo. Example:
# - command: "sudo apt-get update && sudo apt-get install -y httpie"
# user: "1000"
# description: Install httpie for hello-agent's API calls
+7
View File
@@ -0,0 +1,7 @@
# Bundle identity (optional). Without this file, Coyote derives the bundle
# name from the repository name. The manifest never lists files: everything
# Coyote installs is discovered by scanning the asset directories.
name: coyote-bundle-template
version: "1.0.0"
description: Starter template for Coyote bundles
homepage: https://github.com/Dark-Alex-17/coyote-bundle-template
+25
View File
@@ -0,0 +1,25 @@
schemaVersion: "1"
kind: mixin
name: shared-custom-tools
description: >
Example global sbx mixin that applies to every Coyote sandbox you launch.
Use this for binaries and network domains shared by multiple custom tools
in functions/tools/. For per-tool needs that aren't shared, create
functions/<tool-name>/sbx-mixin.yaml instead (per-tool mixins are also
auto-discovered).
Delete this file if your fork doesn't need extra sandbox setup.
network:
allowedDomains:
# Replace with the domains your custom tools reach.
# Example: a tool that calls a private API:
# - "api.your-company.com:443"
commands:
install:
# Replace with binaries your custom tools depend on. Runs as the
# `agent` user (UID 1000) with passwordless sudo. Example:
# - command: "sudo apt-get update && sudo apt-get install -y httpie xmlstarlet"
# user: "1000"
# description: Install custom tool dependencies