Documentation

Install Pixel, wire it into your agents, and read what its answers promise and what they do not.

Updated

Install

Pixel is a single binary for macOS and Linux. Pick one channel:

brew install LivioGama/tap/pixel
curl -fsSL https://github.com/LivioGama/pixel/releases/latest/download/install.sh | sh

The script downloads the latest release, checks its checksum and installs it into $PIXEL_INSTALL_DIR (default ~/.local/bin). To build from source instead, see CONTRIBUTING.md.

Then let your agents use it, and check the result:

pixel install         # once, from anywhere
pixel prepare-repo .  # optional: index, graph and a warm daemon for this repository
pixel doctor .        # optional: health check
pixel list-signatures path/to/a/large/file   # first result: full read vs Pixel, in tokens

The index, the code graph and the optional history data live in .pixel/ at the repository root and never leave the machine, and there is no telemetry. The network is used only for Git remote operations, the optional pixel classify and pixel web-search, and the embedding model downloaded from Hugging Face on first use (security model).

What pixel install wires

pixel install is global: run it once, from anywhere. It deploys the agent prompt to ~/.local/share/pixel/ (agent-prompt.md, plus the short subagent-prompt.md for sub-agents) and wires it into the agents it knows:

AgentHow the prompt reaches it
Claude CodeSessionStart and UserPromptSubmit hooks in ~/.claude/settings.json inject the prompt as context, plus a PostToolUse hook on Edit and a SessionStart hook on compact. No shell wrapper, never blocks.
Codexthe developer_instructions key of ~/.codex/config.toml, which every Codex front end reads, plus a metrics PostToolUse hook
Pi~/.pi/agent/APPEND_SYSTEM.md, read automatically
OpenCodethe prompt appended to AGENTS.md
Antigravitythe Pixel plugin deployed and enabled, and its guard hooks registered

Each agent’s page under For your agent names the files, the check and the removal, including the agents pixel install leaves alone.

pixel uninstall removes everything pixel install wrote, and the binary at ~/.local/bin/pixel, where the install script puts it. A package manager removes its own copy: brew uninstall LivioGama/tap/pixel, or mise uninstall pixel.

Per-repository guards

pixel install --repo <path> writes project-local enforcement only and skips every global step:

  • <repo>/.claude/settings.local.json: the guard hook, in Claude Code’s personal project settings (the shared .claude/settings.json never carries it); <repo>/.claude/pixel-rtk-hooks.json keeps an rtk hook claude group the guard takes over
  • <repo>/.codex/config.toml: the same developer_instructions key as the global install
  • <repo>/.codex/hooks.json: the guard hook, with <repo>/.codex/pixel-composed-guard-backup.json holding the hooks it replays; left alone when Git tracks .codex/hooks.json
  • <repo>/.devin/config.local.json: the guard hook for Devin
  • <repo>/.pi/extensions/pixel-guard.ts: Pi’s guard extension, loaded once Pi trusts the project

Every one of those files except .codex/config.toml names this machine’s pixel binary, so the install lists it in the clone’s .git/info/exclude and a git add -A cannot publish it.

The guard is advisory. It steers agents toward Pixel commands, for example with a notice before an untargeted read of a large source file, and never blocks a tool call. pixel doctor <repo> reports the global wiring and the per-repository guards as green, stale or missing.

Updating

Upgrading replaces the binary only. The agent prompt and the per-agent config keys belong to you, not to the package manager, so they keep the old release’s text until you refresh them.

Installed withUpgrade the binary
Homebrewbrew update && brew upgrade LivioGama/tap/pixel
misemise upgrade pixel
install.shrun the same curl … | sh line again
Source checkoutpixel self-update rebuilds and reinstalls the running binary

Then, whatever the channel:

pixel install
pixel doctor . --fix   # runs each repair a flagged check names, then re-checks

pixel doctor . reports the wiring as stale until you do, with the command that repairs each finding, and exits 1 while a check is red.

Plugins

Each agent CLI below can load Pixel’s protocol through its own plugin mechanism, or for the last row a rules file you copy, with no pixel install step. The pixel binary still has to be installed: the plugin never installs it. When the binary is missing or too old for the commands the protocol names, the plugin injects a one-paragraph notice instead of the protocol.

ToolInstall
Claude Code/plugin marketplace add LivioGama/pixel, then /plugin install pixel@pixel
Codexcodex plugin marketplace add LivioGama/pixel, then codex plugin add pixel@pixel
Copilot CLIcopilot plugin marketplace add LivioGama/pixel, then copilot plugin install pixel@pixel
Devinadd github.com/LivioGama/pixel as a Devin plugin
Gemini CLIgemini extensions install https://github.com/LivioGama/pixel
Pipi install git:github.com/LivioGama/pixel
Cursor, Windsurf, Kiro, Cline, Qoderrules ship under .cursor/rules/, .windsurf/rules/, .kiro/steering/, .clinerules/ and .qoder/rules/: copy them into your project

