| name | envit |
| description | How to use envit, the repo-context tool — it materializes the source code of a project's dependencies into .envit/repos/ so you can read real library source instead of guessing. Use this skill whenever you see an envit.json or .envit/ directory in a project, whenever you need to read the source of a dependency or open-source library, whenever library context seems missing or stale, or whenever the user mentions envit, repo context, or asks you to add/pin/update a context repo. |
| license | MIT OR Apache-2.0 |
envit — repo context for agents
envit is a virtualenv for repo context. The project's envit.json declares
which git repositories an agent should be able to read; envit sync
materializes them, read-only and commit-pinned, under .envit/repos/.
The bytes live once per machine in a shared store — never edit them, and
never commit .envit/ (it's gitignored; the manifest and envit.lock.json are
committed instead).
Reading context (the common case — no commands needed)
- Read
.envit/AGENTS.md first: it lists every available repo, its
commit, and its resolved path.
- Dependency source lives at
.envit/repos/<name>/ — real, complete,
at the exact commit the lockfile pins. Prefer reading it over guessing
at a library's behavior from memory.
- The entries are symlinks:
rg and fd skip them by default.
Use rg --follow / fd -L, or search the resolved store path from
AGENTS.md (generated) directly.
- Everything is read-only by design. If you need to modify a
dependency, that's a fork/vendor decision for the user — say so
instead of fighting the permissions.
If .envit/repos/ is missing but envit.json exists, run envit sync.
Commands
| Command | Use it to |
|---|
envit sync | Materialize everything the manifest declares. Fast when warm (~ms). Advances stale branch-tracking repos at most once per 24h. |
envit sync --frozen | Reproduce the lockfile exactly (CI, sandboxes, teammates). Errors on manifest/lock drift instead of resolving. |
envit sync --offline | Never touch the network; link only what the store already has. |
envit add <source> [--ref R] [--name N] | Declare a new repo. github:owner/repo, other forge shorthands, or any https git URL. Omit --ref to track the default branch. Does not sync. |
envit remove <name> | Remove a declaration. |
envit update [name…] | Deliberately move branch-tracking repos to current remote heads. Prints old → new. |
envit pin <name> | Freeze a repo at its currently locked commit. |
envit unpin <name> | Resume tracking its original ref. |
envit status | Per repo: ref, locked commit, link health, policy/staleness. Never touches the network. |
envit gc [--dry-run] | Remove store checkouts no project references. |
Env vars: ENVIT_HOME (store location, default ~/.envit),
ENVIT_NO_REFRESH=1 (block all implicit refresh),
ENVIT_REFRESH_TTL (e.g. "1h", global staleness window).
Manifest format (envit.json)
JSON: a list of repo links, plus an optional skills object. A bare
"owner/repo" string means GitHub at the default branch; an entry needing
options becomes an object:
{
"repos": [
"tokio-rs/tokio",
{ "source": "Effect-TS/effect", "ref": "next" },
{ "source": "serde-rs/serde", "ref": "v1.0.200", "update": "frozen" }
],
"skills": {
"vercel-labs/agent-skills": ["web-design-guidelines"]
}
}
Per-entry keys: source (required), name, ref, update
(auto/manual/frozen), ttl (e.g. "1h"), history ("full").
Skills sources also take path (subdirectory in a monorepo) and
modelInvocable (true/false): whether the model may invoke the
skill on its own. Overrides the author's controls for both Claude
(disable-model-invocation) and Codex (allow_implicit_invocation).
Applies per source, or per skill via
{ "name": ..., "modelInvocable": ... } in a pick list.
Prefer envit add/remove/pin over hand-editing; CLI edits re-emit
canonical pretty-printed JSON.
Situations and the right move
You need source the project doesn't declare yet (debugging into a
library, checking an API): envit add github:owner/repo && envit sync.
Tell the user you added it — it edits their committed manifest.
Context changed under you mid-task (files shifted after a sync
advanced a branch): envit pin <name> freezes the repo at the commit
you're looking at, instantly. Note the pin in your summary so the user
knows to unpin later.
Context looks stale (the lockfile commit is weeks old and you need
newer code): envit update <name>. Never assume freshness — envit status shows what's pinned and when remotes were last checked.
Bootstrapping a fresh checkout or sandbox: envit sync --frozen
gives bit-identical context to the committed lockfile. This is the only
sync mode CI and cloud environments should use.
Merge conflict in envit.lock.json: don't hand-merge — resolve the
manifest, then run envit sync; the lock is machine-regenerated
canonically.
Semantics worth knowing
- The manifest is intent ("track main");
envit.lock.json is fact ("main was
3f2a9c1 when materialized"). Both are committed.
- Plain
sync does not chase branches — a locked repo stays put unless
it is auto (the default) and its remote hasn't been checked in 24h.
update is the explicit "move now."
- Checkouts are keyed by commit SHA in the store, so two projects pinned
to different commits coexist and nothing changes behind a project's
back. Refreshes swap the symlink atomically.
- envit runs no daemons; nothing happens between invocations.
If the envit binary is not on PATH, ask the user how it is installed in
this environment (in envit's own development repo it is
target/release/envit after cargo build --release).