AI Security Posture Management (AI-SPM) for developer machines. Sigil watches AI coding agent guard surfaces — hooks, permissions, sandbox boundaries — scores their risk, and feeds hash-anchored events to your SIEM.
Claude Code, Codex, Gemini CLI, Cursor — each AI coding agent ships its own
guard surface (hooks, permissions, [sandbox], MCP allowlists) across
user-global, per-project, and per-session scopes. The autonomy ratchet keeps
moving: hooks run in the host shell, matchers can be .*, and a PreToolUse
hook containing rm -rf is treated by these tools the same as one that just
logs. Security teams have no fleet view, no drift alert, no risk index.
Sigil measures. It does not block. It watches the guard surfaces of every supported AI agent, scores their risk against a transparent rubric (sandbox boundary × hook content × matcher scope × source provenance), and emits the score plus the underlying reasons as a hash-anchored JSONL event your SIEM can ingest. Enforcement stays where it belongs — in your MDM, your EDR, or your operator's hands. Sigil's job is to make sure those decisions are informed.
Underneath the AI-SPM layer is a generic file-posture sensor: a small Rust
agent that watches policy-defined files on macOS, Windows, and Linux, hashes
every change with blake3, and ships the events through a signed-policy
pipeline (mTLS, ed25519). The risk scoring is layered on top — it parses AI
agent config files, applies the rubric, and emits richer evidence variants
alongside the raw file_change events.
Each event is one JSON object on its own line:
{
"schema_version": 1,
"event_id": "019e0cea-42f1-7ef3-9a6a-1721e98ee2ba",
"ts": "2026-05-10T07:14:32.512Z",
"host_id": "a2e1f4c9b8d7",
"agent_version": "0.1.0",
"severity": "warn",
"source": {"kind": "file_system"},
"subject": {"kind": "path", "value": "/Users/alice/.cursor/mcp.json"},
"evidence": {
"kind": "file_change",
"change_kind": "modified",
"before_hash": "blake3:a31f1c7e9d8b…",
"after_hash": "blake3:0d72f8a4c6e8…",
"size_after": 2148,
"evidence_quality": "definitive"
},
"target_id": "team-mcp-allowlist"
}And — coming in Phase 3b — a richer evidence variant for AI guard surfaces:
{
"evidence": {
"kind": "ai_guard_risk_assessed",
"tool": "claude-code",
"scope": "user-global",
"score": 7.5,
"reasons": [
{"kind": "destructive_in_hook", "pattern": "rm -rf",
"hook_event": "PreToolUse", "snippet": "..."},
{"kind": "no_sandbox", "executor": "host-shell"},
{"kind": "broad_matcher", "matcher": ".*"}
]
}
}- Measures, doesn't block. AI guard surfaces are scored, not enforced. Enforcement is left to MDM/EDR; Sigil's job is to make sure those decisions are informed.
- Tiny, honest, host-only. Pure user-space. No kernel module, no eBPF, no phone-home. A single binary plus a YAML policy file.
- Hash-anchored events. Every observation carries blake3 hashes (before /
after) and an
evidence_qualitymarker, so a SIEM can tell a clean observation apart from one that was coalesced or delayed. - Versioned schema.
schema_versionis part of the contract; rename = break. - AI-aware defaults. Built-in policies cover the paths AI coding agents actually touch on macOS, Windows, and Linux — including Claude Code, Codex, Gemini CLI, and Cursor guard files.
Out of the box, with built-in defaults plus your policy YAML:
- AI agent guard surfaces —
~/.claude/settings*.jsonand<repo>/.claude/,~/.codex/config.tomland<repo>/.codex/,~/.gemini/and<repo>/.gemini/,~/.cursor/mcp.json. Hash-anchored events on every change; risk score on the contents (Phase 3b). - Hook scripts — convention dirs (
~/.claude/hooks/**,<repo>/.claude/hooks/**) watched recursively, so a hook script silently going from "deny" to "exit 0" is visible. - MCP & launch surfaces —
~/.cursor/mcp.json, new.plistin~/Library/LaunchAgents/, etc. - Credential & shell startup —
~/.aws/credentials,~/.ssh/,.zshrc,.bashrc,.profile. - Anything you list under
targets:in your policy YAML.
Sigil is a Rust workspace with five crates, organized as two long-running processes plus three shared libraries.
Processes
sigil-agent— the host daemon (sigilbinary). Owns thetokioruntime, thenotify-based filesystem watcher, the event pipeline, CLI commands, and platform glue. Writes JSONL posture events to the local spool.sigil-sender— the uploader (sigil-senderbinary). Reads JSONL batches from the spool, ships them to a SIEM endpoint over HTTPS (rustls), and hands signed policy responses back to the agent over IPC.
Libraries
sigil-core— pure domain library (event, policy, state, hashing, …). No OS,tokio, or filesystem-watcher dependencies. Consumed by both processes.sigil-spool— JSONL=IPC primitive (Producer/Consumer/Checkpoint/Retention) used at the agent → sender hop. Durable, crash-recoverable, domain-neutral.sigil-rules-basic— compile-time-embedded baseline rulesets (macOS and Windows defaults). The OSS fallback when no operator policy is supplied; extended rule packs ship separately.
flowchart LR
FS[("Filesystem<br/>policy targets")]
SIEM[("Your SIEM<br/>endpoint")]
subgraph agent["sigil-agent (bin: sigil)"]
direction TB
a_pipe["watcher · debouncer<br/>normalizer · hasher<br/>sink_task · state_task"]
a_ctrl["supervisor · policy_apply<br/>cli · doctor · show"]
end
subgraph sender["sigil-sender (bin: sigil-sender)"]
direction TB
s_pipe["batch_reader · manifest<br/>transport (HTTPS + rustls)"]
s_ctrl["control_task · agent_ipc<br/>dead_letter · heartbeat"]
end
subgraph spool["sigil-spool (JSONL=IPC)"]
spoolmods["Producer · Consumer<br/>Checkpoint · Retention"]
end
subgraph core["sigil-core (pure domain)"]
coremods["event · policy · state<br/>host_id · host_meta · hashing<br/>debounce · ratelimit · sink · stats"]
end
subgraph rules["sigil-rules-basic"]
rulesmods["compile-time YAML<br/>(macOS / Windows defaults)"]
end
FS --> a_pipe
a_pipe -- "writes JSONL" --> spool
spool -- "reads JSONL" --> s_pipe
s_pipe -- "HTTPS" --> SIEM
s_ctrl -. "apply_policy IPC" .-> a_ctrl
agent -. uses .-> core
sender -. uses .-> core
agent -. embeds .-> rules
- 0.1.x — alpha. The event schema and CLI surface can break between minor
releases until 0.2.
schema_versionin every event lets downstream consumers detect this. - Platforms. macOS, Windows, and Linux at runtime. The Linux runtime
landed as a minimal foundation (Phase 3a) and is exercised in CI; some
refinements are marked
TODO(community)inplatform/linux.rs— see CONTRIBUTING.md. - Schema. Version
1.
- Phase 1 — shipped. Filesystem watcher, JSONL sink, host metadata, state database, debounce / rate-limit, JSONL retention GC.
- Phase 2 — shipped. Split-process IPC via the durable spool, signed policy envelopes, a sender that ships JSONL over mTLS, an operator signing CLI, and an OSS reference server. Transport spec was locked on 2026-05-10.
- Phase 3a — shipped. Linux runtime (inotify watcher,
/etc/passwduser enumeration, hardware fingerprint). Minimal foundation; refinements open for community contribution. - Phase 3b — planned. AI Agent Risk Index: scoring rubric for
Claude Code / Codex / Gemini CLI / Cursor hooks, permissions, and
sandbox boundaries. Emits
ai_guard_risk_assessedevidence variants alongside the underlyingfile_changeevents. Per-fleet aggregation in the SIEM. - Phase 3c — planned. Reproducible-build attestation; additional posture signals.
- No kernel module, no eBPF. OS-provided file-event APIs only.
forbid(unsafe_code)in the core domain crate.- Reproducible release builds.
lto = "thin",codegen-units = 1,strip = "symbols",panic = "unwind". - Host-only telemetry. The agent never opens an outbound connection on its own. Shipping events anywhere is a separate, explicit component.
- The event schema is a public contract. Wire-string renames and field removals are breaking changes and bump the major version.
Install the Rust toolchain listed in rust-toolchain.toml, then build the
workspace:
cargo build --releaseThe agent binary is produced at:
target/release/sigilFor development builds, run:
cargo buildAll four binaries (agent, sender, server, signer) are packaged for
Debian/Ubuntu and RHEL/Rocky/Fedora. Daemons install a (disabled-by-default)
systemd unit + /etc/sigil/<binary>.yaml.example; sigil-signer is an
operator CLI so it ships just the /usr/bin/sigil-sign binary.
cargo install cargo-deb cargo-generate-rpm # one-time
packaging/build.sh # all 4 packages, both formats
packaging/build.sh sender rpm # or: just one package, one format
# Agent (host daemon).
sudo dnf install ./target/generate-rpm/sigil-0.1.0-1.x86_64.rpm
sudo systemctl enable --now sigil
# Sender (uploads spool to a sigil-server over mTLS).
sudo dnf install ./target/generate-rpm/sigil-sender-0.1.0-1.x86_64.rpm
sudo cp /etc/sigil/sender.yaml.example /etc/sigil/sender.yaml && sudo $EDITOR /etc/sigil/sender.yaml
sudo systemctl enable --now sigil-sender
# Server (OSS reference: receives events, serves signed policy).
sudo dnf install ./target/generate-rpm/sigil-server-0.1.0-1.x86_64.rpm
sudo cp /etc/sigil/server.yaml.example /etc/sigil/server.yaml && sudo $EDITOR /etc/sigil/server.yaml
sudo systemctl enable --now sigil-server
# Signer (operator CLI: keygen / sign / verify / inspect).
sudo dnf install ./target/generate-rpm/sigil-signer-0.1.0-1.x86_64.rpm
sigil-sign --helpSee packaging/README.md for details.
Run the agent:
cargo run -p sigil-agent -- runInspect the effective configuration:
cargo run -p sigil-agent -- show configInspect expanded watch paths:
cargo run -p sigil-agent -- show pathsRun diagnostics without starting the daemon:
cargo run -p sigil-agent -- doctorPrint version information:
cargo run -p sigil-agent -- versionSigil uses built-in defaults plus an optional YAML policy file.
Example policy:
version: 1
host_id_strategy: machine_id
overrides:
- id: shadow-ai-binaries-macos
tier: standard
targets:
- id: team-mcp-allowlist
description: Example MCP allowlist file
tier: critical
platform: any
paths:
- "~/.config/example/mcp-allowlist.json"
recursive: false
follow_symlinks: falseAn example policy file is available at config/policy.example.yaml.
You can override runtime paths from the command line:
cargo run -p sigil-agent -- \
--policy config/policy.example.yaml \
--state-db ./state.db \
--events-dir ./events \
runDefault production policy locations are platform-specific. The example policy
can be adapted for /etc/sigil/policy.yaml on Unix-like systems or
%ProgramData%\Sigil\policy.yaml on Windows.
For responsible disclosure of vulnerabilities, see SECURITY.md.
Bug reports, policy suggestions, and patches are welcome. See CONTRIBUTING.md before opening a PR.
This project is licensed under the Apache License 2.0.
You may use this software for personal, internal, and commercial purposes, subject to the terms of the Apache License 2.0.
See LICENSE and NOTICE for details.
This software is provided "as is", without warranties or guarantees of any kind.
The author does not guarantee correctness, availability, reliability, security, compatibility, or fitness for any particular purpose.
The author is not responsible for any direct, indirect, incidental, consequential, special, exemplary, or other damages, including but not limited to outages, data loss, security incidents, business interruption, incorrect results, compatibility problems, or other problems arising from the use of this software.
Use this software at your own risk.
Commercial support, hosted services, enterprise features, paid add-ons, consulting, or professional services may be offered separately in the future.
Some future commercial features, hosted components, enterprise modules, or binary-only add-ons may be distributed under separate commercial terms.
The open-source version remains available under the Apache License 2.0.