OpenCode has no Pixel plugin package published yet, so it is not in the table: pixel install puts the protocol in its global AGENTS.md instead (Pixel for OpenCode).

Any other agent: paste PIXEL.md, the plain-Markdown protocol, into whatever instruction surface it offers. Manual setup covers wiring the full prompt by hand.

The workflow

The agent prompt walks every change through the same path:

pixel scope-task "<task>"        # first call on multi-file work: P0/P1/P2 targets
pixel find-code "<phrase>"       # before any free-text search for a name
pixel impact "<symbol>"          # before editing any symbol: its blast radius
pixel what-changed               # before an edit batch: what already differs
pixel review-changes             # the working tree, structured
pixel commit-and-push --files <f1> --files <f2> -m "msg" --request-id "id" origin HEAD

Two rules hold throughout. pixel impact runs before any edit, because editing blind is how callers you never saw break. And the agent never commits or pushes unless asked: every write takes a --request-id, which makes it crash-safe and idempotent.

Commands

The most used commands, by job. pixel --help lists all of them, and ARCHITECTURE.md describes each in one line.

Find code

Instead ofRun
grep, rgpixel search-content "re" [path]: the same regex, indexed and capped
grep for a function by namepixel find-code "name": a phrase resolved through the concept index
grep for a definitionpixel find-symbol "Foo": the exact symbol, from the code graph
“how is auth handled?”pixel search-meaning "how is auth handled?": semantic, not regex
reading a whole filepixel list-signatures <file> or pixel pack-context <uid>: the skeleton, or one symbol fitted to a budget

Scope and impact

QuestionRun
Which files does this task touch?pixel scope-task "task"
What breaks if I change this?pixel impact "symbol"
Who calls it, what does it call?pixel who-calls "X" --role callers
How does A reach B?pixel call-path "A" "B"
What did I already change?pixel what-changed
A checklist for a multi-file fixpixel plan "task"

History

Instead ofRun
git log -S "x"pixel dig-history --phrase "x"
git log --grep "x"pixel search-history "x"
git log --follow fpixel file-history --file f
git blame fpixel who-wrote f
“it worked before”pixel plan-rollback "<problem>": flags the breaking commit, writes nothing without --apply

Git changes

Instead ofRun
git statuspixel repo-state
git diffpixel review-changes
git log --onelinepixel commit-history
git branch -a -vvpixel list-branches
git pull --rebasepixel sync-branch
git add and git commitpixel commit --files <f1> --files <f2> -m "msg" --request-id "id"
git pushpixel push: a leased push, never a raw --force

Past sessions

pixel recall searches the transcripts of every agent on the machine (Claude Code, Codex, Pi and others). pixel recall search "token" finds an exact string, pixel recall ask "topic" a topic in your own words, and pixel recall show <ref> --turn N..M reads the turns around a hit.

Reading the answers

Every result carries a marker set by the system, not by the model:

  • complete: every match was returned.
  • capped: the answer was truncated and more matches may exist. Narrow the pattern or the path.
  • unresolved: nothing was found. Try another query, or pixel search-meaning.

Graph answers (pixel impact, pixel who-calls, pixel call-path) also carry an epistemics object:

  • closed_world is always false. Static analysis is never complete, so “0 callers” means none were found, not that none exist.
  • lower_bound: true flags same-name call sites the resolver could not settle: more edges may exist.
  • extraction_limits names the known blind spots: callbacks passed as arguments, dynamic dispatch, macro-generated calls, eval.

When native tools are right

Pixel does not cover every job. Use the native command for grep flags Pixel lacks (-l, -m), pipelines, files outside the index (git-ignored, binary, or over 4 MiB), in-place edits with sed, interactive Git such as rebase -i and stash, and network operations such as clone.

Token savings

pixel token-savings reports, for the retrieval commands you ran, the fraction of the candidate pool the agent did not have to read. It measures what reached the agent’s context, not your invoice. The replay of shunt’s benchmark on Pixel’s own repository is on the home page, and its method on the benchmarks page.

Each Pixel command also prints a 🟩 Pixel line on stderr with its measured duration and two estimates: tokens saved against the native workflow, and time saved against sequential round trips. Both are estimates, and zero or negative values are valid. --metrics=off or PIXEL_METRICS=0 turns the line off.

One command measures instead of estimating: pixel list-signatures <file> stands in for reading that file, so its line compares the file with the outline it printed, as full read 10365 tok, pixel answer 641 tok (-94%) (Requests’ models.py). Both counts are bytes divided by four, rounded down, the method of the benchmarks page, and it works on a fresh clone with no session behind it.