A complete invoicing workflow for software contractors and freelancers using Emacs Org mode.
Track contracts, generate invoices, export professional PDFs — all without leaving Emacs.
- Contract-based management — one directory per client with a master index
- Auto-incrementing invoice numbers — configurable format (e.g.,
INV-2026-0001) - Configurable tax — HST, GST, VAT, or any tax label/rate per contract
- Configurable payment terms — Net 15, Net 30, Due on Receipt, or custom
- PDF export via LaTeX — clean, professional template (customizable)
- Plain Org records — every invoice is a readable
.orgfile - Unpaid invoice tracking — list all outstanding invoices across contracts
- Financial summary — per-contract YTD and all-time totals (invoiced, paid, outstanding) auto-updated in the contract index
- Works everywhere — vanilla Emacs, Doom Emacs, Spacemacs
- Emacs 27.1+
- Org mode 9.0+
pdflatex(for PDF export) — typically from TeX Live or MiKTeX
org-invox is available on MELPA. Add MELPA to your package archives if you haven’t already:
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)Then install:
M-x package-install RET org-invox RET
In packages.el:
(package! org-invox)In config.el:
(use-package! org-invox
:after org
:config
(require 'org-invox-export))(use-package org-invox
:ensure t
:after org
:config
(require 'org-invox-export))Clone the repository and add it to your load path:
(add-to-list 'load-path "/path/to/org-invox")
(require 'org-invox)
(require 'org-invox-export)(setq org-invox-from-name "Jane Smith"
org-invox-from-company "Smith Consulting Inc."
org-invox-from-address "123 Main St, Toronto, ON M5V 1A1"
org-invox-from-email "jane@smithconsulting.ca"
org-invox-from-phone "+1 (416) 555-0123"
org-invox-root-directory "~/invoices")M-x org-invox-new-contract
You’ll be prompted for:
- Client/company name
- Client address & email
- Service description (defaults to “Software Development Services”)
- Hourly rate
- Currency (defaults to CAD / $)
- Tax rate & label (defaults to 13% HST)
- Payment terms (defaults to Net 30)
This creates a directory structure like:
~/invoices/
└── acme-corp/
└── index.org ← contract details + invoice index
M-x org-invox-create
Select a contract, enter hours and period dates. org-invox handles everything else:
- Auto-generates the next invoice number
- Computes subtotal, tax, and total
- Creates a standalone
.orgfile - Updates the contract index
~/invoices/
└── acme-corp/
├── index.org
├── INV-2026-0001.org ← invoice files
├── INV-2026-0002.org
└── exports/ ← generated PDFs
├── INV-2026-0001.pdf
└── INV-2026-0002.pdf
M-x org-invox-export-pdf
Generates a professional PDF via LaTeX into the exports/ subdirectory of the contract directory. Build artifacts (.aux, .log, .out, .tex) are cleaned up automatically.
M-x org-invox-mark-paid — marks the current invoice as paid (updates both the invoice and the contract index).
M-x org-invox-list-unpaid — shows all unpaid invoices across all contracts.
M-x org-invox-update-summary — manually refreshes the * Financial Summary table in the contract index with current YTD and all-time totals (invoiced, paid, outstanding). This table is also updated automatically on invoice creation and org-invox-mark-paid.
| Variable | Default | Description |
|---|---|---|
org-invox-from-name | "" | Your name |
org-invox-from-company | "" | Your company name |
org-invox-from-address | "" | Your address |
org-invox-from-email | "" | Your email |
org-invox-from-phone | "" | Your phone |
org-invox-root-directory | "~/invoices" | Where contracts/invoices are stored |
org-invox-default-tax-rate | 13.0 | Default tax percentage |
org-invox-default-tax-label | "HST" | Default tax name |
org-invox-default-payment-terms=| ="Net 30" | Default payment terms | |
org-invox-default-currency | "CAD" | Default currency code |
org-invox-default-currency-symbol | "$" | Default currency symbol |
org-invox-number-format | "INV-%Y-%04d" | Invoice number format string |
org-invox-date-format | "%B %d, %Y" | Date display format |
org-invox-latex-template-file | nil | Path to custom LaTeX template |
The org-invox-number-format variable supports:
%Y— 4-digit year%04d— zero-padded sequence number (adjust width as needed)
Examples:
| Format | Result |
|---|---|
INV-%Y-%04d | INV-2026-0001 |
INV-%04d | INV-0001 |
%Y%02d | 202601 |
ACME-%Y-%03d | ACME-2026-001 |
Set org-invox-latex-template-file to point to your own .tex template.
The following placeholders are available:
| Placeholder | Replaced with |
|---|---|
<<INVOICE_NUMBER>> | Invoice number |
<<INVOICE_DATE>> | Invoice date |
<<DUE_DATE>> | Due date |
<<INVOICE_PERIOD>> | Billing period |
<<FROM_BLOCK>> | Full sender block (name, company, address, etc.) |
<<TO_BLOCK>> | Full recipient block (name, company, address, etc.) |
<<LINE_ITEMS>> | Formatted line items |
<<SUBTOTAL>> | Subtotal amount |
<<TAX_LABEL>> | Tax label (e.g., HST) |
<<TAX_RATE>> | Tax rate (e.g., 13.0) |
<<TAX_AMOUNT>> | Tax amount |
<<TOTAL>> | Total amount |
<<CURRENCY>> | Currency code |
<<CURRENCY_SYM>> | Currency symbol |
<<PAYMENT_TERMS>> | Payment terms |
- Once per client:
M-x org-invox-new-contract— set up client details, rate, tax - Every 2 weeks:
M-x org-invox-create— enter hours and period → invoice is generated - Immediately after:
M-x org-invox-export-pdf— generate PDF inexports/to send - When paid:
M-x org-invox-mark-paid— update status (summary auto-updates) - Periodically:
M-x org-invox-list-unpaid— check outstanding invoices - On demand:
M-x org-invox-update-summary— refresh financial totals in the contract index
GPLv3. See LICENSE.