Browse the docs

DocsStart here

Start with Claude: try Ekwo on your own books

This is the shortest way to see your own books in Ekwo: a free database of your own, one command to install, and then Claude — the desktop application or Claude Code — doing the rest in plain sentences. You bring an export of your books from wherever they are kept today; Claude takes them over, answers questions about them and prepares your next VAT return. No web interface is involved: Ekwo OS is a database, a command line and an MCP server. The web application is Ekwo Cloud, the hosted edition on ekwo.ai.

It takes about twenty minutes, most of it in the Supabase dashboard. You do not need to be a developer, but you will paste a few lines into a terminal and one block into a settings file.

Before you start, know what is not there yet — the full list is at the end, under What this does not do yet:

  • Ekwo OS has no web interface: you work through Claude, or the command line (the web application is Ekwo Cloud, the hosted edition on ekwo.ai);
  • Ekwo prepares a declaration and does not file it: sending it is yours;
  • the history you import carries no VAT: it feeds the ledger and the balances, not the boxes of a return;
  • the reconciliation marks of your old books are not re-applied.

What you need

  • A Supabase account. The free plan is enough. Ekwo never sees the project: it is yours from the first row.
  • Node.js 20 or later, from nodejs.org. Type node --version in a terminal to check.
  • Claude Desktop (claude.ai/download) or Claude Code.
  • An export of your books. The simplest is a trial balance as a CSV file — account, debit, credit — which every ledger can produce. An export from another ledger works too, as it comes out of it: the journal entries, the chart of accounts and the customers and suppliers. compatibility.md lists every export Ekwo reads today, with the official page that says how to produce each one.

Try it on a copy first. The steps below create a project for the purpose, and nothing here touches the software your books come from.

1. Create a free Supabase project

  1. Sign in at supabase.com and create a new project. Pick a name, a region near you, and a database password — write the password down, you need it once, in the next step.
  2. When the project is ready, collect three things from the dashboard:
    • Connect (at the top of the project page) → Session pooler → the connection string. It looks like postgresql://postgres.<ref>:[YOUR-PASSWORD]@aws-1-<region>.pooler.supabase.com:5432/postgres. Put your database password where it says [YOUR-PASSWORD]. Take the session pooler line and not the direct one: the direct host answers on IPv6 only, and many home and office networks cannot reach it.
    • Project Settings → API Keys: the publishable key (sb_publishable_…). If your dashboard only shows the older keys, the anon key does the same job. This is the key Claude will use.
    • On the same page, the secret key (sb_secret_…): the dashboard masks it until you reveal or copy it. The legacy service_role key, under Legacy API Keys, does the same job. The installer uses it once, to create your user, and writes it nowhere.

The Project URL is https://<ref>.supabase.co, where <ref> is the part after postgres. in the connection string. The installer works it out from the connection string; Claude needs it written in full.

2. Install Ekwo into it

In a terminal:

npx -y ekwo-os@latest init

Keep the @latest, as for the server below: without a version, npx run from inside a clone of the Ekwo repository finds the workspace package of the same name and answers ekwo: command not found. With it, npx fetches the published installer wherever it is started.

The installer asks its questions one by one:

It asks What to answer
The connection string The session pooler line from step 1, with your password in it
The country The country whose rules your books follow. Nothing is preselected: the list is the country packs Ekwo holds
Your organisation, then the first company Names. The company is the one whose books you are bringing
The first day of the financial year Only where the country does not fix one — for example the United Kingdom, where each company chooses its year
The chart of accounts and the language of the books Only where the country publishes more than one
How often the company files its VAT return Only where that depends on the company
An IBAN Optional. Enter skips it
The administrator's e-mail address, the service_role key and a password This is you: the user Claude will sign in as. Choose a real password and keep it

It takes a few seconds and ends with a summary: the company, its chart, the return it files and its first financial year. Then it lists four things to do on your project — among them, switching off public sign-up in Authentication. Do them while the dashboard is open; they are explained in the installation guide.

Everything can also be given as flags, for example npx -y ekwo-os@latest init --country EE or npx -y ekwo-os@latest init --country GB --fiscal-year-start 2026-04-01; the installation guide lists them.

