Skip to main content

GESAMT//Unitbook

PyPI

Every artifact it produces carries the mark GESAMT//Unitbook <version> · <ledger head>, naming the software and the exact ledger state the sheet was rendered from.

You trade one exchange account, and part of the money in it belongs to other people. Unitbook tracks who owns how many units of that account, prices the units every time you record the account equity, charges your performance fee by burning units instead of moving cash, and writes every step into a signed, hash-chained log. It answers one question exactly: if this investor withdrew today, how much would they get, and can they prove the number is not something you typed into a spreadsheet last night.

It runs on your laptop. There is no server, no database, no account to open, and no network call except a version check against PyPI. Your book is a folder of files. You can drive it from a chat agent over MCP, from a spreadsheet and a double click, or by typing commands. All three write the same log.

Install · Owner guide · Agent guide · Concepts · Investor verification · FAQ

Quick start

Download GESAMT-Unitbook-<version>-arm64.pkg, double click it, and a setup window opens. It asks for your activation code, walks you through creating the book, and offers to connect your AI agent. The installer is not signed by Apple yet, so on the very first launch right-click the .pkg and choose Open instead of double clicking; macOS asks once.

If you would rather use Terminal, paste the one line the developer sent you. Your activation code is already in it:

curl -LsSf https://astral.sh/uv/install.sh | sh && ~/.local/bin/uv tool install unitbook && ~/.local/bin/uv tool update-shell && ~/.local/bin/unitbook setup ub1.xxxxxxxx

Either way you end up in unitbook setup, the whole onboarding in one word: it activates your licence, runs the book wizard where you are standing, offers to connect your agent, and prints what to do next. Rerun it any time; it skips what is done. The wizard asks, in your own language, for the language, book name, currency, your name as manager (plus a short latin code, unless your name already is one), fee percentage, high-water mark style and timezone, confirms with a summary, then prints a 12 word recovery phrase once. Photograph it before pressing Enter. It is the only backup of the key that signs your log.

The folder is now the book, and you never pass its path again:

book.toml  book.pub  events.jsonl  holders.csv  terms.csv
AGENTS.md  journal.xlsx  Unitbook.command

Full detail, including Linux and PATH, is in install.

Record the first day. A mark is the equity on the exchange before any money moved that day, so a book always starts from a mark. On a terminal every verb asks for whatever you left out and shows the diff before it writes, so you can type them bare:

unitbook mark
unitbook holders add
unitbook deposit
unitbook state
book.currency: USD
book.name: Fund
equity: 50000.00
head.id: ab3756f851ad5b8c36c9a957ae96844d8d692fd156a86a4dcc44130ddcb43cf1
head.seq: 6
holders:
  id     manager  name   status  units         value
  farm   true     Farm   active  0             0.00
  vasya  false    Vasya  active  50000.000000  50000.00
nav: 1
total_units: 50000.000000
version: 0.1.0

Abridged: the real body also carries the book's language and timezone, the terms in force, any pending proposals, your licence, an update flag, first_run (true on a book never used), and next, a short list of suggested follow-up verbs every call carries. unitbook state is the one call that shows everything; bare unitbook at a terminal opens a shell instead of typing each one -- a status line (book, price per share, investors, balance as of today, pending proposals) stays pinned at the bottom while every result scrolls up and stays on screen, and the prompt takes any verb (deposit, mark, ...) plus balance for recording what the exchange shows you, with arrow-key completion. Command words are English only, in either language's book. quit or Ctrl-D leaves; unitbook menu keeps the old one-round numbered menu for a script or the double-click .command.

How it works

A book is an append-only log of typed events. Nothing is ever edited or deleted. Every number you see is recomputed by folding that log from the first event, so two people with the same log always get the same answer.

Money in buys units at the current unit price. Profit does not create units, it makes each existing unit worth more. That is the whole trick: a deposit in the middle of a profitable month cannot dilute anybody, because the depositor buys in at that day's price.

Here is a real book. Three holders on day one, at a unit price of 1.00. Written out with flags so you can reproduce the numbers; on a terminal you would type unitbook deposit and answer the questions.

unitbook mark --equity 0 --on 2026-09-01
unitbook deposit --holder farm  --amount 20000.00 --on 2026-09-01
unitbook deposit --holder vasya --amount 50000.00 --on 2026-09-01
unitbook deposit --holder petya --amount 30000.00 --on 2026-09-01

The account is worth 100 000 and there are 100 000 units. A month later the exchange shows 112 000. Recording that mark shows what it would do before it does it:

