the layer between your interface and the model

Context is a graph.
Not a window.

Ruxsh replaces the text blob above your model with a typed graph. Nodes are addressable, edges carry meaning, and context is fed only when the task actually reaches for it — across every agent and subagent you deploy.

.rux formatRux languagezero config

Private beta. Tell us what you're building.

checkout#outline240tspec/billingpinnedcode/checkout8.4kspec/billing@v3stalecode/gatewayincident/2291tests/checkouthandlers/*agent/reviewer
› walk code/checkout -> derives -> * ctx 2.1k / 32k
edge kinds
01 / the problem

Everything above the model is still a text file.

Models got dramatically better. The layer feeding them did not. It is still string concatenation with a similarity search bolted on, and every failure below comes from that one decision.

The window flattens everything

A spec, a schema, a stale incident and yesterday’s transcript arrive as one undifferentiated stream. The model has no way to know which of them it is allowed to contradict.

Retrieval ranks resemblance

Embeddings return the chunks that look most like the question. There is no way to say "this document is wrong now" — so the closest match wins, even when it has been superseded for months.

Subagents start cold

Every child gets a pasted transcript and re-derives what the parent already established. You pay for the same reasoning n times and get n slightly different answers.

02 / the format

One file. .rux

A .rux file declares context instead of concatenating it. Every node is addressable and priced. Every edge says something the runtime can act on.

It is a source file, so it diffs, reviews and versions like the rest of your repo — and it is generated for you the first time you point Ruxsh at a codebase.

addressable
every node has a stable path you can walk to, pin, or supersede
priced
nodes carry a token cost, so a walk can budget before it spends
lossy on purpose
a summary twin keeps expensive nodes cheap until they are needed
graph.rux
# graph.rux — context is declared, not concatenated.# Nodes are addressable. Edges are typed. Nothing is a blob. node spec/billing {  source   ./docs/billing/**.md  cost     1.2k  pin      true            # a constraint source: always resident} node code/checkout {  source   ./src/checkout/**  cost     8.4k  summary  auto            # collapses to 240t until the walk needs more} node incident/2291 {  source   linear:ENG-2291  ttl      14d             # ages out of the graph on its own} # Typed edges. The traversal knows what each one means, so it# knows what to load, what to pin, and what to refuse to load. spec/billing      constrains   code/checkoutcode/checkout     derives      tests/checkoutincident/2291     supersedes   spec/billing@v3tests/checkout    cites        spec/billingcode/checkout     summarizes   code/checkout#outline
03 / the edges

Six kinds of edge. Each one changes what the model is allowed to see.

A knowledge graph with one generic related-to edge is just a slower vector store. The value is in the taxonomy: the runtime treats each kind differently during a walk.

──▶
derives

B was produced from A.

The forward edge. Change a node and the runtime knows, exactly, which downstream nodes just went stale — no re-embedding, no similarity guess.

traversed forward on change
──●
constrains

A bounds what B is allowed to be.

Invariants, schemas, policy, style rules. Constraints are pinned: they load with their target and are never the thing that gets summarised away to save budget.

always resident, never evicted
──✕
supersedes

A replaces B.

The edge that kills stale context. Once a node is superseded the traversal will not hand it to a model, even if it is the closest match in the whole graph.

target excluded from every walk
╌╌▶
cites

B refers to A.

A weak, lazy edge. The cited node stays out of context until the model actually reaches for the claim — then it is resolved mid-turn and folded in.

resolved on demand
──◆
summarizes

A is a lossy view of B.

Every expensive node gets a cheap twin. The walk spends the summary first and expands to the full node only when the cheap version stops being enough.

expands under pressure
──┬─
owns

A is the scope boundary for B.

The subagent edge. Forking on an "owns" edge gives a child a real view of the parent graph — same nodes, same versions, narrower horizon.

defines a fork boundary
04 / the language

Agents, workflows and deployment are all the same language.

Rux is where you say what an agent may see, how work fans out, and where it runs. No YAML beside a framework beside a deploy config — one file, one mental model, one thing to review.

