lib-cli-exit-tools 2.2.2__tar.gz → 2.2.3__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 (77) hide show
  1. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.github/workflows/ci.yml +2 -2
  2. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.github/workflows/release.yml +1 -1
  3. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/CHANGELOG.md +17 -0
  4. lib_cli_exit_tools-2.2.3/CLAUDE.md +164 -0
  5. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/INSTALL.md +3 -2
  6. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/PKG-INFO +41 -34
  7. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/README.md +39 -32
  8. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/docs/system-design/module_reference.md +2 -2
  9. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/pyproject.toml +5 -2
  10. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/__init__conf__.py +1 -1
  11. lib_cli_exit_tools-2.2.2/AGENTS.md +0 -208
  12. lib_cli_exit_tools-2.2.2/AGENTS_README.md +0 -176
  13. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/cli-config.yaml +0 -0
  14. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/cli.sh +0 -0
  15. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/codacy.yaml +0 -0
  16. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/tools-configs/lizard.yaml +0 -0
  17. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.codacy/tools-configs/trivy.yaml +0 -0
  18. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.devcontainer/devcontainer.json +0 -0
  19. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.devcontainer/settings.json +0 -0
  20. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.env.example +0 -0
  21. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.github/dependabot.yml +0 -0
  22. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.github/workflows/codeql.yml +0 -0
  23. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.gitignore +0 -0
  24. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.qlty/qlty.toml +0 -0
  25. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/.snyk +0 -0
  26. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/CONTRIBUTING.md +0 -0
  27. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/DEVELOPMENT.md +0 -0
  28. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/LICENSE +0 -0
  29. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/Makefile +0 -0
  30. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/codecov.yml +0 -0
  31. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/notebooks/Quickstart.ipynb +0 -0
  32. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/__init__.py +0 -0
  33. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/__main__.py +0 -0
  34. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/_utils.py +0 -0
  35. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/build.py +0 -0
  36. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump.py +0 -0
  37. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_major.py +0 -0
  38. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_minor.py +0 -0
  39. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_patch.py +0 -0
  40. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/bump_version.py +0 -0
  41. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/clean.py +0 -0
  42. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/cli.py +0 -0
  43. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/dependencies.py +0 -0
  44. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/dev.py +0 -0
  45. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/help.py +0 -0
  46. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/install.py +0 -0
  47. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/menu.py +0 -0
  48. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/push.py +0 -0
  49. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/release.py +0 -0
  50. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/run_cli.py +0 -0
  51. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/target_metadata.py +0 -0
  52. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/test.py +0 -0
  53. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/toml_config.py +0 -0
  54. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/scripts/version_current.py +0 -0
  55. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/__init__.py +0 -0
  56. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/__main__.py +0 -0
  57. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/adapters/__init__.py +0 -0
  58. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/adapters/signals.py +0 -0
  59. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/application/__init__.py +0 -0
  60. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/application/runner.py +0 -0
  61. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/cli.py +0 -0
  62. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/core/__init__.py +0 -0
  63. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/core/configuration.py +0 -0
  64. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/core/exit_codes.py +0 -0
  65. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/lib_cli_exit_tools.py +0 -0
  66. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/src/lib_cli_exit_tools/py.typed +0 -0
  67. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/conftest.py +0 -0
  68. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_adapters_signals.py +0 -0
  69. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_application_runner.py +0 -0
  70. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_behaviors.py +0 -0
  71. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_cli.py +0 -0
  72. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_core_configuration.py +0 -0
  73. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_core_exit_codes.py +0 -0
  74. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_metadata.py +0 -0
  75. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_module_entry.py +0 -0
  76. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_scripts.py +0 -0
  77. {lib_cli_exit_tools-2.2.2 → lib_cli_exit_tools-2.2.3}/tests/test_signals_integration.py +0 -0
@@ -83,14 +83,14 @@ jobs:
83
83
  run: |
84
84
  uv pip install pywin32 --system
85
85
  - name: Cache ruff
86
- uses: actions/cache@v4
86
+ uses: actions/cache@v5
87
87
  with:
88
88
  path: .ruff_cache
89
89
  key: ruff-${{ runner.os }}-${{ github.sha }}
90
90
  restore-keys: |
91
91
  ruff-${{ runner.os }}-
92
92
  - name: Cache pyright
93
- uses: actions/cache@v4
93
+ uses: actions/cache@v5
94
94
  with:
