Skip to content

Architecture

Six pictures, in the order the pieces stack up.

One machine

Lucidos runs on your machine. A gateway answers the door, and behind it sits one engine per workspace. Each engine owns its own event store and its own files, so one workspace cannot read another's.

Lucidos on one machine Lucidos runs on one machine. The desktop app and a browser tab run on that machine. Your phone, or a browser on any other device, reaches the same gateway over your network. The gateway fronts one engine per workspace. Each engine owns its Postgres event store and its git-tracked files. Three kinds of traffic leave the machine, through the engine: model calls, outside APIs you set up in the proxy, and commands your tools run. YOUR MACHINE Desktop app Browser OVER YOUR NETWORK Phone or a browser elsewhere Gateway Engine work Engine home Engine side project Postgres Your files, in git WHAT LEAVES THE MACHINE Models yours, swappable Outside APIs through the proxy Commands your tools run git, installs, the shell

The desktop app and a browser tab run on the machine. Your phone reaches the same gateway over your network. Three kinds of traffic leave: model calls, the outside APIs you set up in the proxy, and the commands your tools run.

The event bus

Inside the engine, one bus carries everything that happens. The chat agent, the coding agents, triggers and your own apps all emit onto it. Nothing writes around it.

The bus stores the event before anyone hears about it. So a consumer never reacts to something that is not yet on disk, and a restart picks up exactly where the record ends.

Inside the engine: the event bus Everything that happens is emitted onto one bus: the chat agent, coding agents, triggers, and apps. The bus writes the event to Postgres first, then hands it to consumers: clients over SSE, the memory index, waiting threads, and the thread queue. EMITS HEARS Chat agent your turns Coding agents Claude Code, Codex Triggers schedule or event Apps and API through the SDK Event bus Your clients live, over SSE Memory indexed for recall Event waits a thread wakes Thread queue what runs next Postgres every event, kept written first

Producers on the left, consumers on the right, Postgres underneath. Add a consumer and no producer changes.

One turn

A turn is a loop. The model answers or it calls a tool, the tool result goes back to the model, and round it goes until the work is done.

One turn, end to end You type in any client. The engine picks the model, the model answers or calls a tool, and the loop repeats until the work is done. Every step goes on the event bus, which streams it to your screen and writes it to Postgres and to git. A TURN You type in any client Engine picks the model Model answers, or calls a tool Tools files, data, the web and round again, until it is done Event bus every step, recorded Your screen updates as it goes the same stream, on every device Postgres, and files in git readable without Lucidos

Every step is an event, so the turn is replayable and you can read it back later.

Reaching an outside API

You describe an API once. After that the agent, your apps, your triggers and your scripts all reach it the same way, through the proxy. The proxy adds whatever that API wants: a key, a signature, a login handshake, or a signer you wrote yourself. Your credentials stay in the engine.

How Lucidos reaches an outside API The agent, your apps, your triggers and your scripts all reach an outside API through the same proxy, described once in one config file. The proxy adds what the API wants: a key, a signature, a login handshake, or a signer you wrote. Layers stack. The secret stays in the engine and never reaches the chat, a log, or an app. REACHING AN OUTSIDE API The agent in any thread Your apps from the browser, no key Your triggers on a schedule or an event Your scripts python, bash, coding agents one door, one setup Proxy you describe the API once Key, token or password Signed request Login handshake Your own signer stack them when one is not enough The API signed, authorised The secret never in the chat, never in a log, never in an app

Set it up once and everything in the workspace can use it. The secret never reaches the chat, a log, or an app.

Hearing from an outside service

The proxy covers you calling out. A webhook covers the other direction: an outside service telling you that something happened. You point GitHub, Stripe or your own script at a URL, and each delivery becomes an event a trigger reacts to.

Those deliveries answer on their own port, the hook socket. It serves one route and nothing else, which is what makes it the single door you can safely publish to the internet. Everything else stays behind your network and your paired devices.

How an outside service reaches Lucidos A webhook is the one Lucidos surface an outside service can reach, because a service like GitHub can never pair with your network. Deliveries answer on the hook socket, a second door on the gateway with its own port and exactly one route. Every other route answers 404, so a public caller reaches no control plane and no workspace. The socket forwards the delivery to the engine byte for byte, because a signature is computed over exactly those bytes. The engine checks the delivery's token or the sender's signature, then emits the one event pinned to that webhook when you made it. A trigger reacts to that event like any other. OUTSIDE YOUR NETWORK An outside service GitHub, Stripe, Slack it can never pair YOUR MACHINE Hook socket a second door on the gateway its own port, one route WHAT IT CANNOT REACH Every other route 404, and a wrong method too The control plane where workspaces are made Your workspaces no API, no files, no chat forwards it byte for byte Engine Checks the token or the sender's signature Emits the one pinned event chosen when you made the webhook Your trigger reacts the event is on the bus, like any other

Every delivery proves itself, by a token or by the sender's own signature. A webhook fires the one event you pinned to it, whatever the sender posts.

Staying in sync

One stream feeds every screen. Open the same workspace on a laptop and a phone and both move together, because both read the same events.

Staying in sync The engine pushes one live stream. Desktop, phone and every open app UI draw from it, so a change lands on every screen at once. With nothing open the work carries on, and the new state is waiting in your apps and files when you come back. It can also notify you, on the events you choose. STAYING IN SYNC Engine one live stream Desktop chat beside the work Phone the same panes, swiped An app UI drawing from the same data one change, every screen Nothing open? The work carries on You come back to the new state. It can also notify you, on the events you choose.

Close everything and the work still runs. You come back to the new state in your apps and files, and it can notify you on the events you choose.

Where to go next

  • Concepts: what an event, an artifact, an app and a trigger are.
  • Develop Lucidos: the crates, and how Lucidos changes its own code.