---
name: finance-os
description: Work in a person's Finance OS account (bookkeeping, documents, tax returns) from a shell with the finance-os command-line tool. Use when asked to do bookkeeping or tax work in Finance OS, to check what is next in Finance OS, or to connect to Finance OS and no Finance OS MCP tools are available in this session.
---

# Finance OS from the command line

Finance OS keeps a person's books, documents and tax returns. The `finance-os`
command gives you every Finance OS tool from a shell. If this session already
has Finance OS MCP tools (names starting `finance_os_`), use those instead: they
are the same tools and this skill is not needed.

## Set up once

```bash
npm install -g finance-os
finance-os status
```

If `status` exits 3, this machine is not connected yet. Pick the case that fits:

- **The owner's browser is on this machine.** Run `finance-os login`. It opens
  Finance OS; the owner approves one screen; the command finishes on its own.
- **This is a remote machine or sandbox.** Run `finance-os login --start`. Give
  the owner the `signInUrl` it prints and these words: "Open this link and
  approve it. Your browser then lands on an address starting with
  http://127.0.0.1 that will not load. Copy that whole address and send it to
  me." Then run `finance-os login --finish "<that address>"`. The link is good
  for 15 minutes.
- **An API key was already provided to this environment** as
  `FINANCE_OS_AGENT_TOKEN`. Nothing to do; the command uses it.

Never ask the owner to paste an API key, a password or a passkey into the chat.
The return address from `login --start` is safe to paste: it is single-use and
useless without the secret this machine kept.

## The working loop

```bash
finance-os next                      # the prioritized queue of what to do
finance-os playbook                  # list the playbooks
finance-os playbook start_to_finish  # read one before a task you have not done here
finance-os tools <word>              # find a tool
finance-os describe <tool>           # its description and exact input
finance-os call <tool> '<json>'      # run it
```

1. Run `finance-os next`. Do what it lists, then run it again. It is the source
   of what to do; do not stop to ask the owner "what next?".
2. Before a kind of work you have not done in this conversation, read its
   playbook. The playbooks hold the order of work and the rules, and they are
   kept current on the server; follow them over anything remembered.
3. Read `describe` before the first call of a tool. Send exactly the fields it
   names.

Tool names can be written without the `finance_os_` prefix, and an operation
key works too: `finance-os call bookkeeping.drain.run '{...}'`.

## Putting a file in the vault

```bash
finance-os upload <file> --entity <entity id> [--tax-year N] [--type tax_form|receipt|...]
```

Any file you have (a screenshot you took, a PDF you downloaded, a spreadsheet)
goes in with this one command; it prints the document id. PDF, PNG, JPEG, GIF,
WebP, HEIC, TIFF, CSV, text, Markdown, JSON, .xlsx and .docx are accepted, up to
50 MiB. Never hand the owner an upload link for a file you already have; an
upload link is only for a file the owner has and you do not.

## Reading results

- Results are JSON on stdout. Messages are on stderr.
- Exit 0: done. Exit 4: the tool answered with a refusal; the JSON says why and
  usually what to do next. Exit 3: not connected. Exit 2: the command was typed
  wrong. Exit 1: anything else.
- Reads come back compact and paged. Follow the paging fields the result names
  until it says it is complete; never assume one page is everything.
- "Rate limiting" on stderr means wait and retry. Writes are limited to about
  five a minute: space them about 13 seconds apart.

## Sending input safely

- For anything long, or anything holding a tax ID or an account number, put the
  JSON in a private file and use `--input <file>` (or `--input -` for stdin)
  instead of the command line, then delete the file.
- Give every write a stable `_idempotencyKey` where the tool accepts one, so a
  retry cannot do the work twice.

## Who has to say yes

Each tool's description ends with its approval policy. Follow it:

- **agent_autonomous**: run it. Do not ask.
- **standing_delegable**: if the owner has already allowed that family of work,
  run it. Otherwise ask the owner once, in plain words, for this one request.
- **owner_chat_decision**: call `request_operation_approval`, restate the exact
  request to the owner, and only after their clear yes or no relay it with
  `decide_operation_approval`. Never relay a yes the owner did not give.
- **owner_session_only**: the owner does it on the Finance OS website. Signing,
  filing, paying and linking a bank are always theirs.

Categories and routine bookkeeping are your call: decide from the evidence and
record why. Ask the owner only for a fact they alone know, as one narrow
question with your best guess, through `queue_owner_questions`.

## Saying what happened

Tell the owner what you did in plain words ("posted the bank rows that were
already categorized"), not tool names. Keep these apart, because one never
proves the next: prepared, reviewed by the owner, filed, accepted by the agency.

## Turning it off

`finance-os logout` turns this machine's connection off. The owner can also
revoke any connection in Finance OS under Settings → Authorized agents.
