bus — dispatcher and `.bus` command-file runner
bus — dispatcher for modules and .bus files
Synopsis
bus [<command> [args...]]
bus [--check] [--transaction <provider>] [--scope <scope>] [--trace] <file.bus> [<file2.bus> ...]
./file.bus
Use bus in two modes:
Normal dispatch uses bus <module> [args...] and calls bus-<module> from PATH. Busfile mode uses bus <file>.bus [...] and executes one or more .bus command files.
Description
bus is the single CLI entrypoint for BusDK. It does not implement accounting logic itself; it routes commands to module CLIs (bus-journal, bus-bank, and so on), and it can execute deterministic .bus files.
If you run bus with no arguments, it prints usage and a quick tip suggesting bus shell for interactive command entry.
Run bus --help when you need the current syntax-first global help with grouped dispatcher usage and the current available-command list.
When running busfiles, bus always does a full syntax preflight across all provided files before executing any command. If preflight fails, nothing is executed.
Dispatcher-level -C/--chdir applies to busfile mode too, so relative busfile paths are resolved after switching into the selected workspace and the executed module commands inherit that same effective working directory.
For first use, start with .bus files — getting started step by step, then continue with the full .bus script files (writing and execution guide).
If you edit .bus files regularly, install the Bus language package for
VS Code compatible editors as described in Editor support for .bus
files.
That same editor-support surface now also includes a Tree-sitter grammar and a
lightweight stdio language server, so .bus files can be highlighted and
semantically tokenized outside VS Code-compatible editors too.
This feature is available under FSL-1.1-MIT (Functional Source License 1.1, MIT Future License), and source code is already available.
Normal dispatch
bus <module> <args...> dispatches to bus-<module>. For example, bus journal add ... runs bus-journal add .... bus run ... is treated like any other module dispatch target.
That same rule applies to BusDK installer and package-manager flows. bus update ... and bus update package ... both delegate to bus-update; the dispatcher does not embed package download, package database, or installer logic itself. In a bootstrap-installed setup, this keeps bus as the stable entrypoint while bus-update remains the owning module for release checks, managed executable packages, and bootstrap-root behavior.
Busfile mode
A path is treated as a busfile when:
it ends with .bus, or it is executable and starts with #!/usr/bin/bus or #!/usr/bin/env bus.
Busfile line rules:
Blank lines are ignored. Lines whose first non-whitespace character is # are comments. Lines ending with .bus are treated as nested includes. Other lines are parsed as a single command line with shell-like quoting.
A line that contains only dispatcher global flags acts as a sticky directive for
subsequent commands in the same .bus session. This uses the same global-flag
parser as normal dispatch, so later single-value flags replace earlier ones.
For example, --chdir data followed later by --chdir reports means later
commands receive only --chdir reports. Sticky state can be reset with
--no-perf, --no-quiet, --no-verbose, --no-chdir, --no-output, and
--no-format. Color uses --color ... and --no-color. Sticky directives
also propagate into included .bus files that are expanded after the
directive.
Variable expansion, command substitution, pipes and redirection, and ; separators are not interpreted.
Busfile options
These flags are interpreted only in busfile mode:
--check runs preflight (and optional validation) only and does not apply changes. --transaction <provider> accepts none (default), fs, git, snapshot, or copy. --scope <scope> accepts file (default) or batch. --trace prints file:line traces before execution.
--check should rely on module-native non-mutating validation where available.
Dispatcher also rejects clearly invalid common patterns during preflight. For
journal add, that preflight accepts the same posting token shapes as the
module help, including ACCOUNT=AMOUNT=ROW_DESCRIPTION with quoted UTF-8 row
text in .bus files.
Execution model
- Global syntax preflight: read/tokenize all provided busfiles first.
- Optional data validation (workspace/module support dependent).
- Apply in order with fail-fast semantics.
Scope file is the default and applies each file independently after global preflight. Scope batch treats all files as one apply unit, with all-or-nothing behavior only when the chosen provider supports it.
Exit status
Exit 0 means success. Exit 1 means command execution failed. Exit 2 means usage error such as invalid flags, missing file, or missing subcommand in normal dispatch usage. Exit 65 means busfile syntax or tokenization error. Exit 127 means missing normal-dispatch target (bus-<command> not found on PATH).
If a dispatched module returns a specific non-zero code, bus returns that code.
Examples
Normal dispatch:
bus init all
bus accounts list
bus journal add --date 2024-02-29 --desc "Example" --debit 1910=10 --credit 3000=10
bus update package install --module bus-ledger
Single busfile:
#!/usr/bin/env bus
# 2024-02-29 Bank import-bank-00001
bank add transactions \
--set bank_txn_id=import-bank-00001 \
--set import_id=import-bank-2024 \
--set booked_date=2024-02-29 \
--set value_date=2024-02-29 \
--set amount=-861.6800000000 \
--set currency=EUR \
--set counterparty_name='Example Vendor' \
--set counterparty_iban='' \
--set reference='REF-00001' \
--set message='EXAMPLE PAYMENT MESSAGE' \
--set end_to_end_id=import-e2e-00001 \
--set source_id='bank_row:00001'
journal add \
--date 2024-02-29 \
--desc 'Bank import-bank-00001 Example Vendor payment' \
--debit 2949=861.68 \
--credit 1910=861.68 \
--source-id bank_row:00001:journal:1
Run monthly files directly:
bus 2024-01.bus 2024-02.bus 2024-03.bus
Example month runner file:
#!/usr/bin/env bus
2024-01.bus
2024-02.bus
2024-03.bus
Check-only and trace:
bus --check --trace 2024-01.bus 2024-02.bus 2024-03.bus
Force transaction settings for one run:
bus --transaction git --scope batch 2024-01.bus 2024-02.bus 2024-03.bus
Using from .bus files
bus is the dispatcher itself. In .bus files you normally call module targets directly and include other .bus files.
# include another .bus file
2026-02.bus
# module command line (same as: bus journal add --date 2026-02-28 --desc "Adjust" --debit 1910=100 --credit 3000=100)
journal add --date 2026-02-28 --desc "Adjust" --debit 1910=100 --credit 3000=100
# module command line (same as: bus run send-feedback --message "Close run complete")
run send-feedback --message "Close run complete"
Notes
Atomicity is configurable and the default transaction provider is none. Prefer the .bus extension for deterministic recognition. For safer batch runs, keep --check support enabled in referenced modules.
Dispatch during busfile runs is automatic: an in-process runner is used when available, otherwise shell lookup (bus-<module> on PATH) is used when enabled. Shell lookup can be disabled with bus.busfile.dispatch.shell_lookup_enabled=false in preferences or workspace config.
For deeper transaction/dispatch internals, see Module reference: bus (dispatcher).