envit security

What envit contacts, what it writes, how releases are verified.

Supply chain

Every release binary is built by a public GitHub Actions workflow from a version tag. You can check where a binary came from.

controlwhat it gives you
Build provenanceEach release asset has a signed GitHub attestation that names the workflow, commit, and tag that built it.
SHA-256 checksumsOne checksum file per asset. The install script checks it.
SBOMA CycloneDX inventory of every dependency in the build, attested and attached to the release.
Pinned workflow actionsEvery action is pinned to a commit SHA. A tag cannot be moved under us.
cargo denyRuns on every push. Fails on known advisories, unapproved licenses, wildcard dependencies, and unknown sources.
zizmorAudits the workflows themselves on every push and weekly.
gitleaksScans the full git history for secrets on every push and weekly.
DependabotWeekly update PRs for Cargo and Actions. Security alerts on.
#![forbid(unsafe_code)]No unsafe Rust in envit. The embedded git and HTTP stacks are third-party crates and carry their own audits.

Verify a downloaded asset:

gh attestation verify envit-aarch64-apple-darwin.tar.gz --owner plannotator

The install script runs this check when the GitHub CLI is present and reports the result. It always checks the SHA-256.

Workflow source: .github/workflows.

Network

envit contacts only the git remotes in your manifests. It uses the plain git protocol over HTTPS with an embedded git implementation. No telemetry. No update checks. No open ports. No forge APIs.

requestwhen
git fetch to a declared remotesync when the store lacks the checkout, or a stale auto repo (at most once per 24 h), or update
nonesync --offline, sync --frozen with a warm store, status, skills, pin, gc

ENVIT_NO_REFRESH=1 blocks every implicit fetch. sync --offline guarantees no network for one run.

Filesystem

Every path envit writes, and how to undo it.

pathwhatundo
~/.envit/the store: bare git repos, read-only checkouts keyed by commit, locks, the project registry, the optional global manifestenvit gc removes unreferenced checkouts; delete the directory to reset
envit.json, envit.lock.jsonyour manifest and lock, in the project rootyours; edit or delete
.envit/symlinks into the store, a generated AGENTS.md, a CLAUDE.md symlink to itgitignored; delete the directory
.agents/skills/<name>, .claude/skills/<name>one symlink per declared skill (a managed copy when modelInvocable is set)remove the skill from the manifest; sync prunes only entries it created
~/.agents/skills/, ~/.claude/skills/the same, for the global manifestsame
AGENTS.md, CLAUDE.md in the project roota fenced note between <!-- envit:begin --> and <!-- envit:end -->, only when the file already existsset "agentsMd": false, or delete the block
.gitignoreone line, .envit/, added by init when the file existsdelete the line

envit never modifies files inside a checkout, never creates AGENTS.md or CLAUDE.md, and never deletes a symlink or directory it did not create.

Skills are instructions

A skill is text an agent will follow. Treat a skills source like a dependency that can run code. envit gives you three controls.

Read a skills source before you add it. Set "update": "frozen" on it if you want no drift.

Report a vulnerability

Do not open a public issue. Use GitHub's private reporting form with the affected version, steps to reproduce, and impact. Fixes go to the latest released version.

These checks reduce risk. They do not prove the absence of vulnerabilities. envit claims no certification.