Skip to content

Changelog

All notable changes to wealthbox-cli are documented here. The format follows Keep a Changelog, and this project adheres to Semantic Versioning.

[2.4.1] - 2026-06-12

Patch release fixing a startup crash in 2.4.0. The cli/_factory.py module (introduced in the 2.4.0 refactor) imported click at module level to annotate a TyperGroup subclass, but click is only referenced in type annotations. On installs where typer (>=0.26) does not pull in click as a transitive dependency, wbox crashed on launch with ModuleNotFoundError: No module named 'click' — the same failure class fixed for skill_ref_gen in 2.3.1. This was not caught by CI because the test environment always has click present via the dev dependencies.

Fixed

  • wbox startup crash (ModuleNotFoundError: click) on clean installs that lack click. The import click in cli/_factory.py is now guarded by TYPE_CHECKING (it is only used in annotations, which are not evaluated at runtime under from __future__ import annotations).

Internal

  • CI gains a smoke job that installs the built wheel in isolation without dev dependencies and runs wbox --version, so a missing-runtime-dependency startup crash can no longer reach PyPI. The publish job now depends on it.

[2.4.0] - 2026-06-12

The notable user-facing change in this release is differentiated CLI exit codes — scripts that branch on a specific non-zero code should read the note below. Beyond that, 2.4.0 is largely an internal hardening release: src/ is now mypy --strict clean and gated in CI, the test matrix gained a Windows leg and a coverage floor, and the CLI command layer was refactored onto a shared resource-command factory. Command syntax, options, help text, and output are unchanged.

Changed

  • Differentiated CLI exit codes (behavior change). Previously every error exited with code 1. wbox now distinguishes failure classes: validation / user errors and non-auth 4xx responses (e.g. 404, 422) still exit 1, authentication errors (401/403) now exit 2, and server errors (5xx) now exit 3. Scripts that branched on a specific non-zero code for auth or server failures must be updated. (Click usage errors — unknown flags, missing arguments — continue to exit 2 as before; that overlap is pre-existing.)

Added

  • WBOX_DEBUG environment variable: set it to any non-empty value (e.g. WBOX_DEBUG=1) to print the full Python traceback to stderr alongside the friendly one-line error message. The mapped exit code is unchanged, so it is safe to enable in scripts.
  • Documented the existing WBOX_BRIEF / --brief output mode (strips *_html duplicate fields to cut response size) in the README and CLI reference.

Security

  • Token config file (config.json) and the rate-limit state file are now written with 0600 permissions on POSIX so other local users cannot read a stored token.
  • Malformed Retry-After response header values are truncated to 100 characters before being logged, bounding a hostile/oversized header.

Internal

  • Typing: src/ is now mypy --strict clean (zero errors, zero type: ignore). Client mixins share a typed request protocol and fetch_all_pages returns a typed pagination envelope. A new typecheck CI job runs mypy src/ and gates publishing.
  • CI: added a windows-latest test leg (Python 3.12), a coverage floor (--cov-fail-under=91 on the Ubuntu leg), a publish-time check that the top CHANGELOG version matches pyproject.toml, a weekly Dependabot config, and a .pre-commit-config.yaml (ruff, mypy, skill-ref drift).
  • Refactor: cli/_util.py was split into _client, _format, _resolve, and _factory modules (with _util kept as a re-export shim). The notes, projects, tasks, events, opportunities, and workflows command groups now generate their commands from a shared resource-command factory; contacts remains hand-written. No change to the CLI surface.
  • Tests: added coverage for delete commands, project/workflow updates, contacts list filters, HTTP base-client edge cases (missing/malformed Retry-After, 5xx, missing collection key), exit codes, and an update-model contract meta-test (every *UpdateInput rejects an empty payload).

[2.3.1] - 2026-06-01

Patch release fixing a startup crash introduced in 2.3.0. wbox crashed on launch in clean environments because skill_ref_gen.py imported click at module level — and typer 0.26+ dropped click as a dependency, so it was no longer guaranteed to be present. The fix defers the import inside the hidden regen-skill-refs dev command so normal CLI invocations never touch it. CI also gains skip_existing on the PyPI publish step to survive re-pushed tags without a spurious 400 error.

Fixed

  • wbox startup crash (ModuleNotFoundError: click) in environments where click is not installed. The skill_ref_gen import is now deferred to the body of the hidden regen-skill-refs command, which is only ever invoked during development.
  • PyPI publish job now uses skip_existing: true so re-pushing a tag (e.g. to re-run a failed release workflow) does not fail with a 400 from PyPI when the wheel was already uploaded on the first push.

[2.3.0] - 2026-06-01

