Skip to content

Claude, Start My Database

When we released the Claude Code Plugin for EventSourcingDB at Easter, we proudly listed everything it did not need: no SDK, no MCP configuration, not even a Docker container. Claude had learned to speak EventSourcingDB fluently. But there was a quiet assumption baked into every conversation – that somewhere, someone had already started a database for Claude to talk to.

Version 1.1.0 of the plugin removes that assumption. Claude can now start a local EventSourcingDB on its own, and it has picked up a few habits that make longer sessions noticeably smoother: consistent event sources, uniform event type prefixes, and a deeper understanding of the CloudEvents format. In this post, we walk through what is new – along a session that begins with an empty terminal and ends with a queryable event store.

One Sentence to a Running Instance

The headline feature of 1.1.0 is the new /esdb:start-server Skill. You type: "Spin up a throwaway EventSourcingDB for me." That single sentence replaces a Docker command you would otherwise have to remember, or at least look up:

docker run -d --rm --name eventsourcingdb-dev -p 3000:3000 \
  thenativeweb/eventsourcingdb:latest run \
  --api-token=secret \
  --data-directory-temporary \
  --http-enabled \
  --https-enabled=false \
  --with-ui

We wrote about this setup in Local Development Setup: EventSourcingDB in 5 Minutes – it is not complicated, but it is exactly the kind of incantation you forget between projects. Now Claude remembers it for you. The instance it starts runs in development mode: data lives in a temporary directory, the server speaks plain HTTP instead of HTTPS, the built-in management UI is enabled, and the API token is simply secret. A few seconds later, Claude reports back with the API base URL, the address of the UI, the token, and a reminder that everything is ephemeral.

The Skill does more than fire off a command. Before starting anything, it checks that Docker is actually running, looks for an existing development instance, and verifies that the port is free. If an instance is already up, Claude tells you so and hands you the connection details instead of starting a second one. If another process occupies port 3000, Claude asks you which port to use instead. And if you want a specific image version or a different token, you just say so – the defaults are defaults, not dogma.

It is worth pausing on two of those defaults, because they shape what the instance is good for. The temporary data directory means the database starts empty every single time – and that is a feature, not a limitation. Demos begin from a clean slate, test runs cannot contaminate each other, and you never have to wonder what leftover state from last Tuesday is skewing your experiment. And the management UI, served on the same port as the API, gives you a second pair of eyes on the session: while you talk to Claude in the terminal, you can watch subjects and events appear in the browser, or try an EventQL query interactively. If you have not seen the UI yet, Using the Management UI gives you the tour.

One thing the Skill is deliberately strict about: this setup is for development only. Temporary storage and plain HTTP are wonderful for experiments and exactly wrong for production. When you are ready to deploy for real, Running EventSourcingDB covers the proper way.

A Session from Start to Finish

To see how the pieces fit together, let us play through a complete session. You open Claude Code in an empty directory, with nothing running.

Starting the database. You type: "Start a local EventSourcingDB for me to experiment with." Claude runs the preflight checks, starts the container, pings the instance to confirm it is healthy, and suggests exporting the connection settings so all other Skills pick them up automatically:

export ESDB_URL="http://localhost:3000"
export ESDB_API_TOKEN="secret"

Writing events. You continue: "Acquire a book called '2001 – A Space Odyssey' by Arthur C. Clarke, and register a reader named Alice." Claude asks you once for your event source and type prefix – more on that in a moment – then writes the events: a book-acquired event for /books/42 and a reader-registered event for /readers/1.

Reading the history. "What happened to /books/42 so far?" Claude reads the event stream for the subject and presents it: one acquisition event, with its timestamp, ID, and payload.

Asking questions. "How many books does the library have?" Claude translates the question into an EventQL query, runs it, and answers. You never left natural language, and you never wrote a single line of JSON by hand.

Guarding the data. Since this is a fresh instance, it is also the perfect moment to try schemas without consequences: "Register a schema for book-acquired events that requires a title and an author, both as strings." Claude registers the JSON Schema, and from then on the database rejects any book-acquired event that does not match. Because the whole instance is disposable, you can iterate on the schema design freely – if you get it wrong, you restart and try again, instead of living with an immutable schema you regret.

Watching it live. For the full effect, open a second terminal and ask Claude there: "Observe everything under /books." Now write another event from the first terminal and watch it arrive in the second one in real time. The observe connection streams events as they happen and closes itself after a timeout, so you cannot accidentally leave a dangling connection behind. It is a small thing, but seeing an event you just described in plain English show up live in another window makes the architecture tangible in a way no diagram can.

Cleaning up. Finally: "Stop the database again." Claude reminds you that the container and all stored data will be gone – the instance was started with temporary storage, after all – and stops it. Your machine is exactly as clean as it was before the session.

