wealthbox-cli 2.2.0__tar.gz → 2.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/CHANGELOG.md +16 -0
  2. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/PKG-INFO +1 -1
  3. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/pyproject.toml +1 -1
  4. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/self_cmd.py +21 -0
  5. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/self_upgrade.py +30 -0
  6. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/.github/workflows/ci.yml +0 -0
  7. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/.github/workflows/docs.yml +0 -0
  8. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/.github/workflows/release-binaries.yml +0 -0
  9. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/.gitignore +0 -0
  10. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/CONTRIBUTING.md +0 -0
  11. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/LICENSE +0 -0
  12. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/README.md +0 -0
  13. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/SECURITY.md +0 -0
  14. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/agents/domain.md +0 -0
  15. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/agents/issue-tracker.md +0 -0
  16. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/agents/triage-labels.md +0 -0
  17. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/cli-reference.md +0 -0
  18. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/getting-started.md +0 -0
  19. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/index.md +0 -0
  20. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/overrides/main.html +0 -0
  21. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/docs/promotion.md +0 -0
  22. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/mkdocs.yml +0 -0
  23. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/__init__.py +0 -0
  24. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/__init__.py +0 -0
  25. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/_config.py +0 -0
  26. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/_skill_bootstrap.py +0 -0
  27. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/_skill_paths.py +0 -0
  28. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/_skill_platforms.py +0 -0
  29. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/_util.py +0 -0
  30. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/activity.py +0 -0
  31. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/categories.py +0 -0
  32. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/config.py +0 -0
  33. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/contacts.py +0 -0
  34. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/doctor.py +0 -0
  35. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/events.py +0 -0
  36. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/firm.py +0 -0
  37. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/households.py +0 -0
  38. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/internals.py +0 -0
  39. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/main.py +0 -0
  40. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/me.py +0 -0
  41. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/notes.py +0 -0
  42. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/opportunities.py +0 -0
  43. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/prefs.py +0 -0
  44. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/projects.py +0 -0
  45. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/skills.py +0 -0
  46. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/tasks.py +0 -0
  47. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/users.py +0 -0
  48. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/cli/workflows.py +0 -0
  49. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/__init__.py +0 -0
  50. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/activity.py +0 -0
  51. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/base.py +0 -0
  52. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/categories.py +0 -0
  53. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/comments.py +0 -0
  54. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/contacts.py +0 -0
  55. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/events.py +0 -0
  56. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/households.py +0 -0
  57. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/me.py +0 -0
  58. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/notes.py +0 -0
  59. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/opportunities.py +0 -0
  60. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/projects.py +0 -0
  61. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/tasks.py +0 -0
  62. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/users.py +0 -0
  63. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/client/workflows.py +0 -0
  64. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/firm/__init__.py +0 -0
  65. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/firm/archive.py +0 -0
  66. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/firm/diff.py +0 -0
  67. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/internals/__init__.py +0 -0
  68. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/internals/skill_ref_gen.py +0 -0
  69. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/__init__.py +0 -0
  70. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/activity.py +0 -0
  71. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/comments.py +0 -0
  72. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/common.py +0 -0
  73. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/contacts.py +0 -0
  74. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/custom_fields.py +0 -0
  75. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/enums.py +0 -0
  76. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/events.py +0 -0
  77. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/households.py +0 -0
  78. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/notes.py +0 -0
  79. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/opportunities.py +0 -0
  80. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/projects.py +0 -0
  81. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/tasks.py +0 -0
  82. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/models/workflows.py +0 -0
  83. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/py.typed +0 -0
  84. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/SKILL.md +0 -0
  85. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/bootstrap.md +0 -0
  86. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/firm-examples/contacts.md +0 -0
  87. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/firm-examples/events.md +0 -0
  88. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/firm-examples/notes.md +0 -0
  89. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/firm-examples/opportunities.md +0 -0
  90. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/firm-examples/projects.md +0 -0
  91. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/firm-examples/tasks.md +0 -0
  92. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/firm-examples/workflows.md +0 -0
  93. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/contacts.md +0 -0
  94. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/events.md +0 -0
  95. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/households.md +0 -0
  96. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/lookups.md +0 -0
  97. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/notes.md +0 -0
  98. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/opportunities.md +0 -0
  99. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/projects.md +0 -0
  100. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/tasks.md +0 -0
  101. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/src/wealthbox_tools/skills/wealthbox-crm/references/workflows.md +0 -0
  102. {wealthbox_cli-2.2.0 → wealthbox_cli-2.2.1}/uv.lock +0 -0
