본문으로 건너뛰기
cccskills
무료GitHub에 공개

cashflow

Categorize jb55's personal finance ledger from the command line via the `cashflow` CLI (crates/cashflow_cli) — burn down the uncategorized ("unknown") transactions with rules, overrides, splits and transfer links, previewing every write first. Use when asked to categorize transactions, clear the triage queue, add or fix a categorization rule, link transfers between own accounts, or review what an agent session categorized — e.g. "categorize my amex rows", "burn down the unknowns", "why is this charge in expenses:unknown", "undo what that session did".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

damus-io/notedeck스타 317(GitHub 317 + cccskills 0)

실행 점수 미검증

설치 방법 보기

포함된 파일(1)

  • SKILL.md11.4 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Categorizing with the cashflow CLI

cashflow reads raw, content-addressed journal segments from $CASHFLOW_DIR (default ~/.local/share/cashflow) and derives every transaction's category at load time from the vault's edits: an override or split first, then the first matching rule, then the importer's default (expenses:unknown, income:unknown, income:zap, income:lnurl). The edits are small nostr notes in a sealed vault; the bulk data never leaves the journal. Source: crates/cashflow_cli.

So categorizing is writing edits, never touching segments:

  • Never re-import to fix a category. Importing only adds segments; the category of a row already imported comes from the edits, and a re-import changes nothing about it.
  • Never edit files under journal/. Segments are named by their hash and a changed one fails verification.

Running it

cargo build -p cashflow_cli          # produces target/debug/cashflow
target/debug/cashflow <command>      # or: cargo run -q -p cashflow_cli -- <command>

Below, cashflow means whichever form you use. cashflow --help lists the commands; cashflow <command> --help is each one's page, with its flags and JSON shape spelled out in prose. Read a page before using a command this skill doesn't show.