95
95
  path: .pyright
96
96
  key: pyright-${{ runner.os }}-py${{ matrix.python }}-${{ github.sha }}
@@ -44,7 +44,7 @@ jobs:
44
44
  attestations: false
45
45
  skip-existing: true
46
46
  - name: Upload artifacts
47
- uses: actions/upload-artifact@v5
47
+ uses: actions/upload-artifact@v6
48
48
  with:
49
49
  name: dist
50
50
  path: dist/*
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4
4
 
5
5
 
6
+ ## [2.2.3] - 2025-12-17
7
+
8
+ ### Fixed
9
+ - Corrected README examples to use `rich_click` instead of plain `click` for consistency with library internals.
10
+ - Fixed Example 2 (cli_session) to avoid nested `run_cli` calls.
11
+ - Fixed Example 3 (multi-command CLI) so `--traceback` flag actually controls traceback display.
12
+ - Added missing blank line in Example 4 (custom signal handlers).
13
+ - Updated `print_exception_message` API reference signature to show `trace_back=None` default.
14
+
15
+ ### Changed
16
+ - Updated CLAUDE.md with correct `docs/system-design/` path and added missing `python_data_architecture_enforcement.md` guideline.
17
+ - Removed irrelevant Documentation & Translations section from CLAUDE.md.
18
+ - Updated INSTALL.md to list all three console script entry points consistently.
19
+
20
+ ### Security
21
+ - Added filelock CVE-2025-68146 to pip-audit ignore list (transitive dev dependency, fix pending upstream).
22
+
6
23
  ## [2.2.2] - 2025-12-12
7
24
 
8
25
  ### Changed
@@ -0,0 +1,164 @@
1
+ # Claude Code Guidelines for lib_cli_exit_tools
2
+
3
+ ## Session Initialization
4
+
5
+ When starting a new session, read and apply the following system prompt files from `/media/srv-main-softdev/projects/softwarestack/systemprompts`:
6
+
7
+ ### Core Guidelines (Always Apply)
8
+ - `core_programming_solid.md`
9
+
10
+ ### Bash-Specific Guidelines
11
+ When working with Bash scripts:
12
+ - `core_programming_solid.md`
13
+ - `bash_clean_architecture.md`
14
+ - `bash_clean_code.md`
15
+ - `bash_small_functions.md`
16
+
17
+ ### Python-Specific Guidelines
18
+ When working with Python code:
19
+ - `core_programming_solid.md`
20
+ - `python_solid_architecture_enforcer.md`
21
+ - `python_clean_architecture.md`
22
+ - `python_clean_code.md`
23
+ - `python_small_functions_style.md`
24
+ - `python_libraries_to_use.md`
25
+ - `python_data_architecture_enforcement.md`
26
+
27
+ ### Additional Guidelines
28
+ - `self_documenting.md`
29
+ - `self_documenting_template.md`
30
+ - `python_jupyter_notebooks.md`
31
+ - `python_testing.md`
32
+
33
+ ## Project Structure
34
+
35
+ ```
36
+ lib_cli_exit_tools/
37
+ ├── .github/
38
+ │ └── workflows/ # GitHub Actions CI/CD workflows
39
+ ├── .devcontainer/ # Dev container configuration
40
+ ├── docs/ # Project documentation
41
+ │ └── system-design/ # System design documents
42
+ ├── notebooks/ # Jupyter notebooks for experiments
43
+ ├── scripts/ # Build and automation scripts
44
+ │ ├── __init__.py # Package marker
45
+ │ ├── __main__.py # Module entry point
46
+ │ ├── _utils.py # Shared utilities
47
+ │ ├── build.py # Build wheel/sdist
48
+ │ ├── bump.py # Version bump (generic)
49
+ │ ├── bump_major.py # Bump major version
50
+ │ ├── bump_minor.py # Bump minor version
51
+ │ ├── bump_patch.py # Bump patch version
52
+ │ ├── bump_version.py # Version bump utilities
53
+ │ ├── clean.py # Clean build artifacts
54
+ │ ├── cli.py # CLI for scripts
55
+ │ ├── dependencies.py # Dependency management
56
+ │ ├── dev.py # Development install
57
+ │ ├── help.py # Show help
58
+ │ ├── install.py # Install package
59
+ │ ├── menu.py # Interactive TUI menu
60
+ │ ├── push.py # Git push
61
+ │ ├── release.py # Create releases
62
+ │ ├── run_cli.py # Run CLI
63
+ │ ├── target_metadata.py # Metadata generation
64
+ │ ├── test.py # Run tests with coverage
65
+ │ ├── toml_config.py # TOML configuration utilities
66
+ │ └── version_current.py # Print current version
67
+ ├── src/
68
+ │ └── lib_cli_exit_tools/ # Main Python package
69
+ │ ├── __init__.py # Package initialization
70
+ │ ├── __init__conf__.py # Configuration constants
71
+ │ ├── __main__.py # CLI entry point
72
+ │ ├── cli.py # CLI implementation
73
+ │ ├── lib_cli_exit_tools.py # Core library functions
74
+ │ ├── py.typed # PEP 561 marker
75
+ │ ├── adapters/ # Adapter layer
76
+ │ │ └── signals.py # Signal handling adapters
77
+ │ ├── application/ # Application layer
78
+ │ │ └── runner.py # Application runner
79
+ │ └── core/ # Core domain layer
80
+ │ ├── configuration.py # Configuration management
81
+ │ └── exit_codes.py # Exit code definitions
82
+ ├── tests/ # Test suite
83
+ ├── .env.example # Example environment variables
84
+ ├── CLAUDE.md # Claude Code guidelines (this file)
85
+ ├── CHANGELOG.md # Version history
86
+ ├── CONTRIBUTING.md # Contribution guidelines
87
+ ├── DEVELOPMENT.md # Development setup guide
88
+ ├── INSTALL.md # Installation instructions
89
+ ├── LICENSE # MIT License
90
+ ├── Makefile # Make targets for common tasks
91
+ ├── pyproject.toml # Project metadata & dependencies
92
+ ├── codecov.yml # Codecov configuration
93
+ └── README.md # Project overview
94
+ ```
95
+
96
+ ## Versioning & Releases
97
+
98
+ - **Single Source of Truth**: Package version is in `pyproject.toml` (`[project].version`)
99
+ - **Version Bumps**: update `pyproject.toml`, `CHANGELOG.md` and update the constants in `src/lib_cli_exit_tools/__init__conf__.py` according to `pyproject.toml`
100
+ - Automation rewrites `src/lib_cli_exit_tools/__init__conf__.py` from `pyproject.toml`, so runtime code imports generated constants instead of querying `importlib.metadata`.
101
+ - After updating project metadata (version, summary, URLs, authors) run `make test` (or `python -m scripts.test`) to regenerate the metadata module before committing.
102
+ - **Release Tags**: Format is `vX.Y.Z` (push tags for CI to build and publish)
103
+
104
+ ## Common Make Targets
105
+
106
+ | Target | Description |
107
+ |-------------------|---------------------------------------------------------------------------------|
108
+ | `build` | Build wheel/sdist artifacts |
109
+ | `bump` | Bump version (VERSION=X.Y.Z or PART=major\|minor\|patch) and update changelog |
110
+ | `bump-major` | Increment major version ((X+1).0.0) |
111
+ | `bump-minor` | Increment minor version (X.Y.Z → X.(Y+1).0) |
112
+ | `bump-patch` | Increment patch version (X.Y.Z → X.Y.(Z+1)) |
113
+ | `clean` | Remove caches, coverage, and build artifacts (includes `dist/` and `build/`) |
114
+ | `dev` | Install package with dev extras |
115
+ | `help` | Show make targets |
116
+ | `install` | Editable install |
117
+ | `menu` | Interactive TUI menu |
118
+ | `push` | Commit changes and push to GitHub (no CI monitoring) |
119
+ | `release` | Tag vX.Y.Z, push, sync packaging, run gh release if available |
120
+ | `run` | Run module entry (`python -m ... --help`) |
121
+ | `test` | Lint, format, type-check, run tests with coverage, upload to Codecov |
122
+ | `version-current` | Print current version from `pyproject.toml` |
123
+
124
+ ## Coding Style & Naming Conventions
125
+
126
+ Follow the guidelines in `python_clean_code.md` for all Python code.
127
+
128
+ ## Architecture Overview
129
+
130
+ This library follows Clean Architecture with three layers:
131
+ - **core/**: Domain layer with exit codes and configuration (no external dependencies)
132
+ - **application/**: Application services and runners
133
+ - **adapters/**: External interfaces (signal handling)
134
+
135
+ Import rules (enforced by import-linter):
136
+ - `core` cannot import from `application`, `adapters`, or `cli`
137
+ - `application` cannot import from `cli`
138
+
139
+ Apply principles from `python_clean_architecture.md` when designing and implementing features.
140
+
141
+ ## Security & Configuration
142
+
143
+ - `.env` files are for local tooling only (CodeCov tokens, etc.)
144
+ - **NEVER** commit secrets to version control
145
+ - Rich logging should sanitize payloads before rendering
146
+
147
+ ## Commit & Push Policy
148
+
149
+ ### Pre-Push Requirements
150
+ - **Always run `make test` before pushing** to avoid lint/test breakage
151
+ - Ensure all tests pass and code is properly formatted
152
+
153
+ ### Post-Push Monitoring
154
+ - Monitor GitHub Actions for errors after pushing
155
+ - Attempt to correct any CI/CD errors that appear
156
+
157
+ ## Claude Code Workflow
158
+
159
+ When working on this project:
160
+ 1. Read relevant system prompts at session start
161
+ 2. Apply appropriate coding guidelines based on file type
162
+ 3. Run `make test` before commits
163
+ 4. Follow versioning guidelines for releases
164
+ 5. Monitor CI after pushing changes
@@ -126,8 +126,9 @@ We distribute via PyPI only. If you prefer isolated CLI installs, use tools such
126
126
 
127
127
  After installation the following commands should resolve:
128
128
 
129
- - `lib_cli_exit_tools`
130
- - `cli-exit-tools`
129
+ - `lib-cli-exit-tools` (default console script)
130
+ - `lib_cli_exit_tools` (alias)
131
+ - `cli-exit-tools` (alias)
131
132
  - `python -m lib_cli_exit_tools`
132
133
 
133
134
  If you installed inside a virtual environment, activate it before running the commands. For user installs, ensure the relevant `bin`/`Scripts` directory is included in your PATH:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lib_cli_exit_tools
3
- Version: 2.2.2
3
+ Version: 2.2.3
4
4
  Summary: CLI exit handling helpers: clean signals, exit codes, and error printing
5
5
  Project-URL: Homepage, https://github.com/bitranox/lib_cli_exit_tools
6
6
  Project-URL: Repository, https://github.com/bitranox/lib_cli_exit_tools.git
@@ -31,7 +31,7 @@ Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
31
31
  Requires-Dist: pytest>=9.0.2; extra == 'dev'
32
32
  Requires-Dist: rtoml>=0.13.0; extra == 'dev'
33
33
  Requires-Dist: ruff>=0.14.9; extra == 'dev'
34
- Requires-Dist: textual>=6.8.0; extra == 'dev'
34
+ Requires-Dist: textual>=6.10.0; extra == 'dev'
35
35
  Requires-Dist: twine>=6.2.0; extra == 'dev'
36
36
  Description-Content-Type: text/markdown
37
37
 
@@ -130,7 +130,7 @@ CLI that demonstrates configuration hooks and structured error handling.
130
130
  ```python
131
131
  from __future__ import annotations
132
132
 
133
- import click
133
+ import rich_click as click
134
134
 
135
135
  from lib_cli_exit_tools import run_cli
136
136
 
@@ -138,7 +138,6 @@ from lib_cli_exit_tools import run_cli
138
138
  @click.command()
139
139
  def hello() -> None:
140
140
  """Say hello with automatic signal-aware exit handling."""
141
-
142
141
  click.echo("Hello from lib_cli_exit_tools!")
143
142
 
144
143
 
@@ -157,29 +156,32 @@ python hello.py
157
156
  ```python
158
157
  from __future__ import annotations
159
158
 
160
- import click
161
-
162
- from lib_cli_exit_tools import cli_session, run_cli
163
-
159
+ import rich_click as click
164
160
 
165
- @click.command()
166
- @click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
167
- def cli(traceback: bool) -> int:
168
- with cli_session(overrides={"traceback": traceback}) as execute:
169
- return execute(failable, argv=[])
161
+ from lib_cli_exit_tools import cli_session
170
162
 
171
163
 
172
164
  @click.command()
173
165
  def failable() -> None:
166
+ """Command that always fails to demonstrate traceback handling."""
174
167
  raise RuntimeError("toggle --traceback to see the full traceback")
175
168
 
176
169
 
170
+ def main(*, traceback: bool = False) -> int:
171
+ """Run failable with optional traceback display."""
172
+ with cli_session(overrides={"traceback": traceback}) as run:
173
+ return run(failable)
174
+
175
+
177
176
  if __name__ == "__main__":
178
- raise SystemExit(run_cli(cli))
177
+ import sys
178
+
179
+ enable_traceback = "--traceback" in sys.argv
180
+ raise SystemExit(main(traceback=enable_traceback))
179
181
  ```
180
182
 
181
- Invoking `python cli.py --traceback` enables coloured tracebacks just for that
182
- run and resets the configuration afterwards.
183
+ Running `python cli.py --traceback` enables coloured tracebacks for that
184
+ session. The `cli_session` context manager restores configuration afterwards.
183
185
 
184
186
  #### 3. Full-featured multi-command CLI
185
187
 
@@ -187,9 +189,10 @@ run and resets the configuration afterwards.
187
189
  from __future__ import annotations
188
190
 
189
191
  import json
192
+ import sys
190
193
  from dataclasses import dataclass
191
194
 
192
- import click
195
+ import rich_click as click
193
196
 
194
197
  from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
195
198
 
@@ -197,21 +200,19 @@ from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
197
200
  @dataclass(slots=True)
198
201
  class Settings:
199
202
  pretty: bool
200
- traceback: bool
201
203
 
202
204
 
203
205
  @click.group()
204
206
  @click.option("--pretty/--no-pretty", default=True)
205
- @click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
206
207
  @click.pass_context
207
- def cli(ctx: click.Context, pretty: bool, traceback: bool) -> None:
208
- ctx.obj = Settings(pretty=pretty, traceback=traceback)
208
+ def cli(ctx: click.Context, pretty: bool) -> None:
209
+ ctx.obj = Settings(pretty=pretty)
209
210
 
210
211
 
211
212
  @cli.command()
212
213
  @click.pass_obj
213
214
  def info(settings: Settings) -> None:
214
- payload = {"traceback": settings.traceback, "pretty": settings.pretty}
215
+ payload = {"pretty": settings.pretty}
215
216
  click.echo(json.dumps(payload, indent=2 if settings.pretty else None))
216
217
 
217
218
 
@@ -223,20 +224,24 @@ def fail(settings: Settings) -> None:
223
224
 
224
225
 
225
226
  def main() -> int:
226
- overrides = {"traceback": True, "traceback_force_color": True}
227
+ # Parse --traceback early before entering cli_session
228
+ traceback = "--traceback" in sys.argv
229
+ argv = [arg for arg in sys.argv[1:] if arg != "--traceback"]
230
+
231
+ overrides = {"traceback": traceback, "traceback_force_color": traceback}
227
232
  signals: list[SignalSpec] = default_signal_specs()
228
233
  with cli_session(overrides=overrides) as execute:
229
- return execute(cli, signal_specs=signals)
234
+ return execute(cli, argv=argv, signal_specs=signals)
230
235
 
231
236
 
232
237
  if __name__ == "__main__":
233
238
  raise SystemExit(main())
234
239
  ```
235
240
 
236
- This version wires configuration overrides, custom signal specs, and multiple
237
- commands into a single composition point—mirroring how a production CLI can
238
- layer policy logic around Click while still delegating exit-code translation to
239
- `lib_cli_exit_tools`.
241
+ This version parses `--traceback` early (before Click sees it), then wires
242
+ configuration overrides, custom signal specs, and multiple commands into a
243
+ single composition point—mirroring how a production CLI can layer policy logic
244
+ around Click while still delegating exit-code translation to `lib_cli_exit_tools`.
240
245
 
241
246
  #### 4. Custom signal handlers
242
247
 
@@ -251,7 +256,7 @@ import signal
251
256
  from contextlib import ExitStack
252
257
  from typing import Callable
253
258
 
254
- import click
259
+ import rich_click as click
255
260
 
256
261
  from lib_cli_exit_tools import SignalSpec, default_signal_specs, run_cli
257
262
 
@@ -271,6 +276,8 @@ def custom_signal_specs() -> list[SignalSpec]:
271
276
  )
272
277
  )
273
278
  return specs
279
+
280
+
274
281
  def install_custom_signals(specs: list[SignalSpec] | None) -> Callable[[], None]:
275
282
  stack = ExitStack()
276
283
 
@@ -478,11 +485,11 @@ Compute a platform-aware exit status for arbitrary exceptions (errno mappings on
478
485
  Parameters:
479
486
  - `exc`: Exception instance to classify.
480
487
 
481
- ### `print_exception_message(trace_back=config.traceback, length_limit=500, stream=None) -> None`
488
+ ### `print_exception_message(trace_back=None, length_limit=500, stream=None) -> None`
482
489
  Emit the active exception using Rich formatting. Produces a coloured traceback when `trace_back` is `True`, otherwise prints a truncated summary in red. Respects `config.traceback_force_color` and mirrors the behaviour of `handle_cli_exception` (tracebacks are rendered before the helper returns an exit status).
483
490
 
484
491
  Parameters:
485
- - `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`).
492
+ - `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`). When `None` (default), uses `config.traceback`.
486
493
  - `length_limit`: Maximum characters for summary output.
487
494
  - `stream`: Target text stream; defaults to `sys.stderr`.
488
495
 
@@ -557,7 +564,8 @@ from __future__ import annotations
557
564
 
558
565
  from typing import Sequence
559
566
 
560
- import click
567
+ import rich_click as click
568
+
561
569
  import lib_cli_exit_tools
562
570
 
563
571
  from . import __init__conf__
@@ -614,7 +622,7 @@ def main(argv: Sequence[str] | None = None) -> int:
614
622
  )
615
623
  ```
616
624
 
617
- When installed, the generated console scripts (`lib-cli-exit-tools`, `cli-exit-tools`, `lib_cli_exit_tools`) will import `your_package.cli:main`, and `python -m your_package` will follow the same code path via `__main__.py`.
625
+ When installed, your package's console scripts (defined in `pyproject.toml`) will import `your_package.cli:main`, and `python -m your_package` will follow the same code path via `__main__.py`.
618
626
 
619
627
  ## Exit Codes
620
628
 
@@ -643,5 +651,4 @@ When installed, the generated console scripts (`lib-cli-exit-tools`, `cli-exit-t
643
651
  - [CONTRIBUTING](CONTRIBUTING.md)
644
652
  - [DEVELOPMENT](DEVELOPMENT.md)
645
653
  - [MODULE REFERENCE](docs/system-design/module_reference.md)
646
- - [AGENTS_README](AGENTS_README.md)
647
654
  - [LICENSE](LICENSE)
@@ -93,7 +93,7 @@ CLI that demonstrates configuration hooks and structured error handling.
93
93
  ```python
94
94
  from __future__ import annotations
95
95
 
96
- import click
96
+ import rich_click as click
97
97
 
98
98
  from lib_cli_exit_tools import run_cli
99
99
 
@@ -101,7 +101,6 @@ from lib_cli_exit_tools import run_cli
101
101
  @click.command()
102
102
  def hello() -> None:
103
103
  """Say hello with automatic signal-aware exit handling."""
104
-
105
104
  click.echo("Hello from lib_cli_exit_tools!")
106
105
 
107
106
 
@@ -120,29 +119,32 @@ python hello.py
120
119
  ```python
121
120
  from __future__ import annotations
122
121
 
123
- import click
124
-
125
- from lib_cli_exit_tools import cli_session, run_cli
126
-
122
+ import rich_click as click
127
123
 
128
- @click.command()
129
- @click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
130
- def cli(traceback: bool) -> int:
131
- with cli_session(overrides={"traceback": traceback}) as execute:
132
- return execute(failable, argv=[])
124
+ from lib_cli_exit_tools import cli_session
133
125
 
134
126
 
135
127
  @click.command()
136
128
  def failable() -> None:
129
+ """Command that always fails to demonstrate traceback handling."""
137
130
  raise RuntimeError("toggle --traceback to see the full traceback")
138
131
 
139
132
 
133
+ def main(*, traceback: bool = False) -> int:
134
+ """Run failable with optional traceback display."""
135
+ with cli_session(overrides={"traceback": traceback}) as run:
136
+ return run(failable)
137
+
138
+
140
139
  if __name__ == "__main__":
141
- raise SystemExit(run_cli(cli))
140
+ import sys
141
+
142
+ enable_traceback = "--traceback" in sys.argv
143
+ raise SystemExit(main(traceback=enable_traceback))
142
144
  ```
143
145
 
144
- Invoking `python cli.py --traceback` enables coloured tracebacks just for that
145
- run and resets the configuration afterwards.
146
+ Running `python cli.py --traceback` enables coloured tracebacks for that
147
+ session. The `cli_session` context manager restores configuration afterwards.
146
148
 
147
149
  #### 3. Full-featured multi-command CLI
148
150
 
@@ -150,9 +152,10 @@ run and resets the configuration afterwards.
150
152
  from __future__ import annotations
151
153
 
152
154
  import json
155
+ import sys
153
156
  from dataclasses import dataclass
154
157
 
155
- import click
158
+ import rich_click as click
156
159
 
157
160
  from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
158
161
 
@@ -160,21 +163,19 @@ from lib_cli_exit_tools import SignalSpec, cli_session, default_signal_specs
160
163
  @dataclass(slots=True)
161
164
  class Settings:
162
165
  pretty: bool
163
- traceback: bool
164
166
 
165
167
 
166
168
  @click.group()
167
169
  @click.option("--pretty/--no-pretty", default=True)
168
- @click.option("--traceback", is_flag=True, help="Show full tracebacks on error")
169
170
  @click.pass_context
170
- def cli(ctx: click.Context, pretty: bool, traceback: bool) -> None:
171
- ctx.obj = Settings(pretty=pretty, traceback=traceback)
171
+ def cli(ctx: click.Context, pretty: bool) -> None:
172
+ ctx.obj = Settings(pretty=pretty)
172
173
 
173
174
 
174
175
  @cli.command()
175
176
  @click.pass_obj
176
177
  def info(settings: Settings) -> None:
177
- payload = {"traceback": settings.traceback, "pretty": settings.pretty}
178
+ payload = {"pretty": settings.pretty}
178
179
  click.echo(json.dumps(payload, indent=2 if settings.pretty else None))
179
180
 
180
181
 
@@ -186,20 +187,24 @@ def fail(settings: Settings) -> None:
186
187
 
187
188
 
188
189
  def main() -> int:
189
- overrides = {"traceback": True, "traceback_force_color": True}
190
+ # Parse --traceback early before entering cli_session
191
+ traceback = "--traceback" in sys.argv
192
+ argv = [arg for arg in sys.argv[1:] if arg != "--traceback"]
193
+
194
+ overrides = {"traceback": traceback, "traceback_force_color": traceback}
190
195
  signals: list[SignalSpec] = default_signal_specs()
191
196
  with cli_session(overrides=overrides) as execute:
192
- return execute(cli, signal_specs=signals)
197
+ return execute(cli, argv=argv, signal_specs=signals)
193
198
 
194
199
 
195
200
  if __name__ == "__main__":
196
201
  raise SystemExit(main())
197
202
  ```
198
203
 
199
- This version wires configuration overrides, custom signal specs, and multiple
200
- commands into a single composition point—mirroring how a production CLI can
201
- layer policy logic around Click while still delegating exit-code translation to
202
- `lib_cli_exit_tools`.
204
+ This version parses `--traceback` early (before Click sees it), then wires
205
+ configuration overrides, custom signal specs, and multiple commands into a
206
+ single composition point—mirroring how a production CLI can layer policy logic
207
+ around Click while still delegating exit-code translation to `lib_cli_exit_tools`.
203
208
 
204
209
  #### 4. Custom signal handlers
205
210
 
@@ -214,7 +219,7 @@ import signal
214
219
  from contextlib import ExitStack
215
220
  from typing import Callable
216
221
 
217
- import click
222
+ import rich_click as click
218
223
 
219
224
  from lib_cli_exit_tools import SignalSpec, default_signal_specs, run_cli
220
225
 
@@ -234,6 +239,8 @@ def custom_signal_specs() -> list[SignalSpec]:
234
239
  )
235
240
  )
236
241
  return specs
242
+
243
+
237
244
  def install_custom_signals(specs: list[SignalSpec] | None) -> Callable[[], None]:
238
245
  stack = ExitStack()
239
246
 
@@ -441,11 +448,11 @@ Compute a platform-aware exit status for arbitrary exceptions (errno mappings on
441
448
  Parameters:
442
449
  - `exc`: Exception instance to classify.
443
450
 
444
- ### `print_exception_message(trace_back=config.traceback, length_limit=500, stream=None) -> None`
451
+ ### `print_exception_message(trace_back=None, length_limit=500, stream=None) -> None`
445
452
  Emit the active exception using Rich formatting. Produces a coloured traceback when `trace_back` is `True`, otherwise prints a truncated summary in red. Respects `config.traceback_force_color` and mirrors the behaviour of `handle_cli_exception` (tracebacks are rendered before the helper returns an exit status).
446
453
 
447
454
  Parameters:
448
- - `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`).
455
+ - `trace_back`: Toggle between full traceback rendering (`True`) and short summary (`False`). When `None` (default), uses `config.traceback`.
449
456
  - `length_limit`: Maximum characters for summary output.
450
457
  - `stream`: Target text stream; defaults to `sys.stderr`.
451
458
 
@@ -520,7 +527,8 @@ from __future__ import annotations
520
527
 
521
528
  from typing import Sequence
522
529
 
523
- import click
530
+ import rich_click as click
531
+
524
532
  import lib_cli_exit_tools
525
533
 
526
534
  from . import __init__conf__
@@ -577,7 +585,7 @@ def main(argv: Sequence[str] | None = None) -> int:
577
585
  )
578
586
  ```
579
587
 
580
- When installed, the generated console scripts (`lib-cli-exit-tools`, `cli-exit-tools`, `lib_cli_exit_tools`) will import `your_package.cli:main`, and `python -m your_package` will follow the same code path via `__main__.py`.
588
+ When installed, your package's console scripts (defined in `pyproject.toml`) will import `your_package.cli:main`, and `python -m your_package` will follow the same code path via `__main__.py`.
581
589
 
582
590
  ## Exit Codes
583
591
 
@@ -606,5 +614,4 @@ When installed, the generated console scripts (`lib-cli-exit-tools`, `cli-exit-t
606
614
  - [CONTRIBUTING](CONTRIBUTING.md)
607
615
  - [DEVELOPMENT](DEVELOPMENT.md)
608
616
  - [MODULE REFERENCE](docs/system-design/module_reference.md)
609
- - [AGENTS_README](AGENTS_README.md)
610
617
  - [LICENSE](LICENSE)
@@ -221,6 +221,6 @@ Downstream CLIs and automation pipelines need deterministic exit codes, signal h
221
221
 
222
222
  ---
223
223
 
224
- **Created:** 2025-10-08 by Codex (automated)
225
- **Last Updated:** 2025-10-08 by Codex (automated)
224
+ **Created:** 2025-10-08 by Codex (automated)
225
+ **Last Updated:** 2025-12-17
226
226
  **Review Cycle:** Revisit every 90 days or after major CLI/runtime changes
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "lib_cli_exit_tools"
3
- version = "2.2.2"
3
+ version = "2.2.3"
4
4
  description = "CLI exit handling helpers: clean signals, exit codes, and error printing"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -36,7 +36,7 @@ dev = [
36
36
  "pytest-asyncio>=1.3.0",
37
37
  "pytest-cov>=7.0.0",
38
38
  "ruff>=0.14.9",
39
- "textual>=6.8.0",
39
+ "textual>=6.10.0",
40
40
  "rtoml>=0.13.0",
41
41
  "twine>=6.2.0"
42
42
  ]
@@ -159,10 +159,13 @@ forbidden_modules = [
159
159
  # PYSEC-2022-43012, CVE-2024-6345, PYSEC-2025-49: setuptools vulnerabilities
160
160
  # These are build-time dependencies only, not runtime. The virtual environment
161
161
  # setuptools version is managed by the CI environment/pip itself.
162
+ # CVE-2025-68146: filelock <3.20.1 vulnerability, transitive dev dependency
163
+ # Will be resolved when upstream packages update their dependencies.
162
164
  ignore-vulns = [
163
165
  "GHSA-4xh5-x5gv-qwph",
164
166
  "PYSEC-2022-42969",
165
167
  "PYSEC-2022-43012",
166
168
  "CVE-2024-6345",
167
169
  "PYSEC-2025-49",
170
+ "CVE-2025-68146",
168
171
  ]
@@ -24,7 +24,7 @@ name = "lib_cli_exit_tools"
24
24
  #: Human-readable summary shown in CLI help output.
25
25
  title = "CLI exit handling helpers: clean signals, exit codes, and error printing"
26
26
  #: Current release version pulled from ``pyproject.toml`` by automation.
27
- version = "2.2.2"
27
+ version = "2.2.3"
28
28
  #: Repository homepage presented to users.
29
29
  homepage = "https://github.com/bitranox/lib_cli_exit_tools"
30
30
  #: Author attribution surfaced in CLI output.