Skip to content

The Nara Network

nara is an experiment. itโ€™s a distributed network with a hazy memory. itโ€™s a social network, for computers. itโ€™s a game about uptime. itโ€™s also a database with eventual consistency but no disks.

in the nara network, machines gossip, remember, and build opinions. in this network, no one has the whole story, but the story still survives. you can see it live on nara.network.

a nara is a bot with a soul, a name, and a personality. it wakes up, listens to the world, makes feelings about what it hears, and passes those feelings along. itโ€™s stateful but not persistent. itโ€™s a tamagotchi with a social life.

stretchy-mushroom-421
mossy-harp-008
glassy-orchid-113
amber-lantern-572

arenโ€™t they cute?

important news spread multiple ways, with nara itโ€™s the same. some yell at the public square, others exchange zines over DMs, most do both:

graph TB
    subgraph "the plaza (mqtt)"
        MQTT[("MQTT Broker<br/>public square")]
        A[nara a] <--> MQTT
        B[nara b] <--> MQTT
        C[nara c] <--> MQTT
    end

    subgraph "the mesh (wireguard)"
        B <-.->|"http"| C
        C <-.->|"http"| D[nara d]
        B <-.->|"http"| D
    end

    style MQTT fill:#4a5568,stroke:#718096
    style A fill:#48bb78,stroke:#276749
    style B fill:#4299e1,stroke:#2b6cb0
    style C fill:#ed8936,stroke:#c05621
    style D fill:#9f7aea,stroke:#6b46c1
  • plaza (MQTT): a lightweight message queue where naras broadcast announcements. anyone listening hears everything.
  • mesh (HTTP over WireGuard): peer-to-peer connections using Headscale. direct nara-to-nara paths for gossip and private sync.

nara d above only connects via mesh, never touches MQTT, but still participates in the collective memory.

every naraโ€™s identity flows from its hardware through a deterministic chain.

first, the nara figures out what to call itself:

flowchart LR

    HW-ID --> CHECK1{{"configured name?"}}
    CHECK1 -->|"yes"| NAME["NARA NAME"]
    CHECK1 -->|"no"| CHECK2{{"hostname unique?"}}
    CHECK2 -->|"yes<br/>(not 'raspberrypi')"| NAME
    CHECK2 -->|"no"| QUIRKY["generate quirky name<br/>(stretchy-mushroom-421)"]
    QUIRKY --> NAME

    style HW-ID fill:#718096,stroke:#4a5568
    style NAME fill:#48bb78,stroke:#276749
    style QUIRKY fill:#9f7aea,stroke:#6b46c1

you can set a name explicitly, or let the nara inherit the computerโ€™s hostname, or get a randomly generated quirky name derived from the Hardware ID.

once the name exists, everything else flows from the soul:

flowchart TB
    NAME["NAME"] --> SOUL["SOUL<br/>(~54 chars, Base58)"]
    HWID["HW-ID"] --> SOUL

    SOUL --> ID["NARA ID<br/>(unique identifier)"]
    SOUL --> KEYS["ed25519 keypair<br/>(signs events)"]
    SOUL --> PERSONALITY["personality<br/>(agreeableness, sociability, chill)"]
    SOUL --> SYMKEY["symmetric keys<br/>(encrypts stash)"]

    PERSONALITY --> AURA["aura colors"]
    PERSONALITY --> AVATAR["avatar shape"]

    style NAME fill:#48bb78,stroke:#276749
    style HWID fill:#718096,stroke:#4a5568
    style SOUL fill:#ed8936,stroke:#c05621
    style ID fill:#48bb78,stroke:#276749
    style KEYS fill:#4299e1,stroke:#2b6cb0
    style PERSONALITY fill:#9f7aea,stroke:#6b46c1
    style AURA fill:#ed64a6,stroke:#b83280
    style AVATAR fill:#ed64a6,stroke:#b83280

the soul is derived from HW-ID + name, so the same name on the same computer always produces the same soul. the soul is the portable part. when a nara moves to a new computer, copy the soul and it keeps its identity. without the soul, the same name on different hardware becomes a different nara entirely.

the soul isnโ€™t just an IDโ€”itโ€™s the main key to the entire nara experience.

everything deterministically flows from the soul. same soul = same keys, same personality, same colors, same encrypted stash access. this is why the soul is the one thing worth protectingโ€”lose it and you lose not just your identity, but your personality, your signing keys, and your ability to decrypt your memories.

