- Project overview at README
- Detailed feature descriptions at FEATURES
- Technical deployment details at DOCS
Fund accounting is an optional double-entry ledger, off by default. Turn it on when you want LP numbers to come from real books rather than pasted statements. This covers both halves: standing the books up for a vehicle, and how every entry is booked once they're running.
In this system a vehicle is a portfolio_group: fund_id is the company/installation, and each
SPV / Fund I / Fund II is a portfolio_group under it, with its own separate books (chart,
ledger, capital accounts, bank feed, periods).
Contents
- Setting up a vehicle — prerequisites and the three onboarding scenarios
- Going live & keeping the books
- Management companies — the firm's own books, and intercompany
- Double-entry reference — how each entry type is booked
- The capital-account roll-forward
- Verifying the books — the checks that should always hold
- Authoring in text
- Agents
How to stand up the books for a vehicle — a brand-new fund, or an entity that already exists on the platform.
- Enable Accounting. Settings → Feature visibility → set Accounting to
admin(it shipsoff). It's admin-only. - Apply the migrations (
supabase db push) so the ledger tables exist. If you'd already applied an earlier version of these migrations, convert theportfolio_group/ period columns to an additiveALTERfirst. - LP + commitment data must exist for the vehicle. The allocation basis and the reconcile
answer-key come from
lp_investments(investors → entities → commitment/paid-in/distributions perportfolio_group). A vehicle only appears in the Accounting vehicle selector once it has LP data, a fund-group config, or cash flows for thatportfolio_group. If the entity is already on the platform (e.g. built from an LP report snapshot), this is already done.
Then, in every scenario: pick the vehicle in the selector at the top of the Accounting section — everything you do scopes to it.
The entity's LPs, commitments, and prior figures are already in the platform. You choose how much history to bring in. Both paths start the same:
- Accounting → home → Seed the chart of accounts (one click).
Best when volume is low and you want a complete, auditable trail.
- Bank transactions → paste or Upload CSV/XLS of the bank history from inception. Rows are deduped and each drafts a balanced entry.
- Categorize with AI to classify the fuzzy rows against the chart.
- For each inflow that's a capital call, Book as call (allocates per LP by commitment) or Match call if you already recorded it. Post the drafts.
- Book the investment purchase on the journal's Plain text tab (rare, so it's a text entry):
Dr Assets:Investments-At-Cost:1100 / Cr Assets:Cash:1000. - Record each periodic mark: Journal → New entry → Revalue investment (enter the new fair value; the delta is booked as unrealized, and the close allocates it per LP and moves NAV).
- Reconcile → Load from LP snapshot to prefill the answer-key from
lp_investments, then reconcile the ledger capital accounts against it. Use the statements As of control to tie out at each historical date. - Close & lock each completed period (see Going live).
Best for other vehicles where reconstructing history isn't worth it.
- Accounting → home → choose Cutover opening balance → pick the cutover date → Bootstrap
opening balances. This reads the vehicle's
lp_investmentsand books, as of that date,Dr Cash / Cr each LP's capitalfor paid-in − distributions. (Capital in nets against cash.) - Book the investment purchase on the journal's Plain text tab so cash moves into the investment
(
Dr 1100 / Cr 1000), leaving ending cash = paid-in − cost. - Run forward from the cutover: book new calls/distributions/fees/marks as they happen.
Greenfield: no history to reconstruct — you're the book of record from first close.
- Create the vehicle's LP data first so it appears in the selector: in the LPs section add
the investors/entities and their commitments under the new
portfolio_group(or import them). Set the vehicle's economics on its admin status page (Entities → the vehicle → Admin,/funds/[id]/status): vintage on the vehicle record, plus carry terms (rate, preferred return, catch-up, and the receiving GP entity) and allocation terms (each partner's commitment, including the GP's, and who bears fees, expenses, and carry). - Pick the new vehicle → Accounting → home → Seed the chart of accounts.
- Book from first close forward:
- Capital call: issue it from Capital accounts, then match the wire from the bank feed
— it ends as
Dr Cash / Cr each LP capital. - Investment purchase: the journal's Plain text tab (
Dr 1100 / Cr 1000), or a plain entry. - Management fee / expenses / gains: Journal → New entry (Management fee, Partnership expense, Realized gain) as they occur — each shows the entry before it is written.
- Revalue at each reporting date.
- Capital call: issue it from Capital accounts, then match the wire from the bank feed
— it ends as
- Reconcile cash against the bank feed; close & lock each period.
No bootstrap and no historical import — you simply start posting.
- Deploy against a fresh Supabase project and run all migrations.
- Complete onboarding to create the fund and the first admin user (
fund_members). - Create the first vehicle's LP data (Scenario B, step 1), then follow Scenario A or B per vehicle.
Everything is per-vehicle from there, so the same company can run an SPV and a fund side by side.
- Period close (P&L): Period close allocates each month's income and expenses to the partners' capital accounts through the undistributed-earnings bridge, with a preview first.
- Correct a posted entry: open it in the Journal and Reverse it — a dated contra-entry lands as a draft, the original stays posted, and the pair nets to zero from that date. Void is for drafts and same-day slips; a reversal is what a preparer expects to see. An accrual can be given a Reverses on date when it is entered, and the reversal draft is created for you.
- Lock the period: Periods → Close & lock the date range. This snapshots the whole ledger as plain-text double-entry (the audit record) and blocks any new posting dated inside the range until you reopen it.
- Amend a closed period: Periods → Reopen, post the fix, close & lock again.
- Statements at any date: the Financial statements page has an As of control so every statement can be viewed at a chosen date.
An individual (kind = 'individual') is a person investing for their own account, or the
single-member LLC they do it through — an angel. For tax the LLC is disregarded, so the two keep
the same books.
The investment side of those books is a fund's, code for code: per-company cost and unrealized accounts under 1100/1200, marks, the schedule of investments, realized gains by lot. What differs is the equity and the expenses:
- Equity is one owner. 3000 Owner's capital and 3100 Owner's draws. No GP, no LPs, no commitments, no allocation terms. The pages that exist for partners — Capital accounts, Portfolio construction, the fund-of-funds pages — are hidden.
- Expenses are the preparer's lines. Investment expenses, professional fees, software, travel, home office, dues, education, interest, other — the categories a personal return asks about, so the year-end export keys onto the schedule instead of being reclassified by hand.
- The close rolls into owner's capital. See below. The Tax page's Realized gains by lot is the Schedule D and Form 8949 input; the tax package carries it as a CSV.
A fund's close allocates each P&L category across the partners by their basis. A management
company and an individual have no partners: net income goes to one equity account — members'
capital for a manco, owner's capital for an individual (both carry the subtype members_capital,
which is how the close finds them) — and there is nothing to split. The close still posts one
entry per category through the bridge (3200), tagged close:<period>, so reopening voids exactly
those entries and the statement of operations keeps its lines. Carry, note interest on a fund's
positions and associate economics do not apply and are not run. lib/accounting/close-owner.ts
builds the entries; closesToOwnerEquity in lib/vehicle-kinds.ts decides which kinds take it.
A management company is the firm's own operating entity: it employs the team, collects the management fee and pays the rent. It is not an investment vehicle, and the difference runs deeper than a label — it has no commitments, no NAV, no TVPI and no partners in the LP sense, so almost everything on this page above does not apply to it.
It is therefore a vehicle kind of its own (manco), with its own chart, its own lead page —
cash, the quarterly fee cycle, where the money goes, and what the funds owe it, in place of the
performance page a fund gets — and, this being the part worth reading carefully, its own access
grant (switched on in Settings → Feature visibility).
It is not a section of its own. It was, while its pages were a parallel copy of the fund ones; a
manco keeps double-entry books like any other entity, so those are the same pages now and it is a
row in Entities addressed the same way (/funds/<id>/journal). The grant did not move with the
URL, because the grant never depended on it — see below.
Everywhere else in this system, related things share a grant when one is derivable from the other:
a K-1 is derived from the capital accounts, which ARE the ledger, so tax_reporting sits inside
accounting rather than pretending to a boundary that does not exist.
A management company is the opposite case. Its ledger carries salaries, bonuses and partner draws, and none of that appears anywhere in a fund's trial balance — the fund sees one number, the management fee it pays. The boundary is real, so it is enforced rather than described:
management_companyis a domain of its own, seeded atnonefor every existing member. An admin grants it deliberately, per person. (Every other domain was seeded atwrite, because it was describing behaviour that already existed. This one has none to preserve.)- A manco is excluded from
listVehicles, which is whatresolveVehicleresolves against — so every accounting route, every MCP tool, the Analyst's context and the pending-action builders refuse it by default, without having been changed. Two callers opt in (lib/accounting/http-vehicle.ts) and both check the grant immediately. - Reaching a manco's ledger through the shared accounting pages needs both grants:
management_companybecause the books are the firm's, andaccountingbecause those pages call/api/accounting/*. A manco-only bookkeeper gets the entity list and its lead page — the dashboard, the chart, the statements and intercompany, all/api/manco/*— and needs fund accounting to open the ledger pages. - Because every entity now shares one set of pages, "which grant does this page need" is no longer
answerable from the URL. It is answered from the entity:
requireVehicleAccess(app/(app)/funds/guard.ts) resolves the vehicle every entity page has to resolve anyway, and demandsmanagement_companywhen that vehicle is a manco. It is the page twin ofassertVehicleDomain, and it is deliberately the same shape — the check lives inside the call a page cannot skip, so a new page under/funds/[id]cannot forget it.
tests/manco-vehicle-domain.test.ts pins all of it.
- Settings → Feature visibility → Management company (ships
off). - Entities → Admin → Add vehicle, type Management company. It is the same button that adds a fund; the type decides the chart, the pages and the grant.
- Set up books seeds the chart below. There is no cutover / full-history choice and no capital accounts to create: those are about LPs.
- Import the QuickBooks general ledger from the entity's page if there is history to bring in. The mapping proposer knows the manco vocabulary — payroll, benefits, occupancy, technology — so most accounts arrive already matched.
| Code | Account | Type | Normal side |
|---|---|---|---|
| 1000 / 1050 | Cash — operating / reserve | asset | debit |
| 1100 | Accounts receivable | asset | debit |
| 1300 | Prepaid expenses | asset | debit |
| 1350 | Security deposits | asset | debit |
| 1400 / 1450 | Furniture and equipment / accumulated depreciation | asset | debit |
| 1900 | Due from affiliates | asset | debit |
1900-<id> |
Due from <vehicle> (one per counterparty) |
asset | debit |
| 2000 / 2100 | Accounts payable / accrued expenses | liability | credit |
| 2150 | Accrued compensation | liability | credit |
| 2200 | Payroll liabilities | liability | credit |
| 2400 | Deferred management fee revenue | liability | credit |
| 2500 | Note payable | liability | credit |
| 2900 | Due to affiliates | liability | credit |
2900-<id> |
Due to <vehicle> (one per counterparty) |
liability | credit |
| 3000 / 3100 | Members' capital / member distributions | equity | credit |
| 3200 | Undistributed earnings (bridge) | equity | credit |
| 4000 | Management fee income | income | credit |
| 4100 | Expense reimbursement income | income | credit |
| 4200 / 4900 | Interest income / other income | income | credit |
| 5000 / 5010 / 5020 / 5030 | Salaries / payroll taxes / benefits / bonus | expense | debit |
| 5100 | Rent and occupancy | expense | debit |
| 5200 / 5210 / 5220 | Legal / audit and tax / fund administration | expense | debit |
| 5300 / 5400 / 5500 | Technology / travel / marketing | expense | debit |
| 5600 / 5700 | Insurance / office and general | expense | debit |
| 5800 / 5900 | Depreciation / interest expense | expense | debit |
Three of these are decisions rather than lines, and they are why a fund chart cannot be reused:
- Compensation is four accounts, not one. "What does a head cost us" is 5000+5010+5020; "what did we pay out on last year's performance" is 5030. Rolled together, neither question can be answered again from the ledger.
- 2400 exists because the fee is billed before it is earned. A quarterly fee charged in advance lands on 1 January for a quarter that has not happened. Recognising all of it in January overstates Q1 revenue by two thirds; 2400 holds the unearned part and releases it monthly.
- 1900 and 2900 never net. What the funds owe the firm and what the firm owes them are balances with different counterparties settling on different dates, and each has to be confirmed against another entity's books. A net figure matches neither side.
3200 is the same bridge the fund chart uses, and a manco needs it for the same reason: the period close flattens the P&L into it and rolls the result into members' capital.
A charge between two vehicles of the same firm is one economic fact and two ledgers. Entered as two ordinary journal entries, nothing knows they are the same charge: the firm's receivable and the fund's payable are independent numbers that agree only while both were typed correctly, and when they stop agreeing there is no way to tell which one moved.
So Record a charge on the management company's page writes both sides in one action, each
entry tagged source_ref = intercompany:<id>, with the pair recorded in
intercompany_transactions.
Accrual (management fee, expense reimbursement, allocated cost, other):
payee (the firm) Dr 1900-<payer> Cr 4000 Management fee income
payer (the fund) Dr 5000 Management fee Cr 2900-<payee>
Settlement, when the cash actually moves — a separate event, often a separate quarter:
payee Dr 1000 Cash Cr 1900-<payer>
payer Dr 2900-<payee> Cr 1000 Cash
Advances and repayments move cash as they are recorded, so they have one event and no settlement of their own — an advance is cleared by recording a repayment, because that is what happened.
Two things follow from the design and are worth knowing:
- The balance shown per counterparty is read off the ledger (the 1900-
<id>/ 2900-<id>accounts), never summed from the register. A manual correcting entry — how half of all intercompany disputes are actually resolved — is reflected without anyone amending a row. - Both sides post or neither does. If the payer's entry fails (a closed period on the fund's books is the realistic case), the payee's entry is voided and the charge is removed.
Each side's accounts are resolved from its own chart by subtype, so a fund, a GP entity and another management company can all be the counterparty. Where a side has no defensible account for the charge, the post is refused with a message naming what is missing — a charge in the wrong income account still balances, so nothing downstream would ever flag it.
Neither capital_contribution nor equity funding is an intercompany charge: funding an affiliate is
equity, not a balance one side can demand back, and it is booked as an ordinary entry against
members' capital on both sets of books.
No capital accounts, no capital calls, no schedule of investments, no allocation terms, no waterfall, no LP statements, no K-1s. It has no limited partners. Its period close rolls the operating result into members' capital and nothing else.
It is also excluded from the /funds overview, the fund switcher, and per-vehicle performance
roll-ups. Every column there would be a dash.
How every entry type is booked, in both T-account form and the plain-text double-entry format you
author in. Use this to write entries on the journal's Plain text tab and to verify the books are set up
correctly. Everything here matches what the entry builders in lib/accounting/entries.ts produce.
- Signed amounts, debits positive. Every posting is a signed number: a debit is positive, a credit is negative.
- Every entry sums to zero (per currency). If it doesn't balance, it can't be posted.
By convention, a posting's amount is simply the signed change to that account, so the plain text and the ledger agree with no sign flipping.
| Code | Account | Type | Normal side |
|---|---|---|---|
| 1000 | Cash | asset | debit |
| 1100 | Investments at cost | asset | debit |
| 1200 | Unrealized appreciation/(depreciation) | asset | debit |
| 1300 | Due from LPs | asset | debit |
| 2000 | Accrued expenses | liability | credit |
| 2100 | Due to GP | liability | credit |
| 3000 | Partners' capital — GP | equity | credit |
| 3100 | Partners' capital — LP (unallocated) | equity | credit |
| 3200 | Undistributed earnings (bridge) | equity | credit |
3100-<id> |
Partners' capital — <LP name> (one per LP) |
equity | credit |
| 4000 | Realized gains | income | credit |
| 4100 | Interest and dividend income | income | credit |
| 4200 | Change in unrealized appreciation | income | credit |
| 5000 | Management fee | expense | debit |
| 5100 | Partnership expenses | expense | debit |
| 5200 | Organizational expenses | expense | debit |
Per-LP capital accounts (3100-<id>) are created automatically the first time an allocation touches
that LP. In text they read Equity:Partners-Capital-<Name>:3100-<id>.
Fees, expenses, and income need to be in two places: the income statement (as expense/income)
and each LP's capital account (reducing/increasing it). The entry you book — by hand, from the
journal's New entry menu, or from the bank feed — posts the P&L side only (Dr 5000 / Cr 2100
for a fee). The period close then posts the capital side for every category in the month: it
debits or credits each partner's capital account for their share and parks the offset in
Undistributed earnings (3200). During a period the income statement is right and the capital
accounts lag by the unclosed month; at close they catch up, and the balance sheet's unallocated
earnings line goes to zero. The T-accounts for entries 4–7 below show the whole economic picture,
the P&L line and the capital lines together; the capital lines are the close's, not the entry's.
Each type below shows the debits/credits, the source (which drives the capital-account roll-forward
line), and the text you'd author. Dr = positive, Cr = negative.
Take over at a date with each LP's capital from their last statement. Capital in nets against cash — the opening credits each LP's capital and debits Cash; the investment purchase is booked separately (entry 3), which moves that cash into the investment. Roll-forward line: beginning.
| Account | Dr / Cr |
|---|---|
| 1000 Cash | Dr total |
3100-<id> each LP capital |
Cr their opening balance |
2021-06-30 * "Opening capital (cutover)"
source: "opening_balance"
Assets:Cash:1000 3000000.00 USD
Equity:Partners-Capital-John-Smith:3100-aaaa -1800000.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb -1200000.00 USD
After this, book the investment purchase (entry 3) to move cash into the investment, so ending cash = paid-in − investment cost.
Cash comes in; each LP's capital increases pro-rata by commitment. Line: contributions.
| Account | Dr / Cr |
|---|---|
| 1000 Cash | Dr total |
3100-<id> each LP capital |
Cr their share |
2021-07-01 * "Capital call — Q3"
source: "capital_call"
Assets:Cash:1000 5000000.00 USD
Equity:Partners-Capital-John-Smith:3100-aaaa -3000000.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb -2000000.00 USD
Buy the SPV's investment. No allocation — just moves cash into the asset. There is no dedicated action; book it here in text (or via a bank outflow re-categorized to 1100).
| Account | Dr / Cr |
|---|---|
| 1100 Investments at cost | Dr cost |
| 1000 Cash | Cr cost |
2021-07-15 * "Investment — purchase"
Assets:Investments-At-Cost:1100 4800000.00 USD
Assets:Cash:1000 -4800000.00 USD
Expense hits the income statement; each LP's capital is reduced. Line: managementFees.
| Account | Dr / Cr |
|---|---|
| 5000 Management fee (expense) | Dr total |
| 2100 Due to GP (liability) | Cr total |
3100-<id> each LP capital |
Dr their fee |
| 3200 Undistributed earnings | Cr total |
2021-09-30 * "Management fee — Q3"
source: "management_fee"
Expenses:Management-Fee:5000 50000.00 USD
Liabilities:Due-To-Gp:2100 -50000.00 USD
Equity:Partners-Capital-John-Smith:3100-aaaa 30000.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb 20000.00 USD
Equity:Undistributed-Earnings:3200 -50000.00 USD
Paying the fee later is a separate plain entry: Dr 2100 Due to GP / Cr 1000 Cash.
Same shape as the fee, but paid from cash and allocated pro-rata. Line: expenses.
| Account | Dr / Cr |
|---|---|
| 5100 Partnership expenses | Dr total |
| 1000 Cash | Cr total |
3100-<id> each LP capital |
Dr their share |
| 3200 Undistributed earnings | Cr total |
2021-10-05 * "Audit fee"
source: "partnership_expense"
Expenses:Partnership-Expenses:5100 12000.00 USD
Assets:Cash:1000 -12000.00 USD
Equity:Partners-Capital-John-Smith:3100-aaaa 7200.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb 4800.00 USD
Equity:Undistributed-Earnings:3200 -12000.00 USD
Cash/income in; each LP's capital increases. Line: gains.
| Account | Dr / Cr |
|---|---|
| 1000 Cash | Dr total |
| 4000 Realized gains (income) | Cr total |
| 3200 Undistributed earnings | Dr total |
3100-<id> each LP capital |
Cr their share |
2023-03-01 * "Partial realization"
source: "realized_gain"
Assets:Cash:1000 500000.00 USD
Income:Realized-Gains:4000 -500000.00 USD
Equity:Undistributed-Earnings:3200 500000.00 USD
Equity:Partners-Capital-John-Smith:3100-aaaa -300000.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb -200000.00 USD
Mark the investment to a new fair value. You enter the new fair value; the system books the delta vs the current carrying value. Line: gains. (A mark-down flips every sign.)
| Account | Dr / Cr |
|---|---|
| 1200 Unrealized appreciation (asset) | Dr delta |
| 4200 Change in unrealized (income) | Cr delta |
| 3200 Undistributed earnings | Dr delta |
3100-<id> each LP capital |
Cr their share |
2022-12-31 * "Year-end mark"
source: "valuation"
Assets:Unrealized-Appreciation:1200 1000000.00 USD
Income:Change-In-Unrealized-Appreciation:4200 -1000000.00 USD
Equity:Undistributed-Earnings:3200 1000000.00 USD
Equity:Partners-Capital-John-Smith:3100-aaaa -600000.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb -400000.00 USD
Cash out to LPs; each LP's capital decreases. Line: distributions.
| Account | Dr / Cr |
|---|---|
3100-<id> each LP capital |
Dr their distribution |
| 1000 Cash | Cr total |
Declaring from the Capital accounts page posts the same debit against 2300 Distributions payable instead of cash; the wire that follows settles the payable (source: distribution_settlement), which is what lets a bank row match back to the declaration. A fund-wide declaration is split through the vehicle's waterfall (lib/accounting/distribution-waterfall.ts): prior distributions are replayed through the tiers to find where return of capital, the preferred return and the GP's catch-up stand, and only then is this one split. The GP's take posts as a second entry with source: carry_distribution — Dr the recipient's capital, Cr 2300 — which the roll-forward files on the carried interest line against the accrual, so a paid carry reads as carry paid rather than as a return of the GP's own capital. Both entry ids sit on the distributions register row with the tier amounts and the split method.
2023-03-15 * "Distribution"
source: "distribution"
Equity:Partners-Capital-John-Smith:3100-aaaa 300000.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb 200000.00 USD
Assets:Cash:1000 -500000.00 USD
Move profit from LPs to the GP. Line: other (on the LP roll-forward).
| Account | Dr / Cr |
|---|---|
3100-<id> each LP capital |
Dr their carry |
| 3000 Partners' capital — GP | Cr total |
2023-03-15 * "Carried interest"
source: "carried_interest"
Equity:Partners-Capital-John-Smith:3100-aaaa 60000.00 USD
Equity:Partners-Capital-Acme-LLC:3100-bbbb 40000.00 USD
Equity:Partners-Capital-Gp:3000 -100000.00 USD
Zero every income/expense account into the bridge. No LP postings — capital is already current.
| Account | Dr / Cr |
|---|---|
| each income/expense account | the negation of its balance |
| 3200 Undistributed earnings | the net |
2022-12-31 * "Period close"
source: "period_close"
Income:Realized-Gains:4000 500000.00 USD ; was a -500000 credit balance
Expenses:Management-Fee:5000 -200000.00 USD ; was a +200000 debit balance
Equity:Undistributed-Earnings:3200 -300000.00 USD
A SAFE or convertible note converting into a priced round (e.g. Series A). In the tracker it is
recorded as the priced-round investment it becomes, linked to the instrument it converted from
(converts_from_txn_id); there is no separate transaction type. Saving it drafts the entry
below — like every tracker→ledger mirror, it lands as a draft for review, not a post.
A conversion is a pure roll-over — it carries no cash of its own. New money written at the same
round is recorded as a separate investment row (same round name), so it stays a distinct line.
The source instrument's principal is already in 1100 from its own purchase date and is never
re-posted. The conversion books only what changes on the conversion date, as one entry with up
to three independently-balanced pieces:
| Account | Dr / Cr | When present |
|---|---|---|
1100-<co> Investments at cost |
Dr interest | a note with accrued interest |
1150-<co> Accrued interest |
Cr interest | a note with accrued interest |
1200-<co> Unrealized appreciation |
Dr step-up | round price ≠ carried basis |
| 4200 Change in unrealized (income) | Cr step-up | — |
where carried basis = source principal + converted interest, and step-up = (shares × round price) − carried basis (negative on a down round → an unrealized loss). With no round price the position is held at carried cost and no step-up is booked. (A pure SAFE conversion with no interest books only the step-up.)
2022-06-01 * "Conversion to equity — Acme (Series A)" ; $100k SAFE → 50,000 @ $3.00 = $150k
source: "investment"
Assets:Unrealized-Appreciation:1200-acme 50000.00 USD ; the +$50k step-up
Income:Change-In-Unrealized-Appreciation:4200 -50000.00 USD
; a pure conversion moves no cash and does not touch 1100 — the principal is already there
How it reaches the statements (all derived from the posted ledger):
- Balance sheet — the position's carrying value (
1100 + 1200) becomes shares × round price;1150accrued interest clears into basis. (Any new check at the round is its own investment row.) - Statement of operations — the step-up is change in unrealized appreciation (
4200), in the period of the conversion date, not the SAFE's original date. Interest that accrued before conversion already hit4100over prior closes, so it is not re-recognized here. - Cash flows — a conversion moves no cash, so it appears under supplemental non-cash investing & financing (ASC 230), never as an outflow. (A new check at the round is a separate investment row and shows as its own operating outflow.)
- Schedule of investments — cost = carried basis, fair value = shares × round price, and the
ledger ties to the tracker because the step-up actually posted to
1200. - Changes in partners' capital — the step-up allocates to LPs (line gains) at the next period close; until then it sits in unallocated earnings.
Each LP's statement is built from the postings to their capital account, bucketed by the entry's
source:
ending = beginning
+ contributions (capital_call)
- distributions (distribution)
- management fees (management_fee)
- partnership expenses (partnership_expense)
+ gains (realized_gain, valuation)
+ other (carried_interest, anything else)
ending is computed as the raw sum of that LP's capital postings, so it always ties to the
ledger regardless of how lines are labeled. Fund NAV = sum of every LP's ending capital.
Checks that should always hold — use these to confirm a new setup and to sanity-check a close:
- Every entry balances. The journal (the entry form and the Plain text tab) rejects unbalanced entries; the trial balance (Financial statements) shows equal total debits and credits.
- Balance sheet identity. Assets = Liabilities + Partners' capital. On the Financial statements
page the balance-sheet
checkis 0 once the period is closed (before close, the residual equals net income not yet closed to capital). - NAV ties. Fund NAV on the Capital accounts page = sum of the LPs' ending capital = the equity total on the balance sheet.
- Bridge nets to zero after close. Account 3200 Undistributed earnings should be 0 once you've run the period close; income/expense accounts should be 0 too.
- Reconcile against the LP snapshot. On Reconciliation → Load from LP snapshot, contributions should match paid-in and distributions should match the LP data already in the platform.
- Bank reconciliation. Ledger cash (1000) equals the bank feed's ending balance once every transaction is matched.
- Per-vehicle isolation. Each
portfolio_grouphas its own chart, entries, and capital accounts; switching the vehicle selector should change every figure.
- A transaction is
DATE FLAG "narration"then indented postings.*posts;!saves a draft. - Reference accounts by full name (
Assets:Cash:1000) or just the code is matched from the last component. Unknown accounts are reported, never guessed. - One posting per entry may omit its amount — it's inferred so the entry balances.
source: "<type>"metadata sets the roll-forward line; omit it for a plainmanualentry.- Lines starting with
;are comments;open/close/other directives are ignored.
Everything above is also available to agents over MCP/REST (Settings → Agent access): seed the
chart, import a bank feed, categorize, book calls, revalue, author entries as text, reconcile, and
close periods — each scoped to a vehicle via the vehicle argument.