Terminal app for vagal tone training. Single-file Python, no dependencies. Grounded in CHF clinical trials (Bernardi, Vaschillo, Lehrer). macOS.
Status: Draft — not yet approved for implementation
Date: 2026-06-07
Parent: TODO #14 · Spec: breathing-dsl-spec.md
Python (breathe.py) = v1.x — feature-frozen, bugfixes only. The
cardiac-safe resonance breathing pacer. Stays on PyPI. The code and
tests serve as the living spec / reference implementation for the Go
rewrite.
Go = v2.x — the universal breathing pacer with the DSL. Same repo
(marekkowalczyk/breathe-cli). Ships as a single compiled binary.
Why Go:
go build.brew install, go install, or download from GitHub
Releases.Why same repo:
v1-python/ archive directory.What the Python code provides for the Go rewrite:
breathe-cli/
cmd/breathe/ # Go main package
internal/
parser/ # DSL parser + well-formedness validation
safety/ # safety rules (per-mode)
config/ # session config, presets
tui/ # terminal rendering, ANSI, state machine
audio/ # platform audio (macOS/Windows/Linux)
go.mod
go.sum
README.md
LICENSE
v1-python/ # archived Python v1
breathe.py # reference implementation (frozen)
test_breathe.py # reference tests
dev/
breathe-cli-spec.md
breathing-dsl-spec.md
breathing-dsl-versions.md # this file
TODO.md
...
Status: Stable. Bugfixes only. No new features.
The existing app: cardiac-safe resonance breathing pacer, single-file
Python, stdlib only. Remains on PyPI as breathe-cli.
User-visible change: Same app, now a Go binary. All v1 features work identically.
Work:
INHALE/EXHALE/PAUSED).afplay, Windows winsound equivalent).--preset, --ratio, --duration, --no-sound,
--quiet, --no-log, --log, --safety, --list-presets,
--version.test_breathe.py to Go tests.q, Ctrl+C, terminal restoration in all cases.
The defer block is the most important code in the binary.Why first: Feature parity before new features. If the Go version can’t pass all 25 manual acceptance tests, nothing else matters.
Release: v2.0.0 on GitHub Releases. Homebrew tap. Python v1
archived to v1-python/.
User-visible change: None.
Work:
(inhale, exhale) to
(inhale, hold1, exhale, hold2) with holds pinned to 0.--ratio 4:6 maps to (4, 0, 6, 0) internally.Why here: Foundation for everything that follows. Trivial in Go since we’re already building the data structures fresh.
Note: in practice this may be folded into v2.0 since we’re building from scratch anyway. Kept as a separate logical step for clarity.
--pattern flag and parserUser-visible change: New --pattern "4-0-6-0" flag. Holds must
still be zero.
Work:
I-H1-E-H2 syntax.--pattern + --ratio (conflict).Why separate: Proves the parser in isolation. No state machine changes yet.
User-visible change: --pattern "4-7-8-0" works. Hold phases
are displayed and paced.
Work:
HOLD_IN and HOLD_OUT states.INHALE -> HOLD_IN -> EXHALE -> HOLD_OUT
-> INHALE. Zero-duration holds are skipped.H1 <= 30s, H2 <= 30s, cycle >= 8s).INHALE.Risk: Largest single step. Consider sub-steps:
User-visible change: --preset box, --preset relaxation, etc.
Work:
box -> 5-5-5-5, relaxation -> 4-7-8-0.--list-presets shows expanded table.Good candidate for the Show HN update (TODO #16).
User-visible change: 10(4-0-6-0) runs exactly 10 cycles.
Work:
--duration must not be specified
when count is present (conflict is an error — spec §5.1).User-visible change: 5(4-0-6-0)+10(5-5-5-5) runs two segments
in sequence.
Work:
+ operator joining segments.--duration conflicts with chains that have counts (spec §5.1).User-visible change: 4m-0-6n-0 shows “IN (mouth)” /
“OUT (nose)” in the TUI.
Work:
4nm, 4ds).Lowest priority. DSL is fully functional without modifiers.
v1.x Python (frozen, bugfixes only)
v2.0 Go scaffold + feature parity with Python v1
|
v
v2.1 Internal four-phase model (may fold into v2.0)
|
v
v2.2 --pattern flag + parser
|
v
v2.3 Hold phases in state machine + TUI <-- first new feature
|
v
v2.4 Named presets (box, relaxation, ...) <-- Show HN moment
|
v
v2.5 Repetition counts 10(...)
|
v
v2.6 Chaining ... + ...
|
v
v2.7 Modifiers 4m, 6n, 5nd
--mode cardiac a flag, or
is it implicit from the preset/pattern? Decide before v2.3.breathe-cli on
PyPI get a deprecation notice pointing to the Go binary? Or
does it stay as-is for Python users who prefer it?