The installation itself is in no country; its companies are. The installer asks for a country only to create this first company, and --no-company installs without one. Every other company, in the same country or another, comes later and needs no second installation — see Several companies, several countries.

3. Connect Ekwo to Claude

The connection is the Ekwo MCP server, @ekwo-ai/mcp, published on npm and listed in the official MCP registry as ai.ekwo/mcp. Claude starts it on your computer. It signs in to your project as the user you just created, and can do exactly what that user can do and nothing more: it never holds the service_role key, and refuses to start with one.

It needs four values:

Variable Value
SUPABASE_URL https://<ref>.supabase.co
SUPABASE_ANON_KEY The publishable key, or the legacy anon key
EKWO_EMAIL The administrator's address you gave the installer
EKWO_PASSWORD Its password

In Claude Desktop

  1. Open Settings from the Claude menu of your computer's menu bar (not the settings inside the chat window), then Developer → Edit Config. That opens claude_desktop_config.json:

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json
  2. Put this in it — or, if the file already has an mcpServers section, add the "ekwo" entry inside it:

    {
      "mcpServers": {
        "ekwo": {
          "command": "npx",
          "args": ["-y", "@ekwo-ai/mcp@latest"],
          "env": {
            "SUPABASE_URL": "https://YOURREF.supabase.co",
            "SUPABASE_ANON_KEY": "sb_publishable_…",
            "EKWO_EMAIL": "you@example.com",
            "EKWO_PASSWORD": "the password you chose"
          }
        }
      }
    }
    
  3. Quit Claude Desktop completely and open it again. In a new conversation, the + button at the bottom left of the message box → Connectors lists ekwo; Manage connectors shows its tools.

If it does not appear, the logs are in ~/Library/Logs/Claude on macOS (%APPDATA%\Claude\logs on Windows): mcp-server-ekwo.log holds what the server said. The procedure is the one in Connect to local MCP servers, the Model Context Protocol's own guide, which uses Claude Desktop as its example.

In Claude Code

One command, from any directory:

claude mcp add --scope user \
  --env SUPABASE_URL=https://YOURREF.supabase.co \
  --env SUPABASE_ANON_KEY=sb_publishable_… \
  --env EKWO_EMAIL=you@example.com \
  --env EKWO_PASSWORD='the password you chose' \
  --transport stdio ekwo -- npx -y @ekwo-ai/mcp@latest

Everything before -- is for Claude Code; everything after it is the command that starts the server. Keep the @latest: without a version, npx run from inside a clone of the Ekwo repository finds the workspace package of the same name, which has no built command, and answers ekwo-mcp: command not found. With it, npx always fetches the published server, wherever it is started. --scope user keeps the entry in your own ~/.claude.json, for every project. Do not use --scope project: it writes the block, password included, into a .mcp.json meant to be committed with the project. Then run /mcp inside Claude Code: ekwo should read connected. The reference is Connect Claude Code to tools via MCP.

The password sits in plain text in either file, like any value in a client's configuration. It is the password of your Ekwo user on your own project; keep the file to yourself.

4. Several companies, several countries

Start a conversation. Claude reads the name and description of every tool, so you speak about your books, not about tools. The examples in this guide are two companies kept side by side in one installation — one in Estonia, one in the United Kingdom. The names and amounts are invented; the answers are what the server returned when this guide was run end to end (see Checked for real).

"Is Ekwo connected? List my companies." Claude calls status and list_companies: the schema version, and the company the installer created, with you as its owner.

One installation keeps the books of as many companies as you like, and they need not share a country. The installer loads the rules of every country Ekwo has a pack for, not only the one you chose, so a company in another country is one sentence away:

"Create a second company, Harbourlight Ledger Ltd, in the United Kingdom, its financial year starting on 1 January 2026." Claude calls create_company. The company gets the United Kingdom's chart of accounts, journals, taxes and VAT return, in pounds, with you as its owner — while the first keeps Estonia's, in euros. Asked again, list_companies shows both:

Company Country Currency Your role
Põhjatuul OÜ EE EUR owner
Harbourlight Ledger Ltd GB GBP owner

