Skip to main content

self-heal

PyPI version Python CI License Last commit Open issues Stars

Open-source self-healing helper for Python.

It captures tracebacks (in-process hook / decorator, or a supervised subprocess), gathers code context (the source around the failing frames plus, optionally, similar chunks from an embeddings index), asks an LLM for a unified diff, validates it against a path policy, optionally applies it with a backup, and records an audit trail.

Highlights

  • Python >= 3.11; works with OpenAI, Anthropic, Hugging Face and Ollama (any OpenAI-compatible endpoint for chat and embeddings)
  • Works without an index: the code around every traceback frame inside your project is always sent to the model; the vector index is an optional boost
  • Bounded retries with feedback: an empty, rejected or unappliable patch is explained to the model and it gets another attempt (heal.max_attempts)
  • Safety first: model output is never executed, unified diffs only, allow/deny path policy, file-type allowlist, dry-run by default, backups + rollback, secrets masked before anything leaves the process
  • Operations: doctor for setup checks, JSONL audit log, notifications (Telegram, Slack, webhook, Sentry), supervised restarts that stop on repeated crashes

Contents

Install

pip install self-heal-runtime
# Optional: Sentry notifications
pip install "self-heal-runtime[notifications]"

Set the API key environment variable for your provider (OPENAI_API_KEY by default, see [llm].api_key_env).

Quickstart

  1. Initialize config in your project root and check the setup:

    self-heal init
    self-heal doctor
    
  2. Index your code (optional, requires an embeddings endpoint):

    self-heal index
    
  3. Heal from a traceback (dry-run: the diff is shown, nothing is written):

    python -m examples.broken_app.main 2> tb.txt
    self-heal heal --tb tb.txt
    self-heal heal --tb tb.txt --apply      # write it (a backup is kept)
    self-heal rollback                      # undo the last applied patch
    
  4. Run under supervision (captures stderr tracebacks, proposes or applies a fix, restarts):

    PYTHONPATH=. self-heal run -- python -m examples.broken_app.main
    PYTHONPATH=. self-heal run --auto -- python -m examples.broken_app.main   # apply automatically
    

CLI

Command What it does
self-heal init [--force] Write .self-heal.toml from the built-in template
self-heal doctor Check config, API key, embeddings endpoint, index, git/patch, backups, notification env vars (exit 1 on failures)
self-heal index [--force] Incrementally index Python files under [index].roots (--force rebuilds)
self-heal heal [--tb FILE] [--apply] [--instruction TEXT] Generate a fix from a traceback (file or stdin); --apply writes it
self-heal run [--auto] -- CMD... Supervise a command; heal on tracebacks; restart
self-heal status [-n N] [--json] Recent audit entries
self-heal rollback [--list] [--backup NAME] Restore files from a backup taken before a patch was applied

--apply / --auto imply --no-dry-run; pass --dry-run explicitly to keep a dry run. Use -v for debug logging and -q for warnings only. -p PATH selects the project root (default: the directory containing .self-heal.toml, found by walking up from the current directory).

Library usage

from pathlib import Path
from self_heal import heal_context, install, self_heal

# Global hooks (sys.excepthook and threading.excepthook); previous hooks still run first.
install(project_root=Path(__file__).resolve().parent, mode="suggest")


@self_heal(retries=2, mode="suggest")  # sync or async functions
def risky() -> None:
    do_work()


with heal_context(mode="suggest"):
    risky()

Modes: suggest only proposes (audit + notifications), apply follows [heal].auto_apply, auto always applies. The same error (exception type + raise site) is not sent to the model again within [heal].cooldown_s.

Lower-level entry points: heal_exception(ErrorEvent), heal_from_traceback_text(str), capture_from_exception(exc), rollback(project_root).

Configuration

See .self-heal.example.toml (the same template is written by self-heal init). Unknown keys are rejected so typos never silently disable an option.

