errlens-cli 0.1.0__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 (75) hide show
  1. errlens_cli-0.1.0/.github/workflows/publish.yml +109 -0
  2. errlens_cli-0.1.0/.github/workflows/tests-macos.yml +27 -0
  3. errlens_cli-0.1.0/.github/workflows/tests.yml +61 -0
  4. errlens_cli-0.1.0/.gitignore +23 -0
  5. errlens_cli-0.1.0/CHANGELOG.md +40 -0
  6. errlens_cli-0.1.0/CONTRIBUTING.md +26 -0
  7. errlens_cli-0.1.0/LICENSE +21 -0
  8. errlens_cli-0.1.0/MANIFEST.in +7 -0
  9. errlens_cli-0.1.0/PKG-INFO +233 -0
  10. errlens_cli-0.1.0/README.md +208 -0
  11. errlens_cli-0.1.0/docs/actions4-diagnosis.md +69 -0
  12. errlens_cli-0.1.0/docs/manual-acceptance.md +607 -0
  13. errlens_cli-0.1.0/docs/release-notes-0.1.0.md +24 -0
  14. errlens_cli-0.1.0/docs/releasing.md +186 -0
  15. errlens_cli-0.1.0/docs/terminal-design.md +245 -0
  16. errlens_cli-0.1.0/docs/windows-conpty.md +160 -0
  17. errlens_cli-0.1.0/experiments/manual_acceptance.py +75 -0
  18. errlens_cli-0.1.0/experiments/terminal_probe.py +81 -0
  19. errlens_cli-0.1.0/pyproject.toml +47 -0
  20. errlens_cli-0.1.0/setup.cfg +4 -0
  21. errlens_cli-0.1.0/src/errlens/__init__.py +7 -0
  22. errlens_cli-0.1.0/src/errlens/__main__.py +6 -0
  23. errlens_cli-0.1.0/src/errlens/_conpty.py +236 -0
  24. errlens_cli-0.1.0/src/errlens/_conpty_worker.py +158 -0
  25. errlens_cli-0.1.0/src/errlens/_pty_child.py +25 -0
  26. errlens_cli-0.1.0/src/errlens/analyzers/__init__.py +1 -0
  27. errlens_cli-0.1.0/src/errlens/analyzers/base.py +45 -0
  28. errlens_cli-0.1.0/src/errlens/analyzers/python.py +362 -0
  29. errlens_cli-0.1.0/src/errlens/capture.py +92 -0
  30. errlens_cli-0.1.0/src/errlens/cli.py +177 -0
  31. errlens_cli-0.1.0/src/errlens/conpty_runner.py +269 -0
  32. errlens_cli-0.1.0/src/errlens/i18n.py +61 -0
  33. errlens_cli-0.1.0/src/errlens/locales/en.json +96 -0
  34. errlens_cli-0.1.0/src/errlens/locales/ru.json +96 -0
  35. errlens_cli-0.1.0/src/errlens/models.py +120 -0
  36. errlens_cli-0.1.0/src/errlens/posix_shell.py +71 -0
  37. errlens_cli-0.1.0/src/errlens/powershell.py +77 -0
  38. errlens_cli-0.1.0/src/errlens/pty_runner.py +172 -0
  39. errlens_cli-0.1.0/src/errlens/py.typed +0 -0
  40. errlens_cli-0.1.0/src/errlens/render.py +96 -0
  41. errlens_cli-0.1.0/src/errlens/rules/__init__.py +1 -0
  42. errlens_cli-0.1.0/src/errlens/rules/python.py +84 -0
  43. errlens_cli-0.1.0/src/errlens/runner.py +241 -0
  44. errlens_cli-0.1.0/src/errlens/service.py +58 -0
  45. errlens_cli-0.1.0/src/errlens_cli.egg-info/PKG-INFO +233 -0
  46. errlens_cli-0.1.0/src/errlens_cli.egg-info/SOURCES.txt +73 -0
  47. errlens_cli-0.1.0/src/errlens_cli.egg-info/dependency_links.txt +1 -0
  48. errlens_cli-0.1.0/src/errlens_cli.egg-info/entry_points.txt +2 -0
  49. errlens_cli-0.1.0/src/errlens_cli.egg-info/requires.txt +7 -0
  50. errlens_cli-0.1.0/src/errlens_cli.egg-info/top_level.txt +1 -0
  51. errlens_cli-0.1.0/tests/fixtures/README.md +25 -0
  52. errlens_cli-0.1.0/tests/fixtures/conpty_python313.json +10 -0
  53. errlens_cli-0.1.0/tests/fixtures/python_diagnostics.json +351 -0
  54. errlens_cli-0.1.0/tests/fixtures/recorded_python313.json +26 -0
  55. errlens_cli-0.1.0/tests/integration/test_conpty.py +322 -0
  56. errlens_cli-0.1.0/tests/integration/test_execution.py +151 -0
  57. errlens_cli-0.1.0/tests/integration/test_explanation_cli.py +163 -0
  58. errlens_cli-0.1.0/tests/integration/test_installed_package.py +45 -0
  59. errlens_cli-0.1.0/tests/integration/test_interrupt_pid.py +108 -0
  60. errlens_cli-0.1.0/tests/integration/test_posix_shell.py +173 -0
  61. errlens_cli-0.1.0/tests/integration/test_powershell.py +112 -0
  62. errlens_cli-0.1.0/tests/integration/test_pty.py +221 -0
  63. errlens_cli-0.1.0/tests/integration/test_python_analysis.py +95 -0
  64. errlens_cli-0.1.0/tests/integration/test_vt_forwarding.py +20 -0
  65. errlens_cli-0.1.0/tests/integration/test_windows_encoding.py +36 -0
  66. errlens_cli-0.1.0/tests/unit/test_analyzers.py +38 -0
  67. errlens_cli-0.1.0/tests/unit/test_capture.py +65 -0
  68. errlens_cli-0.1.0/tests/unit/test_cli.py +78 -0
  69. errlens_cli-0.1.0/tests/unit/test_explanations.py +100 -0
  70. errlens_cli-0.1.0/tests/unit/test_i18n.py +61 -0
  71. errlens_cli-0.1.0/tests/unit/test_models.py +56 -0
  72. errlens_cli-0.1.0/tests/unit/test_python_analyzer.py +166 -0
  73. errlens_cli-0.1.0/tests/unit/test_render.py +65 -0
  74. errlens_cli-0.1.0/tests/unit/test_runner.py +100 -0
  75. errlens_cli-0.1.0/tests/unit/test_vt_diagnostics.py +85 -0