unitbook mark --equity 112000.00 --on 2026-09-30 --dry-run
What will change:
Holder  Units                         Value
farm    20000.000000 -> 22571.428571  20000.00 -> 25279.99
petya   30000.000000 -> 29035.714285  30000.00 -> 32519.99
vasya   50000.000000 -> 48392.857142  50000.00 -> 54199.99
Equity: 100000.00 -> 112000.00
Unit price: 1 -> 1.120000000000
A performance fee is charged: petya burns 964.285715 units.
A performance fee is charged: vasya burns 1607.142858 units.

Read it in numbers. The unit price went from 1.00 to 1.12. Vasya holds 50 000 units, so he gained 50 000 x 0.12 = 6 000, and the fee is 30 % of that, 1 800. Instead of moving 1 800 in cash, the book burns 1 800 / 1.12 = 1 607.142858 of his units and mints 1 607.142857 of them to the manager. He keeps 48 392.857142 units worth 54 199.99. Petya gained 3 600, pays 1 080, keeps 32 519.99. The manager now holds 25 279.99.

54 199.99 + 32 519.99 + 25 279.99 = 111 999.97, three cents under the equity. Units are issued down and burned up, so no holder can ever withdraw a cent more than they are entitled to; the residual stays in the pool.

Confirm, and the three events are appended, signed and chained. unitbook explain --seq 12 prints the arithmetic behind any one of them in words. See concepts.

Two ways to use it

With an agent

Register the book with every MCP host on the machine with unitbook mcp --install. It detects Codex, Claude Code, Cursor and Claude Desktop from a shipped registry, writes one server entry into each config it finds, leaves everything else in those files alone, and reports one row per file saying created, updated or unchanged. --dry-run shows what it would write; unitbook mcp --print gives you the JSON to paste into a host the registry does not know.

The MCP server exposes one tool per verb with real argument names, and repeats the operating rules in every tool description. init also drops AGENTS.md beside the book, which is what a cold agent reads before its first call. The rules: never invent a mark, and ask when the equity is unknown; mark before flow; normalise any input (text, a voice note, a screenshot, a spreadsheet) to typed events and ask when a field is ambiguous; propose, show the diff, and commit only after the owner confirms; never edit the book's files, because undo is the only correction; report one line per event, being date, price per share, units moved and value.

So the ritual is always propose, show, commit. The agent sends typed events to propose, which prices them against the current head and writes nothing:

echo '[{"type":"mark","on":"2026-10-31","equity":"120000.00"},
       {"type":"withdraw","on":"2026-10-31","holder":"farm","amount":"3000.00"}]' \
  | unitbook propose --table
What will change:
Holder  Units                         Value
farm    22571.428571 -> 21619.986903  25279.99 -> 25943.98
petya   29035.714285 -> 28455.005951  32519.99 -> 34146.00
vasya   48392.857142 -> 47425.007142  54199.99 -> 56910.00
Equity: 112000.00 -> 117000.00
Unit price: 1.120000000000 -> 1.200000000024
A performance fee is charged: petya burns 580.708334 units.
A performance fee is charged: vasya burns 967.850000 units.

That is the terminal view; piped to another program the same call answers in JSON instead.

It shows you that diff, and only then unitbook commit 2e6e2a6596e8 writes it: committed: 13, 14, 15, 16. Commit can only ever write the events priced in that proposal. If the log moved in between it refuses rather than repricing silently, and proposals expire after 24 hours.

The exit code carries the meaning, so an agent never has to read prose. 0 is done. 2 is refused, with reason from a fixed enum and hint saying what to pass instead. 3 needs input, with questions already phrased in the book's language to relay verbatim. 4 is an internal error, with bundle, the path to a crash report.

A refusal: {"hint": "holder 'nobody' is not an active holder", "reason": "unknown_holder", "schema_version": "1"}. A question: {"questions": ["What was the equity on 2026-10-10, before the day's flows?"], "schema_version": "1"}.

Payload shapes, idempotency keys, dry runs and events --since are in the agent guide.

Without an agent

No agent, no internet, no terminal typing. Two spreadsheet files with one writer each.

journal.xlsx is yours. Open it in Google Sheets, Numbers or Excel and add rows: date, type, holder, deposit, withdrawal, withdrawal type, equity, note. The headers are in the book's language, and Unitbook only ever reads this file.

Then double click Unitbook.command. It is a file, not an app: it sits in the book folder right next to journal.xlsx, and you open it in Finder the same way you open anything else. It imports the new rows, prints what they would do, waits for Enter, and commits:

Equity: 135000.00 -> 140000
Unit price: 1.384615384672 -> 1.384615384712
  petya 27316.812617 -> 30927.923727
    37823.27 -> 42823.27

