A zero-dependency debugging engine for Python that intercepts unhandled exceptions, extracts post-mortem state, masks sensitive data, and provides formatted crash reports with an interactive debugging REPL.
Project description
crash_sight
Production-Grade Debugging Engine · A zero-dependency runtime exception interceptor that hijacks
sys.excepthookto maximize Developer Experience (DX).
crash_sight is a post-mortem debugging engine for Python 3.8+ that operates at the runtime interceptor level. When an unhandled exception escapes your application, crash_sight captures the precise execution context, scrubs sensitive data, generates a beautifully formatted ANSI terminal report, exports a clean Markdown log, and drops you into an interactive REPL at the exact crash site — all with zero external dependencies.
Core Pillars
crash_sight's architecture is composed of five tightly integrated modules, each responsible for a critical stage of the post-mortem pipeline:
| Module | Responsibility |
|---|---|
Core Interceptor (crash_sight.core.interceptor) |
Registers a global hook on sys.excepthook, traverses the stack frame window to the deepest frame, and orchestrates the entire pipeline. |
Security Data Scrubber (crash_sight.security.masker) |
Scans local and global variables using case-insensitive regex pattern matching, replacing sensitive values (e.g., password, secret, token, apiKey, credential) with "******** (SECURED)". Supports nested dictionaries, lists, and tuples with infinite recursion depth. |
Terminal Formatter (crash_sight.formatter.terminal) |
Renders a visually stunning ANSI-colored crash report complete with source code context, variable dump, and precise arrow markers — all using only standard library linecache. |
Post-Mortem REPL (crash_sight.repl.console) |
Launches an interactive Python shell (code.InteractiveConsole) injected with the exact masked locals and globals from the crash frame, allowing real-time forensic inspection. |
Markdown Exporter (crash_sight.exporter.markdown) |
Strips ANSI color codes and writes a pristine Markdown version of the crash report to crash_report_[YYYYMMDD_HHMMSS].md for logging, CI/CD, or team sharing. |
Installation
Install crash_sight locally in development/editable mode from the project root:
pip install -e .
Zero Dependencies Guarantee –
pip freezewill show zero additional packages. crash_sight uses only Python Standard Library modules:sys,inspect,linecache,code,os,re,datetime,typing.
Quick Start
Create a file called test_crash.py with the following content:
import crash_sight
crash_sight.install()
def risky_function(user_input):
user_password = "sup3rS3cr3t!"
apiKey = "AIzaSyD-abc123def456"
my_secret_token = "ghp_xxxxxxxxxxxx"
ratio = 100 / user_input # will trigger ZeroDivisionError when user_input = 0
risky_function(0)
Then run it:
python test_crash.py
That's it — two lines to activate crash_sight. The rest is automatic.
Aesthetic Terminal Preview
When you run the example above, crash_sight will print a report like this to stderr:
🔍 crash_sight — Post-Mortem Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚡ ZeroDivisionError: division by zero
📍 Location:
📄 File: /path/to/test_crash.py
🔧 Function: risky_function
⏰ Line: 8
📄 Code Context:
5 | def risky_function(user_input):
6 | user_password = "sup3rS3cr3t!"
7 | apiKey = "AIzaSyD-abc123def456"
8 ───> ratio = 100 / user_input
9 |
10 | risky_function(0)
🔍 Local Variables (Masked):
user_input = 0
user_password = ******** (SECURED)
apiKey = ******** (SECURED)
my_secret_token = ******** (SECURED)
ratio = <not defined>
📁 Report saved to: crash_report_20250320_143022.md
💻 Opening interactive REPL at crash site...
Type 'exit()' or 'quit()' to return to the shell.
Security & Masking Specifications
The security engine (crash_sight.security.masker) applies a deterministic, pattern-based masking algorithm with the following rules:
Pattern Matching (Case-Insensitive)
Any variable key containing any of these substrings (case-insensitive) will have its value replaced:
| Keyword | Example Keys That Trigger Masking |
|---|---|
password |
password, userPassword, PASSWORD, passwords_list |
secret |
secret, my_secret_token, SECRET_KEY, secret_answer |
token |
token, api_token, TOKEN, auth_tokens |
apikey |
apiKey, API_KEY, apikey, api_key_v2 |
credential |
credential, credentials, CREDENTIALS |
Recursive Scrubbing — Full Nested Support
Masking is applied recursively to arbitrary-depth data structures:
- Nested dictionaries:
{"db": {"password": "s3cr3t"}}→{"db": {"password": "******** (SECURED)"}} - Lists of dictionaries:
[{"apiKey": "xyz"}, {"other": 42}]→[{"apiKey": "******** (SECURED)"}, {"other": 42}] - Tuples:
("user", {"token": "abc"})→("user", {"token": "******** (SECURED)"}) - Mixed nesting is fully supported.
False-Positive Guard
Variables whose keys contain certain "safe" substrings are intelligently bypassed:
not_secret→ NOT masked (contains "secret" but guarded)public_token_id→ NOT masked (contains "token" but guarded)
Built-in exception list: not_secret, not_password, public_token, non_credential, and equivalents are safely ignored.
Python 3.14 Compatibility Note
crash_sight is fully compliant with PEP 667 (introduced in Python 3.13, standard in 3.14). The extract_deepest_context() function explicitly converts frame.f_locals and frame.f_globals to standard dict objects using dict() constructor, ensuring seamless compatibility with Python 3.13+ where FrameLocalsProxy is returned instead of a plain dictionary.
This safeguard is encapsulated in the core interceptor:
# In Python 3.13+, frame.f_locals returns FrameLocalsProxy, not a plain dict
f_locals: Dict[str, Any] = dict(frame.f_locals)
f_globals: Dict[str, Any] = dict(frame.f_globals)
Tested and verified across Python 3.8 through 3.14-pre release.
Testing
crash_sight ships with a comprehensive test suite (90+ tests covering unit, integration, and edge-case scenarios). Run the full suite with:
python -m unittest discover -s tests -p "test_*.py" -v
Test categories include:
- Core interceptor installation/idempotency/uninstallation
- Deepest frame extraction (including chain tracebacks)
- Security masker — pattern matching, nested structures, false-positive guard
- Terminal formatter (ANSI rendering, code context windows)
- Markdown exporter (cleaning, naming conventions)
- REPL initialization and context injection
- Cross-version compatibility (Python 3.8–3.14)
Development & Contributing
-
Clone the repository:
git clone https://github.com/annaqibz01/crash_sight.git cd crash_sight
-
Install in editable mode:
pip install -e .
-
Run the tests:
python -m unittest discover -s tests -p "test_*.py" -v
-
Submit a pull request or open an issue on GitHub Issues.
License
Distributed under the MIT License. See LICENSE for more information.
crash_sight — Zero-dependency debugging. Precision post-mortem. Maximum DX.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file crash_sight-1.0.0.tar.gz.
File metadata
- Download URL: crash_sight-1.0.0.tar.gz
- Upload date:
- Size: 33.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea4c4e90e39092fe54ce4591567fadf95eb7eb171e525b9db29a12f0f6b7d89e
|
|
| MD5 |
91721342577ccef1ebe2a57da4d50bdd
|
|
| BLAKE2b-256 |
4c5b5b369193b15ef0c4c844336441dddcafe54c7d299fc654b11f1a6eff34b2
|
File details
Details for the file crash_sight-1.0.0-py3-none-any.whl.
File metadata
- Download URL: crash_sight-1.0.0-py3-none-any.whl
- Upload date:
- Size: 20.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92297fb663037e36c88c2a3136e4d800a9016906a51184b9a684fe4493e2f1a4
|
|
| MD5 |
6ca2f9802fe235c602f4436b627a1e5d
|
|
| BLAKE2b-256 |
e24b8172e608af020433366464446d5e6af544487b549748cf64b8751644b9d5
|