diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c3ce733..976b050 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,6 +14,23 @@ updates: labels: - dependencies - rust + ignore: + # Pinned in Cargo.toml — major bumps broke build or drift hashes (see comments there). + - dependency-name: "toml" + update-types: + - version-update:semver-major + - version-update:semver-minor + - version-update:semver-patch + - dependency-name: "similar" + update-types: + - version-update:semver-major + - version-update:semver-minor + - version-update:semver-patch + - dependency-name: "sha2" + update-types: + - version-update:semver-major + - version-update:semver-minor + - version-update:semver-patch - package-ecosystem: github-actions directory: "/" diff --git a/Cargo.lock b/Cargo.lock index 861ebe6..16d9894 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,12 +146,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.12.1" @@ -266,15 +260,14 @@ checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "console" -version = "0.15.11" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" dependencies = [ "encode_unicode", "libc", - "once_cell", "unicode-width", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -324,14 +317,13 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +checksum = "25f104b501bf2364e78d0d3974cbc774f738f5865306ed128e1e0d7499c0ad96" dependencies = [ "console", "shell-words", "tempfile", - "thiserror 1.0.69", "zeroize", ] @@ -353,23 +345,23 @@ dependencies = [ [[package]] name = "directories" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] @@ -411,16 +403,6 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" -[[package]] -name = "filetime" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" -dependencies = [ - "cfg-if", - "libc", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" @@ -810,11 +792,11 @@ dependencies = [ [[package]] name = "inotify" -version = "0.10.2" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" +checksum = "533e68a5842e734946fe159fb03fc9bbbb254f590dd0d8ad321ae5ff7beca2c1" dependencies = [ - "bitflags 1.3.2", + "bitflags", "inotify-sys", "libc", ] @@ -828,15 +810,6 @@ dependencies = [ "libc", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "ipnet" version = "2.12.0" @@ -898,7 +871,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087" dependencies = [ - "bitflags 2.12.1", + "bitflags", "libc", ] @@ -935,7 +908,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83270a18e9f90d0707c41e9f35efada77b64c0e6f3f1810e71c8368a864d5590" dependencies = [ - "bitflags 2.12.1", + "bitflags", "libc", ] @@ -1013,12 +986,11 @@ dependencies = [ [[package]] name = "notify" -version = "7.0.0" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" +checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.12.1", - "filetime", + "bitflags", "fsevent-sys", "inotify", "kqueue", @@ -1027,14 +999,14 @@ dependencies = [ "mio", "notify-types", "walkdir", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] name = "notify-debouncer-mini" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa5a66d07ed97dce782be94dcf5ab4d1b457f4243f7566c7557f15cabc8c799" +checksum = "17849edfaabd9a5fef1c606d99cfc615a8e99f7ac4366406d86c7942a3184cf2" dependencies = [ "log", "notify", @@ -1044,11 +1016,11 @@ dependencies = [ [[package]] name = "notify-types" -version = "1.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174" +checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "instant", + "bitflags", ] [[package]] @@ -1082,7 +1054,7 @@ dependencies = [ "sha2", "similar", "tempfile", - "thiserror 2.0.18", + "thiserror", "tokio", "tokio-stream", "toml", @@ -1222,7 +1194,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.18", + "thiserror", "tokio", "tracing", "web-time", @@ -1243,7 +1215,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.18", + "thiserror", "tinyvec", "tracing", "web-time", @@ -1319,18 +1291,18 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.12.1", + "bitflags", ] [[package]] name = "redox_users" -version = "0.4.6" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror 1.0.69", + "thiserror", ] [[package]] @@ -1417,7 +1389,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.12.1", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -1492,7 +1464,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.12.1", + "bitflags", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -1505,7 +1477,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.12.1", + "bitflags", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -1754,33 +1726,13 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "thiserror-impl", ] [[package]] @@ -1953,7 +1905,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.12.1", + "bitflags", "bytes", "futures-util", "http", @@ -2265,7 +2217,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.12.1", + "bitflags", "hashbrown 0.15.5", "indexmap", "semver", @@ -2315,15 +2267,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -2333,15 +2276,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" @@ -2360,21 +2294,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -2408,12 +2327,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -2426,12 +2339,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -2444,12 +2351,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2474,12 +2375,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -2492,12 +2387,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -2510,12 +2399,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -2528,12 +2411,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -2619,7 +2496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.12.1", + "bitflags", "indexmap", "log", "serde", diff --git a/Cargo.toml b/Cargo.toml index 9a4b9a1..2620421 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,10 +25,10 @@ anyhow = "1" axum = "0.8" base64 = "0.22" clap = { version = "4", features = ["derive", "env"] } -directories = "5" +directories = "6" keyring = { version = "3", features = ["apple-native", "windows-native", "linux-native"] } -notify = "7" -notify-debouncer-mini = "0.5" +notify = "8" +notify-debouncer-mini = "0.7" reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "stream"] } serde = { version = "1", features = ["derive"] } serde_json = "1" @@ -36,14 +36,14 @@ serde_yaml = "0.9" thiserror = "2" tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" -toml = "0.8" +toml = "0.8" # pinned: 1.x breaks merge_codex_toml API tower = "0.5" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } -console = "0.15" -dialoguer = "0.11" -similar = "2" -sha2 = "0.10" +console = "0.16" +dialoguer = "0.12" +similar = "2" # pinned: 3.x API break in ui/diff.rs +sha2 = "0.10" # pinned: 0.11 finalize formatting differs from drift hashes [dev-dependencies] assert_cmd = "2" diff --git a/README.md b/README.md index 8f962b9..5f17505 100644 --- a/README.md +++ b/README.md @@ -4,103 +4,95 @@ [![CodeQL](https://github.com/xb3sox/omnid/actions/workflows/codeql.yml/badge.svg)](https://github.com/xb3sox/omnid/actions/workflows/codeql.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) -Unified agent plane for AI coding tools. One folder (`~/.config/omni/`) syncs **MCP**, **rules**, and **skills** to Cursor, Claude Code, VS Code, Windsurf, Codex, and 15+ other agents. +**One config folder. 20+ AI coding agents. MCP, rules, and skills — kept in sync.** -## Install +omnid is a Rust CLI that owns `~/.config/omni/` and pushes a non-destructive MCP proxy stub, compiled rules, and linked skills to Cursor, Claude Code, VS Code, Windsurf, Codex, and the rest of your toolchain. + +## Quick start + +```bash +omnid # scaffold config, sync if drift, show status +omnid add server # add MCP backends when ready +omnid init # optional guided setup +``` -### Pre-built binaries (recommended) +Set `OMNID_NONINTERACTIVE=1` in CI to skip prompts. -Download the latest release for your platform from [GitHub Releases](https://github.com/xb3sox/omnid/releases). +## Install + +**Binaries** — [GitHub Releases](https://github.com/xb3sox/omnid/releases) ```bash -# Linux (x86_64) — asset name: omnid-x86_64-unknown-linux-gnu.tar.gz +# Linux x86_64 curl -fsSL https://github.com/xb3sox/omnid/releases/latest/download/omnid-x86_64-unknown-linux-gnu.tar.gz | tar xz sudo mv omnid /usr/local/bin/ -# macOS (Apple Silicon) — asset name: omnid-aarch64-apple-darwin.tar.gz +# macOS Apple Silicon curl -fsSL https://github.com/xb3sox/omnid/releases/latest/download/omnid-aarch64-apple-darwin.tar.gz | tar xz sudo mv omnid /usr/local/bin/ ``` ```powershell -# Windows (x86_64) — asset name: omnid-x86_64-pc-windows-msvc.zip +# Windows x86_64 irm https://github.com/xb3sox/omnid/releases/latest/download/omnid-x86_64-pc-windows-msvc.zip -OutFile omnid.zip Expand-Archive omnid.zip -DestinationPath . ``` -### Build from source +**From source** ```bash cargo install --git https://github.com/xb3sox/omnid -# or, from a clone: -cargo install --path . -``` - -## Getting started in 60 seconds - -```bash -omnid # scaffolds, syncs, shows status -omnid add server # when you need MCP backends -``` - -Optional guided setup: - -```bash -omnid init +# or: cargo install --path . ``` ## What gets synced -| Artifact | Source | Strategy | +| Artifact | Source | Behavior | |----------|--------|----------| -| MCP | `matrix.yaml` | Non-destructive omnid proxy stub per agent | -| Rules | `rules/global.md` | Compiled to `.mdc`, `CLAUDE.md`, `AGENTS.md`, etc. | -| Skills | `skills/*/SKILL.md` | Symlink or copy to Cursor + Claude Code | -| Hooks | `hooks/omnid.json` | Opt-in only (`artifacts.hooks.enabled: true`) | +| **MCP** | `matrix.yaml` | Proxy stub per agent — existing servers untouched | +| **Rules** | `rules/global.md` | Compiled to `.mdc`, `CLAUDE.md`, `AGENTS.md`, … | +| **Skills** | `skills/*/SKILL.md` | Symlink or copy into Cursor + Claude Code | +| **Hooks** | `hooks/omnid.json` | Opt-in (`artifacts.hooks.enabled: true`) | ``` ~/.config/omni/ - matrix.yaml - rules/global.md - skills/my-skill/SKILL.md - hooks/omnid.json # optional, disabled by default - .sync-state.json +├── matrix.yaml # MCP backends + targets +├── rules/global.md +├── skills/*/SKILL.md +├── hooks/omnid.json # optional, off by default +└── .sync-state.json # drift tracking ``` ## Commands -| Command | Description | -|---------|-------------| -| `omnid` | Status dashboard; drift-only auto-sync | -| `omnid init` | Guided first-time setup | -| `omnid add server` | Add MCP server interactively | +| Command | What it does | +|---------|--------------| +| `omnid` | Status dashboard; auto-sync on drift only | +| `omnid init` | First-time guided setup | +| `omnid add server` | Add MCP server (interactive) | | `omnid add rule` | Append to `rules/global.md` | | `omnid add skill` | Scaffold a new skill | -| `omnid check` | Validation + agent health | -| `omnid sync` | Force sync (`--dry-run` shows diffs) | +| `omnid check` | Validate config + agent health | +| `omnid sync` | Force sync (`--dry-run` for diffs) | | `omnid sync --force` | Sync even when no drift | | `omnid daemon` | Watch config and re-sync | | `omnid proxy --stdio` | MCP multiplexer (spawned by agents) | | `omnid uninstall` | Remove omnid-owned artifacts | -| `omnid agents list` | Agent compatibility table | +| `omnid agents list` | Agent paths + compatibility | -Set `OMNID_NONINTERACTIVE=1` to skip prompts in CI. +## Supported agents -## Agent capability matrix (v1) +| Tier | Agents | MCP | Rules | Skills | Hooks | +|------|--------|:---:|:-----:|:------:|:-----:| +| Full | Cursor, Claude Code | ✓ | ✓ | ✓ | opt-in | +| Rules + MCP | Windsurf, Codex, OpenCode, Cline, Roo, Kilo, VS Code | ✓ | ✓ | — | — | +| MCP only | 11 others (20 total) | ✓ | — | — | — | -| Agent | MCP | Rules | Skills | Hooks | -|-------|-----|-------|--------|-------| -| Cursor | yes | yes | yes | opt-in | -| Claude Code | yes | yes | yes | opt-in | -| Windsurf | yes | yes | — | — | -| Codex / OpenCode | yes | yes | — | — | -| Cline / Roo / Kilo | yes | yes | — | — | -| VS Code | yes | yes | — | — | -| Others (20+ total) | yes | — | — | — | +Run `omnid agents list` for exact config paths on your machine. -Run `omnid agents list` for MCP config paths. +## Configuration -## matrix.yaml +Minimal `matrix.yaml`: ```yaml version: 1 @@ -115,32 +107,31 @@ servers: targets: auto_detect: true -# Optional overrides: # artifacts: # hooks: # enabled: false ``` -`omnid add server` edits `matrix.yaml` via serde — YAML comments are not preserved. Edit the file directly to keep comments. +`omnid add server` edits via serde — YAML comments are dropped. Edit the file directly to keep comments. -## Architecture +## How it works -- **matrix.yaml** — MCP backends, credentials, tool frontmatter -- **omnid proxy** — merges MCP capabilities, routes `server__tool` names -- **sync engine** — MCP stub + rules compiler + skills linker; tracks drift in `.sync-state.json` -- **daemon** — watches `matrix.yaml`, `rules/`, `skills/`, `hooks/` - -MCP backends reload when agents restart their MCP connection (proxy processes keep the old pool until reconnect). - -## For AI agents +``` +matrix.yaml → sync engine → agent configs (stub + rules + skills) + ↓ + omnid proxy → MCP backends (server__tool routing) +``` -Contributing with Cursor, Claude Code, Copilot, or other agents? Read [AGENTS.md](AGENTS.md) for architecture, conventions, security rules, and where to find key code. +- **Non-destructive MCP** — omnid writes its proxy stub; your other MCP entries stay. +- **Drift-aware sync** — `.sync-state.json` tracks hashes; default run syncs only when needed. +- **Daemon** — watches `matrix.yaml`, `rules/`, `skills/`, `hooks/` and re-syncs. +- **Backend reload** — MCP pool refreshes when agents restart their MCP connection. ## Development ```bash cargo install just cargo-deny # once -just ci # fmt + clippy --locked + test --locked + deny +just ci # fmt + clippy + test + deny ``` -See [CONTRIBUTING.md](CONTRIBUTING.md) for the full workflow. Report security issues via [SECURITY.md](.github/SECURITY.md). Please read our [Code of Conduct](CODE_OF_CONDUCT.md). +Contributing: [CONTRIBUTING.md](CONTRIBUTING.md) · AI agents: [AGENTS.md](AGENTS.md) · Security: [SECURITY.md](.github/SECURITY.md) · [Code of Conduct](CODE_OF_CONDUCT.md) diff --git a/src/sync/state.rs b/src/sync/state.rs index 95c6c22..f5976dd 100644 --- a/src/sync/state.rs +++ b/src/sync/state.rs @@ -95,13 +95,21 @@ pub fn file_hash(path: &Path) -> Result { } hasher.update(&buf[..n]); } - Ok(format!("{:x}", hasher.finalize())) + Ok(digest_hex(hasher.finalize())) } pub fn string_hash(content: &str) -> String { let mut hasher = Sha256::new(); hasher.update(content.as_bytes()); - format!("{:x}", hasher.finalize()) + digest_hex(hasher.finalize()) +} + +fn digest_hex(digest: impl AsRef<[u8]>) -> String { + digest + .as_ref() + .iter() + .map(|byte| format!("{byte:02x}")) + .collect() } pub fn empty_hash() -> String {