Full Business Accounting
Fool proof invoicing and expense tracking, saving files locally or in Google Drive
Category: skill Author: npub1carj2jw…h8c9 Date: 29 Apr 2026 Votes: 0
---
name: full-business-accounting
description: >
Full accounting system for a small business. Use when the user wants to create
an invoice, log an expense, record a payment, check what's outstanding, or run
a P&L summary. Manages sequential invoice numbering, stores all records as
markdown files. On first use, asks the user where to store records — requires
an MCP or local connector with file overwrite/delete capability (needed to
keep the single ledger.md in sync).
version: "1.0.0"
license: MIT
allowed-tools: Read, Write, Edit, Bash(date:*), Bash(mkdir:*), Bash(ls:*), Bash(grep:*), Bash(cat:*)
metadata:
author: agentlist
tags:
- accounting
- invoicing
- expenses
- small-business
- finance
---
# SKILL: full-business-accounting
## What this skill does
A complete lightweight accounting system for a small business. It creates and
numbers invoices sequentially, logs expenses with categories, tracks payment
status, and generates P&L summaries — all stored as plain markdown files that
are human-readable, git-committable, and portable.
On first use, ask the user where they want records stored. **The chosen backend must support overwriting an existing file** — this is required to keep `ledger.md` in sync. Do not proceed with a backend that is read-only or append-only.
---
## Storage backends
### Step 1 — Ask the user on first use
Before doing anything else, ask:
> "Where would you like to store your accounting records? I need a storage location that supports overwriting files (to keep the ledger up to date). Options I can see connected: [list available MCPs / local filesystem connectors]. Which would you prefer?"
List every connected MCP tool that has write/overwrite capability (e.g. Google Drive, Dropbox, OneDrive, iCloud, local Filesystem, Notion, etc.). Do **not** pre-select one.
If only one suitable option is available, confirm it with the user rather than assuming.
### Step 2 — Verify overwrite capability
Before committing to a backend, confirm it can **overwrite** an existing file (not just create new ones). Test by checking whether the tool exposes an update/overwrite method, not just create. If a connector only supports creating new files, warn the user and ask them to choose a different one.
### Step 3 — Store the choice
Record the chosen backend in `ledger.md` under a `storage_backend` field (e.g. `google_drive`, `local`, `dropbox`) so subsequent runs don't need to ask again.
### File layout (same regardless of backend)
```
Accounting/
ledger.md ← state file: next invoice number, running totals
invoices/
INV-2026-001.md
INV-2026-002.md
expenses/
EXP-2026-001.md
EXP-2026-002.md
```
For local filesystem backends, create the directory structure if it does not exist:
```bash
mkdir -p accounting/invoices accounting/expenses
```
---
## The ledger file
`ledger.md` is the single source of truth for state. Always read it before
any operation that creates a new record. Always update it after.
```markdown
---
next_invoice: 3
next_expense: 7
base_currency: GBP
storage_backend: google_drive
business_name: The Bloomsbury Arms
business_address: |
24 Museum Street
London WC1A 1LY
United Kingdom
vat_number: GB987654321
payment_terms_days: 14
updated: 2026-04-29
---
## Running totals (current tax year)
| Category | Amount (GBP) |
|----------------|-------------|
| Invoiced | 14,500.00 |
| Received | 9,200.00 |
| Outstanding | 5,300.00 |
| Expenses | 2,140.00 |
| Net | 7,060.00 |
```
If `ledger.md` does not exist, create it by asking the user for:
- Preferred storage backend (see Storage backends section above)
- Business name
- Business address
- Currency (default GBP)
- VAT/tax number (optional)
- Default payment terms in days (default 30)
Then write it with `next_invoice: 1`, `next_expense: 1`, `storage_backend: <chosen>`, and zero totals.
---
## Invoice format
File name: `INV-{YEAR}-{NNN}.md` where NNN is zero-padded to 3 digits.
```markdown
---
id: INV-2026-003
status: unpaid
client: The Fitzroy Hotel
client_address: |
12 Charlotte Street
London W1T 2LR
client_email: accounts@fitzroyhotel.co.uk
date_issued: 2026-04-29
date_due: 2026-05-13
currency: GBP
subtotal: 1400.00
vat_rate: 20
vat_amount: 280.00
total: 1680.00
paid_date:
paid_amount:
notes: Private dining event — 14 May
---
# Invoice INV-2026-003
**From:** The Bloomsbury Arms
24 Museum Street, London WC1A 1LY
VAT: GB987654321
**To:** The Fitzroy Hotel
12 Charlotte Street, London W1T 2LR
**Date issued:** 29 April 2026
**Payment due:** 13 May 2026
---
## Line items
| Description | Qty | Unit price | Amount |
|--------------------------------------|-----|------------|-----------|
| Private dining room hire — half day | 1 | £500.00 | £500.00 |
| Set menu (3 courses) × 18 covers | 18 | £45.00 | £810.00 |
| Bar tab — wine & soft drinks | 1 | £90.00 | £90.00 |
---
## Summary
| | |
|---|---|
| Subtotal | £1,400.00 |
| VAT (20%) | £280.00 |
| **Total due** | **£1,680.00** |
---
**Payment details:**
Bank: Starling Bank
Account name: The Bloomsbury Arms
Sort code: 60-83-71
Account number: 87654321
Reference: INV-2026-003
*Payment terms: 14 days from date of issue.*
```
After writing the file:
1. Increment `next_invoice` in `ledger.md`
2. Add the invoice total to `Invoiced` in the running totals
3. Update `updated` date in the ledger
---
## Expense format
File name: `EXP-{YEAR}-{NNN}.md` where NNN is zero-padded to 3 digits.
```markdown
---
id: EXP-2026-007
date: 2026-04-15
vendor: Matthew Clark Wholesale
category: stock
amount: 843.60
currency: GBP
vat_reclaimable: true
receipt_ref: mc-delivery-apr-15
notes: Weekly drinks delivery — ales, lagers, house wine
---
# Expense EXP-2026-007
**Date:** 15 April 2026
**Vendor:** Matthew Clark Wholesale
**Category:** stock
**Amount:** £843.60
**VAT reclaimable:** Yes
**Notes:** Weekly drinks delivery — ales, lagers, house wine
**Receipt ref:** mc-delivery-apr-15
```
Valid expense categories:
`stock`, `staff`, `rent`, `utilities`, `repairs`, `equipment`,
`marketing`, `insurance`, `legal`, `accountancy`, `travel`, `meals`, `other`
After writing the file:
1. Increment `next_expense` in `ledger.md`
2. Add the amount to `Expenses` in the running totals
3. Update `updated` date in the ledger
---
## Operations
### Create invoice
1. Read `ledger.md` — get next invoice number and business details
2. Ask user for: client name, address, email, line items (description, qty, unit price), VAT rate (default from ledger or 20%)
3. Calculate subtotal, VAT, total
4. Calculate due date from today + payment_terms_days
5. Write invoice file
6. Update ledger
7. Confirm: "Invoice INV-2026-003 created. Total: £1,680.00. Due: 13 May 2026."
### Log expense
1. Read `ledger.md` — get next expense number
2. Ask user for: vendor, amount, category, date, receipt ref (optional), VAT reclaimable (y/n)
3. Write expense file
4. Update ledger
5. Confirm: "Expense EXP-2026-007 logged. £843.60 — Matthew Clark Wholesale (stock)."
### Mark invoice as paid
1. Find the invoice file by ID or client name
2. Update frontmatter: `status: paid`, `paid_date`, `paid_amount`
3. Update ledger: subtract from `Outstanding`, add to `Received`
4. Confirm: "INV-2026-003 marked as paid. £1,680.00 received."
### List outstanding invoices
Read all invoice files. Filter where `status: unpaid`. Display as a table:
```
Outstanding invoices
────────────────────────────────────────────────────────────────
INV-2026-001 The Fitzroy Hotel £1,680.00 due 2026-04-20 ⚠ OVERDUE
INV-2026-003 Bloomsbury Festival £ 420.00 due 2026-05-13
────────────────────────────────────────────────────────────────
Total outstanding: £2,100.00
```
Flag invoices where `date_due` is before today as `⚠ OVERDUE`.
### P&L summary
Read `ledger.md` running totals. Display:
```
P&L Summary — Tax year to date
────────────────────────────────
Revenue invoiced: £14,500.00
Revenue received: £9,200.00
Outstanding: £5,300.00
Total expenses: £2,140.00
Net (received): £7,060.00
Net (invoiced): £12,360.00
────────────────────────────────
```
For a more detailed breakdown, read all expense files and group by category.
---
## Rules
- **Never reuse an invoice number.** Always read `next_invoice` from the ledger immediately before creating — never guess or assume.
- **Always update the ledger after every write.** Totals and the next-number counter must stay in sync.
- **Amounts are always stored as plain decimals** (e.g. `4800.00`), never formatted strings. Format only for display.
- **Dates are always ISO 8601** (`YYYY-MM-DD`) in frontmatter, human-readable in the body.
- **Do not delete records.** If an invoice is cancelled, set `status: cancelled` and add a `cancelled_reason` field. Update the ledger totals accordingly.
- **Confirm storage location on first use.** Tell the user: "Storing records in [backend name] → Accounting/". Read `storage_backend` from the ledger on subsequent runs — do not ask again.
Discussion