@@ -4,6 +4,22 @@ All notable changes to `wealthbox-cli` are documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
5
5
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.2.1] - 2026-05-13
8
+
9
+ Bug-fix release. `wbox self upgrade` was silently no-op'ing for users who
10
+ installed `wbox` via `uv tool install` or `pipx`: it computed the install root
11
+ from `sys.executable` (the venv's `python.exe`) and tried to swap the
12
+ console-script shim there, but `~/.local/bin/wbox.exe` (or pipx's equivalent)
13
+ is a separate copy uv/pipx made — replacing the venv-side shim never changed
14
+ what `PATH` resolved.
15
+
16
+ ### Fixed
17
+ - `wbox self upgrade` now detects the install kind (`bundle` / `uv-tool` /
18
+ `pipx` / `pip`) up front. Non-bundle installs exit `1` with the correct
19
+ follow-up command (`uv tool upgrade wealthbox-cli`, `pipx upgrade
20
+ wealthbox-cli`, or `pip install --upgrade wealthbox-cli`) instead of
21
+ scheduling a swap that would never take effect on `PATH`.
22
+
7
23
  ## [2.2.0] - 2026-05-13
8
24
 
9
25
  Small feature + correctness release. Disambiguates the two IDs returned by
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wealthbox-cli
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: CLI and client library for the Wealthbox CRM API
5
5
  Project-URL: Homepage, https://github.com/massive-value/wealthbox-cli
6
6
  Project-URL: Documentation, https://massive-value.github.io/wealthbox-cli/
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "wealthbox-cli"
7
- version = "2.2.0"
7
+ version = "2.2.1"
8
8
  description = "CLI and client library for the Wealthbox CRM API"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -37,8 +37,29 @@ def _default_install_root() -> Path:
37
37
  return Path(sys.executable).resolve().parent
38
38
 
39
39
 
40
+ _NON_BUNDLE_UPGRADE_HINTS = {
41
+ "uv-tool": "uv tool upgrade wealthbox-cli",
42
+ "pipx": "pipx upgrade wealthbox-cli",
43
+ "pip": "pip install --upgrade wealthbox-cli",
44
+ }
45
+
46
+
40
47
  @app.command("upgrade", help="Upgrade the `wbox` CLI to the latest GitHub release.")
41
48
  def upgrade_cmd() -> None:
49
+ kind = self_upgrade._install_kind()
50
+ if kind != "bundle":
51
+ # The frozen-bundle swap would either silently no-op (uv copies the
52
+ # shim to ~/.local/bin so replacing the venv-side shim doesn't change
53
+ # what PATH resolves) or wedge the venv. Refuse before downloading.
54
+ hint = _NON_BUNDLE_UPGRADE_HINTS.get(kind, _NON_BUNDLE_UPGRADE_HINTS["pip"])
55
+ typer.echo(
56
+ "wbox self upgrade only swaps the standalone binary from "
57
+ "install.ps1.",
58
+ err=True,
59
+ )
60
+ typer.echo(f"This wbox was installed via {kind} — run: {hint}", err=True)
61
+ raise typer.Exit(code=1)
62
+
42
63
  candidate = self_upgrade.check()
43
64
  if candidate is None:
44
65
  typer.echo("Already on the latest version.")
@@ -51,6 +51,7 @@ __all__ = [
51
51
  "check_release_staleness",
52
52
  "apply",
53
53
  "_cleanup_stale_backups",
54
+ "_install_kind",
54
55
  ]
55
56
 
56
57
  _RELEASES_LATEST_URL = (
@@ -139,6 +140,35 @@ def _running_version() -> str:
139
140
  return __version__
140
141
 
141
142
 
143
+ def _install_kind() -> str:
144
+ """Classify how the running ``wbox`` was installed.
145
+
146
+ The :func:`apply` swap is only correct for the standalone PyInstaller
147
+ bundle that ``install.ps1`` ships. Under uv / pipx / pip the install is
148
+ a tiny console-script shim around a venv; replacing it with a frozen
149
+ binary would either silently no-op (PATH points at a copy uv made
150
+ elsewhere, e.g. ``~/.local/bin/wbox.exe``) or wedge the venv on the
151
+ next ``uv tool sync``. The gate in :mod:`cli.self_cmd` consults this
152
+ classifier to refuse with a clear "use <installer> instead" message.
153
+
154
+ Returns one of:
155
+
156
+ - ``"bundle"`` — frozen PyInstaller EXE (``sys.frozen`` is set).
157
+ - ``"uv-tool"`` — ``sys.executable`` lives under a ``uv/tools/`` venv.
158
+ - ``"pipx"`` — ``sys.executable`` lives under a ``pipx/`` venv.
159
+ - ``"pip"`` — anything else (ordinary pip/venv install).
160
+ """
161
+ if getattr(sys, "frozen", False):
162
+ return "bundle"
163
+ parts = [p.lower() for p in Path(sys.executable).resolve().parts]
164
+ for i in range(len(parts) - 1):
165
+ if parts[i] == "uv" and parts[i + 1] == "tools":
166
+ return "uv-tool"
167
+ if "pipx" in parts:
168
+ return "pipx"
169
+ return "pip"
170
+
171
+
142
172
  # ---------------------------------------------------------------------------
143
173
  # Internal helpers
144
174
  # ---------------------------------------------------------------------------
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes