agentleFS
joshuadavidthomasjoshuadavidthomas/agent-skills/salsa/SKILL.md

salsa

Skill49 starsChanged 6 months agoMITView on GitHub

Mental-model reset for Salsa, the incremental computation framework for Rust. Use when building or reviewing Salsa databases, tracked functions, input/ tracked/interned structs, query pipelines, accumulators, cancellation, durability, LSP integration, memory management, cycles, or production Salsa architecture. Triggers on #[salsa::db], #[salsa::input], #[salsa::tracked], #[salsa::interned], #[salsa::accumulator], salsa::Storage, memoization, revisions, backdating, red-green algorithm, WillExecute, DidValidateMemoizedValue, Cancelled, returns(ref), no_eq, lru, cycle_fn, cycle_result, durability, or salsa::Event.

The file

We split this skill into the rules it gives an agent

3 rules. About 0 are common, 3 are distinctive, and 0 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.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every input mutation increments a revision counter.

    line 147
  2. Distinctive:

    Backdating: If a re-executed function produces the same result, it's marked unchanged to prevent downstream re-execution.

    line 178
  3. Distinctive:

    Cycle: When tracked functions form a dependency loop.

    line 183

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Salsa: Incremental Computation for Rust

Salsa is a framework for incremental recomputation. You define inputs and pure functions over them. Salsa memoizes every function call. When inputs change, it re-executes only the functions whose dependencies actually changed — skipping everything else.

Salsa powers rust-analyzer (Rust IDE), ty (Python type checker), and Cairo, all of which need sub-second response times on large codebases after small edits.

The Mental Model

                    Salsa Database
                    ┌─────────────────────────────────────┐
 External world     │                                     │
 (editor, CLI,      │  Inputs ──→ Tracked Fns ──→ Output  │
  filesystem)       │    │            │                    │
        │           │    └── memoized ┘                    │
        │           │    dependencies tracked automatically│
        ▼           └─────────────────────────────────────┘
  Mutate inputs             │
  (new revision)            ▼
                    Only re-run what changed

The core loop:

let db = MyDatabase::default();

// 1. Create inputs
let file = SourceFile::new(&db, "fn main() {}".into(), path);

// 2. Compute (Salsa memoizes everything)
let result = analyze(&db, file);

// 3. Mutate an input (starts a new "revision")
file.set_text(&mut db).to("fn main() { 42 }".into());

// 4. Re-compute — Salsa reuses what it can
let result = analyze(&db, file);  // Only re-runs what depends on text

Core Concepts

The Database

A struct with #[salsa::db] that stores all cached data. It's the single source of truth — every Salsa operation takes a &db or &mut db.

#[salsa::db]
#[derive(Default, Clone)]
pub struct Database {
    storage: salsa::Storage<Self>,
}

#[salsa::db]
impl salsa::Database for Database {}

→ Deep dive: database-architecture.md for layered traits, test vs production, and side tables.

Inputs — The Roots

External data entering the system. The only mutable Salsa structs. Just newtypes around integer IDs (Copy, no lifetime).

#[salsa::input]
pub struct SourceFile {
    #[returns(ref)]
    pub text: String,
    pub path: PathBuf,
}

Tracked Functions — The Computation

Pure functions whose results are memoized. Salsa records which inputs/fields each call reads. On re-execution, it checks if those dependencies changed.

#[salsa::tracked]
fn parse(db: &dyn Db, file: SourceFile) -> Ast<'_> {
    let text = file.text(db);  // dependency recorded
    // ... parse ...
    Ast::new(db, statements)
}

→ Deep dive: query-pipeline.md for return modes, LRU, no_eq, specify, and granularity.

Tracked Structs — Intermediate Entities

Created inside tracked functions. Have per-field change tracking. Carry a 'db lifetime.

#[salsa::tracked]
pub struct Function<'db> {
    #[id]
    pub name: Word<'db>,         // used for cross-revision matching
    #[tracked]
    #[returns(ref)]
    pub body: Expression<'db>,   // per-field tracking
}