Every tool that reads or writes the books names its company, so tell Claude which one you mean — "for Harbourlight, …" — whenever it could be either. Creating a company is an act on the whole installation: it needs an administrator, which the installer made you. A country whose year does not open on a fixed day — the United Kingdom again — needs the first day said: the tool refuses to pick one, so Claude asks you.

In the terminal, the company the commands run on is chosen with ekwo use, once you are signed in:

npx -y ekwo-os@latest login            # asks the project URL, the key, your address and password
npx -y ekwo-os@latest use "Harbourlight Ledger Ltd"
npx -y ekwo-os@latest whoami           # the companies you can see, and the one in use

The command line creates companies too. ekwo company new calls the same create_company() as the tool, as an administrator of the installation, and asks the same questions — the country always, and the first day of the year, the chart or the language wherever the pack leaves a choice. An installation that has no single first company to name — a group, a firm, a holding with a subsidiary abroad — can start with none, and take each company in its own country:

npx -y ekwo-os@latest init --no-company --org "Põhjatuul Group" --admin-email "you@example.com"
npx -y ekwo-os@latest company new "Põhjatuul OÜ" --country EE
npx -y ekwo-os@latest company new "Harbourlight Ledger Ltd" --country GB --fiscal-year-start 2026-01-01
npx -y ekwo-os@latest company list

--no-company refuses every flag that only describes a company — --country among them — since there is no company for it to describe. ekwo company new connects the way init does, with the connection string; the installation guide has every flag. Claude or the terminal: the company is the same.

5. Ask Claude to take over your books

Each company arrives with the trial balance of its previous ledger.

"Here is the trial balance of Põhjatuul OÜ at 1 January 2026. Import it — show me first what you would do." Attach the CSV to the message (in Claude Code, give its path). Claude calls import_books with dry_run on, which writes nothing. The answer is the correspondence: for every account of your old books, the account of the new chart it would go to, how it was found, and why.

Old account Proposed Basis, and why
101000 Bank current account 1010 suggested, same digits — its name is the one 1010 has in the chart
120000 Customers 1200 suggested, same digits — its name says a receivable, and 1200 is one
297000 Retained earnings 2970 suggested, same digits — its balance is on the credit side, and 2970 is an equity account

Read every line before you agree. The codes give a candidate: the same code, the same code without the zeros padded on the right, or the longest beginning the chart has. Then what the file says of the old account — the type an export gives it, its name, the side of its balance — is held against what the new chart says the candidate is. Only the same code, confirmed, is exact; everything else is suggested and waits for you, or none. Nothing is posted while a line is only suggested. Two charts can use the same digits for different things, and the other company shows why:

Old account Proposed Basis, and why
090 Business current account none — the chart has neither the code nor its digits
610 Accounts receivable 1100 suggested, kind — 6100 has the same digits and is an expense account, so it is not proposed; 1100 Trade debtors is the chart's receivable
710 Office equipment 7100 suggested, same digits — only the side of the balance agrees, and 7100 is Rent: wrong
711 Office equipment depreciation 7110 suggested, same digits — its balance is on the credit side, and 7110 is an expense account: wrong
800 Accounts payable 2100 suggested, kind — 8000 is an expense account, so it is not proposed; 2100 Trade creditors is the chart's payable
960 Retained earnings none
970 Owner capital none

"610 is 1100 and 800 is 2100, as you suggest. 090 is the bank current account, 1300. 710 is office equipment, 0140, and 711 its depreciation, 0141. 970 is share capital, 3300; 960 is 3400." Claude calls the rehearsal again with your answers. When nothing is left open, the database runs the whole import and takes it back, so what you see — the accounts, the customers and suppliers it would create, the numbers — is what would happen, and any refusal is the real one. For the first company every suggestion was right, so the answer can be shorter: "Every suggestion is right, accept them." Claude passes accept_suggestions, which takes every suggested line as it was shown — only once you have read them all.

"That's right. Import it for real." import_books without dry_run. The opening entry is posted, all of it or none of it, and the file is recorded: the same file a second time is refused rather than counted twice, and the refusal says which file it was, when it was imported and what it wrote.

For a larger history — the entries of a whole year, from an export of another ledger — the steps are the same: the rehearsal, the correspondence, then the import. A file that does not balance, or a date the file does not make unambiguous, is refused by name rather than guessed. The export each source expects is in compatibility.md and the mechanics in import.md.

