bus-ledger — local daybook and ledger browser UI

bus-ledger — local daybook and ledger browser UI

Synopsis

bus ledger [global flags] [serve | version]
bus-ledger [global flags] [serve | version]

With no subcommand, serve runs.

Description

bus-ledger provides a focused full-stack browsing flow for journal/daybook transactions. It starts a token-gated local server, serves an embedded WASM frontend client, and exposes server API endpoints used by the client. The frontend composes reusable UI primitives from bus-ui so shared controls can be reused consistently across BusDK modules without tight coupling.

The frontend shows a deterministic transactions list view, supports opening a transaction detail panel, and includes Previous/Next navigation so users can move transaction-by-transaction without returning to the list. Each transaction detail also includes one-row-per-entry line summaries (type/amount/from/to) and supports opening a full line-details panel on the right. When evidence is available either from journal path fields or from attachment metadata linked to the transaction voucher, both the transaction detail and the line-details panel now use the same shared evidence surface: one common document is shown inline below the line table with PDF preview plus explicit open and download controls, and non-previewable files still keep those controls with visible document metadata. If multiple documents are linked, the transaction detail lists them directly. Transactions with evidence are marked with a document icon in the transactions list. The list surface also supports explicit Day book and General ledger modes. List and detail tables use explicit toggle controls for open/close transitions, so row index cells are plain values instead of navigation links and closing follows the same toggle interaction pattern as opening. When AI is enabled, the app also exposes a foldable AI Assistant side panel that uses a local Codex app-server process in the same workspace where bus-ledger started, so assistant actions can run repository-local bus commands with explicit approval prompts. The panel supports sending additional messages while a turn is active; those inputs are forwarded as turn steering. The panel also supports multiple threads, archival, restoring persisted thread history from .bus/bus-ledger/, thread rename, and selecting the model from an available model list without requiring a manual submit action. The model dropdown is seeded with shared Codex defaults (including gpt-5.4) and is expanded by all model candidates observed from backend payloads, so the list reflects complete available options instead of only the first discovered model. The thread list also keeps a stable “AI working” marker on the busy thread, and reopening another saved thread no longer shows the generic responding placeholder unless that reopened thread is the one still running. The shared close guard also blocks browser close while assistant work is still active, such as a pending approval, so the session is not torn down accidentally in the middle of an unfinished AI task. The shared composer also preserves trailing spaces while the AI input is still focused, even if the panel re-renders, and only normalizes the draft once you blur or send it. The same shared bus-ui AI surface also renders command-session activity in place. When the assistant is waiting on approval or has just completed a verification command, the panel shows the command, output, status, and review actions through the shared terminal session panel instead of a ledger-local terminal UI. The same shared surface now also shows per-thread workspace isolation state. When another AI thread already owns the workspace lock, the blocked thread shows the shared conflict card with the owner thread identifier and deterministic branch/worktree naming instead of silently failing or rendering ledger-local lock text.

The AI message surface is conversation-oriented. User and assistant messages are rendered as separate items, inline markdown code spans are formatted, and workspace file references can be rendered as clickable links through the token-gated server route instead of exposing absolute filesystem paths in the UI. The composer uses Enter-to-send and Shift+Enter for newline, supports drag and drop over the whole assistant panel, and keeps dropped files as explicit pending attachments that users can review and remove before sending. Inline Markdown rendering is deterministic and safe by default: HTML is escaped and the enabled syntax set is limited to inline code, emphasis, markdown links, and URL/path autolinks. Rendering features can be toggled with URL query flags (ai_md_code, ai_md_links, ai_md_autolink, ai_md_bold, ai_md_italic) using 0/1 values. When embedded webview drag data does not expose OS file paths, the client uses browser file-object upload fallback so drop import still works. Imported files are deduplicated by content hash in .bus/bus-ledger/drops/ so repeated drops of the same file reuse the existing stored copy instead of creating duplicate timestamped files.

Approval requests are shown inline in the message flow with clearer action labels and command/path presentation optimized for review. Assistant-status and engine/auth/model metadata are shown in compact form below the composer so the message area remains focused on conversation content. Detail-load warnings are shown in the ledger detail panel and are separated from assistant runtime errors, so AI/action error state does not overwrite ledger data warnings.

For operations and troubleshooting, browser-side diagnostics from the WASM UI are forwarded to server logs via v1/client-log. This includes explicit UI logger messages and global browser failures (window error events and unhandledrejection) so uncaught frontend initialization/auth issues are visible from server stderr. Repeated identical log lines are collapsed with summary output (... and N more) to reduce noise during high-frequency UI events such as drag-over. AI account-state refresh and account/login event handling also log explicit auth-detection reasons (including unresolved payload diagnostics), so “not logged in” status changes can be diagnosed from server logs without browser debugging. Server log verbosity follows global flags consistently: default output includes warnings and errors, -v enables info logs, -vv enables debug logs, and -q suppresses all non-error logs. Frontend wiring lifecycle is explicit: AI/drop/resize listeners and poll timers are registered with tracked disposers and can be released deterministically via app cleanup in reusable host/test scenarios. The same cleanup path is also wired to browser lifecycle events (beforeunload, pagehide) so production teardown releases listeners/timers deterministically. The server also exposes accountant-focused read-only projection endpoints under v1/projections/* for trial balance, period comparison, dimensional, VAT, cash, subledger, audit-trail, and closing-diagnostics views.

This module is intentionally narrow. It does not implement accounting logic and does not replace existing accounting modules. It provides a local browsing surface over workspace data.

Commands

serve starts the local web server. By default it binds to 127.0.0.1 and an auto-selected port. version prints tool name and version.

Serve supports --listen, --port, --token, --token-bytes, --journal-file, --ai, --no-ai, --webview, and --print-url. By default --webview opens an app-style local web shell window and --print-url disables auto-open. Journal source is resolved via bus-journal layout APIs unless overridden by --journal-file.

Examples

bus ledger serve --print-url
bus ledger -C ./workspace serve --journal-file journal.csv --print-url
bus-ledger version

Using from .bus files

ledger serve --print-url
ledger -C ./workspace serve --print-url