diff --git a/Agents.md b/Agents.md index 4eac3e9..b10449d 100644 --- a/Agents.md +++ b/Agents.md @@ -789,12 +789,21 @@ Coyote comes packaged with some useful built-in agents: * `librarian`: A graph-based agent that researches external references. It finds official docs, production OSS examples, and web best practices. The "external grep" sibling of `explore` (which handles internal/codebase grep). Designed to be delegated to by `sisyphus` whenever an unfamiliar library, API, or framework is involved. -* `oracle`: An agent for high-level architecture, design decisions, and complex debugging +* `oracle`: An agent for high-level architecture, design decisions, complex debugging, and reviewing implementation + plans before execution (via the `plan-review` skill, returning a `PLAN_REVIEW: OKAY`/`REJECT` verdict) * `report-writer`: An agent to polish research findings into clear, citation-preserving final reports * `sisyphus`: A powerhouse orchestrator agent for writing complex code and acting as a natural language interface for your codebase (similar to ClaudeCode, Gemini CLI, Codex, or OpenCode). Uses sub-agent spawning to delegate to - `explore`, `librarian`, `coder`, and `oracle`. + `explore`, `librarian`, `coder`, `oracle`, and `step-runner`. Also supports plan-driven workflows: authoring phased + implementation plans (via the `plan-authoring` skill), having `oracle` review them, and executing them one reviewed + step at a time. * `sql`: A universal SQL agent that enables you to talk to any relational database in natural language +* `step-runner`: A graph-based agent that executes ONE step of a phased implementation plan (a `plans/` repo authored + with the `plan-authoring` skill) with the step protocol enforced as graph edges: orient from the previous handoff -> + staleness-check the plan -> implement (delegating to `coder`) -> format/lint/build/full-test verification -> edge-case + sweep -> optional independent review (`code-reviewer`) -> evidence-backed handoff -> hard-stop user approval gate. + Returns `STEP_COMPLETE`/`STEP_BLOCKED`/`STEP_REJECTED`/`STEP_FAILED` to the caller. Designed to be delegated to by + `sisyphus`. Coyote writes these built-in agents to your agents directory on first run and never overwrites them afterward, so any edits you make to them are preserved across Coyote updates. To discard your local changes and reinstall the built-in diff --git a/Bash-Prompt-Helpers.md b/Bash-Prompt-Helpers.md index 900ee99..d94f1bd 100644 --- a/Bash-Prompt-Helpers.md +++ b/Bash-Prompt-Helpers.md @@ -202,7 +202,10 @@ open_link https://www.google.com ## guard_operation Prompt for permission to run an operation. -Can be disabled by setting the environment variable `AUTO_CONFIRM`. +Can be disabled by setting the environment variable `AUTO_CONFIRM` to any non-empty value, +or by starting Coyote with `--dangerously-skip-permissions` (which sets `AUTO_CONFIRM=true` +for the entire session, including all spawned tools and agents). Use the flag with care! +It disables *every* `guard_*` prompt for the invocation. **Example:** ```bash @@ -213,7 +216,10 @@ _run_sql ## guard_path Prompt for permission to perform path operations. -Can be disabled by setting the environment variable `AUTO_CONFIRM`. +Can be disabled by setting the environment variable `AUTO_CONFIRM` to any non-empty value, +or by starting Coyote with `--dangerously-skip-permissions` (which sets `AUTO_CONFIRM=true` +for the entire session, including all spawned tools and agents). Use the flag with care! +It disables *every* `guard_*` prompt for the invocation. **Example:*** ```bash diff --git a/Clients.md b/Clients.md index 855229c..2cf3ac9 100644 --- a/Clients.md +++ b/Clients.md @@ -128,10 +128,33 @@ coyote --authenticate Alternatively, you can use the REPL command `.authenticate`. This opens your browser for the OAuth authorization flow. Depending on the provider, Coyote will either start a -temporary localhost server to capture the callback automatically (e.g. Gemini) or ask you to paste the authorization -code back into the terminal (e.g. Claude). Coyote stores the tokens in `~/.cache/coyote/oauth` and automatically refreshes +temporary localhost server to capture the callback automatically (e.g. Gemini, OpenAI) or ask you to paste the authorization +code back into the terminal (e.g. Claude). Coyote stores the tokens in `/coyote/oauth` and automatically refreshes them when they expire. +### OpenAI OAuth Note + +OpenAI OAuth requires a **ChatGPT Plus or Pro subscription**. It uses the shared Codex CLI OAuth app registered with +OpenAI, so no additional API credentials or app registration are needed. + +When authenticating, Coyote starts a localhost server on port **1455** to capture the OAuth callback automatically. This port is +fixed by OpenAI's app registration and cannot be changed. Make sure port 1455 is available when you run +`--authenticate`/`.authenticate`. + +When `auth: oauth` is set and no `api_base` is configured, Coyote automatically routes all requests through +`chatgpt.com/backend-api/codex/responses` (the OpenAI Responses API), which is what ChatGPT Plus/Pro subscribers have +access to. If you later add an `api_key` or a custom `api_base`, Coyote will use the standard `api.openai.com/v1` +endpoint instead. + +Example configuration: + +```yaml +clients: + - type: openai + name: openai-oauth + auth: oauth +``` + ### Gemini OAuth Note Coyote uses the following scopes for OAuth with Gemini: * https://www.googleapis.com/auth/generative-language.peruserquota @@ -165,6 +188,7 @@ coyote -m my-claude-oauth:claude-sonnet-4-20250514 "Hello!" ## Providers That Support OAuth * Claude * Gemini +* OpenAI (requires ChatGPT Plus or Pro subscription) # Extra Settings Coyote also lets you customize some extra settings for interacting with APIs: diff --git a/Environment-Variables.md b/Environment-Variables.md index dfde5e4..9f7546d 100644 --- a/Environment-Variables.md +++ b/Environment-Variables.md @@ -37,6 +37,9 @@ Below are the most commonly used configuration settings and their corresponding | `rag_top_k` | `COYOTE_RAG_TOP_K` | | `rag_chunk_size` | `COYOTE_RAG_CHUNK_SIZE` | | `rag_chunk_overlap` | `COYOTE_RAG_CHUNK_OVERLAP` | +| `rag_extractor_model` | `COYOTE_RAG_EXTRACTOR_MODEL` | +| `rag_extractor_prompt` | `COYOTE_RAG_EXTRACTOR_PROMPT` | +| `rag_graph_hops` | `COYOTE_RAG_GRAPH_HOPS` | | `highlight` | `COYOTE_HIGHLIGHT` | | `theme` | `COYOTE_THEME` | | `serve_addr` | `COYOTE_SERVE_ADDR` | @@ -97,7 +100,7 @@ The following variable controls Coyote's [Sandbox mode](Sandboxes): created. - The path is passed verbatim to `sbx create --kit`; it must be a valid sbx kit (containing `spec.yaml`), not just any directory. -- No environment variables map to the new sandbox-mode CLI flags (`--fresh`, `--no-mixins`). These are intentionally +- No environment variables map to the sandbox-mode CLI flags (`--fresh`, `--no-mixins`). These are intentionally CLI-only. They're one-time per-invocation decisions, not configuration knobs. # Logging Related Variables @@ -114,5 +117,5 @@ can also pass the `--disable-log-colors` flag as well. # Miscellaneous Variables | Environment Variable | Description | Default Value | |----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------| -| `AUTO_CONFIRM` | Bypass all `guard_*` checks in the bash prompt helpers; useful for agent composition and routing | | +| `AUTO_CONFIRM` | Bypass all `guard_*` checks in the bash prompt helpers; useful for agent composition and routing. Can also be enabled for a single invocation by passing `--dangerously-skip-permissions` (Coyote sets `AUTO_CONFIRM=true` for the process and all spawned tools/agents). | | | `LLM_TOOL_DATA_FILE` | Set automatically by Coyote on Windows. Points to a temporary file containing the JSON tool call data.
Tool scripts (`run-tool.sh`, `run-agent.sh`, etc.) read from this file instead of command-line args
to avoid JSON escaping issues when data passes through `cmd.exe` → bash. **Not intended to be set by users.** | | diff --git a/Graph-Agents.md b/Graph-Agents.md index cc14f94..9cbf6b2 100644 --- a/Graph-Agents.md +++ b/Graph-Agents.md @@ -521,10 +521,11 @@ Agent nodes (which spawn full sub-agents) intentionally have no ## rag -Runs a hybrid (vector + keyword) retrieval against a per-node knowledge base -and writes the result into state. This is how a graph agent does -Retrieval-Augmented Generation: the `rag` node retrieves context, downstream -`llm`/`agent` nodes inject it into their prompts via normal templating. +Runs a hybrid (vector + full-text + optional graph) retrieval against a +per-node knowledge base and writes the result into state. This is how a +graph agent does Retrieval-Augmented Generation: the `rag` node retrieves +context, downstream `llm`/`agent` nodes inject it into their prompts via +normal templating. ```yaml research_context: @@ -569,6 +570,18 @@ base is first built): - **`chunk_size`:** Document chunk size. - **`chunk_overlap`:** Overlap between chunks. - **`reranker_model`:** Reranker applied to hybrid-search results. +- **`extractor_model`:** Chat model for graph-based entity/relationship extraction. + When set, a knowledge graph is built at index time and used as an additional + retrieval signal alongside vector and BM25. Falls back to the global + `rag_extractor_model` config when omitted. See [RAG > Graph-Based RAG](RAG#graph-based-rag) + for guidance on model selection. +- **`extractor_prompt`:** Custom extraction prompt template. Must contain a `__CHUNK__` + placeholder. Falls back to `rag_extractor_prompt` then the built-in prompt. Useful for + domain-specific entity types (e.g. legal, medical, code). See + [RAG > Custom extraction prompt](RAG#custom-extraction-prompt). +- **`graph_hops`:** Number of graph hops to expand from matched entities at query time + (default: `1`). `0` returns only documents directly linked to matched entities with no traversal. + Falls back to `rag_graph_hops`. Higher values surface more loosely related documents; keep at `1` for most corpora. - **`batch_size`:** Embedding-request batch size. Each falls back to the app-level `rag_*` config when omitted. **When @@ -615,9 +628,12 @@ inspected, not run, so knowledge-base building is skipped entirely.) ### Retrieval -Retrieval at execution time is fast (no re-embedding of the corpus). It's -the same hybrid vector + keyword search normal Coyote RAG uses. The corpus -embedding/chunking cost is paid once, at load time. +Retrieval at execution time is fast (no re-embedding of the corpus). The corpus +embedding/chunking cost is paid once, at load time. The retrieval strategy +matches normal Coyote RAG: vector + full-text (BM25) signals are always active, +and a third graph-based signal is added when an `extractor_model` is set at +build time. All active signals are fused via RRF; if a `reranker_model` is set, +it replaces RRF and graph search is not applied. --- @@ -1522,7 +1538,8 @@ A short, honest list of things that bite people: - Built-in graph agents shipped with Coyote: [`coder`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/agents/coder) (implement -> verify_build -> verify_tests -> self_review -> fix-loop), [`deep-research`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/agents/deep-research) (the canonical reference that exercises every node type), - [`librarian`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/agents/librarian) (triage -> parallel doc + OSS search -> synthesize -> trim; a compact illustration of static fan-out with reducers). + [`librarian`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/agents/librarian) (triage -> parallel doc + OSS search -> synthesize -> trim; a compact illustration of static fan-out with reducers), + [`step-runner`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/agents/step-runner) (orient -> staleness check -> implement via a `coder` agent node -> verify -> edge-case sweep -> handoff -> approval gate; a workflow-enforcement example combining agent nodes, approval gates, script routing, and bounded fix-loops). See [Agents > Built-In Agents](Agents#built-in-agents) for descriptions. - [Agents](Agents) - non-graph agent system (config.yaml + LLM loop) - [Custom Tools](Custom-Tools) - building `tools.sh` / `tools.py` / diff --git a/Installation.md b/Installation.md index aa553f5..ac1e72a 100644 --- a/Installation.md +++ b/Installation.md @@ -7,6 +7,14 @@ Coyote requires the following tools to be installed on your system: * [docker](https://docs.docker.com/engine/install/) * [uv](https://docs.astral.sh/uv/getting-started/installation/) * `curl -LsSf https://astral.sh/uv/install.sh | sh` +* [iwe](https://github.com/iwe-org/iwe) (`iwec`, for the built-in `iwe` MCP server that navigates large markdown knowledgebases) + * **Homebrew:** `brew tap iwe-org/iwe && brew install iwe` + * **Cargo:** `cargo install iwec` +* [ast-grep](https://ast-grep.github.io/) (for the built-in `ast_grep` structural code search tool, used by the `explore` agent) + * **Homebrew:** `brew install ast-grep` + * **Cargo:** `cargo install ast-grep --locked` + * **npm:** `npm i -g @ast-grep/cli` + * Optional: if `ast-grep` is not installed, the `ast_grep` tool reports it and agents fall back to `fs_grep` These tools are used to provide various functionalities within Coyote, such as document processing, JSON manipulation, and they are used within agents and tools. diff --git a/MCP-Servers.md b/MCP-Servers.md index a8bfd99..d160d51 100644 --- a/MCP-Servers.md +++ b/MCP-Servers.md @@ -30,9 +30,9 @@ allows it to be omitted and infers `stdio` from the presence of a `command`). So a new server, look at its docs and find the Claude Code configuration example. You should be able to use the exact same configuration in your `functions/mcp.json` file. Just make sure every entry has an explicit `type`. -**Note:** Coyote does not support Claude Code's `"streamable-http"` alias (use `"http"` instead), nor extras -like `oauth` or `envFile`. For secrets, use [Coyote Vault](Vault) interpolation rather than Claude Code's `${VAR}` -shell-style expansion. +**Note:** Coyote does not support Claude Code's `"streamable-http"` alias (use `"http"` instead) or `envFile`. +For secrets, use [Coyote Vault](Vault) interpolation rather than Claude Code's `${VAR}` shell-style expansion. +OAuth-protected remote servers are supported natively (see [OAuth Authentication](#oauth-authentication) below). Every server entry **must** include a `"type"` field set to one of: `"stdio"`, `"http"`, or `"sse"`. @@ -40,6 +40,58 @@ Every server entry **must** include a `"type"` field set to one of: `"stdio"`, ` > kit provides. See [Sandbox Compatibility](#sandbox-compatibility) at the bottom of this page for details and > common gotchas. +## Workspace-Local MCP Servers + +In addition to the global `functions/mcp.json`, Coyote automatically loads a workspace-local MCP config from `.coyote/mcp.json` +in the current directory at startup. This lets you ship project-specific MCP servers alongside your code without +touching your global configuration. + +``` +/ +└── .coyote/ + └── mcp.json # same format as functions/mcp.json +``` + +The workspace file uses the exact same format as the global `functions/mcp.json`, including [Vault](Vault) secret +interpolation via `{{SECRET_NAME}}` syntax. Workspace server names shadow global ones on collision. This means that +if both files define a server named `my-db`, the workspace version takes precedence. + +When workspace MCP servers are loaded, Coyote prints a startup notice listing them: + +``` +Loading workspace MCP servers: my-db, project-search +``` + +**Error handling:** missing vault secrets and invalid server specs in the workspace file produce a warning and are +skipped. They do not prevent Coyote from starting (unlike the global file, where missing secrets are a hard error). + +### Opting out + +To disable workspace MCP loading for a session, pass `--no-workspace-mcp`: + +```shell +coyote --no-workspace-mcp +``` + +To disable it permanently in your config: + +```yaml +no_workspace_mcp: true +``` + +### Pairing workspace MCPs with workspace skills + +Workspace MCP servers can be referenced in `.coyote/skills/` skill frontmatter just like global servers: + +```markdown +--- +description: Run project-specific database queries. +enabled_mcp_servers: my-db +--- +``` + +See [Workspace-Local Skills](Skills#workspace-local-skills) for details. + ## Transport Types Coyote supports three MCP transport types: @@ -93,11 +145,14 @@ For remote MCP servers that support the Streamable HTTP transport: } ``` -| Field | Required | Description | -|-----------|----------|--------------------------------------------------------| -| `type` | yes | Must be `"http"` | -| `url` | yes | The server endpoint URL | -| `headers` | no | Custom HTTP headers to include with every request | +| Field | Required | Description | +|----------------------|----------|---------------------------------------------------------------------------------------------------------------| +| `type` | yes | Must be `"http"` | +| `url` | yes | The server endpoint URL | +| `headers` | no | Custom HTTP headers to include with every request | +| `oauth.clientId` | no | OAuth client ID. Omit to use Dynamic Client Registration (auto-registers on first `.mcp auth`) | +| `oauth.callbackPort` | no | Callback port for the OAuth redirect listener. Required when the server enforces a specific redirect URI port | +| `oauth.redirectHost` | no | Hostname used in the OAuth redirect URI. Defaults to `127.0.0.1`. Set to `localhost` if the server's registered redirect URI uses that form instead (e.g. some Slack OAuth apps) | ## SSE Servers @@ -118,16 +173,164 @@ prefer `http` where the server supports it): } ``` -| Field | Required | Description | -|-----------|----------|--------------------------------------------------------| -| `type` | yes | Must be `"sse"` | -| `url` | yes | The server SSE endpoint URL | -| `headers` | no | Custom HTTP headers to include with every request | +| Field | Required | Description | +|----------------------|----------|---------------------------------------------------------------------------------------------------------------| +| `type` | yes | Must be `"sse"` | +| `url` | yes | The server SSE endpoint URL | +| `headers` | no | Custom HTTP headers to include with every request | +| `oauth.clientId` | no | OAuth client ID. Omit to use Dynamic Client Registration (auto-registers on first `.mcp auth`) | +| `oauth.callbackPort` | no | Callback port for the OAuth redirect listener. Required when the server enforces a specific redirect URI port | +| `oauth.redirectHost` | no | Hostname used in the OAuth redirect URI. Defaults to `127.0.0.1`. Set to `localhost` if the server's registered redirect URI uses that form instead (e.g. some Slack OAuth apps) | **Note:** Both `http` and `sse` types use the same underlying transport, which auto-negotiates the protocol with the server. The `type` field primarily serves as documentation of which protocol the server speaks. Neither type supports `command`, `args`, or `cwd` fields. +## OAuth Authentication + +Some remote MCP servers require OAuth 2.0 authentication (e.g. Notion, Jira). Coyote supports these +natively, meaning no manual token management is required. + +### Example: Notion + +```json +{ + "mcpServers": { + "notion": { + "type": "http", + "url": "https://mcp.notion.com/mcp" + } + } +} +``` + +That's it. Then in the REPL: + +``` +.mcp auth notion +``` + +Or from the command line: + +```shell +coyote --auth-mcp notion +``` + +Your browser opens, you log into Notion, and the token is saved. On subsequent startups Coyote injects the token +automatically. When the token expires it is refreshed silently. + +### How it works + +1. **Discovery:** Coyote fetches `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server` + to find the server's authorization and token endpoints (per RFC 9728 / RFC 8414). No manual endpoint configuration needed. +2. **Dynamic Client Registration (RFC 7591):** If the server supports it (the Notion MCP server used in this example does), Coyote + registers itself automatically and caches the client ID in `~/.cache/coyote/oauth/mcp__registration.json`. The + `oauth_client_id` field is only needed when DCR is unavailable. +3. **PKCE authorization code flow:** A localhost callback server is bound on an ephemeral port (or the port specified by + `oauth.callbackPort` if the server requires a fixed redirect URI). Your browser opens for login. + The token is exchanged and stored in `/oauth/mcp__oauth_tokens.json`. +4. **Token injection:** On every connection to the server, Coyote loads the stored token (refreshing if expired) and injects + it as an `Authorization: Bearer` header. No changes to `mcp.json` required. + +### If authentication hasn't been run yet + +If Coyote tries to connect to an OAuth-protected server at startup and gets an auth challenge, it +**warns and skips** the server rather than failing: + +``` +warn: MCP server 'notion' requires authentication. Run `.mcp auth notion` to authenticate. +``` + +Run `.mcp auth notion` (or `coyote --auth-mcp notion`) once to complete the flow, then restart Coyote. + +### Using a pre-existing client ID + +If your organization pre-registers a client with the server (this is rare, as DCR handles this automatically for most servers): + +```json +{ + "mcpServers": { + "my-server": { + "type": "http", + "url": "https://mcp.example.com/mcp", + "oauth": { + "clientId": "your-registered-client-id" + } + } + } +} +``` + +When `oauth.clientId` is set, DCR is skipped and the provided ID is used directly. + +Some servers (e.g. Slack) pre-register an OAuth app with a specific redirect URI and require the callback to land on a +fixed port. Use `oauth.callbackPort` in that case: + +```json +{ + "mcpServers": { + "slack": { + "type": "http", + "url": "https://mcp.slack.com/mcp", + "oauth": { + "clientId": "1601185624273.8899143856786", + "callbackPort": 3118 + } + } + } +} +``` + +Coyote's redirect URI uses `127.0.0.1` by default (e.g. `http://127.0.0.1:3118/callback`). If the OAuth app +you registered uses `localhost` instead, set `oauth.redirectHost` to match: + +```json +{ + "mcpServers": { + "notion": { + "type": "http", + "url": "https://mcp.slack.com/mcp", + "oauth": { + "clientId": "your-slack-client-id", + "redirectHost": "localhost" + } + } + } +} +``` + +> **Note:** This only applies when using a pre-registered `clientId`. When DCR is used (no `clientId` +> configured), Coyote registers its own redirect URI so the host format never mismatches. + +### Using a static token instead of OAuth + +If the server issues long-lived tokens (e.g. Notion internal integrations), you can skip the OAuth flow +entirely and use a static `Authorization` header: + +```json +{ + "mcpServers": { + "notion": { + "type": "http", + "url": "https://mcp.notion.com/mcp", + "headers": { + "Authorization": "Bearer " + } + } + } +} +``` + +Use [Coyote Vault](Vault) to avoid storing the token in plaintext: + +```json +{ + "headers": { + "Authorization": "Bearer {{notion_token}}" + } +} +``` + ## Secret Injection As mentioned in the [Coyote Vault documentation](Vault), you can use Coyote Vault to inject secrets into your MCP configuration file. @@ -142,14 +345,15 @@ Coyote ships with a `functions/mcp.json` file that includes some useful MCP serv * [atlassian](https://github.com/atlassian/atlassian-mcp-server) - Interact with and manage Atlassian tools like Confluence and Jira. * [github](https://github.com/github/github-mcp-server) - Interact with GitHub repositories, issues, pull requests, and more. * [docker](https://github.com/ckreiling/mcp-server-docker) - Manage your local Docker containers with natural language -* [slack](https://github.com/korotovsky/slack-mcp-server) - Interact with Slack * [ddg-search](https://github.com/nickclyde/duckduckgo-mcp-server) - Perform web searches with the DuckDuckGo search engine +* [iwe](https://github.com/iwe-org/iwe) - Navigate and manage large markdown knowledgebases (plan repos, specs, notes) as a structured + graph. The server is rooted at the directory Coyote is launched from (`--project .`), runs fully locally (no network access needed), + and requires the `iwec` binary. Pairs with the built-in `iwe-knowledge-base` [skill](Skills), which enables this server on load. -The `mcp.json` file is created from a bundled template on first run and is never overwritten afterward. It is your own -configuration to edit freely. To discard your changes and restore the bundled template (for example, to pick up new -default servers after a Coyote update), run `coyote --install mcp_config` (or `.install mcp_config` in the REPL). **This is -destructive:** it replaces your entire `mcp.json`, including your configured servers and any secret references in them, -with the bundled template. +The `mcp.json` file is created from a bundled template on first run. It is your own configuration to edit freely. +To pick up new default servers added in a Coyote update, run `coyote --install mcp_config` (or `.install mcp_config` +in the REPL). This **merges** the bundled template into your existing configuration: only servers not already present +in your file are added; your existing servers and any custom secret references are left untouched. # Coyote Configuration MCP servers, like tools, can be used in a handful of contexts: diff --git a/Memory.md b/Memory.md index c6d1eae..c055893 100644 --- a/Memory.md +++ b/Memory.md @@ -95,11 +95,22 @@ Each drill file has YAML frontmatter: name: project_compliance description: Compliance constraints driving the auth rewrite type: project +created: 2026-05-12 +updated: 2026-07-03 --- We must store session tokens server-side per the 2026 audit. ... ``` +`created` and `updated` are stamped automatically by `memory__write` (creation date is preserved across overwrites). +Two more optional fields track staleness: + +- `superseded_by: ` - this memory has been replaced by another drill file +- `expires: YYYY-MM-DD` - this memory stops being true after a known date (e.g. an API freeze window) + +Both are settable via optional arguments to `memory__write`, and `memory__lint` flags superseded and expired files so +the LLM (or you) can clean them up. + `MEMORY.md` is what gets injected on every prompt. It serves two purposes: 1. **An index** of available drill files (one line per file: name + description) 2. **A home for universal facts** the LLM should always see (user identity, hard rules, binding feedback) @@ -124,10 +135,16 @@ categorize its own writes and so you can grep by category. When function calling is enabled, coyote exposes: - `memory__read(name)`: read a specific drill file by its slug -- `memory__write(name, description, content, scope, type)`: create or replace a drill file (`scope`: `global` | - `workspace`) +- `memory__write(name, description, content, scope, type, superseded_by?, expires?)`: create or replace a drill file + (`scope`: `global` | `workspace`). Timestamps are stamped automatically; the response reports whether an existing + file was replaced (and its previous description) so accidental overwrites are visible. +- `memory__rename(name, new_name, scope)`: rename a drill file. Its `MEMORY.md` entry and every `[[wikilink]]` to it + in other memory files are rewritten automatically. +- `memory__delete(name, scope)`: delete a drill file and remove its `MEMORY.md` entry. Reports any `[[wikilinks]]` in + other files left dangling by the deletion. - `memory__list()`: see all known drill files with metadata -- `memory__lint()`: health-check (orphans, broken `[[wikilinks]]`, oversized files >2K chars) +- `memory__lint()`: health-check (orphans, broken `[[wikilinks]]`, oversized files >2K chars, stale files that are + superseded or expired, and index descriptions that drifted from the file's own `description:`) The LLM is instructed to update `MEMORY.md` whenever it writes a new file. Two silent promotions can happen on a `memory__write(scope=workspace)`: diff --git a/RAG.md b/RAG.md index 54c89aa..601817f 100644 --- a/RAG.md +++ b/RAG.md @@ -2,7 +2,8 @@ Retrieval Augmented Generation (RAG) is a method of minimizing LLM hallucination without consuming a significant portion of the context length. It uses documents and other additional resources that you provide to give the model more context for all of your prompts. -Coyote has a built-in vector database and full-text search engine to support RAG knowledge bases for your queries. +Coyote has a built-in vector database, full-text search engine, and optional knowledge graph to support RAG knowledge +bases for your queries. At query time these signals are fused together to maximize retrieval quality. The generated knowledge bases are stored in the `rag` subdirectory of your Coyote configuration directory. The location of this directory varies by system, so you can use the following command to find your RAG directory: @@ -68,14 +69,34 @@ When you define RAG, Coyote will first "build" the RAG. This means that Coyote w generate [embeddings](https://huggingface.co/spaces/hesamation/primer-llm-embedding) for that text. This essentially just means that Coyote translates the document into a language the LLM can understand. -These embeddings are then stored in an in-memory vector database. +These embeddings are stored in an in-memory vector database. Coyote also indexes every document chunk in a full-text +search index (BM25) for keyword-based retrieval. + +If an [extractor model is configured](#graph-based-rag), Coyote additionally runs an LLM-based entity and relationship +extraction pass over each document chunk and builds a **knowledge graph** of named entities and their connections. This +graph is saved alongside the vector and BM25 indexes and enables a third, graph-based retrieval signal at query time. ### 2. Lookup -Coyote sits between you and the model. So when you submit a prompt to the model, before Coyote ever sends it, it will first -convert your prompt into embeddings (LLM language), and look for relevant snippets of text in the vector database. +Coyote sits between you and the model. So when you submit a prompt to the model, before Coyote ever sends it, it runs a +**hybrid search** over your knowledge base using two (or three) complementary signals: -Coyote then passes the top `n`-snippets of text that it finds in the vector database as additional context to the model -before your prompt. +- **Vector search**: Your query is converted to embeddings and matched against the document embeddings using cosine + similarity (HNSW index). +- **Full-text search (BM25)**: A keyword-based search that finds documents containing the same terms as your query. +- **Graph search** *(only when [graph-based RAG](#graph-based-rag) is enabled)*: Entities mentioned in your query are + looked up in the knowledge graph. Coyote expands up to `rag_graph_hops` hops (default: 1) from matched entities, + scoring neighbors by edge weight and query relevance, then returns documents linked to the highest-scoring entities. + +The results from all active signals are merged via [Reciprocal Rank Fusion (RRF)](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion), +giving slightly more weight to semantic similarity: + +| Signal | RRF Weight | +|------------------|------------| +| Vector (HNSW) | 1.125 | +| Full-text (BM25) | 1.0 | +| Graph | 0.9 | + +Coyote then passes the top `n` merged results as additional context to the model before your prompt. ### 2a. Reranking (Optional) The lookup for relevant snippets of texts uses embeddings to find text that is semantically similar to your prompt, and @@ -163,15 +184,91 @@ rag_embedding_model: null # Specifies the embedding model used for contex ``` ## Reranker -By default, Coyote uses [Reciprocal Rank Fusion (RRF)](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion) to merge vector and keyword search results. +By default, Coyote uses [Reciprocal Rank Fusion (RRF)](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reciprocal-rank-fusion) +to merge results from all active retrieval signals (vector, BM25, and graph when enabled). See [How It Works](#how-it-works) for the exact weights. -You can change the default reranker model to any other reranking model in your configured clients. To change the default -reranker model, simply change the value of the `rag_reranker_model` setting in your global configuration file: +When a reranker model is set it replaces RRF: the union of vector and BM25 candidates is re-scored by the reranker for +direct query relevance, and graph-based search is not applied. You can change the default reranker model to any +reranking model in your configured clients: ```yaml -rag_reranker_model: null # By default, +rag_reranker_model: null # Reranker model; when set, replaces RRF (graph search is not applied) ``` +## Graph-Based RAG + +When Coyote builds a knowledge base, it can optionally run an LLM-based entity and relationship extraction pass +over each document chunk to construct a **knowledge graph**. At query time, this graph becomes a third retrieval +signal alongside vector and full-text search. + +To enable graph-based RAG, set `rag_extractor_model` to any chat model in your configured clients: + +```yaml +rag_extractor_model: null # Chat model for entity/relationship extraction; enables graph RAG when set +``` + +When set, Coyote extracts named entities and their relationships from each chunk at build time and stores a +knowledge graph alongside the vector and BM25 indexes. At query time, entities in your query are matched +against the graph and neighbors are expanded up to `rag_graph_hops` hops to surface documents linked to those +entities. This graph signal is then fused into the hybrid search result via [Reciprocal Rank Fusion](#2-lookup). + +> **Graph-based RAG and reranking are mutually exclusive.** If a `rag_reranker_model` is also set, the +> reranker replaces RRF entirely and the graph signal is not applied. See [Reranker](#reranker) for details. + +### Graph expansion depth + +`rag_graph_hops` controls how many hops to expand from matched entities at query time (default: `1`): + +```yaml +rag_graph_hops: 1 # 0 = seed nodes only; 1 = direct neighbors; 2 = neighbors of neighbors; etc. +``` + +- **`0`:** Returns only documents directly linked to query-matched entities; no graph traversal. +- **`1` (default):** Expands to entities directly connected to query matches. Good for most corpora. +- **`2+`:** Traverses further into the graph, surfacing more loosely related documents. Useful for dense, + highly interconnected knowledge bases (e.g. ontologies, large technical wikis). May increase noise on + sparse corpora. + +### Custom extraction prompt + +By default, Coyote uses a built-in prompt that extracts entities of types `PERSON`, `ORGANIZATION`, `CONCEPT`, +`TECHNOLOGY`, `LOCATION`, `EVENT`, and `OTHER`. For domain-specific corpora you can override this with +`rag_extractor_prompt`: + +```yaml +rag_extractor_prompt: null # Custom extraction prompt; must contain __CHUNK__ placeholder +``` + +The prompt must contain the literal string `__CHUNK__`, which Coyote replaces with the document chunk at +extraction time. The response must be a JSON object with `entities` and `relationships` arrays in the same +structure the built-in prompt produces. Example custom prompt for a legal corpus: + +``` +Extract legal entities and relationships from the following text. + +Return JSON: +{ + "entities": [{"name": "...", "type": "STATUTE|CASE|PARTY|COURT|CONCEPT", "description": "..."}], + "relationships": [{"from": "...", "to": "...", "type": "cites|governs|decided_by", "weight": 0.9}] +} + +Only extract what is clearly stated. Return ONLY the JSON object. + +Text: +__CHUNK__ +``` + +### Extractor model guidance + +- **Use a fast, cheap chat model.** e.g. `anthropic:claude-haiku-4-5` or `openai:gpt-4o-mini`. Extraction + runs once per chunk at build time, so speed and cost matter more than raw capability. +- **Graph-based RAG is most useful** for knowledge bases with rich entity relationships: technical documentation, + research papers, wikis. For small corpora or plain prose, vector + BM25 alone is usually sufficient. +- **Individual `rag` nodes in graph agents can override this** with their own `extractor_model`, `extractor_prompt`, + and `graph_hops` fields. See [Graph-Agents](Graph-Agents#rag) for details. +- The extractor model is prompted interactively when you create a new RAG knowledge base via `.rag`. If you skip + it, the knowledge base uses vector + full-text search only (no graph). + ## Chunk Size In the context of RAG, the chunk size is the maximum length of each text chunk (measured in characters) that is created when splitting documents. In Coyote, this defaults to `2000` characters. diff --git a/REPL.md b/REPL.md index 17a815c..79ce622 100644 --- a/REPL.md +++ b/REPL.md @@ -15,6 +15,7 @@ things like * `.model ` to complete chat models * `.set ` to complete configuration keys * `.set key ` to complete configuration values + * `.mcp auth ` to complete remote MCP server names * **Multi-Line Prompts:** You can also type prompts that span more than one line to help organize your thoughts. This can be done in the following ways: * `Ctrl-o` to open the current input buffer in your preferred editor (either the value of `editor` or `$EDITOR`) @@ -263,22 +264,22 @@ directory on first run and are **not** overwritten afterward, so your local edit command force-overwrites a category of bundled assets with the versions packaged in the current Coyote build. This is useful when an update ships improved built-ins you want to adopt. -| Command | Description | -|-----------------------|----------------------------------------------------------------------| -| `.install agents` | Reinstall the built-in agents | -| `.install macros` | Reinstall the built-in macros | -| `.install skills` | Reinstall the built-in skills | -| `.install functions` | Reinstall the built-in tool functions (leaves your `mcp.json` alone) | -| `.install mcp_config` | Replace `mcp.json` with the bundled template (see warning below) | +| Command | Description | +|-----------------------|--------------------------------------------------------------------------------| +| `.install agents` | Reinstall the built-in agents | +| `.install macros` | Reinstall the built-in macros | +| `.install skills` | Reinstall the built-in skills | +| `.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 ` (e.g. `coyote --install agents`). `.install` prompts for confirmation before overwriting anything. Assets you created yourself are never touched. Only Coyote's own bundled assets are replaced. -**Warning:** `.install mcp_config` is destructive in a way the others are not. It replaces your entire `mcp.json` -(your configured MCP servers and any secret references in them) with Coyote's bundled template. The other categories -only overwrite Coyote's built-in assets and leave your custom ones alone. +`.install mcp_config` merges the bundled MCP server list into your existing `mcp.json`. Only servers not already +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 @@ -338,6 +339,31 @@ The following entities are supported: | `.info tools` | List every tool that would be sent in the next chat completion request (composed across role, agent, skills, and MCP filters). Errors when `function_calling_support` is disabled. | | `.info todo` | Show the current todo list driving auto-continuation (goal, progress count, and per-task status). Only available when `auto_continue` is enabled. | +## `.mcp auth` - Authenticate with an OAuth-protected MCP server + +Some remote MCP servers (such as Notion, Jira, etc.) require OAuth authentication before they can be used. +Run this command once per server to complete the authorization flow: + +``` +.mcp auth +``` + +where `` matches the key in your `mcp.json` file. Tab completion is available. + +**What happens:** +1. Coyote discovers the server's OAuth endpoints automatically via [RFC 9728](https://www.rfc-editor.org/rfc/rfc9728) metadata discovery. +2. If the server supports [Dynamic Client Registration (RFC 7591)](https://www.rfc-editor.org/rfc/rfc7591), Coyote registers itself automatically, meaning no `oauth.clientId` configuration is required. +3. Your browser opens to the server's authorization page. Log in and approve access. +4. The token is saved to `/coyote/oauth/` and loaded automatically on subsequent startups. +5. Tokens are refreshed automatically when they expire. + +**If a server requires authentication but you haven't run `.mcp auth` yet**, Coyote will skip that server at startup +with a warning rather than failing outright. The warning tells you exactly which command to run. + +The same flow is available outside the REPL via `coyote --auth-mcp `. + +For full configuration options and an example for Notion, see the [MCP Servers documentation](MCP-Servers#oauth-authentication). + ## `.authenticate` - Authenticate the current model client via OAuth The `.authenticate` command will start the OAuth flow for the current model client if * The client supports OAuth (See the [clients documentation](Clients#providers-that-support-oauth) for supported clients) diff --git a/Roles.md b/Roles.md index 7f3ac23..d5d0fae 100644 --- a/Roles.md +++ b/Roles.md @@ -247,6 +247,7 @@ for more examples. * `code`: Generates code (used by `coyote -c`) * `create-prompt`: Creates a prompt based on the user's input * `create-title`: Creates 3-6 word titles based on the user's input +* `diagnose`: Autonomously diagnoses and fixes technical issues (services, networking, containers, OS) by running diagnostic commands itself * `explain-shell`: Explains shell commands * `functions`: Enable all globally-visible functions * `github`: Interact with GitHub using natural language diff --git a/Sandboxes.md b/Sandboxes.md index ba78571..4c154fc 100644 --- a/Sandboxes.md +++ b/Sandboxes.md @@ -33,7 +33,24 @@ The first run takes a few minutes (building the Coyote sandbox image, installing and installed tools persist inside the sandbox until you `sbx rm` it. Re-running `coyote --sandbox [NAME]` with the same name **re-attaches** to the existing sandbox silently rather than -creating a fresh one. `--fresh` and `--no-mixins` are ignored on re-attach (they only affect new sandbox creation). +creating a fresh one. `--fresh` and `--no-mixins` are ignored on re-attach (they only affect sandbox creation). + +### Multiple sandboxes per workspace + +Pass a distinct name for each sandbox you want to keep alive against the same directory. Coyote will treat them as fully +independent sbx sandboxes. This is handy for branch-per-sandbox workflows, spike vs. main, or running two Coyote +sessions with different vault providers side by side: + +```bash +# From ~/code/my-project +coyote --sandbox feature-branch # create/attach to sandbox 'feature-branch' +coyote --sandbox spike # create/attach to sandbox 'spike' +coyote --sandbox review # create/attach to sandbox 'review' +``` + +`sbx ls` shows each one. Manage them individually with `sbx stop `, `sbx rm `, etc. The bare +`coyote --sandbox` (no name) still resolves to the current directory basename, so treat that as your default sandbox +and use explicit names for the rest. > **Tip:** Inside the sandbox REPL, prefix any line with `!` to run a shell command without going through `sbx exec > -- ` to modify the sandbox state; .e.g, `!apt-get update`, `!git pull`, `!cargo build`, etc. Output @@ -63,22 +80,31 @@ sbx ls # 5. If not, create it with the base kit + every discovered mixin layered on sbx create \ + --name \ --kit /sbx-kit/ \ --kit \ --kit \ --kit \ - coyote --name . + coyote . -# 6. Copy your host config into the sandbox (skipped if --fresh) -sbx exec sh -c "sudo mkdir -p /home/agent/.config && sudo chown agent:agent /home/agent/.config" -sbx cp ~/.config/coyote/ :/home/agent/.config/ +# 6. Copy your host config into the sandbox (skipped if --fresh). Each top-level +# entry is copied individually to sidestep a macOS `docker cp` quirk that +# silently drops files carrying `com.apple.provenance` xattrs when they're +# tarred as part of a recursive directory copy. +sbx exec sh -c "sudo mkdir -p /home/agent/.config/coyote && sudo chown agent:agent /home/agent/.config/coyote" +for entry in ~/.config/coyote/*; do + sbx cp "$entry" :/home/agent/.config/coyote/ +done +sbx exec sh -c "sudo chown -R agent:agent /home/agent/.config/coyote" # 7. Copy your vault password file, if a local provider is configured (skipped if --fresh) sbx exec sh -c "sudo mkdir -p && sudo chown agent:agent " sbx cp : +sbx exec sh -c "sudo chown -R agent:agent " -# 8. Hand control to sbx (Coyote's process is replaced) -exec sbx run --kit /sbx-kit/ +# 8. Hand control to sbx (Coyote's process is replaced). `--kit` is re-passed +# on reattach because sbx expects it even when the sandbox already exists. +exec sbx run --name --kit /sbx-kit/ ``` Once `sbx run` takes over, Coyote on the host exits and your terminal is connected to Coyote inside the sandbox. All diff --git a/Skills.md b/Skills.md index 732a4c4..9ca8461 100644 --- a/Skills.md +++ b/Skills.md @@ -66,6 +66,33 @@ it. To see complete examples, look at the [bundled built-in skills](https://github.com/Dark-Alex-17/coyote/tree/main/assets/skills). +## Workspace-Local Skills + +In addition to global skills, Coyote discovers skills local to the current working directory. Place a skill under `.coyote/skills/` +in your project root and it becomes available whenever you run Coyote from that directory (or any subdirectory): + +``` +/ +└── .coyote/ + └── skills/ + └── / + └── SKILL.md +``` + +Workspace skills work identically to global skills; same `SKILL.md` format, same frontmatter fields, same composition rules. +The only differences are: + +- **Discovery:** Coyote scans `.coyote/skills/` in addition to the global skills directory. +- **Precedence:** If a workspace skill and a global skill share the same name, the workspace version wins. +- **Scope:** Workspace skills are only visible when running from that directory tree; they do not appear in other projects. + +This is useful for project-specific workflows: a `db-migration` skill with your team's migration conventions, a `deploy` +skill that loads the project's deployment MCP server, or any other task-specific overlay that doesn't belong in your +global configuration. + +Workspace skills can reference MCP servers from both the global `functions/mcp.json` and the workspace `.coyote/mcp.json` +(see [Workspace-Local MCP Servers](MCP-Servers#workspace-local-mcp-servers)). + ## Frontmatter The YAML frontmatter at the top of `SKILL.md` is where you declare the skill's metadata and what extra capabilities it @@ -349,14 +376,24 @@ whitelist — but their processes stay cached for fast re-load. # Built-in Skills -Coyote ships with four built-in skills, installed automatically on first run: +Coyote ships with fourteen built-in skills, installed automatically on first run: -| Skill | Granted tools | Purpose | -|-------------------|--------------------------------------------------------------------------|-------------------------------------------------------------------------| -| `git-master` | `execute_command` | Atomic commits, rebase methodology, conflict resolution, investigation. | -| `code-review` | `fs_read, fs_grep, fs_glob, fs_cat, fs_ls` | Correctness/tests/clarity/coupling/footguns review checklist. | -| `ai-slop-remover` | none (knowledge-only) | Detect and remove AI slop from code and prose. | -| `frontend-ui-ux` | `fs_read, fs_write, fs_patch, fs_grep, fs_glob, fs_cat, fs_ls, fs_mkdir` | Designer-turned-developer crafting UI/UX even without mockups. | +| Skill | Granted tools / MCP servers | Purpose | +|-----------------------|--------------------------------------------------------------------------|------------------------------------------------------------------------------| +| `git-master` | `execute_command` | Atomic commits, rebase methodology, conflict resolution, investigation. | +| `code-review` | `fs_read, fs_grep, fs_glob, fs_cat, fs_ls` | Correctness/tests/clarity/coupling/footguns review checklist. | +| `ai-slop-remover` | none (knowledge-only) | Detect and remove AI slop from code and prose. | +| `diagnostics` | `execute_command` | Systematic troubleshooting of technical issues (services, networking, containers, OS) by running diagnostic commands directly. | +| `frontend-ui-ux` | `fs_read, fs_write, fs_patch, fs_grep, fs_glob, fs_cat, fs_ls, fs_mkdir` | Designer-turned-developer crafting UI/UX even without mockups. | +| `delegation-protocol` | none (knowledge-only) | Structured 6-section delegation template and session-continuity rules for sub-agents. | +| `parallel-research` | none (knowledge-only) | Fan-out exploration protocol; parallel research agents without duplicated work. | +| `oracle-protocol` | none (knowledge-only) | Discipline for when and how to consult Oracle. | +| `verification-gates` | `execute_command` | Evidence requirements (diagnostics, builds, tests) before claiming completion. | +| `plan-authoring` | `fs_read, fs_grep, fs_glob, fs_ls, fs_cat, fs_write` | Author executable high-level plans and per-step implementation plans for phased work; defines the plan repo layout and step-plan schema. | +| `plan-review` | `fs_read, fs_grep, fs_glob, fs_ls, fs_cat` | Adversarial review of implementation plans against executability, verifiability, and completeness standards. | +| `step-implementation` | `execute_command` | End-to-end protocol for executing one step of a phased implementation plan. | +| `handoff-protocol` | `fs_read, fs_cat, fs_ls, fs_write` | Schema and discipline for writing and reading step handoff documents between implementation steps. | +| `iwe-knowledge-base` | MCP server: `iwe` | Navigate and curate large markdown knowledgebases (plans, specs, notes) via [IWE](https://github.com/iwe-org/iwe) graph tools. Requires the `iwec` binary. | Each is intentionally short — they're starter templates. Fork them via `.skill ` to customize. diff --git a/Tools.md b/Tools.md index eaa31b0..ad9e9c7 100644 --- a/Tools.md +++ b/Tools.md @@ -15,33 +15,34 @@ be enabled/disabled can be found in the [Configuration](#configuration) section | Tool | Description | Enabled/Disabled | |--------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------| +| [`ast_grep.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/ast_grep.sh) | Structural code search using AST patterns via [ast-grep](https://ast-grep.github.io/). Matches syntax trees instead of text
(e.g. `'$X.unwrap()'` finds every unwrap call regardless of formatting). Supports meta-variables (`$NAME`, `$$$`),
`--lang`, and `--glob` narrowing. Requires the `ast-grep` binary (see [Installation](Installation#prerequisites)); reports a
fallback hint when missing. Used by the `explore` agent for structure-aware searches. | 🟢 | | [`demo_py.py`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/demo_py.py) | Demonstrates how to create a tool using Python and how to use comments. | 🔴 | | [`demo_sh.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/demo_sh.sh) | Demonstrate how to create a tool using Bash and how to use comment tags. | 🔴 | | [`demo_ts.ts`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/demo_ts.ts) | Demonstrates how to create a tool using TypeScript and how to use JSDoc comments. | 🔴 | | [`execute_command.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/execute_command.sh) | Execute the shell command. | 🟢 | -| [`execute_py_code.py`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/execute_py_code.py) | Execute the given Python code. | 🔴 | +| [`execute_py_code.py`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/execute_py_code.py) | Execute the given Python code. | 🟢 | | [`execute_sql_code.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/execute_sql_code.sh) | Execute SQL code. | 🔴 | -| [`fetch_url_via_curl.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fetch_url_via_curl.sh) | Extract the content from a given URL using cURL. | 🔴 | +| [`fetch_url_via_curl.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fetch_url_via_curl.sh) | Extract the content from a given URL using cURL. | 🟢 | | [`fetch_url_via_jina.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fetch_url_via_jina.sh) | Extract the content from a given URL using Jina. | 🔴 | | [`fs_cat.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_cat.sh) | Read the contents of a file at the specified path. | 🟢 | | [`fs_read.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_read.sh) | Controlled reading of the contents of a file at the specified path with line numbers, offset, and limit to read specific sections. | 🟢 | | [`fs_glob.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_glob.sh) | Find files by glob pattern. Returns matching file paths sorted by modification time. | 🟢 | | [`fs_grep.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_grep.sh) | Search file contents using regular expressions. Returns matching file paths and lines. | 🟢 | | [`fs_ls.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_ls.sh) | List all files and directories at the specified path. | 🟢 | -| [`fs_mkdir.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_mkdir.sh) | Create a new directory at the specified path. | 🔴 | -| [`fs_patch.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_patch.sh) | Apply a patch to a file at the specified path.
This can be used to edit a file without having to rewrite the whole file. | 🔴 | -| [`fs_rm.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_rm.sh) | Remove a file or directory at the specified path. | 🔴 | +| [`fs_mkdir.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_mkdir.sh) | Create a new directory at the specified path. | 🟢 | +| [`fs_patch.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_patch.sh) | Apply a patch to a file at the specified path.
This can be used to edit a file without having to rewrite the whole file. | 🟢 | +| [`fs_rm.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_rm.sh) | Remove a file or directory at the specified path. | 🟢 | | [`fs_write.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/fs_write.sh) | Write the full file contents to a file at the specified path. | 🟢 | | [`get_current_time.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/get_current_time.sh) | Get the current time. | 🟢 | | [`get_current_weather.py`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/get_current_weather.py) | Get the current weather in a given location (Python implementation) | 🔴 | | [`get_current_weather.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/get_current_weather.sh) | Get the current weather in a given location. | 🟢 | | [`get_current_weather.ts`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/get_current_weather.ts) | Get the current weather in a given location (TypeScript implementation) | 🔴 | -| [`search_arxiv.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/search_arxiv.sh) | Search arXiv using the given search query and return the top papers. | 🔴 | -| [`search_wikipedia.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/search_wikipedia.sh) | Search Wikipedia using the given search query.
Use it to get detailed information about a public figure, interpretation of a
complex scientific concept or in-depth connectivity of a significant historical
event, etc. | 🔴 | +| [`search_arxiv.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/search_arxiv.sh) | Search arXiv using the given search query and return the top papers. | 🟢 | +| [`search_wikipedia.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/search_wikipedia.sh) | Search Wikipedia using the given search query.
Use it to get detailed information about a public figure, interpretation of a
complex scientific concept or in-depth connectivity of a significant historical
event, etc. | 🟢 | | [`search_wolframalpha.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/search_wolframalpha.sh) | Get an answer to a question using Wolfram Alpha. The input query should be
in English. Use it to answer user questions that require computation, detailed
facts, data analysis, or complex queries. | 🔴 | | [`send_mail.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/send_mail.sh) | Send an email. | 🔴 | | [`send_twilio.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/send_twilio.sh) | Send SMS or Twilio Messaging Channels messages using the Twilio API. | 🔴 | -| [`web_search_coyote.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/web_search_coyote.sh) | Perform a web search to get up-to-date information or additional context.
Use this when you need current information or feel a search could provide
a better answer. | 🔴 | +| [`web_search_coyote.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/web_search_coyote.sh) | Perform a web search to get up-to-date information or additional context.
Use this when you need current information or feel a search could provide
a better answer. | 🟢 | | [`web_search_perplexity.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/web_search_perplexity.sh) | Perform a web search using the Perplexity API to get up-to-date
information or additional context. Use this when you need current
information or feel a search could provide a better answer. | 🔴 | | [`web_search_tavily.sh`](https://github.com/Dark-Alex-17/coyote/blob/main/assets/functions/tools/web_search_tavily.sh) | Perform a web search using the Tavily API to get up-to-date
information or additional context. Use this when you need current
information or feel a search could provide a better answer. | 🔴 | @@ -58,8 +59,8 @@ If you run Coyote inside a [Sandbox](Sandboxes), tools that need extra binaries they're declared in an [`sbx-mixin.yaml`](Sandboxes#extending-the-sandbox-auto-discovered-mixins) somewhere on the discovery path. Coyote ships two relevant pre-built mixins: -- **Base kit prerequisites:** The sandbox base kit already installs `jq`, `curl`, `git`, `uv`, `pandoc`, `bzip2`, and - `usql` for you. Built-in tools that depend on these need no further setup. +- **Base kit prerequisites:** The sandbox base kit already installs `jq`, `curl`, `git`, `uv`, `pandoc`, `bzip2`, + `usql`, `iwec`, and `ast-grep` for you. Built-in tools that depend on these need no further setup. - **`assets/functions/sbx-mixin.yaml`:** When projected into your config via `coyote --install functions`, this mixin allowlists the network domains the built-in tools and default MCP servers reach: Wikipedia, arxiv, jina, wttr, WolframAlpha, Perplexity, Tavily, Twilio, github MCP, atlassian MCP, ddg-search MCP, npm registry, and common Docker