cd /news/developer-tools/glean-run-an-ai-skill-only-over-what… · home topics developer-tools article
[ARTICLE · art-116135] src=github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Glean: Run an AI skill only over what changed since it last ran

Glean, a new Rust-based developer tool, lets AI skills and MCP servers track which files they have already processed and only operate on files changed since the last run, using content hashing and per-consumer baselines stored in .git/glean/. The tool, installable via cargo and available as a Claude Code plugin, scales with the diff and supports commands like list, mark, status, reset, run, and mcp, with features like NUL-separated paths and JSON output.

read5 min views1 publishedAug 31, 2026
Glean: Run an AI skill only over what changed since it last ran
Image: Michielbdejong (auto-discovered)

glean

records which files a tool has already processed, so the next run only sees what changed since. A skill on a loop scopes itself to new edits instead of re-sweeping the whole diff every tick.

Per-consumer baselines. Each skill or tool tracks its own position, so parallel passes share a tree without redoing each other's work.Content-hashed. A file is changed when its bytes differ from the baseline — surviving rebases, branch switches, and rewrites that only bump mtimes.Scales with the diff. The candidate set is the uncommitted working set, so a monorepo with three edits costs three reads.Out of history. Baselines live in.git/glean/

, never committed, separate per worktree.

A single Rust binary. The /glean

skill and the MCP server both resolve it by name on PATH

:

cargo install --path . --root ~/.local   # → ~/.local/bin/glean
glean list   [--as <consumer>] [-z] [-q] [--json]        files changed since this consumer's last mark
glean mark   [--as <consumer>] [--stdin] [-z] [paths…]   record files as processed (no paths = the whole changed set)
glean status [--as <consumer>] [--json]                  counts; with no --as, summarize every consumer
glean reset  [--as <consumer>] [--all]                   forget a baseline to force a full re-sweep
glean run    [--as <consumer>] [--each] -- <cmd>…        run <cmd> on the changed files, mark on success
glean mcp                                                serve the change-set as MCP tools over stdio

A consumer is one skill or tool with its own baseline. --as

names it; it defaults to default

.

$ glean list --as slop        # what has changed since slop last ran?
src/auth.rs
src/db.rs


$ glean mark --as slop src/auth.rs src/db.rs   # record them as done

$ glean list --as slop         # nothing new since
$

-z

writes NUL-separated paths, safe for paths with spaces or newlines; --json

writes a JSON array. -q

prints nothing and exits 0 if anything changed, 1 if not. mark --stdin

reads paths from stdin:

glean list -z --as slop | glean mark --stdin -z --as slop

Consumers are independent. When a file changes, every consumer that has not seen those exact bytes picks it up, including files the other passes edited:

glean list --as slop        # code smells
glean list --as simplify    # structure
glean list --as check       # type checking

glean ships as a Claude Code plugin — the /glean

skill and the glean

MCP server:

/plugin marketplace add amalucelli/glean
/plugin install glean@glean

Both call the glean

binary by name, so install that too. Without the plugin, copy the skill where Claude Code looks for it:

cp -r skills/glean ~/.claude/skills/

/glean <skill>

scopes <skill>

to what changed since it last ran, invokes it, and marks the result. Point a loop at it:

/loop 2m /glean slop         # slop only new edits, every 2 minutes
/loop 5m /glean simplify     # works with built-in skills too

It runs in a forked subagent, so the loop's main context grows by one line per tick rather than by every file the pass reads. Run the skill directly to watch or steer it. The wrapped skill must accept file paths as arguments. Forking from a plugin needs Claude Code v2.1.101+; older versions run it inline.

glean run

packages list → run → mark into one command:

tool <args> <files>   →   glean run --as tool -- tool <args>

It snapshots the changed set, runs the command on it, and marks those files only if the command succeeds — a failing pass leaves its files for the next tick. run

exits with the command's status. In CI, cache .git/glean/

between runs and a step only re-checks files that changed since they last passed.

Formatters rewrite in place, so batch (the default) fits: glean records the formatted bytes as the new baseline.

glean run --as gofmt -- gofmt -w

Linters report per file, so use --each

: the command runs once per file and only passing files are marked. A file with errors returns each tick until it is fixed, instead of pinning the whole batch.

glean run --each --as eslint -- eslint

Outside Claude Code that is a plain shell loop:

while true; do
  glean run --each --as eslint -- eslint
  sleep 300
done

Whole-project tools that cannot take file paths (cargo clippy

, tsc

) do not fit run

. Gate them on -q

instead:

glean list -q --as clippy && cargo clippy && glean mark --as clippy

glean mcp

serves the change-set over stdio. The plugin registers it automatically; for another client, run glean mcp

as the server command.

glean_list

— paths changed since a consumer last marked them.glean_mark

— record paths as processed; omitpaths

to mark the whole changed set.glean_status

— tracked and changed counts per consumer.

run

is not exposed: the MCP surface reads and advances the cursor, it does not execute commands.

  • The candidate set is git diff HEAD

plusgit ls-files --others

— staged, unstaged, and untracked. - Baselines are stored at .git/glean/<consumer>.json

. Git does not track its own directory, so the state stays out of history and out of glean's view of the tree. - Each consumer is the sole writer of its own file, so consumers need no locking.

  • Lockfiles and binary files are excluded from list

. core.fsmonitor

andcore.untrackedCache

speed up large trees.

There is no base flag. For committed work the file set (git diff <ref>

) is static and swept once, so a cursor adds nothing — scope that with git, or with the skill's own branch mode.

MIT. See LICENSE.

── more in #developer-tools 4 stories · sorted by recency
── more on @glean 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/glean-run-an-ai-skil…] indexed:0 read:5min 2026-08-31 ·