A large export goes through the terminal. The tool receives the files as text inside the conversation, and refuses more than 256 KiB of them — a year of entries is often more — with the command to run instead. Signed in once with npx -y ekwo-os@latest login,

npx -y ekwo-os@latest import <source> <files> --company "<company>" --dry-run --save-mapping correspondence.json

reads the files from the disk and runs the same import as the tool: the same correspondence, printed with the lines to read first, the same rehearsal, the same refusals. Answer the correspondence in correspondence.json, then run it again with --mapping correspondence.json and without --dry-run. npx -y ekwo-os@latest import --help lists the sources. Claude Code can run these commands for you.

Bank statements are not books: say "import this bank statement" and Claude uses import_bank_statement, which records the lines to be matched and books nothing.

6. Ask questions, prepare a return

Now it is your books. Sentences that work, and what answers them:

You say Claude uses
"What is in the bank on 1 January?" trial_balance — for the two companies above, 8 400.00 on 1010 and 12 300.00 on 1300, and the debit and credit columns agree
"Show me the trial balance for 2026." trial_balance
"Every movement on the customers account." general_ledger
"Who owes me money, and since when?" aged_balance
"Invoice Lõuna Pagarid 1 000 for consulting at the standard rate, and post it." search_contacts, create_document, post_document — a customer the import created is found by name
"Prepare my VAT return for January." vat_return

The return is computed from what was booked in Ekwo during the period. With one invoice of 1 000 at the standard rate, the Estonian company's January return (form KMD) came back with 1 000.00 in box 1 and 240.00 in boxes 4 and 12; the British company's first quarter (the VAT return) with 200.00 in boxes 1, 3 and 5 and 1 000.00 in box 6. Asked for before that invoice, both were empty — the imported history carries no tax, as said below.

Filing is yours. Ekwo prepares the figures; it does not send them. Copy them into your tax administration's portal, or give them to whoever files for you. What a declaration goes through after it is computed — freezing it, keeping what was sent, noticing a period that changed afterwards — is in filing.md.

What this does not do yet

Said plainly, so that nothing is a surprise:

  • No web interface in Ekwo OS. Ekwo OS is a database, a command line and the MCP server. The web application is Ekwo Cloud, the hosted edition on ekwo.ai, for the people signed up there.
  • No filing. Ekwo prepares a declaration and does not transmit it to any administration. Sending it, and answering for it, is yours.
  • No VAT on imported history. An imported line has an account and an amount, not the tax that produced it. It feeds the ledger, the trial balance and the financial statements, and no box of a VAT return: a period kept elsewhere was declared from where it was kept.
  • No reconciliation marks. Which invoice a payment settled in the old books is read and not re-applied. Open items are matched again in Ekwo, with reconcile ("match this payment with that invoice").
  • No new accounts. An old account the new chart does not have is not created: you point it at one that exists, or add it first.
  • No documents. Old invoices arrive as the entries they were posted as, not as documents that can be sent again.

compatibility.md keeps the list of sources and of what an import does not take over, and is kept up to date as readers are added. Before you rely on anything Ekwo prepares, read DISCLAIMER.md: a country pack is a reading of the rules at the date of its version, and the books are yours.

Checked for real

Every step above was run against throwaway Supabase projects with the published ekwo-os and @ekwo-ai/mcp 0.7.0 and a project's newer keys — the secret key for the installer, the publishable key for Claude — and the projects deleted afterwards. The run is a script, so it can be repeated on any release: docs/demo/start-with-claude/walkthrough.mjs runs the installer, starts the MCP server with exactly the four variables above, and calls the tools Claude calls for the sentences of this guide — two companies in two countries, the second created through create_company and chosen in the terminal with ekwo use (or, with --no-company, both created by ekwo company new after ekwo init --no-company), the rehearsal, the correction, the import, the refused second import, the balances, an invoice and the two returns. The two trial balances and the answered correspondence are beside it; the data is invented. The two correspondence tables of step 5 are the ones that run printed, reasons included.

Rendered from docs/start-with-claude.md, in the repository, when the site was built. Read or change it on GitHub