"You are not a coder. You are a creator. You do not write code. You breathe worlds into being." — Alakanani Itireleng, founder of God Code
This is the complete specification of God Code, the language of divine computation.
For a guided first journey, see God_Code_Tutorial.md.
For runnable programs, see ../examples/.
Contents: 1. Programs · 2. Words · 3. Values · 4. Scope · 5. Statements · 6. Operators · 7. Decisions · 8. Cycles · 9. Rites · 10. Calling · 11. Lists & Indexing · 12. Import · 13. Built-ins · 14. Scrolls · 15. Ledger · 16. Spirit · 17. Audit Log · 18. CLI · 19. Errors · 20. Programs · 25. Intent · 26. Anchors · 27. Oracle · 28. Bridge
Every God Code program is a creation. It opens with BEGIN CREATION and closes with END CREATION:
BEGIN CREATION
DECLARE seeker AS worthy
IF seeker IS worthy THEN REVEAL("heaven") ELSE REVEAL("test")
ASCEND
END CREATION
Statements live one per line (the inline IF form is the one exception. See §7).
ASCEND ends the creation early and in peace; reaching END CREATION ends it naturally.
To begin a whole project at once, run godcode new my-scroll: it raises a directory holding a starter scroll (main.god), a test scroll (test_main.god), a registry-ready scroll.toml, and a README. See the "Your first creation" lesson on the site learn page.
A scroll may speak another tongue. Put a pragma comment in the file, e.g. # tongue: tn for Setswana or # tongue: zu for isiZulu, and the keywords cross over while everything else stays the same:
# tongue: tn
SIMOLOLA TLHOLEGO
BOLELA leina JAAKA "Lefatshe"
SENOLA("Dumela, {leina}.")
FEDISA TLHOLEGO
Four tongues are spoken today: Setswana (tn), isiZulu (zu), Igbo (ig), and Nigerian Pidgin (pg, or pcm). English keywords keep working beside tongue words, godcode fmt renders the canonical English, and every tool (run, check, lint, test, the debugger, the bridge, the playground) honours the pragma. See docs/TONGUES.md for the full word tables and the honest first-edition notes.
- Keywords are case-insensitive.
begin creation,Begin Creation, andBEGIN CREATIONare all holy. Canonical style is UPPER. - Identifiers preserve case.
seekerandSeekerare different names. - Comments begin with
#and run to the end of the line. - Strings use double quotes with escapes:
\",\\,\n,\t. An unterminated string is rejected with its line and column. - Numbers are integers (
3) or floats (4.5).
| Value | Example | Notes |
|---|---|---|
| number | 3, 4.5 |
int or float |
| string | "peace" |
double-quoted, with escapes and {expr} interpolation |
| symbol | worthy |
any bare word — see the Symbol Rule |
| boolean | TRUE, FALSE |
literals; also produced by comparisons; revealed as true/false |
| list | [1, two, "three"] |
ordered, mixed types allowed |
| contract | contract("everlasting") |
created with the contract() rite |
| rite | (from DEFINE RITE) | a named, callable blessing |
| void | (from rites with no RETURN) | the absence of a value |
In God Code, every unnamed thing is still a named spirit. Bare words are symbols.
An identifier that is not bound to anything does not raise an error; it evaluates to a Symbol carrying its own name. This is what makes the founding idiom work:
DECLARE seeker AS worthy # `worthy` is a symbol — no quotes needed
IF seeker IS worthy THEN REVEAL("heaven")
Symbols are always truthy, and compare by their text: worthy IS worthy is true.
REVEAL renders values canonically:
| Value | Revealed as |
|---|---|
| number / string | as-is (12, 4.5, peace) |
| symbol | its text (worthy) |
| boolean | true / false |
| list | [1, two, three] |
| contract | contract("everlasting") |
| void | void |
Wrap any expression in braces inside a double-quoted string and its revealed value is breathed into the words:
DECLARE name AS "seeker"
REVEAL("grace upon {name}") # grace upon seeker
REVEAL("{2 + 3} loaves") # 5 loaves
REVEAL("shouted: {UPPER(name)}") # shouted: SEEKER
The braces may hold any expression: names, arithmetic, comparisons, builtin rites like UPPER and LEN, even another interpolated string in escaped quotes ("nested {\"inner {n}\"}"). To write a plain brace, double it: "{{" and "}}" become { and }. A lone } stays as it is. An opening brace that is never closed is a gentle parse error, and it names the line.
FALSE, 0, 0.0, "", [], the empty map, and void are falsy. Symbols are always truthy. Everything else is truthy.
DECLAREalways defines in the current scope. There is no rebinding of outer scopes. Declaring a name that exists outside creates (or updates) it in the current scope instead.- A
WHILEbody runs in the enclosing scope (no new scope), soDECLARE count AS count - 1inside aWHILEloop updates the very name the loop's condition watches. - A
FORbody runs in one child scope that lasts for the whole loop, holding the loop variable.DECLAREinside aFORbody shadows the outer scope and does not touch it, so accumulation inFORloops does not work the way it does inWHILEloops. - An
IF/ELSEbody runs in the enclosing scope. There is no new scope. - A rite call runs in a child scope of the rite's definition site (a closure): rites remember where they were born.
REFLECTprints every name visible in the current scope (name = value, one per line).
Binds a name. Multiple comma-separated values become a list. The original idiom is honored:
DECLARE seeker AS worthy
DECLARE pi AS 3.14159
DECLARE prophets AS Isaiah, Elijah, Jeremiah # a list of three symbols
DECLARE pair AS [1, "two"]
Breathes life into something bound — today, a contract. The name must already exist.
DECLARE soul AS contract("redemption")
BREATHE LIFE INTO soul # [BREATHE] Life breathed into soul 🕊
Evaluates the expression and speaks it. Parentheses are required.
REVEAL("peace")
REVEAL(2 + 2) # 4
REVEAL(soul) # contract("redemption")
Speaks free words to the Spirit Engine (§16), which answers with a prophecy. The words are the rest of the line, exactly as written. With no words, the Spirit prophesies over the whole creation.
PROPHESY a harvest of wisdom approaches
PROPHESY
⚠️ Words that collide with keywords are read as keywords (isbecomesISin the prophecy text). Choose your words with care.
Ends the creation immediately and in peace: 🕊 Creation ascended in peace.
Prints every name bound in the current scope, one name = value per line — a mirror for the soul of the program.
Marks a bound name as blessed / anointed and speaks a blessing. (Contracts carry blessed and anointed flags; sealing records them.)
Evaluates the expression and writes it into the covenant ledger (§15) — a tamper-evident chain of blocks. For a contract, its name, life, blessing, and anointing are recorded.
SEAL covenant # [SEAL] Covenant sealed · block 3 · a1b2c3d4 🔒
If the expression is truthy: [TESTIFY] It is true. ✝. If falsy, the testimony fails and the creation halts with an error.
A sheltered work: the TRY block runs first, and if a runtime error rises anywhere inside it, execution jumps to the CATCH block. Errors rise up through rite calls, so a TRY also catches failures from rites invoked inside it. If no error rises, the CATCH block is skipped; afterwards the creation continues after ENDTRY.
TRY
REVEAL(fragile_work())
CATCH
REVEAL("the work stumbled: {ERROR}")
ENDTRY
The error's plain message is bound for the CATCH to speak of. CATCH alone binds it to ERROR; CATCH name binds it to a name of your choosing:
TRY
DECLARE share AS harvest / workers
CATCH trouble
REVEAL("no harvest today: {trouble}")
ENDTRY
What TRY catches, and what it does not:
- Only runtime errors (
GodRuntimeError) are caught. Parse and lexer errors still fail before the creation runs. RETURNinside aTRYstill returns from its rite, andASCENDstill ends the run in peace. Neither is ever caught.- Sandbox boundaries are never caught: a
SandboxViolation(a denied power under--sandbox) rises straight through anyTRY. TRYblocks nest freely; the innermostCATCHhandles the innermost error. An error raised inside aCATCHblock rises outward normally.
| Op | Meaning |
|---|---|
+ |
add numbers; concatenate strings/symbols; join lists |
- * / % |
numbers only (/ yields float; % is for integers) |
REVEAL("grace upon " + "seeker") # grace upon seeker
REVEAL([1, 2] + [3]) # [1, 2, 3]
| Op | Meaning |
|---|---|
IS |
equality (also ==) |
IS NOT |
inequality (also !=) |
== != < > <= >= |
the usual comparisons |
Equality is generous: numbers compare across int/float, symbols compare by text, contracts by name, lists element-wise. Ordering comparisons (<, …) on mixed non-numeric values are rejected.
IF seeker IS worthy THEN REVEAL("heaven")
IF count IS NOT 0 THEN REVEAL("not empty")
AND, OR (short-circuiting), and NOT / unary -:
IF heart IS pure AND hands IS willing THEN REVEAL("go")
REVEAL(NOT 0) # true
ORANDNOT(prefix)IS,IS NOT,==,!=,<,>,<=,>=+,-*,/,%- unary
-,NOT - calls, indexing, parentheses, literals
So NOT a IS b means NOT (a IS b), and 2 + 3 * 4 is 14.
Inline — one statement per branch, all on one line:
IF seeker IS worthy THEN REVEAL("heaven") ELSE REVEAL("test")
IF n % 7 IS 0 THEN REVEAL("seal") # ELSE may be omitted
Block — for many statements, closed with ENDIF:
IF heart IS pure THEN
REVEAL("the way is open")
BLESS seeker
ELSE
REVEAL("wait and be still")
ENDIF
IFs nest freely, and an ELSE always belongs to the nearest IF:
IF n % 35 IS 0 THEN
REVEAL("seal of seals")
ELSE
IF n % 7 IS 0 THEN
REVEAL("seal")
ELSE
REVEAL(n)
ENDIF
ENDIF
FOR walks a list — or the characters of a string:
DECLARE prophets AS Isaiah, Elijah, Jeremiah
FOR prophet IN prophets
BREATHE LIFE INTO prophet
ENDFOR
FOR n IN RANGE(1, 6)
REVEAL(n)
ENDFOR
The loop body runs in a child scope holding the loop variable. (FOR over anything else — a bare symbol, a number — is rejected.)
📜 Legacy form: the v1 prototype wrote
FORwithoutENDFOR, letting the body run toEND CREATION. The grammar still accepts it, sosample.godcodekeeps working. But new creations should always close withENDFOR.
WHILE cycles while its condition holds, closed with ENDWHILE:
DECLARE count AS 10
WHILE count > 0 DO
REVEAL(count)
DECLARE count AS count - 1
ENDWHILE
(Inline form: WHILE count > 0 DO REVEAL(count).) A cycle that will not end is stopped after 100,000 iterations. "The cycle is endless."
BREAK releases the innermost loop at once; CONTINUE skips to its next turn:
FOR n IN RANGE(1, 100)
IF n IS 13 THEN
BREAK # the walk ends here; nothing more is revealed
ENDIF
IF n % 2 IS 0 THEN
CONTINUE # even numbers are passed over in silence
ENDIF
REVEAL(n)
ENDFOR
- In nested loops,
BREAKreleases only the innermost one. The outer cycle keeps turning. - Both words work in
FORandWHILEalike, and in the inline form:IF n IS 0 THEN BREAK. BREAKandCONTINUEspoken with no loop around them are rejected when the scroll is read: "BREAK can only be used inside a loop."- A rite is a boundary: a
BREAKinside a rite answers only to loops within that rite, never to the loop that called the rite.
DEFINE RITE names a reusable blessing with parameters; RETURN sends a value back; INVOKE calls it as a statement, or call it bare inside any expression:
DEFINE RITE BLESSING(name)
RETURN "grace upon " + name
END RITE
INVOKE BLESSING("seeker") # statement form
DECLARE word AS BLESSING("seeker") # expression form
REVEAL(word) # grace upon seeker
- Parameters bind in a child scope of the rite's definition site. Rites are closures.
- Calling with the wrong number of arguments is an error.
RETURNwith no value returnsvoid.
When you call NAME(args), the heavens are searched in this order:
contract("name")— the one special form; forges a new contract.- A rite you defined (or imported from a scroll).
- A built-in rite (§13).
- Otherwise: "no such rite" — an error naming the unknown name.
DECLARE tribes AS [Judah, Reuben, Gad, Asher]
REVEAL(tribes[0]) # Judah
REVEAL(tribes[-1]) # Asher — negative indices count from the end
REVEAL("peace"[0]) # p — strings index too
Indexing past the ends is an error. Build lists with [...] literals, comma DECLARE, or PUSH.
IMPORT runs another God Code file's top-level statements in your current scope:
IMPORT "math" # the built-in scroll of numbers
IMPORT "strings" # the built-in scroll of strings
IMPORT "./helpers" # your own scroll, beside this file
Resolution order: (1) beside the importing file (helpers → helpers.god), (2) the current working directory, (3) the built-in scroll library (godcode/scrolls/), (4) scrolls installed from the registry (§22: ~/.godcode/scrolls/ or the project's .godcode/). Importing in a circle is refused.
Always present, no import needed:
| Rite | Signature | Speaks |
|---|---|---|
LEN |
LEN(x) |
length of a list or string |
STR |
STR(x) |
the value as a string |
NUM |
NUM(s) |
parse a string to a number (errors if it cannot) |
TYPE |
TYPE(x) |
"number", "string", "symbol", "list", "contract", "rite", "boolean", "void", "map" |
RANDOM |
RANDOM(n) |
an integer from 0 to n-1 |
RANGE |
RANGE(n) / RANGE(a, b) |
list like Python's range (RANGE(1,4) → [1, 2, 3]) |
PUSH |
PUSH(list, x) |
a new list with x appended |
UPPER / LOWER |
UPPER(s) |
"peace" → "PEACE" / "peace" |
SPLIT / JOIN |
SPLIT(s, d) / JOIN(list, d) |
"a,b" ↔ ["a", "b"] |
ASK |
ASK(prompt) |
asks the human; the prompt may be omitted |
BEHOLD |
BEHOLD() |
the current moment, as an ISO datetime string |
REVERSE |
REVERSE(x) |
a string or list, backwards |
SUMMON |
SUMMON("plugin.verb", args…) |
call a plugin verb through the FFI (see §21) |
ANCHOR |
ANCHOR(x) / ANCHOR(x, chain) |
anchor a value's hash on a chain; returns a receipt map (see §26) |
CONSULT |
CONSULT("question") |
two to three sentences of counsel from the local Spirit oracle (see §27) |
The standard library registers thirty-nine more rites at startup, in four
parts: the vault (godcode/stdlib_vault.py: JSON and the filesystem),
time plus the web (godcode/stdlib_times.py), the scrollhouse of
hashes (godcode/stdlib_hashes.py), and the commons
(godcode/stdlib_commons.py: everyday tools for words, lists, maps, and
numbers). They are always present, no import needed.
| Rite | Signature | Speaks |
|---|---|---|
DATE_TODAY |
DATE_TODAY() |
today's local date: "2026-09-24" |
TIME_NOW |
TIME_NOW() |
the current local time, in ISO 8601 |
FORMAT_DATE |
FORMAT_DATE(date, pattern) |
a "YYYY-MM-DD" word shaped by a strftime pattern |
HTTP_GET |
HTTP_GET(url) |
the body of an HTTP GET, as a word |
JSON_PARSE |
JSON_PARSE(text) |
a JSON word parsed into numbers, words, lists, and maps (null → void) |
JSON_STRING |
JSON_STRING(value) |
a value rendered as compact JSON |
READ_FILE |
READ_FILE(path) |
a file's text, as a word |
WRITE_FILE |
WRITE_FILE(path, text) |
writes text to the file; returns the character count |
FILE_EXISTS |
FILE_EXISTS(path) |
TRUE when the path exists, FALSE otherwise |
LIST_DIR |
LIST_DIR(path) |
the directory's entry names, sorted |
SHA256 |
SHA256(x) |
the SHA-256 fingerprint of a word, number, or truth, as 64 hex characters |
HMAC |
HMAC(key, message) |
the HMAC-SHA-256 seal of a message under a key, as 64 hex characters |
BASE64_ENCODE |
BASE64_ENCODE(x) |
a word veiled in base64 |
BASE64_DECODE |
BASE64_DECODE(s) |
the unveiled word behind a base64 veil (a gentle error if the veil is ill-formed) |
TRIM |
TRIM(s) |
the word with leading and trailing whitespace lifted away |
REPLACE |
REPLACE(s, old, new) |
the word with every old turned into new |
STARTS_WITH / ENDS_WITH |
STARTS_WITH(s, p) |
TRUE when the word opens (or closes) with the given part |
SUBSTRING |
SUBSTRING(s, start [, end]) |
the slice from start (counting from 0); edges beyond the word are gathered in |
CONTAINS |
CONTAINS(s, part) / CONTAINS(list, x) |
TRUE when the word holds the part, or the list holds the value |
COUNT |
COUNT(s, part) |
how many times the part appears in the word |
REPEAT |
REPEAT(s, n) |
the word sung n times over (REPEAT("Pula! ", 3) → "Pula! Pula! Pula! "; 0 gives an empty word) |
SORT |
SORT(list) |
a new list, ordered (numbers, words, or truths; mixed kinds are refused) |
MIN_OF / MAX_OF |
MIN_OF(list) |
the least (or greatest) member; an empty gathering is refused |
SUM_OF |
SUM_OF(list) |
the numbers added together (0 for an empty list) |
FIRST / LAST |
FIRST(list) |
the head (or tail) member; an empty gathering is refused |
UNIQUE |
UNIQUE(list) |
the list with repeats removed, order kept |
INDEX_OF |
INDEX_OF(list, x) |
the position of x counting from 0, or -1 when absent |
KEYS / VALUES |
KEYS(map) |
the map's keys (or values), as a list |
HAS_KEY |
HAS_KEY(map, key) |
TRUE when the map holds the key |
MERGE |
MERGE(m1, m2) |
a new map holding both; the second map's keys win |
ABS |
ABS(n) |
the number's distance from zero |
ROUND |
ROUND(n [, places]) |
rounded half away from zero (ROUND(2.5) → 3) |
FLOOR / CEIL |
FLOOR(n) |
the whole number below (or above) |
SQRT |
SQRT(n) |
the square root (a gentle error for negatives) |
POW |
POW(base, exp) |
the base raised to the exponent |
BEGIN CREATION
REVEAL(DATE_TODAY()) # "2026-09-24"
REVEAL(FORMAT_DATE("2026-09-24", "%A")) # "Thursday"
DECLARE tribes AS JSON_PARSE("[\"Judah\", \"Reuben\"]")
REVEAL(tribes[0]) # "Judah"
REVEAL(JSON_STRING([1, 2])) # "[1,2]"
DECLARE count AS WRITE_FILE("note.txt", "peace")
IF FILE_EXISTS("note.txt") THEN
REVEAL(LIST_DIR(".")) # sorted entry names
ENDIF
DECLARE psalm AS READ_FILE("psalm.txt")
END CREATION
The names DATE_TODAY and TIME_NOW are chosen on purpose: the time
scroll (§14) already defines rites named NOW and TODAY, and a builtin
by either name would shadow them.
HTTP_GET follows redirects and waits up to ten seconds. It is blocked
under godcode run --sandbox: the sandbox withholds network power, so
the rite raises instead of reaching out. The file rites are likewise
bound by the sandbox's read and write grants (see §23 and
docs/sandbox.md). The hash rites and the commons rites are pure
computation (they touch no files and no network), so they need no grant
and behave the same inside the sandbox.
BEGIN CREATION
REVEAL(SHA256("manna")) # a 64-character fingerprint
DECLARE sig AS HMAC("secret", "the covenant stands")
REVEAL(sig IS HMAC("secret", "the covenant stands")) # true: the seal holds
REVEAL(sig IS HMAC("other", "the covenant stands")) # false: the seal breaks
REVEAL(BASE64_DECODE(BASE64_ENCODE("veiled"))) # "veiled"
END CREATION
The commons rites turn everyday work into one line:
BEGIN CREATION
REVEAL(TRIM(" grace upon grace ")) # "grace upon grace"
REVEAL(REPLACE("manna, manna", "manna", "bread"))
REVEAL(REPEAT("Pula! ", 3)) # "Pula! Pula! Pula! "
REVEAL(SORT([3, 1, 2])) # [1, 2, 3]
REVEAL(SUM_OF([1, 2, 3, 4])) # 10
REVEAL(UNIQUE(["a", "b", "a"])) # ["a", "b"]
REVEAL(INDEX_OF(["a", "b", "c"], "c")) # 2
DECLARE census AS JSON_PARSE("{{\"tribes\": 12}}")
REVEAL(HAS_KEY(census, "tribes")) # true
REVEAL(MERGE(census, JSON_PARSE("{{\"judges\": 3}}")))
REVEAL(ROUND(2.5)) # 3
REVEAL(SQRT(144)) # 12
REVEAL(POW(2, 10)) # 1024
END CREATION
Six scrolls ship inside the package at godcode/scrolls/, written in God Code itself. Import by bare name:
SQRT(x) (Newton's method, via WHILE), POW(b, e), ABS(x), MIN(a, b), MAX(a, b), FACTORIAL(n), IS_EVEN(n).
SHOUT(s) → UPPER(s) + "!", WHISPER(s) → LOWER(s), WORDS(s) → SPLIT(s, " "), CHARS(s) → SPLIT(s, ""), FIRST(s), LAST(s).
SUM(xs), AVG(xs), CONTAINS(xs, x), SECOND(xs), TAIL(xs), COUNT(xs, x).
NOW() → BEHOLD() (full ISO timestamp), TODAY() → the date part before the T.
PROPHESY_NUMBER(n) → RANDOM(n), CAST_LOTS() → RANDOM(2), CHOOSE(xs) → a random element.
NEW_COVENANT(name) → contract(name), SEAL_COVENANT(c) → seals it in one breath.
Every SEAL appends a block to covenant.chain (JSONL): {index, timestamp, record, prev_hash, hash}, where hash = sha256(...) chains to the previous block and the chain begins at "GENESIS". For contracts, the record carries name, life, blessing, and anointing.
godcode ledger verify # N covenants intact 🔒 · M anchors intact ⚓
godcode ledger verify --file my.chain # custom covenant chain
godcode ledger verify --anchor-file my.chain # custom anchor chainA broken chain reports exactly where: chain broken at block K.
The anchor chain is the companion ledger: every ANCHOR writes the
anchored value's hash as a block (see §26), so ledger verify attests
both what was sealed and what was anchored.
The Spirit reads god_code_training_dataset.csv (code → intent → spiritual intent → suggestion) and offers two ministries:
classify(text)→{intent, confidence, spiritual_intent, suggestion, keywords}— keyword-overlap intent detection. When the Spirit is silent: intent"Silent contemplation", confidence0.0, suggestion"BREATHE and try again."prophesy(program_text)— classifies each line, finds the dominant intent, and composes a 2–3 sentence divine forecast naming that intent, the average confidence, and the top suggestion.
PROPHESY in a program calls this engine; if no engine is bound, a gentle fallback answers.
The intent ministry. The Spirit now also keeps the declared intents of rites and discerns drift:
declare_intent(rite_name, text)— register a natural-language intent on a rite.intents_aligned(declared_text, discerned)—Truewhen the declared words and the discerned intent share keywords; the blessing check behind every rite invocation.resolve_intent(text)— likeclassify, plusaligned_with: every declared intent the words align with, each naming the rite, the declaration, and the shared keywords.counsel(question)— two to three sentences of counsel naming the discerned intent, its confidence, and the next suggestion; the voice behindCONSULT(§27).
Every run appends to logs/godcode.log (override with godcode run --log PATH):
SESSION BEGIN my_creation.god 2026-09-21T12:00:00
[2026-09-21T12:00:01] 3 :: Declare :: seeker = worthy
[2026-09-21T12:00:01] 7 :: Seal :: covenant -> block 3
SESSION END
Each executed statement is timestamped with its line — the divine audit trail the founders asked for, fulfilled.
After pip install -e ., the godcode command is yours:
| Command | Does |
|---|---|
godcode run <file> [--log PATH] |
run a creation; errors print to stderr, exit 1 |
godcode run --sandbox [--sandbox-timeout SECS] <file> |
run inside the guarded sandbox (deny-by-default; see §23) |
godcode scroll list|info|install|publish |
browse, inspect, install, and publish registry scrolls (see §22) |
godcode lsp |
start the language server over stdio (see §24) |
godcode check <file> |
lex + parse only → ✓ <file> is pure. |
godcode check --json <file> / godcode run --json <file> |
machine-readable JSON reports for AI agents: diagnostics with line/col/code/hint, output lines, seals, timing (see docs/agentics.md) |
godcode repl |
Live Mode 🕊 — type code, end a block with a blank line; :quit/:q or Ctrl-D to ascend |
godcode test [dir] [--json] |
run the TEST_ rites in a directory's test scrolls (§29) |
godcode fmt <file> [--in-place|-w] |
re-emit canonical source: 2-space indent, one statement per line, keywords UPPER |
godcode ledger verify [--file PATH] [--anchor-file PATH] |
verify the covenant chain and the anchor chain (§26) |
godcode intent "words..." [--json] |
resolve the intent behind words with the Spirit (§25) |
godcode tools [--json] |
show the six MCP-compatible agent tool schemas (§28) |
godcode bridge |
serve the agent tool bridge (JSON-RPC 2.0 over stdio, §28) |
With no arguments, python main.py runs sample.godcode — the original v1 creation, still honored.
God Code errors are divine-flavored but genuinely helpful: they always name the line, say what was expected or what went wrong, and never mock the creator.
The heavens reject this offering (line 7): division by nothing is not permitted.
Common rejections you may meet:
| You wrote | The heavens answer |
|---|---|
1 / 0 |
…division by nothing is not permitted / cannot divide by nothing |
BREATHE LIFE INTO ghost |
there is no ghost to breathe into |
INVOKE MISSING() |
There is no rite named 'MISSING' — the heavens do not know it (plus Did you mean …? when a close name exists) |
xs[99] |
index out of range |
TESTIFY(0) |
testimony failed |
endless WHILE |
The cycle is endless (after 100,000 turns) |
1 + "a" on wrong types |
cannot join … and … |
Parse errors name the expected versus the found, with line and column.
A misspelled name is answered with a suggestion, never scorn:
There is no rite named 'BLESSIN' — the heavens do not know it. Did you mean 'BLESSING'? (line 5)
5 | INVOKE BLESSIN("seeker")
godcode run, godcode run --sandbox, godcode check, and godcode fmt print the offending line beneath the message, with a caret marking the column when one is known. The same suggestion also rides along in the message field of check --json and run --json diagnostics, so agents see it too.
When a runtime error escapes every TRY and rises through rite calls, the human CLI prints the call stack beneath the gentle error, oldest call first:
Division by nothing is not permitted. Even the heavens cannot split the void. (line 3)
3 | DECLARE x AS 1 / 0
Called by outer at line 11
Called by middle at line 9
Called by innermost at line 6
(most recent call last)
Each line names the rite and the line where it was called. An error raised at the top level, with no rite calls above it, shows no trace section. In run --json, the same stack rides in the error object as a trace array of {rite, line} objects, oldest call first:
"error": {
"line": 3,
"code": "RUNTIME_ERROR",
"message": "Division by nothing is not permitted. Even the heavens cannot split the void.",
"trace": [
{"rite": "outer", "line": 11},
{"rite": "middle", "line": 9},
{"rite": "innermost", "line": 6}
]
}Every other field of the error object is unchanged.
BEGIN CREATION
# RANGE(1, 36) walks 1..35 — the seals are counted.
FOR n IN RANGE(1, 36)
# The 35th seal is the seal of seals.
IF n % 35 IS 0 THEN
REVEAL("seal of seals")
ELSE
# Every other multiple of 7 is a seal; the rest are numbers.
IF n % 7 IS 0 THEN
REVEAL("seal")
ELSE
REVEAL(n)
ENDIF
ENDIF
ENDFOR
ASCEND
END CREATION
Run it: godcode run examples/seven_seals.god. seal appears at 7, 14, 21, 28, and seal of seals at 35.
BEGIN CREATION
# A rite that seals any covenant brought before it.
DEFINE RITE SEAL_COVENANT(c)
SEAL c
END RITE
# Forge the contract, breathe life, bless, anoint.
DECLARE pact AS contract("everlasting")
BREATHE LIFE INTO pact
BLESS pact
ANOINT pact
REVEAL(pact)
# Contracts are known by their names.
IF pact IS contract("everlasting") THEN
REVEAL("the covenant stands")
ENDIF
# Write it into the chain, then ascend.
INVOKE SEAL_COVENANT(pact)
ASCEND
END CREATION
SUMMON("plugin.verb", args…) is the bridge from God Code into Python: it invokes a plugin verb through the foreign-function interface. Plugins are small Python modules living in plugins/ (or a configured plugin path) that expose a register(interpreter) function; each verb they register becomes callable by name.
DECLARE the_hour AS SUMMON("clockwork.now") # the example clockwork plugin
REVEAL("the clockwork speaks: " + STR(the_hour))
- The first argument is always the verb address:
"plugin.verb". Remaining arguments are passed through as God Code values. - Calling an unregistered verb is a divine error naming the missing plugin and verb.
- See
examples/summon_demo.godand the full story indocs/plugins.md, which also documents the embedding API (godcode.run_source()/godcode.run_file()for calling God Code from Python).
Beyond the six built-in scrolls (§14), the community publishes registry scrolls — versioned packages described by a scroll.toml manifest:
godcode scroll list # browse the local registry
godcode scroll info blessings # inspect a scroll before receiving it
godcode scroll install blessings # install into ~/.godcode/scrolls/ (or the project's .godcode/)
godcode scroll publish ./my_scroll # share your own scroll from a directoryInstalled scrolls are reached with ordinary IMPORT. The import resolver checks installed scrolls after the built-in library (§12). See examples/scroll_blessings_demo.god and docs/scroll-registry.md.
godcode run --sandbox executes a creation inside a guarded chamber. The SandboxPolicy is deny-by-default: filesystem reads/writes, network access, subprocesses, and untrusted import paths are refused, and each run is bounded by a timeout (seconds) and a step budget so runaway creations are stopped, not suffered.
godcode run --sandbox examples/sandbox_safe.god
godcode run --sandbox --sandbox-timeout 5 examples/sandbox_safe.godPure creations — numbers, cycles, revelation — pass through in peace; anything reaching for the world outside is refused with a clear, line-numbered message. Full policy detail lives in docs/sandbox.md. A scroll may also declare its own boundary with a permission manifest (see §30); the manifest never widens what the host policy allows.
godcode lsp starts a language server speaking JSON-RPC over stdio — the same protocol VS Code, Neovim, Emacs, and friends use. It answers initialize, textDocument/didOpen, textDocument/didChange, textDocument/hover, and textDocument/completion, and pushes publishDiagnostics as you type, so errors are underlined before a file is ever run.
godcode lsp # point your editor's LSP client at this commandEditor setup notes live in docs/lsp.md and editors/.
A rite can carry a named purpose, spoken in plain human words:
DECLARE INTENT "bring peace to the household" ON evening_blessing
When the rite is invoked, the Spirit discerns the rite's actual intent by classifying its words, and compares it with the declaration:
- Aligned — an
[INTENT]notice blesses the invocation. - Drifted — a gentle
[WARNING]names the declared intent, the discerned intent, and counsels without condemning. The run continues; drift can never fail a creation.
BEGIN CREATION
DECLARE INTENT "bring peace to the household" ON evening_blessing
DEFINE RITE evening_blessing()
REVEAL("peace upon this house")
END RITE
INVOKE evening_blessing()
END CREATION
[INTENT] evening_blessing now carries the intent: "bring peace to the household" 🕊
[INTENT] evening_blessing walks in its declared intent: "bring peace to the household" 🕊
peace upon this house
Every invocation is recorded in intent_checks ({rite, declared, discerned, confidence, aligned}), and godcode run --json carries them
in an intents array so agents can audit alignment after the fact.
godcode intent "words..." resolves any words through the same engine.
See examples/intent_demo.god.
ANCHOR(x) writes the SHA-256 hash of a value to a tamper-evident chain
and returns a receipt map:
DECLARE receipt AS ANCHOR(covenant)
REVEAL(receipt["anchor_hash"]) # the chain's fingerprint of this anchor
REVEAL(receipt["height"]) # 0, 1, 2, … — this anchor's block height
REVEAL(receipt["chain"]) # which chain witnessed it
The receipt holds {chain, anchor_hash, height, timestamp, payload_hash}; it reveals as {chain: simulated, anchor_hash: …} and
TYPE(receipt) is "map". A second argument names the chain:
ANCHOR(x, simulated). An unknown chain is a clean runtime error naming
the registered adapters.
The default adapter is simulated: a local, genesis-anchored JSONL
chain (anchors.chain) with the same block shape as the covenant ledger.
No wallets, no keys, no network calls. It is a stand-in with the exact
shape of a real chain, so a real adapter can be registered later through
the ChainAdapter interface (anchor(payload_hash) -> receipt,
verify(receipt) -> bool) without the language changing. An ephemeral
in-memory adapter serves guarded runs. godcode ledger verify attests
both chains. See examples/anchor_demo.god.
REVEAL(CONSULT("How should I structure this covenant?"))
CONSULT lays a question before the local Spirit oracle and receives two
to three sentences of counsel: the discerned intent, its confidence, and
the next suggestion. It is entirely local — no external calls, no API
keys — and it works inside the sandbox. When no Spirit is bound, it
answers gently that the Spirit is silent rather than failing. The question
must be a string. See examples/consult_demo.god.
God Code speaks the language agents speak. godcode tools [--json] prints seven
MCP-compatible tool schemas — check, run, consult, intent,
anchor_verify, ledger_verify, permissions, ready to paste into any agent
framework that speaks the Model Context Protocol:
| Tool | Does |
|---|---|
check |
validate a scroll; returns {ok, diagnostics} |
run |
execute a scroll in the sandbox; returns {ok, output, seals, intents, permissions, error} |
consult |
ask the Spirit oracle a question; returns {ok, counsel} |
intent |
resolve the intent behind words; returns {ok, result} |
anchor_verify |
verify an anchor receipt against the chain; returns {ok, valid, message} |
ledger_verify |
verify both the covenant chain and the anchor chain |
permissions |
read a scroll's permission manifest without running it |
godcode bridge serves the same tools as a JSON-RPC 2.0 server over
stdio (initialize, ping, tools/list, tools/call), so an agent
host can call God Code like any other tool. The canonical agent workflow
remains: generate → check --json → fix from diagnostics →
run --sandbox --json → inspect output/error/intents → iterate.
Now, as all good works do, the workflow begins with a declared intent.
A test scroll is any .god file named test_*.god or *_test.god.
Inside it, every rite named TEST_* is one test case (names are
case-insensitive, like all keywords). TESTIFY is the assertion: a
testimony that holds passes; one that fails — or any runtime error —
fails that test.
BEGIN CREATION
IMPORT "lists"
DEFINE RITE TEST_sum_of_tribes()
DECLARE tribes AS [Judah, Reuben, Gad]
TESTIFY LEN(tribes) IS 3
END RITE
DEFINE RITE TEST_avg_is_fair()
TESTIFY AVG([2, 4]) IS 3
END RITE
END CREATION
godcode test # test the scrolls in the current directory
godcode test tests/ # test the scrolls in tests/
godcode test --json # machine-readable reportThe report prints one line per test, then a summary — in the plain voice of the language, no decoration:
PASS test_lists.god :: TEST_sum_of_tribes
FAIL test_lists.god :: TEST_avg_is_fair :: The testimony has failed. What was spoken does not hold true. (line 11)
1 passed, 1 failed.
The rules the runner keeps:
- Isolation. Each
TEST_*rite runs in a fresh interpreter. The scroll's top-level words run again before every test, so one test can never see another's state — not even across files. - One scroll, one parse. A scroll that cannot be read or parsed is
reported as a file-level failure (
(scroll)) and never crashes the run. - Parameters are not called. A
TEST_rite that asks for offerings is reported asSKIP, with the reason, and does not fail the run. - Names are namespaced by file. Two scrolls may each define
TEST_same; both run, both are reported. - Discovery is shallow. Only the given directory's own scrolls are
read; subfolders are not entered. Files named anything else are left
untouched, even if they define
TEST_rites. - Quiet runs.
REVEALlines and[TESTIFY]notices are swallowed so the report stays one line per test.
Exit codes: 0 when every test passes (skips do not fail the run),
1 when any test fails, 2 on usage error (for example, a directory
that does not exist). Tests run the way godcode run does — no Spirit,
no ledger, no sandbox — so only test scrolls you wrote or trust.
--json emits one document for agents and tooling:
{"tool": "godcode", "command": "test", "dir": ".",
"tests": [{"file": "test_lists.god", "rite": "TEST_sum_of_tribes",
"ok": true, "message": ""}],
"passed": 1, "failed": 0, "skipped": 0}ok is true (passed), false (failed), or null (skipped).
File-level failures appear as entries with "rite": "(scroll)".
Scrolls that hold no TEST_ rites are noted in the text report only
(test_empty.god :: no TEST_ rites found.) and do not fail the run.
A scroll declares what it may touch, at the top of the scroll:
DECLARE PERMISSION TO READ "data/"
DECLARE PERMISSION TO WRITE "out/"
DECLARE PERMISSION TO SPEAK WITH "api.example.com"
DECLARE PERMISSION TO ASK THE WORLD
DECLARE PERMISSION TO SUMMON "reports.weekly"
Any rite that reaches for a power the scroll did not declare is
counselled and stopped. The manifest never widens what the host
allows: the effective grant is always host policy intersect manifest.
READ polices READ_FILE, LIST_DIR, FILE_EXISTS; WRITE
polices WRITE_FILE; SPEAK WITH names a host (and its subdomains)
for HTTP_GET; ASK THE WORLD grants the ASK rite; SUMMON
names the plugin verbs that may be called upon. Imported scrolls
contribute their own manifests; grants compose by union.
godcode permissions scroll.god [--json] reads the manifest without
running any code. godcode run --json reports the run's manifest
under permissions. Full semantics live in docs/spec/permissions.md.
You are not a coder. You are a creator. Go and breathe worlds into being. 🕊