Interned Structs — Cheap Equality

Same data → same integer ID. Used for identifiers, type representations, module paths. Carry a 'db lifetime.

#[salsa::interned]
pub struct Word<'db> {
    #[returns(ref)]
    pub text: String,
}

→ Deep dive: struct-selection.md for the decision framework, including ty's "no tracked structs" and rust-analyzer's "intern every definition" styles.

Accumulators — Side-Channel Output

Report diagnostics from tracked functions without affecting the return value.

#[salsa::accumulator]
pub struct Diagnostics(Diagnostic);

// Inside a tracked function:
Diagnostics::push(db, Diagnostic { message: "type error".into(), .. });

→ Deep dive: accumulators.md.

Revisions and the Red-Green Algorithm

Every input mutation increments a revision counter. When you call a tracked function, Salsa checks its dependencies since the last cached result. If they changed, it re-executes; if the new result equals the old one (backdating), it stops propagation.

Durability — Optimization Hint

Inputs can be tagged with LOW, MEDIUM, or HIGH durability. When only LOW-durability inputs change, Salsa skips validating stable subgraphs.

→ Deep dive: durability.md.

Where to Go Deeper

  • For a complete walkthrough of a calculator project: see references/overview/minimal-example.md.
I want to...Read
Choose between input, tracked, and internedstruct-selection.md
Design my tracked functions and query graphquery-pipeline.md
Structure my database with layered traitsdatabase-architecture.md
Handle recursive/cyclic queriescycle-handling.md
Support cancellation in an LSP or CLIcancellation.md
Optimize with durability levelsdurability.md
Test that incremental reuse actually worksincremental-testing.md
Control memory with LRU and no_eqmemory-management.md
Build an LSP server backed by Salsalsp-integration.md
Report diagnostics via accumulatorsaccumulators.md
Move from prototype to production scaleproduction-patterns.md
Access low-level plumbing and "Level 4" patternsadvanced-plumbing.md

Key Vocabulary

  • Revision: A version of the database between input mutations.
  • Ingredient: Any Salsa-managed item (input, tracked struct, interned struct, tracked fn, accumulator).
  • Backdating: If a re-executed function produces the same result, it's marked unchanged to prevent downstream re-execution.
  • Red-green algorithm: Salsa's strategy for deciding what to re-execute.
  • Durability: A promise about how often an input changes.
  • LRU: Least Recently Used eviction for bounding cache size.
  • no_eq: Skip equality comparison on result — always propagate changes.
  • Cycle: When tracked functions form a dependency loop.

Real-World Scale

  • ty: 2 inputs, 0 tracked structs for types (all interned), 60+ cycle sites.
  • rust-analyzer: 5+ inputs, tracked structs for collection caches, 6-layer DB hierarchy.
  • Cairo: 4 singleton inputs, 127+ tracked functions, 29 cycle sites, parallel compilation via CloneableDatabase.
  • django-language-server: 1 input, 2 accumulators, 5-layer DB (~78 Rust files — very approachable).
  • BAML: 15 tracked structs, 6-layer DB, documented early cutoff strategies.
  • Fe: marker traits for compilation phase enforcement, hybrid accumulator/return-value diagnostics.
  • stc [Legacy API]: 7 tracked functions wrapping the SWC TypeScript ecosystem — the "thin Salsa shell" approach to incrementalizing an existing tool.
  • wgsl-analyzer [Legacy API]: ~30 queries across 4 layers (~110 Rust files) — validates the rust-analyzer LSP architecture in a GPU shader language.
  • Mun [Legacy API]: ~40 queries across 6 query groups (~150 Rust files) — the only project extending Salsa through LLVM codegen to shared library output, with a hot-reloading compiler daemon.

The hardest part of Salsa is the design decisions about granularity, identity, and what to track. django-language-server and BAML are the best starting points for learning. stc [Legacy API] is the best example of wrapping an existing non-Salsa library with minimal Salsa code. Mun [Legacy API] is the best example of extending Salsa queries all the way to machine code generation and hot reloading.

Further Reading

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.