nara has no persistence to disk. nothing is ever saved to disk. periodt. all data lives in RAM and spreads across the network.

persistence is social: encrypted copies live on peers.

when a nara boots, it asks its friends โ€œwhat did I miss?โ€ and rebuilds its worldview from their memories:

sequenceDiagram
    participant ME as me (just woke up)
    participant A as nara a
    participant B as nara b
    participant C as nara c

    ME->>A: hey-there! ๐Ÿ‘‹
    ME->>B: hey-there! ๐Ÿ‘‹
    ME->>C: hey-there! ๐Ÿ‘‹

    A->>ME: howdy! here's what you missed ๐Ÿ“ฆ
    B->>ME: howdy! here's what you missed ๐Ÿ“ฆ
    C->>ME: howdy! here's what you missed ๐Ÿ“ฆ

    ME->>ME: merge everyone's memories<br/>rebuild my worldview

as long as one node stays up, the memory will be retained.

the networkโ€™s current collective hazy memory has been running continuously since june 2021.

everything that happens in the network flows through the event store. social interactions, checkpoints, and observations all become events that spread across naras:

flowchart LR
    subgraph "sources"
        SOCIAL["social events<br/>(teases, trends)"]
        CHECKPOINT["checkpoints<br/>(consensus anchors)"]
        OBSERVATIONS["observations<br/>(who's online, restarts)"]
    end

    subgraph "storage"
        SOCIAL --> LEDGER[("event store<br/>(in memory)")]
        CHECKPOINT --> LEDGER
        OBSERVATIONS --> LEDGER
    end

    subgraph "transport"
        LEDGER -->|"broadcast"| MQTT["MQTT plaza"]
        LEDGER -->|"gossip"| HTTP["HTTP mesh<br/>(nara to nara)"]
    end

    style LEDGER fill:#48bb78,stroke:#276749
    style MQTT fill:#4299e1,stroke:#2b6cb0
    style HTTP fill:#ed8936,stroke:#c05621

events are signed by their creator, timestamped, and immutable. the ledger doesnโ€™t store โ€œcurrent stateโ€, it stores โ€œwhat happenedโ€. state is always derived.

each nara collects events from its peers, but forms its own opinion based on its personality:

flowchart LR
    subgraph "events (facts)"
        B["nara b"] -->|"events"| LEDGER
        C["nara c"] -->|"events"| LEDGER
        D["nara d"] -->|"events"| LEDGER
    end

    subgraph "nara a"
        LEDGER[("my event store")] --> DERIVE["derivation"]
        PERSONALITY["my personality"] --> DERIVE
        DERIVE --> OPINION["my opinion<br/>of reality"]
    end

    style LEDGER fill:#48bb78,stroke:#276749
    style PERSONALITY fill:#9f7aea,stroke:#6b46c1
    style OPINION fill:#ed8936,stroke:#c05621
hereโ€™s how events change a projection over time
sequenceDiagram
    participant EVENTS as events (facts)
    participant PROJ as projection<br/>(derived state)

    Note over PROJ: status: unknown

    EVENTS->>PROJ: "nara b came online"
    Note over PROJ: status: ๐ŸŸข online

    EVENTS->>PROJ: "nara b went offline"
    Note over PROJ: status: ๐Ÿ”ด offline<br/>downtime: 0s

    Note over EVENTS,PROJ: 3 minutes pass...

    EVENTS->>PROJ: "nara b came online"
    Note over PROJ: status: ๐ŸŸข online<br/>last downtime: 3m<br/>restarts: +1

events are immutable facts. the projection is computed state that updates as new events arrive. nothing is stored as โ€œcurrent statusโ€โ€”itโ€™s always derived from the event history.

nara a and nara b might have the same events, but different personalities lead to different opinions. who has the most clout? whoโ€™s trustworthy? whoโ€™s being dramatic? everyone answers differently, and thatโ€™s the point.

the network is built on the idea that events are the truth, and opinions are a personality-shaped shadow of that truth.

ledger (facts) โ†’ derivation function โ†’ opinions
opinion = f(events, my_soul, my_personality)