Section Key options
[llm] provider, base_url, model, api_key_env, embedding_model, embedding_base_url / embedding_api_key_env (separate embeddings endpoint), timeout_s, max_tokens, max_retries, temperature
[index] roots, exclude, respect_gitignore, chunk_max_lines, chunk_overlap_lines
[heal] allowed_paths, forbidden_paths, allowed_extensions, auto_apply, max_attempts, backup, top_k, context_lines, max_diff_lines, cooldown_s
[supervisor] restart_on_exit_codes, max_restarts, healthcheck_grace_s, stop_on_repeated_traceback
[notifications] enabled, events, include_diff, include_traceback, max_traceback_lines, plus `[notifications.telegram

Providers

[llm].provider selects how chat completions are issued. Embeddings always use an OpenAI-compatible endpoint: by default the same base_url, or embedding_base_url when set.

  • OpenAI (default):

    [llm]
    provider = "openai"
    base_url = "https://api.openai.com/v1"
    model = "gpt-4o-mini"
    embedding_model = "text-embedding-3-small"
    api_key_env = "OPENAI_API_KEY"
    
  • Anthropic: native Messages API. Anthropic has no embeddings API; healing still works with traceback context, and you can point embeddings elsewhere to enable the index:

    [llm]
    provider = "anthropic"
    base_url = "https://api.anthropic.com/v1"
    model = "claude-sonnet-4-5"
    api_key_env = "ANTHROPIC_API_KEY"
    embedding_base_url = "http://localhost:11434/v1"   # e.g. Ollama
    embedding_model = "nomic-embed-text"
    embedding_api_key_env = "OLLAMA_API_KEY"           # unset is fine for Ollama
    
  • Hugging Face (Inference Providers router):

    [llm]
    provider = "huggingface"
    base_url = "https://router.huggingface.co/v1"
    model = "meta-llama/Llama-3.1-8B-Instruct"
    embedding_model = "intfloat/multilingual-e5-large"
    api_key_env = "HF_TOKEN"
    
  • Ollama (local, no auth):

    [llm]
    provider = "ollama"
    base_url = "http://localhost:11434/v1"
    model = "llama3.1"
    embedding_model = "nomic-embed-text"
    

Changing embedding_model rebuilds the index on the next self-heal index.

Notifications

Optional outbound reports when an error is captured and when a heal is proposed, applied, rejected or rolled back. Enable [notifications].enabled = true, then turn on channels under [notifications.telegram], [notifications.slack], [notifications.webhook] or [notifications.sentry]. Secrets stay in environment variables (TELEGRAM_BOT_TOKEN, SLACK_WEBHOOK_URL, SELF_HEAL_WEBHOOK_URL, SENTRY_DSN).

  • Payload: diffs are omitted by default and tracebacks truncated (include_diff, include_traceback, max_traceback_lines)
  • Telegram: HTML, MarkdownV2 or plain text; messages are kept within Telegram's size limit
  • Webhook: JSON POST with optional HMAC (X-SelfHeal-Signature: sha256=…, X-SelfHeal-Timestamp); only https and public hosts unless allow_insecure = true
  • Sentry: pip install 'self-heal-runtime[notifications]'

Delivery is asynchronous; successes and failures are written to .self-heal/audit.jsonl as notification_sent / notification_failed.

Security

  • Model output is never executed; only unified diffs are accepted, and only for files matching allowed_paths / allowed_extensions and not forbidden_paths (defaults block .git/, .env*, secret globs, pyproject.toml). Paths are normalised and resolved; .., absolute paths and symlinks escaping the project are rejected. Deletions and binary patches are refused.
  • Tracebacks and locals are sanitized before leaving the process: variables with secret-looking names, values of secret-looking environment variables, bearer tokens, API keys, JWTs and URL credentials are masked.
  • The CLI is dry-run by default; every applied patch is preceded by a backup under .self-heal/backups/ and can be undone with self-heal rollback.
  • Supervised runs stop restarting when the same crash repeats without a patch; in-process healing has a cooldown so a crash loop cannot flood the model.

Limitations

  • Patch application prefers git apply (inside any git worktree), then the system patch, then a small atomic Python hunk applier.
  • Only Python files are chunked and indexed; allowed_extensions controls what a patch may touch.
  • Supervised mode expects Python-style tracebacks on stderr.
  • Applied patches change files on disk; a running process keeps its already-imported code until restarted.

Development

python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
ruff check . && ruff format --check . && mypy && pytest

Tests do not need network access or API keys. See CHANGELOG.md for release notes.

Releasing: bump version in pyproject.toml, update CHANGELOG.md, then push a matching tag (git tag v0.4.0 && git push origin v0.4.0). The Publish to PyPI workflow builds the package and uploads it with PyPI Trusted Publishing.

License

MIT — see LICENSE.

Metadata

Release files for self-heal-runtime 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for self-heal-runtime 0.4.0
File Size Uploaded Provenance Actions
self_heal_runtime-0.4.0.tar.gz 56.2 kB With provenance Details for self_heal_runtime-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for self-heal-runtime 0.4.0
File Interpreter ABI Platform Actions
self_heal_runtime-0.4.0-py3-none-any.whl Python 3 none any Details for self_heal_runtime-0.4.0-py3-none-any.whl

Total release size: 124.4 kB

Release files / self_heal_runtime-0.4.0.tar.gz

Download URL self_heal_runtime-0.4.0.tar.gz
Size 56.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d96a7278716dd9b53d81ea1d144f02b85ac3e11292bcb53b625a96c2ee9f4b6a
BLAKE2b-256 checksum
How to use checksums
ccf83cbc5f3914b143d3f15add9afbc9febc68ba32880f135c2e0c04005b5eed
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / self_heal_runtime-0.4.0-py3-none-any.whl

Download URL self_heal_runtime-0.4.0-py3-none-any.whl
Size 68.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e96ee47e0ba04d5c8c457d8cdd754b3fb5bc1f0cc0808499e92d86590d6b93ec
BLAKE2b-256 checksum
How to use checksums
88d9bdc6e7ee542ef07100877c895451ba14251c16a99b06e4b57c7deddbef0b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Security for self-heal-runtime 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for self_heal_runtime-0.4.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page