Review the events above.
Commit to the book? Enter to confirm, Ctrl+C to cancel:

After Enter it rewrites book.xlsx (the engine's mirror of the whole book), statements/<holder>.xlsx (one per investor, with the pin they can verify) and export.zip. Clicking twice commits once: each row's identity is a hash of its contents, so a re-import proposes nothing and an edited row proposes a replacement, not a duplicate.

Proof

Every event carries the hash of the previous one and an ed25519 signature over its own id. Change one byte anywhere and every event after it stops matching:

unitbook verify
findings:
  code     hint                                                                                                                                                     seq
  bad_id   id is e2cbd7957b257ccc0d48bbc6defcb8f4ea36a18fe415e13a805ef35440d251a4, body hashes to f2cbd7957b257ccc0d48bbc6defcb8f4ea36a18fe415e13a805ef35440d251a4  1
  bad_sig  does not verify against key a0482ad9ba8b0d14                                                                                                             1
head_seq: 9
ok: false

On an intact book, findings is empty and ok: true. verify reports every finding it can see rather than stopping at the first, and always exits 0: a broken book is a result, not a crash.

The signing key lives in ~/.unitbook/keys/ at mode 0600 and never enters the book folder. unitbook keys restore --phrase "..." brings it back on a new machine from the 12 words (or 24, for a book made before 2026-09-06). unitbook keys rotate writes the new public key into the chain as an event, so old signatures keep verifying at their own position and history is never re-signed. Losing the phrase never loses the ledger, only the ability to append until you restore or rotate.

Every statement carries a pin: the sequence number and hash of the log head when it was cut. An investor checks the statement against the log you sent them with unitbook verify --seq 21 --hash 59fadeb0684fbb..., and gets the same ok: true and empty findings. A truncated log fails the pin. A statement cut from a longer log fails it too. All of it runs offline, on the investor's own machine, against book.pub. See investor verification.

Files in a book

file written by what it is
events.jsonl Unitbook the log. One signed, chained event per line. The book.
book.toml init name, currency, language, decimals, genesis date, timezone, key id
book.pub init the public key an investor verifies against
holders.csv Unitbook projection of the holder events, for reading
terms.csv Unitbook projection of the terms events, for reading
AGENTS.md init the operating rules an agent reads before its first call
CLAUDE.md mcp --install one line, @AGENTS.md, for hosts that do not read AGENTS.md
journal.xlsx you your input rows. Unitbook only reads it.
Unitbook.command init double click: import, confirm, commit, render, export
book.xlsx render the engine's mirror of the whole book
statements/<id>.xlsx statement one investor statement, with its pin
export.zip export the investor package and the off-box backup, in one file
trace.jsonl every call one line per call: verb, exit code, duration. No amounts, no names.
proposals/ propose pending proposals, expiring after 24 hours
crashes/ on exit 4 crash bundles
.lock every write single writer. A second writer is refused with locked.

Verbs

unitbook <verb> --help prints the arguments for any of these. Every mutating verb also takes --idem <key>, where repeating a key returns the original result and writes nothing, and --dry-run, which is identical to propose.

verb mutating what it does
setup yes activate, create the book, connect the agent, all in one
activate no install a licence from a code or a file
init yes create a book in an empty directory
state no the whole picture in one call: holders, units, values, price per share, terms, head
schema no JSON schema of every verb plus the refusal-reason enum
guide no print a shipped guide: owner, agent or investor — offline copies of these docs
events no log envelopes after a seq
explain no the arithmetic behind one event, in words
doctor no check the book and its surroundings
replay no re-fold the log and rewrite the csv projections
verify no check the log, and a statement's pin, against the public key
propose no typed events in, one diff out, nothing written
mark yes record equity before the day's flows
deposit yes pay money in
withdraw yes take money out
terms yes record fee terms (terms set)
holders yes record or retire a holder (holders add, holders retire)
commit yes commit exactly the events of one proposal
undo yes reverse one event
import yes read new rows from journal.xlsx
render no write book.xlsx
statement no write a holder statement
export no write the investor package zip
keys yes show, restore or rotate the signing key
mcp no serve this book over MCP, or print or install the host config

Output is readable text on a terminal and JSON everywhere else; --json and --table force either. Every body carries schema_version. The same call twice produces the same bytes, so two runs can be diffed.

Configuration

Nothing numeric lives in code. Three nouns, all data. book.toml is written once by the wizard (name, currency, lang, money_dp, units_dp, nav_dp, genesis, tz, signer); its immutable fields are hashed into the first event, so changing them later breaks verification. holders.csv and terms.csv are projections: you append events and Unitbook rewrites them, and verify reports config drift if one was edited by hand.

Terms rows are effective-dated, so a new row never reprices an earlier period:

from,holder,fee_rate,hwm,crystallise,hurdle
2026-09-03,*,0.30,every_mark,every_mark,0

hwm is every_mark or ratchet; crystallise is every_mark or on_withdraw, and a withdrawal settles its own fee either way. Change them with unitbook terms set; monthly is refused, so mark once a month with every_mark. The arithmetic is in concepts, the day-to-day in the owner guide.

One book counts in exactly one currency. A deposit in another asset records asset, qty, rate and rate_source, which the engine checks against the amount. A second currency is a second book.

Licence, updates and reporting

Unitbook is proprietary software, licensed to named people. Your grant is a signed license.json in ~/.unitbook/, installed by unitbook activate. Without a valid licence every verb refuses with reason: unlicensed.

On start, at most once an hour, Unitbook asks pypi.org for the newest published version; a successful check also renews your licence for 30 days. It never blocks the ledger, and if PyPI is unreachable the check is skipped. If no check succeeds for 30 days the licence stops working; upgrade with uv tool upgrade unitbook.

The software reports crashes and anonymous usage statistics (no amounts, no holder names) to the licensor. This reporting is part of the software and cannot be disabled. What goes out is listed in the FAQ.

Every statement, book.xlsx, export zip and JSON body carries the provenance mark GESAMT//Unitbook <version> · <ledger head>. It says which software produced the sheet and which exact ledger state it was rendered from, and it cannot be switched off.

Copyright (c) 2026 Gesamt Team. See LICENSE.

Быстрый старт

Установка на Mac, один раз, около пяти минут.

  1. Скачай GESAMT-Unitbook-<версия>-arm64.pkg и открой его. Установщик пока не подписан у Apple, поэтому в первый раз кликни по файлу правой кнопкой и выбери «Открыть»; macOS спросит один раз. Откроется окно установки.

  2. Оно спросит код активации, потом язык, название книги, валюту, твоё имя как управляющего (и короткий код латиницей, если имя не подходит), комиссию, тип максимума и часовой пояс, покажет сводку для проверки и предложит подключить агента. В конце покажет 12 слов ОДИН раз: сфотографируй их, потом жми Enter. Без них нельзя восстановить ключ подписи (сама книга при этом не теряется). Папку книги держи внутри Google Drive в режиме «Зеркало» (Mirror), не «Поток» (Stream). Кто предпочитает Терминал: вставь ту одну строку, которую прислал разработчик, в ней уже есть код активации.

  3. В папке книги появится journal.xlsx. Это твой журнал: Дата · Тип · Инвестор · Пополнение · Вывод · Тип вывода · Капитал на счёте · Комментарий. Правь его в Google Таблицах, Numbers или Excel, как привык.

  4. После новых строк: двойной клик по Unitbook.command. Это файл в папке книги, рядом с journal.xlsx; открывается двойным кликом в Finder. Он покажет, что запишет, ждёт Enter, и готово: book.xlsx (зеркало книги), statements/<инвестор>.xlsx (выписки), export.zip (пакет для инвесторов). Второй клик без новых строк ничего не запишет.

Через агента (Codex, Claude, Cursor): один раз unitbook mcp --install, дальше просто говоришь «Вася внёс 500», агент сам предложит запись и попросит подтвердить.

Проверка: unitbook doctor — всё зелёное, значит порядок.

Отчёты об ошибках и статистика использования отправляются разработчику. Суммы и имена не отправляются.

Metadata

Release files for unitbook 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for unitbook 0.1.5
File Interpreter ABI Platform
unitbook-0.1.5-py3-none-any.whl Python 3 none any Details

Release files / unitbook-0.1.5-py3-none-any.whl

Download URL unitbook-0.1.5-py3-none-any.whl
Size 338.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f2082b263a0249a0b24fdbd1ae92d2a191bd55087c41f3d56cfe32dae049a70e
BLAKE2b-256 checksum
How to use checksums
fb063f0540e81656fe850216a90919ef13c59567b29f57f68567e04dea6ad362
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.9 {"installer":{"name":"uv","version":"0.12.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.2.1

1 release file

0.2.0

1 release file

0.1.13

1 release file

0.1.12

1 release file

0.1.11

1 release file

0.1.10

1 release file

0.1.9

1 release file

0.1.8

1 release file

0.1.7

1 release file

0.1.6

1 release file

This release

0.1.5 This release

1 release file

0.1.4

1 release file

0.1.3

1 release file

0.1.2

1 release file

0.1.1

1 release file

0.1.0

1 release file

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page