Feature release. Adds writable contact-role support (--advisor-role), fixing a long-standing gap where advisor assignments could not be set through the CLI at all — even the --more-fields / --json escape hatches rejected the payload because ContactRoleAssignment modeled the wrong write shape. Also improves the Windows bootstrap installer (idempotent re-runs, -SkipSkills opt-out, token re-use) and clarifies install/upgrade documentation for uv tool and pipx users.

Added

  • --advisor-role ROLE:USER flag on contacts add person|household|org|trust and contacts update. Resolves role names and user substrings against the workspace category list so human-readable values like "Associate Advisor:Jane Smith" are accepted (#94).
  • install.ps1 gains a -SkipSkills switch for CI and non-agent installs that don't need the bundled agent skill.

Fixed

  • ContactRoleAssignment now uses {id, value} (the Wealthbox write shape) instead of {id, type}, unblocking all contact-role write paths including --more-fields (#94).
  • install.ps1 re-runs are now idempotent: if the skill directory already exists the installer runs wbox skills upgrade instead of erroring.
  • install.ps1 no longer prompts for a token when one is already stored in %APPDATA%\wbox\config.json or WEALTHBOX_TOKEN.

Changed

  • README and docs/getting-started.md now include a per-install-method upgrading table and clarify that wbox self upgrade is for bundle installs only; uv tool upgrade / pipx upgrade are the correct paths for managed installs.

[2.2.1] - 2026-05-13

Bug-fix release. wbox self upgrade was silently no-op'ing for users who installed wbox via uv tool install or pipx: it computed the install root from sys.executable (the venv's python.exe) and tried to swap the console-script shim there, but ~/.local/bin/wbox.exe (or pipx's equivalent) is a separate copy uv/pipx made — replacing the venv-side shim never changed what PATH resolved.

Fixed

  • wbox self upgrade now detects the install kind (bundle / uv-tool / pipx / pip) up front. Non-bundle installs exit 1 with the correct follow-up command (uv tool upgrade wealthbox-cli, pipx upgrade wealthbox-cli, or pip install --upgrade wealthbox-cli) instead of scheduling a swap that would never take effect on PATH.

[2.2.0] - 2026-05-13

Small feature + correctness release. Disambiguates the two IDs returned by wbox me, fixes a silent truncation in wbox users list on large firms, and clears Node 20 deprecation warnings from CI ahead of GitHub's June 2026 cutoff.

Added

  • wbox me user-id — prints current_user.id (the workspace user ID accepted by --assigned-to) as a bare integer, for composing with command substitution: wbox tasks list --assigned-to "$(wbox me user-id)" (#90, #91).
  • wbox me --format table now labels the two IDs as login_id and user_id (--assigned-to) so they aren't confusable at a glance. The JSON shape is unchanged — no breaking change for existing scripts (#91).
  • Skill docs (lookups.md, tasks.md, contacts.md) flag the two-ID trap inline near --assigned-to.

Fixed

  • wbox users list now paginates across all pages. Previously, firms with more than 25 users silently saw a truncated list — the CLI exposes no --page flag, so there was no manual workaround.
  • mkdocs docs deploy was failing on every main push because docs/index.md linked to a missing changelog.md. CHANGELOG.md is now staged into docs/ at build time and listed in nav (#92).

Changed

  • CI actions bumped to Node 24 runtimes ahead of GitHub's June 2 2026 cutoff: actions/checkout v4→v6, astral-sh/setup-uv v6→v8.1.0 (pinned exact — setup-uv v8+ no longer publishes rolling major tags as a supply-chain mitigation), actions/setup-python v5→v6, actions/deploy-pages v4→v5, actions/upload-pages-artifact v3→v5 (#92, #93).

[2.1.0] - 2026-05-09

Repository simplification release. Drops a runtime dep, retires .env support, and switches dev tooling to uv.

Breaking

  • Removed .env file support. Token resolution is now a 3-tier chain: --token flag → WEALTHBOX_TOKEN env var → config file. Users relying on a working-directory .env should migrate to wbox config set-token (preferred) or export WEALTHBOX_TOKEN in their shell. The python-dotenv runtime dependency was dropped.

Changed

  • Development tooling moved to uv. uv sync --extra dev replaces the manual python -m venv + activate + pip install -e dance, and uv run wbox … replaces direct .venv/bin/wbox invocation. CI now uses astral-sh/setup-uv@v6 and uv build for the publish job. Plain pip install -e ".[dev]" continues to work — pyproject.toml is the source of truth for both tools.
  • scripts/run-wbox.sh and scripts/smoke_test.sh invoke via uv run and no longer source a .env file.

Removed

  • .env and .env.example files at the repo root.
  • .python-version file. requires-python = ">=3.11" in pyproject.toml is the authoritative interpreter constraint; uv reads it directly.

[2.0.0] - 2026-05-09

v2 retires the Claude marketplace plugin distribution and ships wbox as a standalone binary plus a PyPI package. Existing v1 users must reinstall via the new bootstrap script or pip install wealthbox-cli — see Breaking below.

Breaking

  • Retired the Claude marketplace plugin distribution. wbox no longer ships through the Claude marketplace. Install via pip install wealthbox-cli or the bootstrap script (curl -fsSL https://github.com/massive-value/wealthbox-cli/releases/latest/download/install.sh | sh). v1's claude plugin install flow is gone.
  • Rewrote install.sh and install.ps1 to fetch a prebuilt binary from GitHub Releases instead of detecting and preferring the Claude marketplace plugin (#42, #43). The installers now verify a checksum manifest before swapping the binary into place.
  • Removed v1 distribution artifacts — the in-repo plugin manifest and marketplace metadata are deleted (#27).
  • Dropped plugin-cache scanning from the skill platform helpers; wbox doctor and wbox skills list no longer probe Claude's plugin cache (#28).

Added

  • wbox firm export — end-to-end export of the configured firm's CRM data to a portable JSON snapshot (#31).
  • wbox firm import with --mode overwrite|merge|abort-on-conflict and --from-url for fetching a snapshot directly from a URL (#36, #46, #45).
  • wbox firm diff — diff a local snapshot against the live firm to preview what an import would change (#47).
  • Post-import provenance metadata and a 90-day freshness warning surfaced by wbox doctor (#48).
  • wbox doctor promoted to a top-level command, with a warning when the local install is more than 30 days behind the latest GitHub release (#41).
  • wbox self upgrade — happy-path binary self-update (#32), Windows deferred-swap support (#67), and a subprocess hand-off so a fresh wbox upgrades bundled skills after the binary swap (#40).
  • wbox prefs — user-preferences slot for per-user defaults (#29).
  • Per-platform PyInstaller build + release workflow that publishes Linux, macOS, and Windows binaries plus a checksum manifest to GitHub Releases (#33).
  • Skill-reference auto-generation markers across the bundled skill (#30, #85) and a CI drift-detection job that fails when generated skill blocks fall out of sync (#86).
  • Bootstrap Q&A skips the onboarding prompts when an imported firm snapshot already carries an onboarded_at timestamp (#49).
  • wbox firm apply and wbox doctor now sweep stale .old.<ts> backup files left behind by interrupted upgrades (#39).

Changed

  • Rewrote the README around the v2 install flow — bootstrap script first, PyPI second, no marketplace path (#83).
  • Documented the three-layer config resolution (flag > env > config file) and the new prefs commands inside the bundled skill (#34).

Fixed

  • wbox self upgrade now reads the checksum manifest under its release-asset filename, fixing the post-#33 break (#82).
  • Pytest no longer clobbers the developer's real ~/.wbox_rate_limit.json; the rate-limit state file is isolated per test session (#56).

1.3.0 - 2026-05-03

Added

  • wbox doctor — comprehensive top-level health check at the CLI root. Reports the wbox CLI version + Python version + binary location; authentication source detection (flag / env var / config file / .env) plus a smoke test against /me; agent CLI presence (claude / codex on PATH); legacy skill installs; plugin installs (managed via claude plugin install / codex plugin install); firm data state with file count, generated-vs-hand-edited split, and oldest-generated-file timestamp; and a Summary section listing actionable issues. wbox skills doctor keeps working as an alias of the new top-level command — both call the same function so output never drifts.
  • wbox skills list and wbox skills doctor now detect plugin-installed copies of wealthbox-crm under ~/.claude/plugins/cache/.../skills/wealthbox-crm/ and ~/.codex/plugins/cache/.../skills/wealthbox-crm/. Previously a user who installed via the marketplace plugin path saw "not installed" everywhere even though the plugin was actively serving the skill.
  • Bootstrap installer (scripts/install.sh / scripts/install.ps1) now prefers the Claude Code plugin marketplace path when claude is on PATH — runs claude plugin marketplace add + claude plugin install directly, then offers a separate Codex install. Falls back to the legacy wbox skills install picker when no claude CLI is detected.
  • Bootstrap installer pre-flight checks Windows PowerShell ExecutionPolicy and offers to set RemoteSigned for the current user if needed (no admin required), instead of bombing partway through with Astral's terse error.

Fixed

  • Bootstrap install.sh no longer hangs at startup. The previous version did `exec