pixtuoid
AGENTS.md551 starsChanged 31 days agoMITView on GitHub
Instructions for any AI coding agent in this repo. Every agent, Claude Code included (v2.1.277 or later), reads these AGENTS.md files natively; there is deliberately no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md, because any of them switches Claude Code to CLAUDE.md-only. This is the workspace map; per-crate detail lives in the nested guides: What the guides hold. A nested AGENTS.md says what its crate IS, plus the facts no single declaration can own: cross-file workflows, comment-less manifests, and directory-shape rules. Everything else…
1 other project uses a version of this.
Adopted by
Most recently taken up by
- pixtuoid/pixtuoidword for word, first seen Oct 13, 2026
Other versions1 project uses a version of this.
Word for word · 1
- pixtuoid/pixtuoid★ 551100% same
Edited · 0
None found.
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,542 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository4 other files it gives its agents.
- site/AGENTS.mdAGENTS.md
- add-sourceSkill
- beautify-decorationSkill
- local-reviewSkill
The file
We split this AGENTS.md into the rules it gives an agent
6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 44
Git: Never force-push and never skip hooks.
- Very specific: line 85
Look-changing PR → just gen, commit everything it rewrote.
- Very specific: line 166
No write to another CLI's config outside install/io.rs (write_config_atomic / ConfigLock).
- Distinctive: line 168
No doc generator or cap in place of a proposed diff: the owner reviews every doc change.
- Very specific: line 169
No stale Closes #N on a re-scope (fires from commit body or PR text, even conditional).
- Distinctive: line 170
No merging past the review gate (PR #23 merged unreviewed with a path traversal).
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AGENTS.md
Instructions for any AI coding agent in this repo. Every agent, Claude Code
included (v2.1.277 or later), reads these AGENTS.md files natively; there is
deliberately no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md, because
any of them switches Claude Code to CLAUDE.md-only. This is the workspace map;
per-crate detail lives in the nested guides:
crates/pixtuoid-core/AGENTS.md— headless lib: sources/decoders, reducer/state. (+tests/AGENTS.md: the test-binary layout, add-a-CLI test steps.)crates/pixtuoid-scene/AGENTS.md— backend-agnostic render+sim engine: sprite format, grid/walkable, pixel painter, layout, walk/pose/pathfind, theme model, weather, pets, chitchat.crates/pixtuoid/AGENTS.md— the binary: install, runtime, cli, config, multi-floor. (+src/tui/AGENTS.md: the terminal painter.)integrations/raycast/AGENTS.md,site/AGENTS.md— the non-Rust--jsonconsumers; their gates aretsc/eslint/just site-check, not cargo.
What the guides hold. A nested AGENTS.md says what its crate IS, plus the
facts no single declaration can own: cross-file workflows, comment-less
manifests, and directory-shape rules. Everything else a change needs —
the constraint that looks like a bug, the WHY, the test that pins it — is on
the narrowest thing it constrains: read the whole item, its doc comment and the
comments on the lines it governs, before changing it.
A third consumer lives outside this repo: homebrew-core's pixtuoid
formula asserts exact CLI output (test do) and needs pixtuoid man /
completions <shell> on clean stdout — breakage surfaces in THEIR CI on an
autobump we never see, while our suite stays green (it asserts the same
strings as goldens). The asserted rows carry a "homebrew-core contract"
comment; release-side consequences
in CONTRIBUTING.md.
<!-- org-rules:begin -->Org rules
Shared by every pixtuoid repo. The source is pixtuoid/.github's .github/actions/org-rules/org-rules.md, and that action fails CI when a repo's copy differs: change the rules there, then sync each repo's copy.
The owner's bar: every change is best practice, the best architecture design and the most future-proof, follows the industry's standard practice and these md rules, and refactors existing code that breaks them; no low-ROI work, no over-engineering, no legacy or backward-compatibility paths.
- Evidence. An external claim, "best practice" included, cites a doc URL or
path:linefetched this session, or is labelled opinion. - Refactor. Existing code a change touches that breaks a written rule is refactored in that change. Any other code may be, in a commit of its own, when that removes a named defect, never on taste alone.
- Every mechanism earns its upkeep. Code, config, a test, a CI job or a doc stays only if it names a failure it prevents that nothing else already does. A maintained library, the platform or the upstream tool's own mechanism is reused before one is built.
- TDD. A failing test, then the minimal implementation, then the commit.
- Comments are WHY only, doc prose and PR bodies included, and sit on the narrowest thing they constrain. Name the authority instead of restating its value. Measurements go in commit messages.
- No magic numbers. Reuse the existing authority, else one named constant at the narrowest scope; when a copy of a value must cross a boundary, a test pins the pair. No
unwrap()outside tests. - Review findings. A finding's premise is checked against the item it names before it is accepted. A refuted finding produces a mechanism (a test, a compile-time constraint, a CI gate) or nothing.
- Docs change in the same commit as what they describe, and no new doc lands unless the owner asks.
- Git. Never force-push and never skip hooks. How a change reaches
mainis each repo's own rule. - The Roadmap is the plan of record, the owner's rule: every step (an item started or finished, a PR opened, merged or closed, a reorder) updates its item, the draft or the issue it tracks, in the same turn. Who may file an issue is each repo's own rule.
<!-- org-rules:end -->What this is
Terminal-native, multi-agent pixel-art visualizer for AI coding agents: each
running CC session is an animated sprite in an ASCII office. Rust workspace,
six crates. Overview: README.md.
Layout
crates/ DAG: pixtuoid-core ← pixtuoid-scene ← {pixtuoid, pixtuoid-web, pixtuoid-web-music} (+ standalone pixtuoid-hook)
├── pixtuoid-core/ headless lib — no terminal deps; `native` feature gates the async
│ source runtime (off = wasm32-clean decode/reduce)
├── pixtuoid-scene/ render+sim engine — terminal- AND window-free BY CRATE BOUNDARY
│ (its music: the external `pixtuoid-lofi`, https://github.com/pixtuoid/lofi)
├── pixtuoid/ binary — two thin painters over pixtuoid-scene: `tui/`, `floating/`
├── pixtuoid-web/ third painter — wasm canvas, publish=false; a SITE BUILD INPUT
│ (`just gen-wasm` → gitignored site/public/wasm/, built in CI)
├── pixtuoid-web-music/ the site's ♩ lofi in its own wasm, so the office's carries none
└── pixtuoid-hook/ tiny shim CC invokes — stdin JSON → socket/named pipe
scripts/ gen-media.py (the ONE driver for the README's committed media and the site's CI-rendered demos), gen-art.py (the generated sprites: every @Nx + the 1x pieces it owns), each shipped plugin's selftest, and in lib/ its harness and the openclaw tier
policy/ CI contracts no linter sees (jq over yq) + behavior tests of workflow shell
fuzz/ cargo-fuzz targets over harness::Drive and remote, its own workspace; `.clusterfuzzlite/` builds them for fuzz.yml
site/ Astro landing page; integrations/raycast/ Raycast extensionBuild & test
just build [--release] · just test # the one test runner (nextest)
just test -p <crate> <filter> # fast loop
just preflight [full] # pre-push gate: lint → clippy; `full` adds hack → test (CI's Rust recipes)
cargo run --release --example snapshot -- /tmp/snap.png # render TUI to PNG
cargo run --profile release-local --example snapshot -- /tmp/snap.png # the same, rebuilt faster; scripts still read target/release- clippy doesn't warm test's build (why) — iterate with one of them. Never pipe preflight through
tail/head(exit code eaten). - Touched
--json/SourceStatus/OutcomeRow/ the source roster →just gen-contract(regenerates schemas + Raycast types). - Look-changing PR →
just gen, commit everything it rewrote. Media is not a PR's: the site's demos render in CI, the README'sdocs/imagesinmedia-regen.ymlfrom main. - Real wire bytes ride ONE pipeline,
pixtuoid_core::harness::Drive— rules intests/AGENTS.md. - Fixtures are RECORDED, never composed (
just hermetic --recordfor a scenario a profile records, elsejust capture-fixture— BILLED), and the recorder blanks every subtree no decoder reads (derived by probe, never listed); every scenario declaresprovenance.json. Rules:tests/sources/README.md.just restrip-fixturesre-strips the committed corpus offline;just corpus-allcensuses local corpora. - Visual verification for sprite work: snapshot example →
scripts/crop-snapshot.py→ READ the PNG; loop in.claude/skills/beautify-decoration/SKILL.md. - CI is the gate, and a green preflight is NOT a green PR. A PR's pushes run only the light tier; the full tier runs on
main, and in the merge queue unless Mergify merges an up-to-date PR alone at the front directly (two-step CI). - Advisory (never gates):
just mutants,just bench,just bench-pacing, CodSpeed,fuzz.yml(a crash's input is its run'scrashes-<target>artifact;just fuzz <target> <file>replays it). - Fluency gate, local and pre-release (a wall-clock budget, so never CI):
just pace-check; its runs and verdict inscripts/pace-check.py's header. - Hooks:
git config core.hooksPath .githooksonce per clone;just setup-toolsinstallsmise.toml's tools and rust-analyzer (without it the agent LSP degrades to grep). - Release is a human step:
CONTRIBUTING.md#releasing.
Workflow
Non-trivial work runs as an arc: read
each step there before taking it, never from recall. Merging is
@mergifyio queue, which a session comments itself once
the merge gate holds, and a release PR
merges by hand. The CI review applies REVIEW.md on every push;
arc step 7 says when the local-review
skill runs it first.
At most 6 open PRs across the sessions (bots' and outside contributors'
aside), the owner's cap: the runners take
20 jobs at once and one
light-tier push needs more, so each open PR past the first lengthens the wait
of every push. A PR
opens, never as a draft, once its branch is ready to merge, its local review
done when one is due. The pre-push hook runs
preflight and CI the rest, so neither is rerun by hand. Until a slot frees, the branch stays pushed
with no PR. A PR
that stops being ready closes with its branch kept and never force-pushed,
since a force-pushed branch can't reopen; a stacked one is retargeted to
main first, because merging its base deletes that branch. Closing leaves its
runs queued, and a plain cancel still runs the always() gate jobs, so
force-cancel
them.
Repo skills (committed): local-review, beautify-decoration,
add-source.
Conventions
- Mechanism upkeep and reuse (org rule): extending a mechanism re-adds it, so one you touch that can't name its failure is deleted, not polished; the load-bearing defenses REVIEW.md's Proportion row lists have named theirs. A reuse is skipped only when its own cost is larger (wasm32, a version freeze), and the PR names that cost.
- Chibi figures and pets stay round, the head flowing into the body.
#[allow(clippy::too_many_arguments)]is a last resort — group related parameters into a struct first.- Comments (org rule): a workflow or manifest comment, a justfile recipe header and a CI contract's
whyare in scope too. Every sentence adds what the earlier ones don't, the first being the whole answer. A rationale stays on the statement, struct-literal field or match arm it governs, never hoisted to the declaration to shorten a body. A change leaves the net comment volume of what it touches no larger unless each added line earns its place. An intra-doc link to the authority also turns a rename into adoc-checkred, private items included. - DRY. One implementation per piece of logic and one source per value: two copies are a latent drift bug.
- Magic numbers (org rule): prefer a type (enum/newtype) for a related set; self-evident
0/1/2, indices and test fixtures stay inline. - Errors:
anyhow::Resultin app code,thiserrorin core; hook listener + JSONL watcher log-and-continue, never panic. - Visibility: layer-internal stays
pub(crate)(unreachable_pubmisses apubreachable through apub mod;just hawk, a full-tier gate, fails on one no other workspace crate's code needs);#[doc(hidden)] pubis a mechanism-not-contract escape hatch: no public signature names one (just api-surfacefails on it), and nothing an out-of-workspace painter (the App) reads is one. The binary's lib has onepub mod, the#[doc(hidden)]pixtuoid::devfacade its examples, tests and benches reach it through, sounreachable_pubreports anypubthat list doesn't name. - No scan-the-history — keep state updated as events arrive; never derive it by scanning backward.
- Shell: match the surrounding shell; macOS-first (BSD CLI, brew).
- Evidence (org rule): a hermetic profile scenario that reaches the surface (
just hermetic) counts as a source too, and the population is the whole upstream repo (gh api .../git/trees/<ref>?recursive=1), not one plausible file. - Review findings (org rule): a refutation adds a code comment only for an EXTERNAL fact (another CLI's wire bytes, an OS semantic), on the narrowest thing it constrains. A real finding ends FIXED, RE-SCOPED → #N or FOLLOW-UP → #N before the PR merges; which applies, the four terminal states and what #N may be are defined once in
CONTRIBUTING.md. Agents never file issues. - Only the latest released version of each agent CLI is supported. When upstream renames or reshapes a wire name, repoint the decoder and the plugin at the CURRENT declaration and DELETE the old one — no dual-listening beside a replacement, no legacy-format arm kept "just in case". Every superseded arm is a second copy of a wire contract that drifts silently. Two things this does NOT govern: OUR OWN upgrade path (an arm for an artifact an older pixtuoid wrote is ours to keep or drop, not upstream's — #457), and mirroring a resolver upstream itself still branches on.
- Path asserts compare
PathBufstructurally, neverto_string_lossy()with a hardcoded separator — string asserts pass on Unix and fail only inwindows-test. Resolution POLICY (HOME vs USERPROFILE, %APPDATA% vs~/.config) is per-CLI: mirror each CLI's own resolver (platform::home_first_dir).
Architecture invariants (load-bearing)
pixtuoid-coreandpixtuoid-scenehave no terminal/window/audio-device deps (compiler-enforced by crate boundary;just archholds their dep set to the allowlist indeny-arch.toml, so a new crate fails until it is listed). New render targets are thin painters overpixtuoid_scene::look::render.- Agent events flow through ONE channel
mpsc::Sender<(Transport, AgentEvent)>; theTransporttag drives hook-wins dedup — producers tag their own events. Daemon presence rides a separateAgentId-free channel (PresenceMsg { key: DaemonInstanceKey, delta }) and never entersReducer::apply. Sourcetrait is the only seam for a transcript-bearing CLI; per-source format knowledge lives in that source's decoder. Exceptions: hook-only CLIs (Reasonix) and the shared ACP wire standard (source/acp.rs, reused by grok) —CONTRIBUTING.mdstep 3 andsource/acp.rs's header.- Hook install writes through symlinks (
resolve_symlinkininstall/io.rs) — critical for stow-managed configs; Windows keeps the bounded rename-retry. - The hook shim never blocks CC — always exit 0 silently; the send bound (pixtuoid-hook's
transport::WRITE_TIMEOUT) is watchdog-enforced on both platforms. Shim coverage is child-process level only. - Walkable mask = ground footprint only; sprite size never moves a sim position — the sprite fit (
keep_sprite_inside) adjusts only a placement's paint top-left (#912).
Ownership by crate
Who owns what: core owns session lifecycle/identity (registration, dedup,
first-sight, liveness ladder, subagent parenting, feature boundaries) ·
scene owns look/motion (per-agent palette recolor, walk timing,
footprints, sky/light invariants, reachability) · binary owns
install/runtime wiring (config rewriting, desk growth, boot order, doctor,
daemon announce-only) · tui owns the flush (popup geometry, the
office's hit-test ladder) · panels owns what both painters' panels share
(their key dispatch and mouse ladder). Terminal cell aspect drives sprite design: the
half-block ▀ technique assumes ~1:2 cells, so sprites past ~16×16 px break on
taller-cell terminals; bundled base character sprites max at 8×12 px (their
@Nx variants are cutaway art the half-block painter never draws).
Things NOT to do
- No write to another CLI's config outside
install/io.rs(write_config_atomic/ConfigLock). - No
println!/eprintln!on production paths — a print macro panics when its reader leaves (| head), so CLI and headless output goes through aCliOut(a command's iscrate::cli_stdout()) and a stderr notice is alet _ = writeln!. Diagnostics aretracing, with a constant message and every value as a field (error = %e,path = ?path,pid): the constant message is a stable grep key and a field is filterable; a value baked into the format string is neither. Every path, session id and cwd rides a?field, never%, whatever its provenance, and so does an error chain that can embed one (SourceDeath.error,SocketBusy):str'sDebugescapes control and bidi chars, while under the defaultfmtlayer a Display field writes them raw andEscapeGuardcovers the message and error text only (test_capture'sdebug_fields_escape_control_and_bidi_chars). Core logs under whatever subscriber hosts it, so the rule is primary; the binary'sEscapedFields(app/logging.rs) escapes every value only as a backstop. Only a whole-message relay re-emitting an already-sanitized user-facing string (config::warn_user, theread_logwarning insources_cli) interpolates. - No doc generator or cap in place of a proposed diff: the owner reviews every doc change. A session pushes its own PR branches freely, never
main. - No stale
Closes #Non a re-scope (fires from commit body or PR text, even conditional). - No merging past the review gate (PR #23 merged unreviewed with a path traversal).
Where to look
- Tool call → sprite:
runtime/driver.rs::run_async→SourceManager::spawn→ source → decoder →reducer::Reducer::apply→ watch channel →TuiRenderer::render→pixtuoid_scene::floor::OfficeSession::render→pixtuoid_scene::look::render→tui::renderer::flush_classic, or the cutaway's tiles viatui::cutaway::TileCutaway. - Architecture + data flow:
docs/ARCHITECTURE.md. - Refactoring the channel type,
Sourcetrait,AgentEvent, or reducer signature touches all three test areas (tests/reducer/,tests/transport/socket.rs,tests/watcher/) +runtime/driver.rs; a newAgentEventvariant needs anagent_id()arm. - Adding an agent CLI:
CONTRIBUTING.md's checklist, which theadd-sourceskill drives.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

