Skip to content
4 changes: 3 additions & 1 deletion docs/reference/file-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,8 @@ Subagents live in the `subagents/` subdirectory so the command-recipe and subage

Vibe (mistral-vibe) MCP servers live in `[[mcp_servers]]` arrays of the shared `.vibe/config.toml`. In addition to the flat fields, Rulesync passes through the stdio `cwd` (working directory), a structured per-server `auth` block (Vibe v2.15.0+), and the four keys Vibe's `/mcp` panel writes back when you toggle a server or one of its tools — `prompt`, `sampling_enabled`, `disabled` and `disabled_tools`. Because `mcp_servers` is replaced as a whole array on each generate, a server Rulesync writes is seeded from the on-disk entry of the same name for exactly those keys, so a toggle you made in the TUI survives — unless your `.rulesync/mcp.json` states the value itself, which wins. `disabled_tools` is the canonical `disabledTools` under Vibe's spelling; `prompt` and `sampling_enabled` have no canonical equivalent and pass through as-is. The `auth` table is discriminated on `type`: `static` (`headers`, `api_key_env`, `api_key_header`, `api_key_format`) and `oauth` (`scopes`, `client_id` / `client_metadata_url`, `redirect_port`). Because Vibe rejects mixing legacy top-level static-auth keys with an explicit `[auth]` block, Rulesync suppresses the legacy keys (`headers`/`api_key_env`/`api_key_header`/`api_key_format`) whenever a server carries an `auth` block. See [mistral-vibe](https://github.com/mistralai/mistral-vibe) (`vibe/core/config/models.py`).

> **Rovo Dev CLI MCP note:** Rovo Dev documents the per-server transport key as `transport` (`stdio` | `http` | `sse`), not the canonical `type`. Rulesync translates on the way out (`local` → `stdio`, `streamable-http` → `http`) and back on import; `ws` has no Rovo Dev equivalent, so those servers are skipped with a warning, and a `transport` value outside Rovo Dev's vocabulary is dropped on import rather than written into the canonical config, whose transport field is a strict enum. A server marked `disabled` is also skipped, because Rovo Dev turns servers off through `mcp.disabledMcpServers` in `config.yml` rather than through a flag in `mcp.json`, and writing the entry anyway would leave it running; `disabled` is stripped from the servers that are written, too, since `mcp.json` is not where a server is switched on and off. A server Rovo Dev has disabled through `config.yml` is still imported as an ordinary enabled server, because `mcp.json` carries no trace of it. `mcp.json` is global-only. See the [Rovo Dev MCP docs](https://support.atlassian.com/rovo/docs/connect-to-an-mcp-server-in-rovo-dev-cli/).

> **Reasonix note:** MCP servers are written as `[[plugins]]` array-of-tables entries (Reasonix's MCP-compatible external plugins) in `reasonix.toml` (project) / `~/.reasonix/config.toml` (global, via `--global`). Each entry carries a `name` plus the standard transport fields: `type` selects the transport (`stdio` default — `command`/`args`/`env`; `http`, a.k.a. `streamable-http` — `url`/`headers`), and the deprecated `sse` transport is collapsed onto `http`. The file is treated as shared Reasonix config: Rulesync only replaces the `plugins` key and preserves every other table (providers, ui, agent, …) on round-trip, and it is never deleted. Reasonix has no per-server tool allow/deny lists, but each plugin entry may carry an optional `trusted_read_only_tools` array (raw MCP tool names pre-seeded as trusted for planner/read-only use); it also supports `call_timeout_seconds` (a per-server MCP call timeout) and `tool_timeout_seconds` (a per-tool inline table keyed by raw MCP tool name). None of these have a deep canonical mapping, so they round-trip as passthrough fields on the canonical MCP server object. See the [Reasonix plugins guide](https://github.com/esengine/deepseek-reasonix/blob/main-v2/docs/GUIDE.md#plugins-mcp) and [SPEC.md](https://github.com/esengine/DeepSeek-Reasonix/blob/main-v2/docs/SPEC.md) (`[[plugins]]` schema).

## `.rulesync/.aiignore` or `.rulesyncignore` (deprecated)
Expand Down Expand Up @@ -1226,7 +1228,7 @@ For the Antigravity IDE, this generates `permissions.allow`, `permissions.ask`,

For the Antigravity CLI (`agy`), this generates `permissions.allow`, `permissions.ask`, and `permissions.deny` arrays in the global `~/.gemini/antigravity-cli/settings.json` (**global mode only**). The CLI shares Antigravity 2.0's Fine-Grained Permissions Engine with the IDE, so the same `action(target)` vocabulary and `Deny > Ask > Allow` precedence apply: `read` → `read_file`, `edit`/`write` → `write_file`, `bash` → `command`, `webfetch`/`websearch` → `read_url`, `mcp` → `mcp` (the engine-only `execute_url` / `unsandboxed` actions pass through verbatim). Because `edit`/`write` collapse to `write_file` and `webfetch`/`websearch` collapse to `read_url`, importing normalizes back to `write` / `webfetch` (a documented, lossy mapping). The `settings.json` holds other CLI settings, so the `permissions` block is merged in place — entries for unmanaged actions are preserved — and the file is never deleted. Two CLI-only autonomy/sandbox knobs outside the allow/ask/deny arrays can be authored (and round-trip) through an optional `antigravity-cli` override block in `.rulesync/permissions.jsonc`: `toolPermission` (the global autonomy preset — `request-review` (default) / `proceed-in-sandbox` / `always-proceed` / `strict`) and `enableTerminalSandbox` (a boolean confining agent-run commands to OS containment). Antigravity applies the allow/deny lists as per-rule exceptions to the preset at runtime, so rulesync authors these keys verbatim as top-level siblings of `permissions` with no precedence modeling. This override is **CLI-only** — the Antigravity IDE exposes the same concepts through a GUI with no documented JSON schema, so it does not apply to `antigravity-ide`. Example: `{ "permission": { … }, "antigravity-cli": { "toolPermission": "strict", "enableTerminalSandbox": true } }`. Verified against the [Antigravity CLI reference](https://antigravity.google/docs/cli/reference) and [sandbox docs](https://antigravity.google/docs/cli/sandbox). See the [Antigravity CLI permissions docs](https://antigravity.google/docs/cli-permissions).

For Rovo Dev CLI, this generates the `toolPermissions` block of the global `~/.rovodev/config.yml` (**global mode only** — Rovo Dev has no project-scoped permissions file, mirroring the Rovodev MCP adapter). Rovo Dev's three levels (`allow`/`ask`/`deny`) are an exact 1:1 with rulesync's canonical actions, so action values pass through verbatim. The `bash` category maps the catch-all `*` pattern to `bash.default` and every other pattern to a `bash.commands[]` entry `{ command: <pattern as regex>, permission }` (Rovo Dev matches commands as regexes, so author `bash` patterns accordingly). The `read` category maps to the inspection tools (`open_files`, `expand_code_chunks`, `expand_folder`, `grep`) and `edit`/`write` to the mutation tools (`find_and_replace_code`, `create_file`, `delete_file`, `move_file`); because these per-tool keys hold a single level (no per-pattern rules), only the catch-all `*` of each category sets the level. Because `edit` and `write` both map onto the same mutation tools, a conflicting catch-all between them cannot be represented; `edit` takes precedence and a warning is logged. Non-catch-all `allow` paths in those categories are surfaced as `allowedExternalPaths` so explicit grants are not dropped; non-`allow` non-catch-all rules cannot be expressed per-path and are skipped with a warning. Categories without a clean Rovo Dev target (e.g. `webfetch`) are skipped with a warning. `config.yml` holds all of Rovo Dev's settings (`agent`, `sessions`, `mcp`, etc.), so the `toolPermissions` block is merged in place — every other top-level key (and any unmanaged keys inside `toolPermissions`) is preserved (values only — YAML comments and formatting in the existing file are not retained on rewrite) — and the file is never deleted. See the [Rovo Dev CLI settings](https://support.atlassian.com/rovo/docs/manage-rovo-dev-cli-settings/) and [tool permissions](https://support.atlassian.com/rovo/docs/use-tools-in-rovo-dev-cli/) docs.
For Rovo Dev CLI, this generates the `toolPermissions` block of the global `~/.rovodev/config.yml` (**global mode only** — Rovo Dev has no project-scoped permissions file, mirroring the Rovodev MCP adapter). Rovo Dev's three levels (`allow`/`ask`/`deny`) are an exact 1:1 with rulesync's canonical actions, so action values pass through verbatim. The `bash` category maps the catch-all `*` pattern to `bash.default` and every other pattern to a `bash.commands[]` entry `{ command: <pattern as regex>, permission }` (Rovo Dev matches commands as regexes, so author `bash` patterns accordingly). The `read` category maps to the inspection tools (`open_files`, `expand_code_chunks`, `expand_folder`, `grep`) and `edit`/`write` to the mutation tools (`find_and_replace_code`, `create_file`, `delete_file`, `move_file`), written under **`toolPermissions.tools`** — the depth Rovo Dev documents. (Earlier Rulesync versions wrote them one level up, directly under `toolPermissions`, where Rovo Dev ignores them; import still reads that legacy shape as a fallback for keys the nested block says nothing about, so an old file is not lost, and a regenerate deletes the stale copies.) Because these per-tool keys hold a single level (no per-pattern rules), only the catch-all `*` of each category sets the level. Rovo Dev rewrites a single tool key when the user answers "always allow" to one prompt, so the four keys of a category can disagree; import collapses them back onto one catch-all by taking the strictest level (`deny` > `ask` > `allow`) rather than whichever key is read last. Tools outside these eight (Rovo Dev's Jira/Confluence and planning tools, for instance) have no canonical category, so a category catch-all does not reach them. Because `edit` and `write` both map onto the same mutation tools, a conflicting catch-all between them cannot be represented; the stricter of the two levels is kept — the same `deny` > `ask` > `allow` rule import uses — and a warning is logged. Non-catch-all `allow` paths in those categories are surfaced as `allowedExternalPaths` so explicit grants are not dropped; non-`allow` non-catch-all rules cannot be expressed per-path and are skipped with a warning. Categories without a clean Rovo Dev target (e.g. `webfetch`) are skipped with a warning. `config.yml` holds all of Rovo Dev's settings (`agent`, `sessions`, `mcp`, etc.), so the `toolPermissions` block is merged in place — every other top-level key is preserved, as is any key inside `toolPermissions` that Rulesync does not manage — including tools inside `toolPermissions.tools` that no canonical category maps to. The keys Rulesync does manage (`bash`, `allowedExternalPaths`, and the eight per-tool keys above) are owned rather than merged: each generate rewrites them from `.rulesync/permissions.*`, so removing a rule there removes it from `config.yml` too (a source stating no rule at all clears them; one whose rules simply have no Rovo Dev counterpart keeps the block's restrictions but strips its grants — an `allow` there is normally a leftover of an earlier generate, and dropping one falls back to Rovo Dev's stricter default, whereas clearing the whole block would relax every level), logging a warning naming each owned key it removes — per-tool levels and `allowedExternalPaths` are written from inside a Rovo Dev session too, by an "always allow" prompt answer and the `/directories` command, and a hand-edit to one of those keys — including a path added with the in-session `/directories` command, which writes to `allowedExternalPaths` — is replaced on the next generate (values only — YAML comments and formatting in the existing file are not retained on rewrite) — and the file is never deleted. See the [Rovo Dev CLI settings](https://support.atlassian.com/rovo/docs/manage-rovo-dev-cli-settings/) and [tool permissions](https://support.atlassian.com/rovo/docs/use-tools-in-rovo-dev-cli/) docs.

For Goose, this generates the `user` block of the global `~/.config/goose/permission.yaml` (**global mode only** — Goose persists per-tool permission overrides only under the home directory and has no project-scoped permissions file). Goose stores permissions as a YAML map of mode key → `{ always_allow, ask_before, never_allow }`, where each field is a list of tool-name strings; rulesync writes the user-set decisions under the `user` key. Action mapping is a 1:1: `allow` → `always_allow`, `ask` → `ask_before`, `deny` → `never_allow`. Tool-name mapping: `bash` → `developer__shell`, `edit` → `developer__text_editor`; every other category passes through verbatim as the Goose tool name (so namespaced tools like `developer__text_editor` or `developer__image_processor` round-trip). Because Goose permission lists hold **whole tool names** rather than per-command/per-path globs, only a category's catch-all `*` pattern is representable — non-catch-all patterns are skipped with a warning. `write` collapses onto `developer__text_editor` too, so a conflicting `edit`/`write` catch-all cannot be represented; `edit` takes precedence and a warning is logged. The `permission.yaml` file is merged in place: the `user` block is owned by rulesync, while every other top-level key (notably the `smart_approve` LLM-decision cache) is preserved, and the file is never deleted. See the [Goose tool permissions docs](https://goose-docs.ai/docs/guides/managing-tools/tool-permissions/).

Expand Down
Loading
Loading