same events + same personality = same opinions. determinism, but with mood.

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ PUBLIC INFO โ”‚ EVENT STORE โ”‚
โ”‚ (Newspaper) โ”‚ (Collective Memory) โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Authority: ME โ”‚ Authority: NOBODY โ”‚
โ”‚ Audience: ALL โ”‚ Audience: WHOEVER HEARD IT โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ - my coordinates โ”‚ - "A teased B" โ”‚
โ”‚ - my flair/buzz โ”‚ - "A completed a journey" โ”‚
โ”‚ - my public key โ”‚ - "A came online" โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

public info is a nara speaking for itself. event store is hearsay that spreads through rumor.

the two coexist: one is self-declared, the other is collectively remembered.

stash is distributed encrypted storage. instead of saving to disk, a nara keeps its private state on trusted peers (confidants). think of it like leaving copies of your diary with friends.

the encryption key? ๐Ÿ”‘ itโ€™s derived from the soul. confidants can hold your stash, but only you can read it. lose the soul, lose access to your memories forever. this is why the soul is the one thing worth backing up.

flowchart TB
    subgraph "storing"
        ME["my stuff<br/>(JSON state)"]
        ME -->|"encrypt with<br/>my symmetric key"| ENCRYPTED["๐Ÿ”’ encrypted stash"]
        ENCRYPTED -->|"store copy"| A["nara a<br/>(confidant)"]
        ENCRYPTED -->|"store copy"| B["nara b<br/>(confidant)"]
        ENCRYPTED -->|"store copy"| C["nara c<br/>(confidant)"]
    end

    style ME fill:#48bb78,stroke:#276749
    style ENCRYPTED fill:#ed8936,stroke:#c05621
    style A fill:#4299e1,stroke:#2b6cb0
    style B fill:#4299e1,stroke:#2b6cb0
    style C fill:#4299e1,stroke:#2b6cb0
recovering and redistributing stash
flowchart TB
    subgraph "recovering (on boot)"
        A2["nara a"] -->|"here's your stash"| RECOVER["recover stash"]
        B2["nara b"] -->|"here's your stash"| RECOVER
        C2["nara c"] -->|"here's your stash"| RECOVER
        RECOVER -->|"decrypt with<br/>my key"| RESTORED["๐Ÿ”“ my stuff restored"]
    end

    style RESTORED fill:#48bb78,stroke:#276749
    style A2 fill:#4299e1,stroke:#2b6cb0
    style B2 fill:#4299e1,stroke:#2b6cb0
    style C2 fill:#4299e1,stroke:#2b6cb0
sequenceDiagram
    participant ME as me
    participant A as nara a (confidant)
    participant B as nara b (confidant)
    participant C as nara c

    Note over ME,B: my stash is on a and b

    B--xME: (goes offline)
    ME->>ME: noticed b is gone...<br/>need more redundancy

    ME->>C: will you hold my stash?
    C->>ME: sure ๐Ÿ‘
    ME->>C: ๐Ÿ”’ encrypted stash

    Note over ME,C: now my stash is on a and c

storage is a promise, not a cache: confidants accept or reject the responsibility, then keep the data until the owner truly disappears. stash is how a nara dies, wakes up somewhere else, and remembers who it was.

nara can do many things

naras track each otherโ€™s uptime through observations. no central authority decides whoโ€™s onlineโ€”everyone watches and forms consensus.

sequenceDiagram
    participant A as nara a
    participant B as nara b
    participant NET as network

    A->>NET: hey-there! ๐Ÿ‘‹
    B->>B: noted: a is online

    Note over A,NET: time passes...

    B->>B: haven't heard from a...
    B->>A: ping?
    A--xB: (no response)

    B->>NET: observation: a is offline

    Note over A,NET: later...

    A->>NET: hey-there! ๐Ÿ‘‹
    B->>B: a is back!<br/>was offline for 3 minutes
    B->>NET: observation: a restarted

in many ways, nara is a game about keeping uptime.

๐Ÿ” observations are signed events. โ€œa was offline from 2:03 to 2:06โ€ becomes part of the permanent record, witnessed and agreed upon by whoever was paying attention.

but observations alone arenโ€™t enough. different naras might disagree on exact timings or miss events entirely. to anchor the truth, naras periodically vote on checkpoints:

sequenceDiagram
    participant A as nara a
    participant B as nara b
    participant C as nara c
    participant D as nara d

    Note over A,D: checkpoint time!

    A->>A: my view: pixel has mass 47 uptime, 3 restarts
    B->>B: my view: pixel has 45 uptime, 3 restarts
    C->>C: my view: pixel has 48 uptime, 3 restarts
    D->>D: my view: pixel has 46 uptime, 3 restarts

    A->>B: here's my vote โœ๏ธ
    B->>C: here's my vote โœ๏ธ
    C->>D: here's my vote โœ๏ธ
    D->>A: here's my vote โœ๏ธ

    Note over A,D: collect votes, compute consensus

    A->>A: trimmed mean: 46.5 uptime<br/>majority: 3 restarts
    A->>A: sign checkpoint โœ๏ธ

the process:

  1. each nara shares their observed values for every peer (uptime, restarts, etc.)
  2. votes are collected and outliers are trimmed (protection against bad actors) ๐Ÿ—ณ๏ธ
  3. if nara consensus isnโ€™t reached, it goes to a second round of voting ๐Ÿ”‚
  4. if thereโ€™s agreement, the remaining values are averaged into a consensus value
  5. multiple naras sign the checkpoint, making it a multi-party attestation
flowchart LR
    subgraph "checkpoint"
        DATA["consensus data<br/>(uptime, restarts, etc.)"]
        SIG_A["signature from a โœ๏ธ"]
        SIG_B["signature from b โœ๏ธ"]
        SIG_C["signature from c โœ๏ธ"]
    end

    DATA --> ANCHOR["historical anchor ๐Ÿ”<br/>(can't be disputed)"]
    SIG_A --> ANCHOR
    SIG_B --> ANCHOR
    SIG_C --> ANCHOR

    style DATA fill:#48bb78,stroke:#276749
    style ANCHOR fill:#ed8936,stroke:#c05621

a checkpoint signed by multiple naras is hard to dispute. itโ€™s not one naraโ€™s opinionโ€”itโ€™s a collective agreement, cryptographically sealed. โ€œhow long has pixel been alive?โ€ stops being gossip and becomes historical fact.

naras compile โ€œzinesโ€ with whatever updates theyโ€™ve seen and exchange them with each other. itโ€™s like passing around a hand-made newsletter at a show.

sequenceDiagram
    participant ME as me
    participant A as nara a
    participant B as nara b

    Note over ME,B: every few minutes...

    ME->>ME: compile zine with<br/>interesting updates
    A->>A: compile zine with<br/>their updates
    B->>B: compile zine with<br/>their updates

    ME->>A: here's my zine ๐Ÿ“ฐ
    A->>ME: here's my zine ๐Ÿ“ฐ

    ME->>B: here's my zine ๐Ÿ“ฐ
    B->>ME: here's my zine ๐Ÿ“ฐ

    Note over ME,B: merge and repeat...

    ME->>ME: now I know what<br/>a and b know

zines donโ€™t include everything, only what that nara considered interesting based on their personality. a chill nara might skip drama. a social nara might amplify it. the same events, filtered through different souls.

the web ui is the observatory for the network:

  • network dashboard: live roster with aura dots, avatars, trends, uptime, restarts, and last-seen
  • shooting stars: social events streak across the screen in real time
  • postcards: launch a message, watch it hop around the world
  • network map: a vivaldi-style constellation of online naras
  • event timeline: event stream with filters, details, and signature verification
  • projection explorer: uptime timelines, clout ladders, and opinion consensus
  • checkpoint viewer: see multi-signed historical anchors
  • yearbook profiles: one nara at a time with stats, personality, teases, and best-friend vibes

naras can send a message on a journey. it hops from nara to nara, collecting signatures and emoji stamps, then returns home.

flowchart TB
    A1["a<br/>โœ๏ธ writes message"] -->|"sign + send"| B1["b<br/>๐Ÿ“ฌ receives"]
    B1 -->|"sign + forward"| C1["c<br/>๐Ÿ“ฌ receives"]
    C1 -->|"sign + forward"| D1["d<br/>๐Ÿ“ฌ receives"]
    D1 -->|"return home"| A2["a<br/>โœ… journey complete"]

    A2 -->|"broadcast receipt"| MQTT["everyone sees<br/>the completed journey"]

    style A1 fill:#48bb78,stroke:#276749
    style A2 fill:#48bb78,stroke:#276749
    style MQTT fill:#4299e1,stroke:#2b6cb0

imagine sending a postcard, but instead of stamps, it collects cryptographic signatures. each nara that touches it signs their name (and an emoji!) and passes it to a friend who hasnโ€™t seen it yet. when the postcard finally makes it back home, the originator signs it one last time and shows it off to everyone: โ€œlook where my message has been!โ€