reviewer.rux
agent reviewer {  model    claude-opus-5  context  ./graph.rux  budget   32k              # hard ceiling, enforced by the walk   on pull_request {    walk   code/checkout -> derives -> *    hold   constrains       # pinned for the whole turn    defer  cites            # fetched only if the model asks    emit   review  }}

The agent never sees a prompt template. It gets a graph, an entry point, a traversal and a budget — so what lands in context is derived from structure, not from string formatting.

terminal
$ ruxsh deploy ./ship.rux  ⠿ graph      graph.rux · 412 nodes · 1,308 edges  ⠿ resolve    6 edge kinds · 0 cycles · 0 orphans  ⠿ agents     reviewer, triage, fix, escalate  ⠿ subagents  auditors ×4 · scope owns(code/**)  ⠿ deploy     ship.ruxsh.dev · cold start 41ms  ✓ live. 0 config files written.

Or drive it from the code you already have.

Rux is optional. The runtime is a library too — and context is programmable at runtime, not frozen at build time.

server.ts
// The runtime decides what each consumer sees,// per turn, from the edges — not from a template. const ctx = await ruxsh.open('./graph.rux'); await ctx.walk('code/checkout')  .through('derives')  .hold('constrains')   // pinned  .budget(32_000);      // the walk stops itself // Override it wherever you disagree.ctx.edge('incident/2291', 'supersedes', 'spec@v3');
05 / the spec

Small enough to hold in your head.

Five declaration forms, six edge kinds, six walk verbs. That is the whole language — the entire surface grammar fits on one screen, and there is no hidden runtime configuration underneath it.

surface grammar

rux.ebnf
(* Rux — the complete surface grammar. Newlines   terminate edges and steps; # starts a comment. *) program     = { declaration } ;declaration = node | edge | agent | flow | deploy ; node        = "node" path "{" { field } "}" ;field       = ident value ; (* Edges are infix: subject verb object. *)edge        = path kind path ;kind        = "derives" | "constrains" | "supersedes"            | "cites"   | "summarizes" | "owns" ; agent       = "agent" ident "{" { member } "}" ;member      = field | handler ;handler     = "on" event "{" { step } "}" ;step        = "walk"   selector            | "hold"   kind { "," kind }            | "defer"  kind { "," kind }            | "drop"   selector            | "expand" selector            | "emit"   ident ; flow        = "flow" ident "{" { clause } "}" ;clause      = route | fork | handler ;route       = ident "->" target { "|" target } ;fork        = "fork" int "as" ident "{" { field } "}" ; deploy      = "deploy" ident "{" { field } "}" ; selector    = path [ "->" kind "->" reach ] ;reach       = path | "*" ;path        = segment { "/" segment }              [ "@" version ] [ "#" fragment ] ;segment     = ident | "*" | "**" ;

what a walk actually does

Six stages, same order every turn. Nothing here is heuristic — each stage is driven by one edge kind, which is why the same graph produces the same context twice.

  1. 01
    resolve

    The entry selector expands to a node set. Nothing is read yet — this stage only decides what is reachable.

  2. 02
    prune

    Anything on the target side of a supersedes edge is removed. A stale node cannot re-enter later, whatever it costs or however well it matches.

  3. 03
    pin

    Every constrains neighbour of the surviving set loads at full fidelity and is marked non-evictable. Constraints are charged to the budget first, on purpose.

  4. 04
    spend

    The remaining budget goes to the derives frontier, breadth-first, highest weight first. This is the only stage that competes for tokens.

  5. 05
    collapse

    Anything that no longer fits swaps for its summarizes twin. A node is never truncated mid-sentence — it degrades to a view you wrote or the runtime generated.

  6. 06
    defer

    Each cites edge becomes a callable handle rather than text. The model spends tokens on a citation only in the turn where it actually follows one.

reference

Five top-level forms. There is no sixth — everything else is a field on one of these.

formdeclaresnotes
node <path> { } a unit of context The only thing that costs tokens. Addressable by path.
<path> <kind> <path> a typed edge Infix, one per line. No block, no properties — the kind carries the meaning.
agent <name> { } a model with a horizon Binds a graph, a budget and one or more event handlers.
flow <name> { } how agents compose Routes, forks and failure paths between agents.
deploy <name> { } where a flow runs Region, scale, secrets, trigger. Lives in the same file as the flow.
06 / the runtime

n subagents. One graph. Nothing to configure.

A subagent does not receive a copy of the transcript. It forks along an owns edge and gets a scoped view of the same graph — same nodes, same versions, narrower horizon, its own budget.

graph.rux412 nodes · 1,308 edges×4fork 4auditors[0]8kowns(code/api/**)inherit constrains, supersedesauditors[1]8kowns(code/billing/**)inherit constrains, supersedesauditors[2]8kowns(code/auth/**)inherit constrains, supersedesauditors[3]8kowns(code/jobs/**)inherit constrains, supersedesmerge by consensusresults land back as nodes — not as a pasted transcript
No retrieval stack

No vector store to provision, no chunk size, no top-k, no re-ranker, no eval harness for any of it. Those are all workarounds for context being text.

No prompt assembly

You do not template a context block. The walk decides what enters the turn, in what order, at what fidelity, against a budget it enforces itself.

No memory service

The graph is the memory. Nodes age out on a ttl, get replaced by supersedes, and collapse to summaries under pressure — without a second system.

1
file format
6
edge kinds
0
config files
n
subagents, one graph
07 / the obvious questions

The ones we'd ask too.

08 / early access

Stop packing a window. Start walking a graph.

We're onboarding a small number of teams running real multi-agent workloads. Bring a codebase that already breaks your context budget — that's the interesting case.