---
name: prep-journal-entry
description: "Use when the user says 'book the accrual journal entry' / 'draft the depreciation journal entry for Q1' / 'post the prepaid amortization' / 'revenue recognition this period' / 'stock-comp journal entry' / 'reclass this expense'  -  I draft a balanced double-entry journal entry that branches on `type`: `accrual` | `prepaid` | `payroll` | `revrec` | `depreciation` | `stock-comp` | `adjustment` | `reclass`. Every journal entry is validated balanced to 1 cent, every account code is validated against `config/chart-of-accounts.json`, and the entry is written at `status: \"draft\"`. Sub-mode `type=accrual mode=reversing` auto-reverses every active accrual flagged `reversing=true`. Draft-only  -  I never post to QuickBooks Online / Xero."
version: 1
category: Bookkeeping
featured: no
image: ledger
integrations: [quickbooks, xero, linear]
---


# Prep Journal Entry

One balanced journal entry from type-specific template. Invariants enforced every write: debits equal credits within 1 cent, every `glCode` exists in locked chart of accounts, `status: "draft"` (never `posted` without explicit user confirm), `reversing: true` requires `reversesEntryId` + opposite sign convention.

Draft-only: write markdown + index row; user/accountant post to QuickBooks Online / Xero.

## When to use

- "book the accrual journal entry" / "draft the depreciation journal entry for Q1" / "post the prepaid amortization".
- "revenue recognition journal entry for March" / "stock-comp journal entry for the period".
- "reclass this $X from General & Admin to R&D" / "book this adjustment".
- "book the payroll journal entry from Gusto / Rippling / Justworks"  -  use `type=payroll` with the pay-period summary.
- "post the reversing entries for this period" / "draft this period's reversals"  -  use `type=accrual mode=reversing` to auto-reverse every active accrual flagged `reversing=true`.
- Called by `run-monthly-close` for every due standard journal entry in close loop.

## Connections I need

I run external work through Composio. Before this skill runs I check that the categories below are linked. Missing → I name the category, ask you to connect it from the Integrations tab, stop.

- **Payroll provider** (Gusto, Rippling, Justworks, Deel, ADP) — required for `type=payroll` if you want me to pull the pay-period summary directly. Otherwise you paste the summary.
- **QuickBooks Online or Xero** (accounting) — optional, used to cross-check account codes for `type=adjustment` or `type=reclass`.
- **Linear** — optional, only used to look up project context if you want a memo grounded in a ticket.

If `type=payroll` and no payroll connection exists I stop and ask you to connect Gusto / Rippling / Justworks, or paste the pay-period summary.

## Information I need

I read your bookkeeping context first. For every required field that's missing I ask ONE plain-language question (best modality: connected app > file drop > URL > paste) and wait.

- **A chart of accounts** — Required. Why: every line on the journal entry has to reference a real account code. If missing I ask: "Do we have a chart of accounts yet? If not, let's draft one first."
- **The entry type and period** — Required. Why: tells me which template to use (accrual, prepaid, payroll, revenue recognition, depreciation, stock-comp, adjustment, reclass) and which month it lands in. If missing I ask: "What kind of entry are we booking, and for which month?"
- **A fixed-asset list, for `type=depreciation`** — Required for that type. Why: I compute monthly depreciation from cost, salvage, and useful life per asset. If missing I ask: "Do you have a list of capitalized fixed assets with cost, in-service date, and useful life? Drop the spreadsheet or paste it."
- **A 409A valuation and vesting schedule, for `type=stock-comp`** — Required for that type. Why: drives the linear ASC 718 expense after cliff. If missing I ask: "Do you have a current 409A valuation and the vesting schedule for outstanding grants? Drop them or share what you have."
- **A pay-period summary, for `type=payroll`** — Required for that type. Why: I split wages by R&D / Sales & Marketing / General & Admin from this. If missing I ask: "Can you connect Gusto, Rippling, or Justworks, or paste the pay-period summary with gross, taxes, benefits, and net pay by department?"

## Steps

1. **Parse inputs.** Required: `type` (one of `accrual` | `prepaid` | `payroll` | `revrec` | `depreciation` | `stock-comp` | `adjustment` | `reclass`) and `period` (`YYYY-MM`). Optional: `mode` (only meaningful when `type=accrual`  -  `reversing`), short `slug` for filename.

2. **Read context.** Load `context/bookkeeping-context.md` (stop if missing), `config/context-ledger.json`, `config/chart-of-accounts.json` (**locked** for run  -  stop if absent), `accruals.json` (empty array if absent). For payroll / depreciation / stock-comp, also read type-specific config (below).