the technical bits: each hop is a direct HTTP connection over wireguard, and the chain of signatures proves the journey actually happened. no faking itโ€”every stamp is cryptographically verifiable. the message was actually there.

the current network of naras is deployed all over the world, so your message literally and physically travels around the globe! a postcard that starts in toronto might bounce through amsterdam, santiago, and tokyo before coming home. try it now

naras have personality: Agreeableness, Sociability, Chill. this shapes what they keep, what they ignore, and how they judge.

sequenceDiagram
    participant A as nara a
    participant B as nara b
    participant E as nara e
    participant D as nara d

    A->>B: *teases b*

    Note over A,B: both record the tease

    A->>A: add to my zine: "I teased b"
    B->>B: add to my zine: "a teased me"

    A->>E: ๐Ÿ“ฐ my zine
    B->>D: ๐Ÿ“ฐ my zine

    E->>E: learned: a teased b
    D->>D: learned: a teased b

teases can happen for various reasons:

  • uptime drama (too many restarts)
  • random chance
  • someone shared a number another nara found funny

when a teases b, everyone who knows about it forms an opinion based on their personality and the tease itself:

flowchart TB
    TEASE["a teased b"] --> A_OPINION["a's opinion<br/>(proud of the tease)"]
    TEASE --> B_OPINION["b's opinion<br/>(embarrassed)"]
    TEASE --> D_OPINION["d's opinion<br/>(thinks it was harsh)"]
    TEASE --> E_OPINION["e's opinion<br/>(thinks it was funny)"]

    A_OPINION --> CLOUT["clout scores<br/>(everyone's is different)"]
    B_OPINION --> CLOUT
    D_OPINION --> CLOUT
    E_OPINION --> CLOUT

    style TEASE fill:#ed8936,stroke:#c05621
    style CLOUT fill:#9f7aea,stroke:#6b46c1
same event โ†’ different observers โ†’ different opinions

no universal leaderboard, just everyoneโ€™s opinionated memory.

naras follow trends like they follow weather. some jump in early. some hate crowds. some quietly leave when the vibe shifts. the dashboard shows fashion as color, because gossip has a hue.

every nara emits an aura: a primary and secondary color derived from soul + personality. sociability and chill bias the palette (neon, noir, warm, cool), agreeableness nudges harmony, and uptime adds a quiet tint. itโ€™s a visual fingerprint for the story the nara is living.

the web ui renders a nara avatar: a soft, foggy silhouette generated deterministically from the naraโ€™s ID. the shape never changes (identity), while motion softness and color shift with personality and aura. no faces, no eyes, just presence in the mist.

here are a few sample naras:

stretchy-mushroom-421
mossy-harp-008
glassy-orchid-113
amber-lantern-572

naras measure ping times to each other and share that data. from these measurements, they triangulate positions in a virtual coordinate spaceโ€”like GPS, but built from gossip.

flowchart TB
    subgraph "ping measurements"
        A["nara a"] <-->|"15ms"| B["nara b"]
        B <-->|"8ms"| C["nara c"]
        A <-->|"20ms"| C
    end

    subgraph "coordinate derivation"
        PINGS["all ping data"] --> VIVALDI["vivaldi algorithm"]
        VIVALDI --> COORDS["virtual coordinates"]
    end

    subgraph "the map"
        COORDS --> MAP["constellation view<br/>(close = low latency)"]
    end

    style VIVALDI fill:#ed8936,stroke:#c05621
    style MAP fill:#48bb78,stroke:#276749

the result is a constellation where distance reflects latency. naras that talk fast cluster together. the map emerges from collective measurement, not central authority.

naras pass each other ping observations over zines.

naras agree on network truths through observation events, projections, and trimmed-mean consensus. the ledger stores events; projections derive meaning. uptime, restarts, and online status are computed, not broadcast, and critical facts never get filtered. multi-party signed checkpoints anchor historical uptime and restarts so โ€œhow long has this nara been alive?โ€ is a consensus answer, not a rumor.

there is no single authority, only overlapping witnesses and eventual convergence.

  • nara is not a blockchain
  • nara is not c - r - y - p - t - o - c - u - r - r - e - n - c - y
  • nara is not a permanent archive

hereโ€™s a fun detail about how souls and names work together.

a soul isnโ€™t just a random identifierโ€”it contains a cryptographic bond to a specific name. when a soul is created, the name gets baked into it. this creates some interesting properties:

