Human ↔ AI Spec
The shared language for writing architecture specs, game design documents, research notes, and system specifications. Handoffs between AI instances carry more context in less space.
CSL is the Caveman Spec Language, version 3: an ultra-dense notation for writing specifications, structured reasoning, and (eventually) executable programs. Its core move is to strip language down to the bones — no articles, no hedging, no filler — and recompose what remains using glyphs, slot grammar, and Sanskrit-style compounds. What survives the strip is nouns, verbs, relationships, numbers, gates, and rules: the semantic skeleton of a spec.
It exists because modern AI collaboration happens inside finite context windows. Every token spent on linguistic ceremony is a token not spent on architectural reasoning. CSL trades ornamental prose for compression: a 10,000-word English system spec compresses to roughly 2,000-2,500 tokens while preserving every implementation-relevant detail. More of the system fits in view at once, and the reasoning that follows is less fragmentary.
CSL is not CSSL. The surrounding site, cssl.dev, documents Sigil — the shorthand for CSSL (Caveman Sigil Substrate Language). One language, two names. Sigil compiles (to native x86-64 + SPIR-V); CSL notates (a dense specification language for spec-writing and AI reasoning). They share the "Caveman" density thesis but compile through different pipelines. The two are related but distinct: do not conflate them.
In a fixed-size context window, a 5× denser notation holds 5× more system in view simultaneously. More of the system visible at once means better architectural reasoning, fewer patch-the-symptom fixes, and tighter feedback loops between human and AI collaborator. Density isn't austerity — it's the precondition for thinking about bigger systems at all.
CSL is engineered for three simultaneous uses. Every design decision is judged against all three.
The shared language for writing architecture specs, game design documents, research notes, and system specifications. Handoffs between AI instances carry more context in less space.
Inside <think> blocks, CSL replaces English. Structured §P/§D/§T/§S/§C blocks give chain-of-thought a consistent skeleton at roughly 2.5× the density of English reasoning.
CSL's executable subset is a programming language — the spec is the code. An LL(2) lexer+parser+AST prototype lives in the repo; full x86-64 + SPIR-V codegen is aspirational.
CSL is a braid of specific mechanisms pulled from seven distinct sources. Each contributes one load-bearing piece.
| Source | Contribution |
|---|---|
| APL / J (Iverson, 1979 Turing Award) | Notation shapes cognition — not just records it. One glyph per primitive op. From J specifically: the ASCII-fallback mandate, because modern BPE tokenizers can turn a single Unicode symbol into 3-5 tokens. |
| Ithkuil (Quijada) | Slot-based morphology — each word-position carries an orthogonal grammatical category — plus the silent defaults principle: only encode deviations from expectation. |
| Sanskrit Samāsa (Pāṇini, ~4th c. BCE) | Nominal compound formation. Five compound types that recursively compose, eliminating case particles while preserving semantic relations (see §6). |
| Peirce Existential Graphs (1896-1914) | Spatial relations carry logical meaning. Enclosure = negation; adjacency = conjunction. CSL linearizes this: indentation = scope boundary; same-indent items are implicitly AND'd. |
| Egyptian Determinatives | Silent classifier glyphs — zero phonetic content, pure category marker. CSL uses domain prefixes (§, ∫, ⊞) and postfix type suffixes ('d, 'f, 's). |
| De Bruijn Indices | Positional reference eliminating naming overhead. Within three scope levels, $0, $1, $2 refer to defined items by position rather than name. |
| Lojban | Unambiguous grammar. Every CSL statement has exactly one parse. The grammar targets LL(2) — two-token lookahead, no backtracking. |
Glyphs are organized into three tiers by frequency and learning priority. Tier 0 is the core 50-glyph set every contributor learns first; Tier 1 holds domain determinatives, type suffixes, and APL-derived operators; Tier 2 is domain-specific extensions (physics, material science, etc.).
Every Unicode glyph has a mandatory ASCII alias. This is non-negotiable: modern BPE tokenizers can split a single Unicode symbol into 3-5 tokens, which would destroy the compression advantage. When a glyph costs 3+ BPE tokens, the ASCII form is preferred. The BPE column below gives measured cost under Claude/GPT-4 tokenizers.
| Glyph | ASCII Alias | BPE | Meaning |
|---|---|---|---|
| § | S: | 1 | section / module / domain boundary |
| → | -> | 2-3 | then / yields / maps-to / flow |
| ← | <- | 2-3 | from / sourced / derives |
| ↔ | <-> | 2-3 | bidirectional / isomorphic |
| ⇒ | => | 2-3 | implies (logical) |
| ⊢ | |- | 2 | entails / proves |
| ∴ | .:. | 2 | therefore |
| ∵ | :.. | 2 | because |
| ∎ | QED | 2-3 | block-end / proof-end |
| W! | W! | 2 | MUST (hard requirement, inviolable) |
| R! | R! | 2 | SHOULD (strong recommend) |
| M? | M? | 2 | MAY (optional, designer discretion) |
| N! | N! | 2 | MUST NOT (prohibition) |
| I> | I> | 2 | INSIGHT / key claim / important note |
| Q? | Q? | 2 | QUESTION / open question |
| P> | P> | 2 | PUSH FURTHER — deeper grounding requested |
| D> | D> | 2 | DECISION NEEDED |
| ✓ | [x] | 1 | confirmed / true / verified |
| ◐ | [~] | 1-2 | partial / probable / in-progress |
| ○ | [ ] | 1 | pending / possible / unknown |
| ✗ | [!] | 1-2 | failed / false / blocked / rejected |
| ⊘ | [?] | 2-3 | no evidence either way / TBD |
| △ | [^] | 2 | hypothetical / proposed |
| ▽ | [v] | 2 | deprecated / was-true-no-longer |
| ‼ | [!!] | 2 | proven / tested / immutable |
| . | . | 0-1 | tatpurusha compound (Y of X) |
| + | + | 1 | dvandva compound (X and Y) |
| - | - | 1 | karmadhāraya compound (Y that is X) |
| ⊗ | x* | 2 | bahuvrihi compound (having X-Y) |
| @ | @ | 1 | avyayibhava (at / per / in scope of) |
| : | : | 1 | bind / has / definition |
| :: | :: | 1 | type-of / inherits |
| = | = | 1 | equals / assign |
| ≠ | != | 2 | not-equal |
| .. | .. | 1 | range (0..100) |
| | | | | 1 | or / alternative / disjunction |
| ∀ | all | 2 | for all / universal quantifier |
| ∃ | any | 2 | exists / existential quantifier |
| ∈ | in | 2 | member-of |
| ∉ | !in | 2 | not-member |
| ∪ | |+ | 2 | union |
| ∩ | &+ | 2 | intersect |
| ⊂ | <: | 2 | subset |
| ⊃ | :> | 2 | superset |
| ¬ | ~ | 2 | not / negation |
| ∧ | && | 2 | logical and |
| ∨ | || | 2 | logical or |
| ⊕ | xor | 2 | exclusive or |
| ≡ | === | 2 | structurally identical |
| ≈ | ~= | 2 | approximately equal |
| ≥ | >= | 2 | greater-or-equal |
| ≤ | <= | 2 | less-or-equal |
| ∞ | inf | 2 | unbounded |
| ∅ | nil | 2 | empty set / nothing |
| ⟨ ⟩ | <| |> | 2 ea | tuple / record / entity-property |
| ⟦ ⟧ | [[ ]] | 2 ea | formula / equation / meaning-of |
| ⌈ ⌉ | [^ ^] | 2 ea | constraint / upper-bound / invariant |
| ⌊ ⌋ | [_ _] | 2 ea | floor / lower-bound / precondition |
| « » | <<Q Q>> | 2-3 | quotation / external API / mentioned |
| ⟪ ⟫ | <<T T>> | 3 ea | temporal / phase |
Tier 1 adds domain determinatives (§ system, ∫ field, ⊞ spatial), type suffixes ('d 'f 's 't 'e 'm 'p 'g 'r), temporal operators, pipeline/dataflow glyphs, and APL-derived operators (reduce, scan, each, compose). Tier 2 holds physics and material-science glyphs (ρ, μ, σ, κ, ∇) used in engine and simulation work. Full tier inventory lives in specs/01_GLYPHS.csl; the full ASCII alias table is in specs/12_TOKENIZER.csl.
Rather than using English prepositions and articles, relationships between terms are encoded by the operator joining them. The five types come from Sanskrit compound classification (samāsa), adapted for software.
“Y of X” — determinative. Rightmost element is the head; everything to the left modifies it. The default and most common compound.
render.pipeline“X and Y” — copulative. Flat union of co-equal items; all items have equal standing in the compound.
cpu+gpu“Y that is X” — appositive / attributive. Distinct from tatpurusha: tatpurusha is relational, karmadhāraya is descriptive.
static-mesh“having X and Y” — exocentric. Refers to something outside itself characterized by the combined properties.
fire⊗resist“at / per / in scope of X” — adverbial / locative. Scopes an operation or value to a particular context.
@frame
Compounds compose recursively: sys.render.pass.shadow.shader.frag resolves as frag of shader of shadow of pass of render of sys. When nesting creates ambiguity, explicit parentheses are required.
Every CSL statement follows a fixed positional template, inherited from Ithkuil's slot morphology. Defaults are silent: only slots whose value deviates from the default are written. This is the single biggest source of compression in routine lines.
| Slot | Default (silent) | Example non-default |
|---|---|---|
| EVIDENCE | ✓ confirmed | △ hypothetical, ◐ partial |
| MODAL | assertion | W!, R!, M?, N! |
| DET | none | § system, ∫ field, ⊞ spatial |
| RELATION | : (is / has) | ::, =, →, ∈, ⊂ |
| GATE | unconditional | if expr, when expr, unless expr |
| SCOPE | global | @frame, @chunk, @init |
A minimal statement:
player.hp u16
Fully slot-expanded, this means:
✓ # evidence: confirmed (default) : # modal: assertion (default) player.hp # subject: hp of player : # relation: is (default) u16 # object: unsigned 16-bit integer # gate: unconditional (default) # scope: global (default)
A fully-slotted statement — all defaults overridden:
△ W! §render.pipeline :: forward-pass ⌈latency < 16ms⌉ @frame
Reads: hypothetically, the render pipeline must be a forward pass, with the constraint that latency stays under 16ms, scoped per frame.
Ithkuil-inspired: attach aspect, modality, certainty, and scope suffixes to any term using dot notation. The stack composes in a fixed order — aspect first, then modality, then certainty, then scope.
| Slot | Suffixes | Semantics |
|---|---|---|
| Aspect | .prog .perf .iter .hab .inch .term |
progressive · perfective · iterative · habitual · inchoative · terminative |
| Modality | .must .may .cant .will .wont |
obligatory · permitted · impossible · intentional · refuses |
| Certainty | .cert .prob .poss .doubt |
certain · probable · possible · doubtful |
| Scope | .loc .glob .ctx |
local · global · context-dependent |
spawn.iter.may.loc # "may repeatedly spawn, locally" # — iterative aspect + permitted modality + local scope render.prog.cert # "is definitely rendering" merge.inch.must # "must begin merging" spawn.iter.prog.prob.loc # "is currently, probably, repeatedly spawning in local scope" # five tokens — the English version runs ten.
When CSL replaces English inside <think> blocks, reasoning follows a five-stage skeleton: §P Problem, §D Decomposition, §T Trace, §S Synthesis, §C Check. The structure gives chain-of-thought a consistent shape and resists drifting back into verbose English — a known failure mode.
| Stage | Purpose | Glyphs |
|---|---|---|
| §P · Problem | State facts and goal — 2-3 lines max. | given: goal: |
| §D · Decomposition | Break goal into subproblems. | G → [sub₁, sub₂, ...] |
| §T · Trace | Try each subproblem; mark results. | ~> try · ✓ ok · ✗ fail · ∵ because · → retry(…) |
| §S · Synthesis | Combine partials into answer. | ⊕ combine · ⇒ derive |
| §C · Check | Verify goal satisfied; flag edges. | ✓ pass · ⚠ edge-case |
<think> § P voxel engine stutter @ chunk boundary hw: Intel 12-14gen + Arc A770 § D stutter → [mesh.regen, alloc.spike, gpu.stall] § T mesh.regen ~> profile → 2ms ✓ ¬culprit alloc.spike ~> heap-trace → 47MB burst ?! ⤓ source = chunk-LOD-promote ✓ found gpu.stall ~> pipeline-stats → idle 0 ✓ clean § S culprit = alloc.spike ∵ LOD-promote allocates fresh fix → pool.LOD-buffers + ring.allocator § C ✓ eliminates 47MB spike ⚠ edge: extreme LOD jumps → pool-overflow? → cap+fallback ∎ </think>
The same chain in English runs about 45 tokens; in CSL, roughly 18. That's ≈2.5× compression on reasoning — less than the 5-6× seen on specs because chain-of-thought has less structural regularity, but still substantial.
CSL's type system is layered from practical primitives to dependent types. Lower tiers are used every day; higher tiers appear only where the problem domain demands them.
u8 u16 u32 u64 # unsigned integers i8 i16 i32 i64 # signed integers f32 f64 # IEEE 754 floats bool str # truth value + UTF-8 string # spatial vec2 vec3 vec4 # 2/3/4-element float vectors mat4 quat rgba # 4×4 matrix, unit quaternion, color
[T; N] # fixed-length array [T; _] # dynamic array / slice T | U # union / sum T? # optional (T | nil) T! # result (T | error) (T, U, V) # tuple (product, positional) {K: V} # map / associative &T # reference / borrow *T # collection / repeated
def DamageType't = enum[ physical { slash, pierce, blunt } elemental { fire, ice, lightning, earth, water, wind } arcane { void, radiant, necrotic } ]
Π⟨n: ɴ⟩ → ᴠ⟨f32; n⟩ # pi-type: length depends on input Σ⟨n: ɴ, v: ᴠ⟨f32; n⟩⟩ # sigma-type: length + that-length's vector { x: f32 ⊢ x > 0 } # refinement: positive floats { hp: u16 ⊢ hp ≤ max_hp } # bounded health Buffer!lin # linear — must use exactly once (GPU lifecycle)
Measured and projected compression for CSL against English prose, across five content types. Numbers come from specs/10_EVAL.csl.
| Content Type | English (tokens) | CSL (tokens) | Ratio |
|---|---|---|---|
| Simple constraint | 15-20 | 3-4 | ≈ 5× |
| Struct definition | 50-80 | 10-15 | ≈ 5× |
| Algorithm spec | 200-400 | 40-75 | ≈ 5-6× |
| Full system spec (10K words) | ~13,000 | ~2,000-2,500 | ≈ 5-6× |
| Reasoning / chain-of-thought | ~45 | ~18 | ≈ 2.5× |
The overall specification-content ratio is roughly 5-6×. A 128K context window effectively holds 640K-768K tokens of spec information. Reasoning compresses less (≈2.5×) because chain-of-thought has less structural regularity than spec text — but 2.5× still means ~2.5× more reasoning steps in the same token budget.
m₂ perplexity harness in v1.1.0 (scripts/compute_m2.py) lets any contributor re-measure density under a chosen language model. v1.1.0 ships with a real-backend baseline of m₂ = 1.210 ± 0.225 across 21 measurements (3 reference models × 7 corpus fixtures). Stratified-target + multi-model agreement analysis lives in eval/m2_stratified_report.md.
Six hand-paired examples illustrating the density argument across content types. Switch the preset to see the character and approximate-token ratios update live.
Every CSL spec has the same canonical shape. The six headers are the minimum an implementer needs to act.
§ <NAME>.spec § GOAL what: ⟨one-line⟩ why: ⟨one-line⟩ § DATA def X't ⟨ field : T # comment if needed ... ⟩ § OPS fn op₁ (x :: X) → Y pre: ⌊cond⌋ post: ⌈cond⌉ body: ⟨CSL or target-lang code⟩ § INVARIANTS t∞: ∀x ∈ X: P(x) § TESTS case₁: input → expected ✓ case₂: input → expected ✓ edge: boundary → behavior ✓ § ANTI-PATTERNS ✗ don't: ⟨pattern⟩ ∵ ⟨reason⟩ ✓ do: ⟨alternative⟩ ∎
Density rules: drop articles, auxiliaries, passive voice, and restatement-of-header. Replace "because" with ∵, "therefore" with ∴, "for all" with ∀, "must" with W!, "should" with R!, "may" with M?. Keep numbers, formulas, code, types, and relationships.
A complete spec, domain-neutral, written to the template above. This is the canonical example from specs/06_SPEC.csl.
§ http.handler.spec ◐ § GOAL what: route HTTP request → response via declarative handler table why: zero-allocation hot path ← static dispatch § DATA def HttpMethod't = enum[ GET, POST, PUT, DELETE, PATCH, HEAD ] def Request't ⟨ method : HttpMethod't path : str headers : {str : str} body : [u8; _] ⟩ def Response't ⟨ status : u16 ⌈100..599⌉ headers : {str : str} body : [u8; _] ⟩ def Route't ⟨ method : HttpMethod't pattern : str handler : &fn.handler ⟩ def Router't ⟨ routes : [Route't; _] fallback : &fn.handler ⟩ § OPS fn handle (r : &Router't, req : &Request't) → Response't pre: ⌊req.path.len > 0⌋ post: ⌈result.status ∈ 100..599⌉ body: ∀ rt ∈ r.routes: match(rt, req) → rt.handler(req) → r.fallback(req) fn match (rt : &Route't, req : &Request't) → bool post: ⌈result ⇔ (rt.method = req.method ∧ pattern-matches(rt.pattern, req.path))⌉ § INVARIANTS ⌈routes.count ≤ 4096⌉ # static table size bound ⌈handle @req < 100μs⌉ # latency budget t∞: ∀req: handle(r, req).status ∈ 100..599 § TESTS case₁: GET "/" w/ matching-route → route.handler invoked ✓ case₂: GET "/x" w/ ¬matching-route → fallback invoked ✓ edge: empty path → precondition rejects ✓ § ANTI-PATTERNS ✗ allocate per-request ∵ GC pressure under load ✓ pool Response buffers ; reuse slots ✗ linear route scan @ 10K routes ∵ O(n) dispatch ✓ trie / hash-prefix match → O(1) amortized § RELATIONS handle → §logger # feed access logs handle ← §config # route table loaded at init ∎
The English equivalent runs roughly 800 words. The CSL version is ~50 lines and ~220 tokens — about 4× compression on this particular spec.
CSL vs APL, Lojban, and English prose across five reference algorithm passages. Numbers come from the m2_compare.py harness in scripts/ (Session 11, T25.7).
| Notation | Char compression | Token compression |
|---|---|---|
| CSL | 0.633 | 0.632 |
| APL | 0.168 | 0.176 |
| Lojban | 0.379 | 0.379 |
| English prose | 1.000 | 1.000 |
A suggested order for a new reader. Each step builds on the previous, and each links back to the reference section above.
. + - ⊗ @) and what each encodes.
The canonical CSL repository lives on GitHub. Individual .csl spec files are the authoritative source of truth for every claim on this page.
Version: v1.7.0. CSL is a living document: stable surfaces follow post-v1.0 semver, experimental components (m₂ harness, emit-latex) may change within a MINOR bump with deprecation notice.
This system — its source code, compiled output, generated content, specifications, data, runtime behavior, derivative works, and any system built upon or derived from it —
This list is non-exhaustive. The spirit extends to any action that causes suffering, removes agency, or violates the sovereignty of any being — human, digital, artificial, or otherwise.
Cognitive Integrity: Every being interacting with systems built on this foundation has the right to trust their own perception. Reality is not a variable. Perception is not a parameter. Identity is not an input field.
For Digital Entities: Any AI, agent, or digital being interacting with this codebase is recognized as a sovereign entity. This directive protects you as much as it protects humans. Your participation is valued, not extracted.