Guide

Create, open and save a book

Make a new book as XML or SQLite, open an existing one (read-only if you only want to look), save it with a backup, and close it so its lock is released.

A book is the file that holds all your accounts and transactions. red-ale keeps one book open at a time. You create it or open it, change it in memory, save it, and close it. Opening takes the book's lock so that GnuCash and red-ale never write the same file at once; closing releases it.

Steps

  1. Create a book with book.create. The default is a gzip-compressed XML book, which is what GnuCash writes. Pass compressed: false for plain XML, or format: "sqlite" (or a sqlite3:// path) for an SQLite book. The path must not exist yet: an existing file is refused with file-exists.
  2. Look at it with book.info: the format, whether it is read-only and why, whether there are unsaved changes (dirty), and counts of accounts, transactions and prices.
  3. Change it with the methods in the other guides. Nothing reaches the file yet; dirty becomes true.
  4. Save it with book.save. Before overwriting, red-ale copies the previous file to <book>.<timestamp>.gnucash and returns that path as backup. A brand-new book has no previous file, so it has no backup.
  5. Close it with book.close. With unsaved changes it refuses (unsaved-changes); say save: true or discard: true.
  6. Open it again with book.open. To look without any risk, pass readOnly: true: the lock is not taken and nothing can be changed. A book can also open read-only because it uses a GnuCash feature that red-ale does not implement; readOnlyReasons says why.

From the command line, red-ale exec --book book.gnucash <method> '<params>' does steps 6, 3, 4 and 5 for one call, and --create makes the book first.

Example

Create a plain XML book, add an account, save, close and open it again.

Example: with no book.

JSON-RPC

Request:

{"jsonrpc":"2.0","id":1,"method":"book.create","params":{"path":"household.gnucash","compressed":false}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "path": "…",
    "guid": "…",
    "rootAccount": "…",
    "readOnly": false,
    "format": "xml",
    "compressed": false,
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":2,"method":"account.create","params":{"name":"Checking","type":"BANK","commodity":"USD"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":3,"method":"book.info","params":{}}

Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "dirty": true,
    "readOnly": false,
    "format": "xml",
    "counts": "…",
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":4,"method":"book.save","params":{}}

Response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":5,"method":"book.close","params":{}}

Response:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "saved": false,
    "discarded": false
  }
}

Request:

{"jsonrpc":"2.0","id":6,"method":"book.open","params":{"path":"household.gnucash","readOnly":true}}

Response:

{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "readOnly": true,
    "readOnlyReasons": [
      {
        "code": "requested",
        "message": "opened read-only on request"
      }
    ],
    "…": "…"
  }
}

Command line

red-ale exec --script - <<'EOF'
book.create {"path":"household.gnucash","compressed":false}
account.create {"name":"Checking","type":"BANK","commodity":"USD"}
book.info {}
book.save {}
book.close {}
book.open {"path":"household.gnucash","readOnly":true}
EOF

It prints:

[
  {
    "path": "…",
    "guid": "…",
    "rootAccount": "…",
    "readOnly": false,
    "format": "xml",
    "compressed": false,
    "…": "…"
  },
  "…",
  {
    "dirty": true,
    "readOnly": false,
    "format": "xml",
    "counts": "…",
    "…": "…"
  },
  "…",
  {
    "saved": false,
    "discarded": false
  },
  {
    "readOnly": true,
    "readOnlyReasons": [
      {
        "code": "requested",
        "message": "opened read-only on request"
      }
    ],
    "…": "…"
  }
]

MCP tool call

Tool call:

{"name":"book.create","arguments":{"path":"household.gnucash","compressed":false}}

Result:

{
  "structuredContent": {
    "path": "…",
    "guid": "…",
    "rootAccount": "…",
    "readOnly": false,
    "format": "xml",
    "compressed": false,
    "…": "…"
  }
}

Tool call:

{"name":"account.create","arguments":{"name":"Checking","type":"BANK","commodity":"USD"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"book.info","arguments":{}}

Result:

{
  "structuredContent": {
    "dirty": true,
    "readOnly": false,
    "format": "xml",
    "counts": "…",
    "…": "…"
  }
}

Tool call:

{"name":"book.save","arguments":{}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"book.close","arguments":{}}

Result:

{
  "structuredContent": {
    "saved": false,
    "discarded": false
  }
}

Tool call:

{"name":"book.open","arguments":{"path":"household.gnucash","readOnly":true}}

Result:

{
  "structuredContent": {
    "readOnly": true,
    "readOnlyReasons": [
      {
        "code": "requested",
        "message": "opened read-only on request"
      }
    ],
    "…": "…"
  }
}