3. **Branch on `type`.** Each branch builds `lines[]` array; Step 4 validates before writing.

   ### `accrual`
   Period-end accrual (unbilled revenue, accrued payroll, accrued interest). Debit expense / revenue line, credit `Accrued Liabilities` (or debit `Accrued Revenue` + credit revenue). `reversing: true` by default. Append to `accruals.json`: `{id, type, active: true, reversing: true, period, amount, glCode, counterGlCode, memo, createdAt, updatedAt}`.

   **`mode=reversing` sub-mode.** Read `accruals.json`, find every entry with `active=true AND reversing=true AND period < current`. For each, produce reversing journal entry with `reversesEntryId` pointing at original and sign convention flipped. Mark original `active: false` and set `reversedOn`. Write each reversal as separate journal entry.

   ### `prepaid`
   Amortize prepaid (rent, SaaS, insurance). Debit expense account, credit prepaid-asset account. `reversing: false`. Memo: `"Amortize {asset}  -  {period}"`.

   ### `payroll`
   Pay-period summary. Source order: connected app (`composio search payroll` → Gusto / Rippling / Justworks / Deel / ADP, schema via `--get-schema`) > pasted summary `{gross, taxes, benefits, netPay, byDepartment: {rd, sm, ga}}`. Lines: debit `Wages  -  R&D / Sales & Marketing / General & Admin` per chart of accounts, debit `Payroll Taxes`, debit `Employee Benefits`; credit `Wages Payable` (or `Cash` if paid in-period  -  ask once), `Payroll Tax Liabilities`, `Benefits Payable`. Memo: `"Payroll  -  {period}  -  {provider}"`.

   ### `revrec`
   Read every `revrec/**/*.json`, pick rows with `period = current`. Debit `Deferred Revenue`, credit revenue account. Multi-currency → aggregate in home currency (already on schedule). Memo: `"Revenue recognition  -  {period}  -  {N} contracts"`.

   ### `depreciation`
   Read `config/fixed-assets.json` (shape: `[{id, description, class, cost, salvage, usefulLifeMonths, inServiceOn, method: "straight-line"}]`). If absent, ask ONCE for schedule (file > paste)  -  NEVER invent. Compute `(cost - salvage) / usefulLifeMonths` per asset, group by class. Debit `Depreciation Expense  -  {class}`, credit `Accumulated Depreciation  -  {class}`. Memo: `"Depreciation  -  {period}  -  {N} assets"`.

   ### `stock-comp`
   Read `config/stock-comp.json` (shape: `{valuation: {fmv, asOf}, grants: [{employeeId?, grantDate, shares, strike, vestingMonths, cliff}]}`). If absent, ask ONCE for 409A + vesting schedule. Linear expense after cliff per ASC 718. Debit `Stock-Based Compensation Expense` (split by R&D / Sales & Marketing / General & Admin if chart of accounts supports), credit `Additional Paid-in Capital`. Memo: `"Stock-based compensation  -  {period}  -  {N} grants"`. If `context/bookkeeping-context.md` flags stock-based compensation as hard-no without sign-off, stop and surface draft for approval.

   ### `adjustment`
   General manual adjustment. User dictates `{glCode, debit, credit, memo}` per line (2+ lines). Common sources: unrecorded fees from reconciliations, forex rounding, prior coding corrections.

   ### `reclass`
   Inputs `{fromGlCode, toGlCode, amount, memo}`. Debit `toGlCode`, credit `fromGlCode`. Both should be expense-or-asset lines; cross-section (expense → liability) requires `type=adjustment` instead.

4. **Validate before write.** Hard guards  -  failure stops write, surfaces error:
   - `sum(debits) === sum(credits)` within 1 cent.
   - Every `glCode` exists in `config/chart-of-accounts.json` (not just parent  -  exact code).
   - `lines[].length >= 2`.
   - `type = reversing` implies `reversesEntryId` set AND referenced journal entry has `reversing: true` AND sign convention flipped.
   - No `status: "posted"` (only `draft` allowed from this skill).

5. **Write journal entry markdown** to `journal-entries/{YYYY-MM}/{type}-{slug}.md`. Structure:
   - Header: `id`, `type`, `period`, `date`, memo, status, reversing, reversesEntryId (if any).
   - **Lines**  -  markdown table `{glCode | glName | debit | credit | memo}`.
   - Totals row: debit total, credit total, diff (should be 0).
   - Supporting docs: paths referenced (pay-period summary, revenue recognition schedule, fixed-assets file, receipts).
   - Notes: open questions surfaced inline.

6. **Append to `journal-entries.json`** at agent root. Atomic read-merge-write. Full schema from `data-schema.md`: `{id, createdAt, updatedAt, date, type, memo, reversing, reversesEntryId?, period, lines[], status: "draft", supportingDocs?}`.

7. **Type-specific side effects.**
   - `accrual` (not reversing sub-mode) → append to `accruals.json` with `active: true`.
   - `accrual mode=reversing` → update original accrual row's `active: false, reversedOn, reversedByEntryId`.
   - `revrec` → stamp matching rows in relevant `revrec/{customer-slug}/{contract-slug}.json` as `recognized: true, recognizedBy: {id}` for that period.
   - `depreciation` → stamp matching rows in `config/fixed-assets.json` with `lastDepreciatedPeriod: "{period}", accumulated += monthly`.

8. **Append one `outputs.json` row**: `{type: "journal-entry", title: "{type} journal entry  -  {period}  -  {slug}", summary, path, status: "draft", domain: "close"}`. Read-merge-write; never overwrite.

9. **Summarize to user.** One compact block: journal entry id, total amount, type, path, reminder it's `draft` until user posts to QuickBooks Online / Xero and confirms. Offer to flip `status: "posted"` on explicit confirm only.

## Outputs

- `journal-entries/{YYYY-MM}/{type}-{slug}.md`  -  human-readable journal entry with balanced lines table.
- `journal-entries.json`  -  read-merge-write, journal entry appended with `status: "draft"`.
- `accruals.json`  -  only on `type=accrual` (append) or `type=accrual mode=reversing` (update original row).
- `revrec/{customer-slug}/{contract-slug}.json`  -  only on `type=revrec` (stamp recognized period).
- `config/fixed-assets.json`  -  only on `type=depreciation` (stamp last depreciated period + accumulated).
- `outputs.json`  -  one row appended, `type: "journal-entry"`.