Every vault command reconciles with a relay (default notedeck's embedded one, ws://127.0.0.1:6677) before reading and publishes after writing. With no relay it works offline against its own cache and a write says (offline: stored locally, not published); the next run that reaches the relay pushes it. The warning: connecting to … lines on stderr are that, not a failure.

If a vault command fails because no key is stored, ask jb55 to run cashflow login. Never handle the key yourself: don't read, print or pass an nsec.

Privacy: counts leave the session, rows don't

The triage queue shows real merchant names, amounts, dates and record ids. They stay in the session. Never put a payee, amount, account number, record id or rule pattern in a commit, a card description or comment, an explainer, a hindsight line or any message outside this conversation. Report outward in counts only: "categorized 412 of 1,930 unknown rows with 14 rules and 6 overrides".

The loop

cashflow transfer suggest --json     # 0. once, first: link transfers (see "Transfers first")
cashflow unknown --json              # 1. the queue, biggest group first
# 2. decide the group's account (see "Choosing the account")
cashflow rule add <account> --match '<pattern>' --source <src> --dry-run   # 3. preview
cashflow rule add <account> --match '<pattern>' --source <src>             # 4. write
cashflow unknown --json | jq .rows   # 5. the count went down by what step 3 said

Repeat from 1. Step 0 comes first because both sides of a card payment sit in the queue until they are linked, and no rule should take them.

1. Read the queue

cashflow unknown --json (--source amex, --limit 50 to narrow):

{ "rows": 51, "groups_total": 7, "home": "CAD",
  "groups": [ { "payee": "corner grocer", "account": "expenses:unknown",
                "rows": 18, "total": "887.24 CAD", "total_qty": "88724",
                "unconverted": 0, "sources": ["amex"], "pattern": "corner grocer",
                "record_ids": ["amex:…", "…"],
                "rule_add": ["cashflow","rule","add","<account>","--match","corner grocer","--source","amex"] } ] }
  • rows is the whole queue's size: the number the loop drives down.
  • A group is one normalized payee (lower-cased, words with digits dropped) on one default account, ranked by its total in the home currency. Take them in order: one rule on the first group moves the most money.
  • rule_add is the rule that takes the whole group. Replace <account> and append --dry-run. Its --source is the segment's source: the importer's name (amex, rbc, cln, …), or ledger for rows from a ledger-cli file. It is null when the payee has no usable substring: categorize those rows one by one, or write a rule on --meta instead.

To see a group's rows before deciding: cashflow report reg expenses:unknown --payee '<pattern>' (date, payee, amount). To see one row's raw metadata (raw-merchant, raw-city, raw-description, raw-zap-p, …), export its day and find its id: cashflow export --begin <day> --end <next day>, then the block holding ; id: <record-id>.

2. Rule or override

  • Rule (rule add) for anything that recurs: a payee, a pattern, a metadata value. It also catches the rows future imports bring.
  • Override (categorize <record-id> <account>) for a one-off: a single purchase, a payee that means different things on different days.
  • Split (split <record-id> a=60 b) for one charge that is two things. Amounts are in the row's commodity, positive in its direction; one bare account takes the rest; the legs must add up exactly.

An override or split beats every rule, so an override is also how to pull one row out of a rule that is otherwise right.

Rules are tried in order and the first match wins. add puts the new rule last, which can't take rows another rule already decides; use --first, --before <rule> or --after <rule> only when you mean to. Conditions: --match (payee substring, case-ignored; repeat for any of), --meta key=value (metadata substring; repeat for all of), --amount min..max (the counter leg in smallest units, cents or msat, sign ignored), --source, --layer. Keep the --source the queue suggests: a pattern that is safe on one card's merchant strings can match CLN descriptions too.

Prefer the queue's pattern to a shorter one. "grocer" catches tomorrow's grocer and also "Grocery Outlet Hardware"; widen a pattern only after reading the dry run's sample.

3. Dry run first, every time

Every write takes --dry-run: rule add|mv|rm|import, categorize, uncategorize, split, transfer link|unlink|suggest --accept-all. The rule commands print, and with --json return:

{ "dry_run": true, "moved": 18,
  "moves": [ { "from": "expenses:unknown", "to": "expenses:food:groceries", "rows": 18 } ],
  "taken": [ { "rule": "void-candy-frog", "rows": 18 } ],
  "sample": [ { "date": "…", "id": "…", "payee": "…", "from": "…", "to": "…" } ] }

Stop and ask jb55 before writing when the dry run shows any of:

  • taken is not empty: a rule change takes rows from an existing rule, so it overrides a decision someone already made;
  • moved is over 200, or transfer suggest --accept-all would link over 200 pairs: big enough that a wrong choice is expensive to find later;
  • replaced is not null on categorize or split: it replaces an override or split someone already wrote.

Then ask, with the row count, the total and the account you'd pick, and go on to the next group meanwhile.

Otherwise check that moves[].from is the default you meant to clear and that the rows belong. sample holds only five; for a group bigger than that, read it whole with cashflow report reg <default> --payee '<pattern>' (the rows a rule would take from elsewhere don't show there, but then taken isn't empty). Then run the same command without --dry-run.

A dry run's added id is a placeholder: the real add names its rule afresh. Read the id from the write's own output, or from rule ls.

4. Check the count

cashflow unknown --json | jq .rows should have fallen by the write's moved, by one for an override or split, and by two for each transfer linked (both sides leave the queue). If it didn't, cashflow rule test <record-id> --json says what decides one row now (decided_by: override, split, transfer, rule or default, plus the rule and the pattern that matched).

Transfers first

Paying the card from chequing is imported twice, once by each source, and reads as an expense on one side and income on the other until linked. A link sends both legs to transfers, where they net to zero.

cashflow transfer suggest --json                 # pairs: own account each side, equal and opposite, ≤ 5 days apart
cashflow transfer suggest --accept-all --dry-run
cashflow transfer suggest --accept-all
cashflow transfer link <record-id> <record-id>   # a pair suggest missed

Read the suggested pairs before --accept-all: two unrelated rows of the same amount a few days apart look like a transfer too. Link the right ones one at a time if any pair is wrong. A row with an override or split can't be linked, and a linked row can't be categorized: uncategorize or transfer unlink it first.

Choosing the account

The account tree is what the books already hold:

cashflow report bal --depth 3        # every account with a balance
cashflow account ls --all            # the tree, plus any names, icons and projects set on it
cashflow rule ls --json              # where the existing rules send things

Put rows under an account that exists, or a new one below a top level, named in the style of its siblings: expenses:food:groceries beside expenses:food:restaurants, or expenses:transport when no branch fits. Prefer an existing branch to a new one, and the shallowest name that says what it is. Never invent a top-level account: the top levels (assets, liabilities, income, expenses, equity, transfers) carry meaning in every report. When nothing fits and you would have to guess, leave the group and list it for jb55 at the end with its row count and total, not its payee.

Don't rename or restructure accounts to fit a rule. cashflow account alias <from> <to> renames a subtree at derive time without touching any rule, but the chart is jb55's: suggest an alias, don't write one.

Not everything in the queue needs moving. income:zap and income:lnurl are already income, and are in the queue only so they can be split per project with a --meta rule (raw-zap-p, raw-lnurl-address). Leave them unless jb55 asked for that.

Provenance and undo

Every write is stamped with $AGENTIUM_SESSION when it is an agentium:<word-id> ref. Check it before the first write (echo "$AGENTIUM_SESSION"); outside a session the writes carry no author and can't be told apart from jb55's own.

To review what a session did:

cashflow rule ls --by agentium:<word-id> --json  # its rules, each with "matches" (rows decided now)
cashflow edits --by agentium:<word-id> --json    # its overrides, splits and transfer links

To undo one: cashflow rule rm <rule>, cashflow uncategorize <record-id> (an override or split), cashflow transfer unlink <a> <b>. Rules are named by word-id or any unique prefix of it. Each undo takes --dry-run too.

Finishing

Report the queue's rows before and after, the number of rules, overrides, splits and links written, and the groups left for jb55 to decide (counts and totals only). cashflow edits --by "$AGENTIUM_SESSION" and cashflow rule ls --by "$AGENTIUM_SESSION" are the review list to hand over.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

agentium

무료

Query and control Dave agentic sessions from the command line via the `agentium` CLI (crates/agentium_cli), and find your OWN session's agentium: reference. Use when an agent running inside a Dave session needs its own ref (e.g. for a headway done-comment), to list sibling sessions, or to pull another session's detail or full conversation transcript — e.g. "what's my agentium ref", "list the running agent sessions", "show sessions in this cwd", "read session X's transcript".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

damus-io/notedeck3172026년 10월 19일 업데이트

Fast-forward master and every git worktree branch up to a target ref (default github/master), skipping any worktree with unmerged commits. Use when the user wants to sync/update their worktree branches to latest master — e.g. "/ff-worktrees", "ff all worktrees to github/master", "fast-forward the worktrees".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

damus-io/notedeck3172026년 10월 19일 업데이트

handoff

무료

Hand off to a fresh Dave session — ask the user what to work on next, spawn a new session in the current worktree, and send it the task as its first message. Use when the user wants to delegate the next unit of work to a brand-new agentic session rather than continue in this one — e.g. "/handoff", "hand this off", "spawn a session to do X next", "start a fresh session on the next task". `/handoff autowork <task>` also branches the new session off the `autowork` branch and has it land its commit there.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

damus-io/notedeck3172026년 10월 19일 업데이트

headway

무료

Read and edit a Headway kanban board from the command line via the `headway` CLI (crates/headway_cli). Use when the user wants to view the board, add/move/edit/archive cards, or shuffle work between columns like Backlog, Todo, In Progress, In Review, and Done — e.g. "move X to done", "show the board", "add a card to todo".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

damus-io/notedeck3172026년 10월 19일 업데이트

nd

무료

Drive the running notedeck from the command line via the `nd` CLI (crates/nd_cli) — list its tools and call any of them over its local socket, or spawn a Dave session, e.g. open a headway card or agentium session in the window, open the review queue, or read board data. Use when the user wants to open something in notedeck from a shell, script the app, or see which tools the running notedeck offers — e.g. "open this card in notedeck", "what tools does notedeck have", "call open".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

damus-io/notedeck3172026년 10월 19일 업데이트

notebook

무료

Read and edit a notebook canvas from the command line via the `notebook` CLI (crates/notebook_cli). Use when the user wants to view the canvas, add/move/edit/recolor/delete nodes, connect or disconnect edges, restack, seed, or rename the canvas — e.g. "show the notebook", "add a node", "move that node", "connect these two nodes".

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

damus-io/notedeck3172026년 10월 19일 업데이트

damus-io의 스킬 모두 보기

이 스킬의 문제 신고