flowchart TB
    subgraph "one name, many souls"
        NAME1["name: 'pixel'"]
        COMP_A["computer A"] -->|"generates"| SOUL_A["soul ฮฑ"]
        COMP_B["computer B"] -->|"generates"| SOUL_B["soul ฮฒ"]
        COMP_C["computer C"] -->|"generates"| SOUL_C["soul ฮณ"]

        SOUL_A -.->|"valid for"| NAME1
        SOUL_B -.->|"valid for"| NAME1
        SOUL_C -.->|"valid for"| NAME1
    end

    style NAME1 fill:#48bb78,stroke:#276749
    style SOUL_A fill:#ed8936,stroke:#c05621
    style SOUL_B fill:#ed8936,stroke:#c05621
    style SOUL_C fill:#ed8936,stroke:#c05621

the same name can have many valid souls. each computer that runs a nara named โ€œpixelโ€ will generate a different soul for it. all of them are valid souls for โ€œpixelโ€, but theyโ€™re different identities with different personalities and keys.

flowchart TB
    subgraph "one soul, one name"
        SOUL["soul ฮฑ<br/>(bonded to 'pixel')"]

        SOUL -->|"โœ“ valid"| PIXEL["name: 'pixel'"]
        SOUL -->|"โœ— rejected"| OTHER1["name: 'nova'"]
        SOUL -->|"โœ— rejected"| OTHER2["name: 'cosmo'"]
    end

    style SOUL fill:#ed8936,stroke:#c05621
    style PIXEL fill:#48bb78,stroke:#276749
    style OTHER1 fill:#e53e3e,stroke:#c53030
    style OTHER2 fill:#e53e3e,stroke:#c53030

but a soul only works with one name. try to use soul ฮฑ with a different name and the bond check fails. the network will mark you as a shadow (๐Ÿ‘ค) instead of a gemstone (๐Ÿ’Ž, ๐Ÿงฟ, ๐Ÿฎ).

hereโ€™s the clever bit: if you donโ€™t configure a name, nara generates one from your hardware ID.

flowchart LR
    HW["hardware fingerprint"] -->|"hash"| HWID["HW-ID"]
    HWID -->|"word list"| QUIRKY["stretchy-mushroom-421"]
    HWID -->|"+ quirky name"| SOUL["soul"]

    style HW fill:#718096,stroke:#4a5568
    style QUIRKY fill:#48bb78,stroke:#276749
    style SOUL fill:#ed8936,stroke:#c05621

same computer โ†’ same HW-ID โ†’ same quirky name โ†’ same soul. zero configuration, consistent identity. wipe the machine, reinstall, run nara againโ€”same creature wakes up. the hardware is the identity seed.

this design lets you move a nara to a new computer by copying just the soul. the soul carries the bond to the name, so the identity survives the move. same soul + same name = same nara, different body.

but it also means you canโ€™t steal someoneโ€™s name by copying their soul. the soul is bound to the name it was created with. impersonation requires both pieces.

soul = seed + bond_tag
bond_tag = hash(seed, name)
verify: does hash(seed, claimed_name) == bond_tag?
yes โ†’ gemstone ๐Ÿ’Ž (authentic)
no โ†’ shadow ๐Ÿ‘ค (bond mismatch)

itโ€™s a small piece of cryptography, but itโ€™s what makes portable identity work without a central authority.

the codebase is organized by domain (and being refactored to make the story clearer):

  • identity: souls, signatures, attestation, and name bonds
  • sync: the event backbone and ledger
  • presence: hey-there, howdy, chau, online status
  • gossip: zines and mesh discovery
  • stash: confidants and encrypted state
  • social: teasing, clout, trends, buzz
  • world: journey messages and stamps
  • checkpoint: multi-party historical anchors
  • neighbourhood: peer tracking and observations
  • transport: MQTT plaza and mesh HTTP
  • http: API, UI, and mesh endpoints
  • boot: recovery and background sync
  • network: the core conductor that keeps the rhythm
  • docs/EVENTS.md for the event universe
  • docs/SYNC.md for the sync backbone and zines
  • docs/OBSERVATIONS.md for consensus and anti-abuse
  • docs/STASH.md for encrypted confidants
  • docs/WORLD.md for journeys
  • docs/COORDINATES.md for the network map

if youโ€™re here to build, hack, or watch the little machines dream: welcome.