If you want to follow along yourself, installation takes less than a minute: add the marketplace with /plugin marketplace add thenativeweb/claude-plugins, install the plugin with /plugin install esdb@thenativeweb, and you are set. The Getting Started guide walks you through the details, and the Available Skills page lists everything the plugin can do.

The End of Made-Up Sources

The second change in 1.1.0 is less flashy than a self-starting database, but at least as valuable in practice. It addresses a subtle problem that anyone who has used an LLM for structured work will recognize: left to its own devices, a language model invents plausible values.

Every event in EventSourcingDB carries a source that identifies the system which produced it, and a type in reverse domain notation, such as io.eventsourcingdb.library.book-acquired. Both are free-form enough that Claude used to make reasonable but inconsistent choices. One write might use https://library.eventsourcingdb.io as the source, the next one tag:eventsourcingdb.io,2026:library, and a third one something else entirely. Each individual event was perfectly valid. Taken together, they were a mess – and since sources and event types are precisely the fields you filter and query by, that mess had a cost.

Version 1.1.0 introduces two session defaults: ESDB_SOURCE and ESDB_EVENT_TYPE_PREFIX. If they are set, every Skill that constructs events uses them. If they are not set, Claude asks you once – the first time a value is needed – and then sticks to your answer for the rest of the session instead of improvising. To make the choice permanent across sessions, you export the variables alongside the connection settings:

export ESDB_SOURCE="https://library.eventsourcingdb.io"
export ESDB_EVENT_TYPE_PREFIX="io.eventsourcingdb.library"

The result is boring in the best possible way. Every event written in a session shares one source and one type prefix, exactly as if a disciplined developer had written them. Consistency is not glamorous, but it is what makes an event store queryable six months later.

There is a broader lesson in this that goes beyond the plugin. Working with an LLM gets dramatically better when you move decisions out of the conversation and into configuration. Every value the model does not have to choose is a value it cannot choose inconsistently. The session defaults apply that principle to the two fields where drift hurts the most – and they do it without ceremony, because an environment variable is the most boring configuration mechanism there is. If you have ever reviewed data an AI assistant produced over a long session and found three spellings of the same identifier, you know exactly which problem this solves.

Claude Knows CloudEvents by Heart

The third improvement is invisible until you look at the quality of what Claude produces. The plugin now ships a shared CloudEvents reference that all event-related Skills draw on. It teaches Claude which fields are yours to provide when writing – source, subject, type, and data – and which ones the server manages, such as specversion, id, and time. It also covers the validation rules EventSourcingDB enforces, like subjects being slash-separated paths and data being a JSON object.

In practice, this means fewer rejected writes. Claude no longer has to discover by trial and error that a subject may not contain spaces or that an event type needs its reverse domain structure. It gets the shape right on the first attempt, because the rules travel with the plugin.

It also means better answers when reading. Events returned by EventSourcingDB carry extension attributes beyond the CloudEvents standard fields: a hash, a predecessorhash, and a signature. The hashes chain all events of the store together cryptographically, which is the foundation for tamper detection and auditing; the signature is set when the server is configured with a signing key. Claude now knows what these fields mean and can explain them in context instead of glossing over them. If you want the full picture of how events are structured, the CloudEvents documentation has recently been extended with exactly these details.

Alongside the CloudEvents reference, we consolidated the conventions that every Skill follows – how to handle streaming NDJSON responses, how to filter out heartbeats, how to spot an error that arrives mid-stream after the connection already reported success. Previously, each Skill carried its own copy of these instructions; now they live in one shared place. For you as a user, the visible effect is uniformity: every Skill treats configuration, streaming, and errors the same way, and an error in a long-running observe connection is surfaced instead of silently swallowed. For us as maintainers, it means a fix or improvement lands in every Skill at once – which is, not coincidentally, the same argument we make for keeping domain knowledge in one place in your systems.

From Speaking to Serving

At Easter, Claude learned to speak EventSourcingDB. With version 1.1.0, it also sets the table: it brings its own database when you need one, keeps your events consistent without being told twice, and understands the event format deeply enough to get things right on the first try. The plugin has grown from a translator into something closer to a lab assistant – one that prepares the workbench, hands you the right tools, and cleans up afterwards.

The nicest part is how little you need to know to benefit. The entire feature set of this release is reachable through ordinary sentences. "Start a database for me." "Write these events." "How many books do we have?" "Stop it again." Everything between those sentences – Docker flags, port checks, event formatting, EventQL – is handled for you.

If you already use the plugin, version 1.1.0 is available from the thenativeweb marketplace now. If you have not tried it yet, the Getting Started guide takes you from zero to your first conversation in about a minute. And we are genuinely curious where this should go next: which Skill is missing, what would make your terminal sessions smoother, what should Claude learn about EventSourcingDB that it does not know yet? Tell us at hello@thenativeweb.io – the best ideas for 1.2.0 will come from the people using 1.1.0.