@@ -0,0 +1,109 @@
1
+ name: Release candidate and Trusted Publishing
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ publish:
7
+ description: Publish approved v0.1.0 to PyPI (false builds artifacts only)
8
+ required: true
9
+ type: boolean
10
+ default: false
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ concurrency:
16
+ group: pypi-${{ github.ref }}
17
+ cancel-in-progress: false
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ actions: read
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: actions/setup-python@v5
28
+ with:
29
+ python-version: '3.12'
30
+ - name: Verify distribution identity
31
+ run: |
32
+ python - <<'PY'
33
+ import tomllib
34
+ from pathlib import Path
35
+ project = tomllib.loads(Path('pyproject.toml').read_text())['project']
36
+ assert project['name'] == 'errlens-cli'
37
+ assert project['version'] == '0.1.0'
38
+ assert project['scripts']['errlens'] == 'errlens.cli:main_entry'
39
+ PY
40
+ - name: Require approved tag and successful Tests for publication
41
+ if: inputs.publish
42
+ env:
43
+ GH_TOKEN: ${{ github.token }}
44
+ run: |
45
+ test "$GITHUB_REPOSITORY" = 'ErrLens/errlens-cli'
46
+ test "$GITHUB_REF" = 'refs/tags/v0.1.0'
47
+ gh run list --repo "$GITHUB_REPOSITORY" --workflow tests.yml --commit "$GITHUB_SHA" --limit 20 --json headSha,status,conclusion > tests-runs.json
48
+ python - <<'PY'
49
+ import json, os
50
+ from pathlib import Path
51
+ runs = json.loads(Path('tests-runs.json').read_text())
52
+ assert runs, 'No Tests run exists for the selected commit'
53
+ latest = runs[0]
54
+ assert latest['headSha'] == os.environ['GITHUB_SHA']
55
+ assert latest['status'] == 'completed' and latest['conclusion'] == 'success', latest
56
+ PY
57
+ - name: Build and check archives
58
+ run: |
59
+ python -m pip install build twine
60
+ python -m build
61
+ python -m twine check --strict dist/*
62
+ python - <<'PY'
63
+ import email, zipfile
64
+ from pathlib import Path
65
+ assert {p.name for p in Path('dist').iterdir()} == {
66
+ 'errlens_cli-0.1.0-py3-none-any.whl', 'errlens_cli-0.1.0.tar.gz'}
67
+ with zipfile.ZipFile('dist/errlens_cli-0.1.0-py3-none-any.whl') as z:
68
+ metadata = email.message_from_bytes(z.read('errlens_cli-0.1.0.dist-info/METADATA'))
69
+ assert metadata['Name'] == 'errlens-cli' and metadata['Version'] == '0.1.0'
70
+ PY
71
+ - name: Smoke-test installed wheel outside checkout
72
+ run: |
73
+ python -m venv .wheel-check
74
+ .wheel-check/bin/python -m pip install dist/*.whl pytest
75
+ .wheel-check/bin/python -m pip check
76
+ .wheel-check/bin/python -m pytest tests/integration/test_installed_package.py tests/integration/test_vt_forwarding.py tests/unit/test_cli.py
77
+ - name: Stage canonical artifacts and hashes
78
+ run: |
79
+ mkdir -p release-artifact/dist
80
+ cp dist/* release-artifact/dist/
81
+ cd release-artifact
82
+ sha256sum dist/* > SHA256SUMS
83
+ - uses: actions/upload-artifact@v4
84
+ with:
85
+ name: release-dist
86
+ path: release-artifact/
87
+ if-no-files-found: error
88
+ retention-days: 30
89
+
90
+ publish:
91
+ if: inputs.publish
92
+ needs: build
93
+ runs-on: ubuntu-latest
94
+ environment:
95
+ name: pypi
96
+ url: https://pypi.org/p/errlens-cli
97
+ permissions:
98
+ id-token: write
99
+ contents: read
100
+ steps:
101
+ - uses: actions/download-artifact@v4
102
+ with:
103
+ name: release-dist
104
+ path: candidate
105
+ - name: Verify retained bytes
106
+ run: cd candidate && sha256sum --check SHA256SUMS
107
+ - uses: pypa/gh-action-pypi-publish@release/v1
108
+ with:
109
+ packages-dir: candidate/dist/
@@ -0,0 +1,27 @@
1
+ name: Tests (macOS manual)
2
+
3
+ on: workflow_dispatch
4
+
5
+ permissions:
6
+ contents: read
7
+
8
+ jobs:
9
+ test:
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ python: ['3.11', '3.12', '3.13']
14
+ runs-on: ${{ matrix.python == '3.11' && 'macos-15' || 'macos-latest' }}
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-python@v5
18
+ with:
19
+ python-version: ${{ matrix.python }}
20
+ - name: Verify shell prerequisites
21
+ run: command -v bash && command -v zsh
22
+ - name: Install development package
23
+ run: python -m pip install -e ".[dev]"
24
+ - name: Check types
25
+ run: python -m mypy
26
+ - name: Test editable package
27
+ run: python -m pytest
@@ -0,0 +1,61 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu-latest, windows-latest]
11
+ python: ['3.11', '3.12', '3.13']
12
+ runs-on: ${{ matrix.os }}
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: ${{ matrix.python }}
18
+ - name: Install Zsh on Ubuntu
19
+ if: runner.os == 'Linux'
20
+ run: sudo apt-get update && sudo apt-get install -y zsh
21
+ - name: Verify shell prerequisites
22
+ if: runner.os != 'Windows'
23
+ run: command -v bash && command -v zsh
24
+ - name: Verify PowerShell prerequisite
25
+ if: runner.os == 'Windows'
26
+ shell: pwsh
27
+ run: if ($PSVersionTable.PSVersion.Major -lt 7) { exit 1 }
28
+ - name: Install development package
29
+ run: python -m pip install -e ".[dev]"
30
+ - name: Check types
31
+ run: python -m mypy
32
+ - name: Test editable package
33
+ run: python -m pytest
34
+ package:
35
+ strategy:
36
+ fail-fast: false
37
+ matrix:
38
+ os: [ubuntu-latest, windows-latest]
39
+ runs-on: ${{ matrix.os }}
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - uses: actions/setup-python@v5
43
+ with:
44
+ python-version: '3.12'
45
+ - name: Install build tools
46
+ run: python -m pip install build
47
+ - name: Build wheel and sdist
48
+ run: python -m build
49
+ - name: Create clean wheel environment
50
+ run: python -m venv .venv-wheel
51
+ - name: Test installed wheel outside editable environment
52
+ shell: python
53
+ run: |
54
+ import os
55
+ from pathlib import Path
56
+ import subprocess
57
+ python = Path('.venv-wheel') / ('Scripts/python.exe' if os.name == 'nt' else 'bin/python')
58
+ wheel = next(Path('dist').glob('*.whl'))
59
+ subprocess.run([str(python), '-m', 'pip', 'install', str(wheel), 'pytest'], check=True)
60
+ subprocess.run([str(python), '-m', 'pip', 'check'], check=True)
61
+ subprocess.run([str(python), '-m', 'pytest'], check=True)
@@ -0,0 +1,23 @@
1
+ .venv/
2
+ .venv-wheel/
3
+ .venv-release/
4
+ .venv-linux/
5
+ __pycache__/
6
+ *.py[cod]
7
+ *.egg-info/
8
+ .pytest_cache/
9
+ .mypy_cache/
10
+ build/
11
+ dist/
12
+ .coverage
13
+ htmlcov/
14
+ venv/
15
+ .ruff_cache/
16
+ .env
17
+ .env.*
18
+ !.env.example
19
+ *.log
20
+ *.tmp
21
+ *.bak
22
+ .idea/
23
+ .vscode/
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 — release candidate (unreleased)
4
+
5
+ Initial CLI candidate. The package metadata remains `0.1.0`; no tag, release date
6
+ or PyPI publication is implied by this entry.
7
+ Distribution: `errlens-cli`; Python import: `errlens`; command: `errlens`.
8
+
9
+ ### Added
10
+
11
+ - `errlens run` with streaming stdout/stderr, bounded diagnostic capture and
12
+ child exit-status propagation. Pipe is the default.
13
+ - Rule-based offline explanations in Russian and English for recognized CPython
14
+ tracebacks, with conservative handling of incomplete diagnostics and chains.
15
+ - Rich terminal cards and plain redirected explanations; `--lang` and `--no-explain`.
16
+ - Explicit `--terminal-mode pty`: POSIX PTY on Linux/macOS and native ConPTY on Windows.
17
+ - Opt-in PowerShell 7, Bash and Zsh integration for `python`, with explicit
18
+ install/status/uninstall, temporary bypass and profile backup/preservation.
19
+ - MIT licensing, packaged translations, CI across Python 3.11–3.13 on three OSes,
20
+ wheel/sdist checks and recorded terminal acceptance evidence.
21
+
22
+ ### Fixed during candidate stabilization
23
+
24
+ - Windows localized Unicode output with non-UTF-8 host text wrappers.
25
+ - Darwin termios assertions account only for kernel-managed PENDIN state.
26
+ - Diagnostic-only VT normalization preserves horizontal traceback indentation,
27
+ with bounded cursor/text expansion and conservative incomplete flags.
28
+
29
+ ### Limitations
30
+
31
+ - Terminal mode merges child output and does not preserve binary identity.
32
+ - Full-screen emulation, complex redraw/grapheme reconstruction, transparent
33
+ pipelines and automatic exception cards inside a successful REPL are not provided.
34
+ - Shell integration is explicit and wraps only `python`; it does not intercept
35
+ arbitrary commands. No fixes or recommended commands are executed automatically.
36
+ - Some physical host combinations remain NOT TESTED. The historical Zsh prompt
37
+ observation has no established root cause; a clean Zsh session was successful.
38
+ - The original PyPI name `errlens` conflicts with an existing distribution.
39
+ The maintainer selected `errlens-cli` instead; publication still requires
40
+ Trusted Publisher setup and approval. See `docs/releasing.md`.
@@ -0,0 +1,26 @@
1
+ # Участие в ErrLens
2
+
3
+ Используйте Python 3.11+ и локальное виртуальное окружение. Инструкция установки
4
+ находится в README. Перед предложением изменений запустите:
5
+
6
+ ```console
7
+ python -m pytest
8
+ python -m mypy
9
+ python -m build
10
+ ```
11
+
12
+ Описывайте проблему, область изменений и выполненные проверки. Добавляйте
13
+ регрессионные тесты для исправляемого поведения. Не заявляйте проверку ОС,
14
+ на которой тесты не выполнялись. Не включайте секреты или личные данные в fixtures.
15
+
16
+ Сохраняйте независимость анализаторов от CLI, переводов и ввода-вывода.
17
+ Не выполняйте рекомендации автоматически. Новые переводы должны иметь те же
18
+ ключи и именованные параметры, что и русская локаль. Сторонние плагины и сетевые
19
+ запросы не должны загружаться или запускаться неявно.
20
+
21
+ Текущий CLI включает объяснения, shell-интеграции и явный PTY/ConPTY-режим.
22
+ Команды рекомендаций должны оставаться display-only argv из доверенных правил;
23
+ не подставляйте произвольные имена из traceback в shell-строки. Проверяйте plain
24
+ text, узкие терминалы и буквальный вывод разметки/управляющих символов.
25
+ Следующие возможности реализуются
26
+ отдельно. Изменения распространяются на условиях MIT License проекта.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ErrLens contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,7 @@
1
+ include CONTRIBUTING.md
2
+ include CHANGELOG.md
3
+ include .gitignore
4
+ recursive-include tests *.py *.md *.json
5
+ recursive-include .github *.yml
6
+ recursive-include docs *.md
7
+ recursive-include experiments *.py
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.4
2
+ Name: errlens-cli
3
+ Version: 0.1.0
4
+ Summary: Local Python error explanations with opt-in terminal and shell integration.
5
+ Author: ErrLens contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/ErrLens/errlens-cli
8
+ Project-URL: Source, https://github.com/ErrLens/errlens-cli
9
+ Project-URL: Documentation, https://github.com/ErrLens/errlens-cli/blob/main/README.md
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Environment :: Console
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: typer<1,>=0.16
19
+ Requires-Dist: rich<15,>=14
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest<10,>=8; extra == "dev"
22
+ Requires-Dist: build<2,>=1.2; extra == "dev"
23
+ Requires-Dist: mypy<2,>=1.15; extra == "dev"
24
+ Dynamic: license-file
25
+
26
+ # ErrLens
27
+
28
+ ErrLens is a local, open-source CLI that adds readable Russian or English explanations to recognized Python errors. It helps developers understand tracebacks without copying them to an external service. Explanations are rule-based and work offline after installation; no API key or AI model is required.
29
+
30
+ ErrLens runs a command through `errlens run`. Its default pipe mode forwards the original stdout and stderr, then appends an explanation to stderr when an error is recognized. Optional shell wrappers intercept only `python`; explicit terminal mode uses merged terminal output.
31
+
32
+ ## Requirements and installation
33
+
34
+ Python 3.11 or newer is required. On Windows, Linux or macOS, install from a local checkout:
35
+
36
+ ```console
37
+ python -m pip install .
38
+ ```
39
+
40
+ For development, use a virtual environment and install `python -m pip install -e ".[dev]"`. Installing dependencies requires an available package index or local wheels.
41
+
42
+ The PyPI distribution name is **errlens-cli**; the Python import and executable
43
+ are both **errlens**. This candidate has not been uploaded. After publication,
44
+ install with `python -m pip install errlens-cli==0.1.0`, then run `errlens --version`.
45
+ Until then use this checkout or a verified supplied wheel:
46
+ `python -m pip install /path/to/errlens_cli-0.1.0-py3-none-any.whl`.
47
+ The existing PyPI package named `errlens` is not the distribution selected for
48
+ this repository. See [release preparation](https://github.com/ErrLens/errlens-cli/blob/main/docs/releasing.md).
49
+ CI covers CPython 3.11–3.13; newer Python versions are not yet qualified.
50
+
51
+ ## Usage
52
+
53
+ ```console
54
+ errlens --help
55
+ errlens --version
56
+ errlens run python main.py
57
+ errlens run --lang en -- python main.py
58
+ errlens run --no-explain -- python main.py
59
+ errlens run python -c "print(undefined_variable)"
60
+ ```
61
+
62
+ Russian is the default; `--lang en` selects English. Place ErrLens options before the executable; arguments after the executable belong to the child process. `--no-explain` skips analysis. The optional `--` makes the boundary explicit.
63
+
64
+ The original traceback remains visible. For example, a `NameError` can be followed by an explanation that the name is unavailable in the current scope and suggestions to check its spelling and definition. Causes are described as possibilities, not established facts. Successful commands and nonzero exits without recognized diagnostics do not produce an explanation.
65
+
66
+ ## Supported diagnostics
67
+
68
+ Rules cover `ModuleNotFoundError`, `ImportError`, `SyntaxError`, `IndentationError`, `TabError`, `NameError`, `TypeError`, `AttributeError`, `KeyError`, `FileNotFoundError` and `PermissionError`. Other structured exceptions receive a neutral notice. Incomplete diagnostics are marked as such; `ExceptionGroup` is summarized at its outer level. For a chain of exceptions, the final diagnostic is explained and linked predecessors are noted.
69
+
70
+ Suggested commands are never executed. A pip command is shown only for the exact `requests` import and an explicitly specified absolute Python executable path, with a condition to confirm that the distribution is actually needed in that environment. Import names do not generally identify package names, and a missing module may be local.
71
+
72
+ ## Behavior and limitations
73
+
74
+ - ErrLens launches argument sequences without `shell=True`. Shell pipelines and builtins are interpreted by the invoking shell, not by ErrLens. On Windows, the operating system may invoke a command interpreter for `.bat` or `.cmd` files even with `shell=False`.
75
+ - Separate bounded buffers retain up to 1 MiB per stream for analysis. Original bytes are forwarded as they arrive; the diagnostic copy may be truncated. No output logs are saved to disk.
76
+ - Pipes change `isatty()` and may affect child buffering and colors. Interactive programs, job control and full-screen applications are not guaranteed to work. The relative ordering of stdout and stderr cannot be reconstructed.
77
+ - The child exit code is preserved for normal exits. On POSIX, signal termination becomes `128 + signal`; user interruption returns 130. Runner failures have their own codes: 125 for internal failures, 126 for permission errors, 127 for missing executables and 141 for broken pipes. Child programs can also use these codes; ErrLens identifies its own failures in stderr when possible.
78
+ - In pipe mode, Ctrl+C handling uses a separate process group. Windows pipe cleanup does not guarantee termination of an arbitrary descendant tree. After the child exits, pipes held open by descendants are subject to a one-second drain timeout. ConPTY uses the Job Object cleanup described below.
79
+ - Recognition targets standard CPython traceback formatting; IPython/Jupyter and logger-prefixed tracebacks are not supported. A traceback-like log can be ambiguous. Stdout diagnostics require a failed Python command. Unknown or incomplete data is not presented as a certain cause.
80
+ - Rich markup and terminal control characters from diagnostic data are rendered literally or escaped in the ErrLens block. Redirected explanations are plain text without ANSI. Original child output is not sanitized.
81
+ - Explanation fields are capped at 2,048 characters; linked exception messages at 256 characters. The forwarded traceback is not shortened by this limit.
82
+ - ErrLens does not fix code, install packages, collect telemetry or contact a service. Shell wrappers and terminal mode are explicit opt-ins; VS Code extension support remains future work.
83
+
84
+ ## Opt-in PowerShell 7 integration (Windows)
85
+
86
+ ```powershell
87
+ errlens shell install powershell
88
+ errlens shell status powershell
89
+ errlens shell uninstall powershell
90
+ ```
91
+
92
+ Installation explicitly edits the current user's **all-hosts PowerShell 7 profile**
93
+ (shared with VS Code), discovered using `pwsh -NoProfile`. Restart PowerShell after
94
+ installation/removal. ExecutionPolicy is never changed; your policy must allow
95
+ loading the profile and the integration script. No administrator access is needed.
96
+ For an isolated trial or a custom host profile use `--profile 'path/to/profile.ps1'`
97
+ on each management command, then dot-source that profile manually.
98
+
99
+ An owned script is placed in an `ErrLens` subdirectory next to the selected profile.
100
+ Only one guarded dot-source line is appended. Existing profile bytes are preserved;
101
+ each modification of an existing profile creates a uniquely named backup alongside
102
+ it. Backups are retained on removal. Edited connection lines and unowned integration
103
+ files are refused rather than overwritten. A newly created profile is left empty
104
+ after removal. Existing `python` aliases/functions are preserved with a warning.
105
+
106
+ After loading, plain `python main.py`, `python -c "print(undefined_variable)"` and
107
+ `python --version` delegate to `errlens run`. Only the command name `python` is
108
+ wrapped. Absolute executable paths, `py`, pip and other commands bypass it.
109
+ The native Python application is resolved from PATH on every invocation, so venv
110
+ activation is respected. The ErrLens runtime is bound to the absolute Python path
111
+ used during installation; `errlens` need not be in PATH. Keep that environment
112
+ installed. To migrate it, uninstall the integration and reinstall from the new runtime.
113
+
114
+ Temporarily bypass analysis with `$env:ERRLENS_DISABLE='1'`; restore it with
115
+ `Remove-Item Env:ERRLENS_DISABLE`. To remove the wrapper from the current session,
116
+ use `Remove-Item Function:python`. Persistent removal takes effect in new sessions.
117
+
118
+ This is a PowerShell function calling a native program, not transparent terminal
119
+ capture. `$LASTEXITCODE` is explicitly propagated. `$?` may report function success
120
+ even when Python fails; inspect `$LASTEXITCODE`. PowerShell 7.3+ uses Standard
121
+ native argument passing locally inside the wrapper; 7.0–7.2 retain their legacy
122
+ quoting/empty-argument limitations. Global preferences are not changed.
123
+ Pipeline output and `>` pass through PowerShell's object/text conversion and do
124
+ not guarantee byte identity (including PowerShell 7.4 native redirection behavior).
125
+ Pipeline input is not forwarded by this wrapper. Avoid binary pipelines, REPLs,
126
+ interactive and full-screen applications; use an absolute Python executable when
127
+ native semantics are needed. ExecutionPolicy, host-specific profile loading and
128
+ VS Code itself require manual verification on the target machine.
129
+
130
+ ## Opt-in Bash and Zsh integration
131
+
132
+ On Linux/macOS, explicitly install with `errlens shell install bash` or
133
+ `errlens shell install zsh`; use `status` or `uninstall` in place of `install`.
134
+ Bash uses `~/.bashrc`; Zsh uses `${ZDOTDIR:-$HOME}/.zshrc`. Bash login shells
135
+ do not necessarily load `.bashrc`: configure your login profile to source it
136
+ yourself if needed. These are interactive startup files; noninteractive shells
137
+ do not automatically load them. `--profile PATH` selects an isolated/custom file.
138
+
139
+ An owned script in `.errlens` beside the profile is sourced by one guarded line.
140
+ Existing profile bytes are retained, changes receive unique backups, repeated
141
+ installation is idempotent, and removal removes only the exact owned line and script.
142
+ Edited lines and unowned scripts are refused. Backups remain after removal.
143
+ Existing `python` functions and aliases take precedence and are preserved.
144
+
145
+ The `python` function resolves the external interpreter and `errlens` on each
146
+ invocation, forwards `"$@"`, working directory and exit status, and respects an
147
+ activated virtual environment. `ERRLENS_DISABLE=1 python ...` bypasses analysis;
148
+ if ErrLens is absent from PATH, the native Python is run directly. Use `unset -f
149
+ python` to disable the wrapper in the current shell. `command python`, an absolute
150
+ path, `python3`, pip and other commands bypass it. Restart or source the profile
151
+ after installation; restart or unset the function after uninstallation.
152
+
153
+ When starting Zsh from Bash with an active virtual environment, the Bash
154
+ activation script may have modified and exported prompt variables. Bash prompt
155
+ escapes are not Zsh prompt syntax and may appear literally. Start a clean Zsh,
156
+ then run `source /path/to/venv/bin/activate` within Zsh. The ErrLens integration
157
+ does not change `PS1` or `PROMPT`; your Zsh configuration can define its own prompt.
158
+ Manual reports of Windows 11/PowerShell and Ubuntu 24.04/WSL Bash and Zsh are
159
+ distinct from the automated CI checks; consult CI results for verified runs.
160
+
161
+ Redirection and pipelines follow the shell and `errlens run` pipe semantics.
162
+ Input is inherited, but interactive/terminal-dependent programs and exact stdout/
163
+ stderr interleaving are not guaranteed. Ctrl+C follows Runner process-group handling;
164
+ PTY and job-control equivalence are not guaranteed. Paths with spaces and Unicode
165
+ are quoted without `eval`. No system profiles or shell settings are modified.
166
+
167
+ ## Explicit terminal mode
168
+
169
+ Use `errlens run --terminal-mode pty -- python script.py` when terminal stdin
170
+ and stdout are available. Linux/macOS use POSIX PTY; Windows 10 1809+ and Windows
171
+ 11 use native ConPTY. Pipe remains the default, including all shell wrappers.
172
+ A transport error never triggers an automatic second run. Windows requires
173
+ actual console handles and a native executable (.exe or .com), with no batch
174
+ file or legacy winpty fallback. No extra runtime dependency or compiler is needed.
175
+
176
+ Terminal mode supplies a terminal, input, window-size propagation and terminal
177
+ Ctrl+C handling. stdout and stderr merge onto ErrLens stdout; echo and LF-to-CRLF
178
+ conversion are normal terminal behavior. Binary identity and original stream
179
+ separation are not guaranteed. Redirected host stdin/stdout are rejected; use
180
+ pipe mode for pipelines. The combined diagnostic tail is limited to 1 MiB.
181
+ Recognized failed Python commands receive one explanation on stderr after terminal
182
+ restoration. Interactive REPL exceptions followed by a successful exit do not
183
+ produce cards. ANSI forwarding is supported, but screen reconstruction, job-control
184
+ transparency, suspended children and arbitrary full-screen applications are not
185
+ guaranteed. A permanently blocked output sink can still block forwarding.
186
+
187
+ The host terminal modes and signal handlers are saved and restored on ordinary
188
+ exit, cancellation and transport errors. SIGKILL or a host crash cannot provide
189
+ that guarantee. POSIX processes that deliberately detach from the session may
190
+ outlive cleanup. ConPTY clients belong to a kill-on-close Windows Job Object:
191
+ remaining descendants are terminated when the main client ends or transport fails.
192
+ Windows uses a separate, short-lived owner process to bound ConPTY shutdown on
193
+ older Windows builds. Input/output are UTF-8/VT text, so invalid bytes, NUL, cursor
194
+ movement, wrapping and screen redraws need not survive as original log bytes.
195
+ The analyzer strips ANSI but does not reconstruct a screen; complex redraws can
196
+ produce incomplete or unrecognized diagnostics.
197
+
198
+ Automated tests use isolated real ConPTY sessions and nested console handles on
199
+ Windows, and nested POSIX PTYs on Linux and in the manual macOS workflow. User-reported manual checks
200
+ cover Windows Terminal and VS Code ConPTY plus selected WSL Bash/Zsh sessions;
201
+ the [acceptance record](https://github.com/ErrLens/errlens-cli/blob/main/docs/manual-acceptance.md) preserves untested combinations.
202
+ Legacy console hosts, detailed REPL editing, Windows 10 lifecycle behavior and
203
+ physical macOS hosts are not fully manually qualified. See
204
+ [Windows ConPTY notes](https://github.com/ErrLens/errlens-cli/blob/main/docs/windows-conpty.md) for lifecycle details.
205
+
206
+ ## Development and checks
207
+
208
+ ```console
209
+ python -m pytest
210
+ python -m mypy
211
+ python -m pip check
212
+ python -m build
213
+ ```
214
+
215
+ The build creates a wheel and source distribution in `dist/`. GitHub Actions #6
216
+ passed all 11 jobs for `84dbb9c927b1b0eaf3ac6efc50863b9f0ef72836`, covering
217
+ Windows, Ubuntu and macOS on Python 3.11–3.13 plus Windows/Ubuntu wheel installation.
218
+ Hosted macOS runners were unavailable in [CI #8](https://github.com/ErrLens/errlens-cli/actions/runs/43235376928).
219
+ The required Tests workflow temporarily runs Linux and Windows on Python 3.11–3.13
220
+ and both packaging jobs. macOS tests remain available through a separate manual
221
+ workflow. Earlier macOS passes apply to their tested commits. The release candidate
222
+ has yet to be tested on macOS. The [release guide](https://github.com/ErrLens/errlens-cli/blob/main/docs/releasing.md)
223
+ records when to restore macOS to the required matrix. The manual publishing workflow
224
+ can retain candidate artifacts for review.
225
+
226
+ See [CONTRIBUTING.md](https://github.com/ErrLens/errlens-cli/blob/main/CONTRIBUTING.md) for contribution guidance. ErrLens is distributed under the [MIT License](https://github.com/ErrLens/errlens-cli/blob/main/LICENSE).
227
+
228
+ ## Roadmap
229
+
230
+ The current CLI focuses on local Python diagnostics, localized explanations,
231
+ opt-in shell wrappers and explicit terminal sessions. Future stages may improve
232
+ terminal compatibility and add VS Code integration, additional analyzers and
233
+ optional AI providers. Those future features are not part of the current CLI.