claude-supervisor 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.
- claude_supervisor-0.1.0/.gitattributes +12 -0
- claude_supervisor-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +47 -0
- claude_supervisor-0.1.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
- claude_supervisor-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +24 -0
- claude_supervisor-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- claude_supervisor-0.1.0/.github/dependabot.yml +16 -0
- claude_supervisor-0.1.0/.github/workflows/ci.yml +65 -0
- claude_supervisor-0.1.0/.github/workflows/release.yml +44 -0
- claude_supervisor-0.1.0/.gitignore +33 -0
- claude_supervisor-0.1.0/.pre-commit-config.yaml +24 -0
- claude_supervisor-0.1.0/CHANGELOG.md +163 -0
- claude_supervisor-0.1.0/CODE_OF_CONDUCT.md +56 -0
- claude_supervisor-0.1.0/CONTRIBUTING.md +63 -0
- claude_supervisor-0.1.0/LICENSE +21 -0
- claude_supervisor-0.1.0/PKG-INFO +302 -0
- claude_supervisor-0.1.0/README.md +231 -0
- claude_supervisor-0.1.0/ROADMAP.md +47 -0
- claude_supervisor-0.1.0/SECURITY.md +48 -0
- claude_supervisor-0.1.0/docs/ALPHA_TESTING.md +105 -0
- claude_supervisor-0.1.0/docs/ARCHITECTURE.md +124 -0
- claude_supervisor-0.1.0/docs/CLAUDE_CODE_INTEGRATION.md +60 -0
- claude_supervisor-0.1.0/docs/RELEASING.md +40 -0
- claude_supervisor-0.1.0/docs/TODO.md +85 -0
- claude_supervisor-0.1.0/examples/config.yaml +72 -0
- claude_supervisor-0.1.0/integrations/claude-code/README.md +12 -0
- claude_supervisor-0.1.0/integrations/claude-code/commands/supervisor.md +12 -0
- claude_supervisor-0.1.0/pyproject.toml +130 -0
- claude_supervisor-0.1.0/src/claude_supervisor/__init__.py +15 -0
- claude_supervisor-0.1.0/src/claude_supervisor/cli/__init__.py +7 -0
- claude_supervisor-0.1.0/src/claude_supervisor/cli/app.py +386 -0
- claude_supervisor-0.1.0/src/claude_supervisor/config/__init__.py +39 -0
- claude_supervisor-0.1.0/src/claude_supervisor/config/loader.py +160 -0
- claude_supervisor-0.1.0/src/claude_supervisor/config/models.py +227 -0
- claude_supervisor-0.1.0/src/claude_supervisor/core/__init__.py +9 -0
- claude_supervisor-0.1.0/src/claude_supervisor/core/stats.py +47 -0
- claude_supervisor-0.1.0/src/claude_supervisor/core/supervisor.py +288 -0
- claude_supervisor-0.1.0/src/claude_supervisor/core/transcript.py +62 -0
- claude_supervisor-0.1.0/src/claude_supervisor/logging/__init__.py +7 -0
- claude_supervisor-0.1.0/src/claude_supervisor/logging/setup.py +97 -0
- claude_supervisor-0.1.0/src/claude_supervisor/parser/__init__.py +31 -0
- claude_supervisor-0.1.0/src/claude_supervisor/parser/events.py +45 -0
- claude_supervisor-0.1.0/src/claude_supervisor/parser/parser.py +99 -0
- claude_supervisor-0.1.0/src/claude_supervisor/parser/patterns.py +194 -0
- claude_supervisor-0.1.0/src/claude_supervisor/parser/reset_time.py +115 -0
- claude_supervisor-0.1.0/src/claude_supervisor/parser/rules/claude.yaml +65 -0
- claude_supervisor-0.1.0/src/claude_supervisor/permissions/__init__.py +15 -0
- claude_supervisor-0.1.0/src/claude_supervisor/permissions/engine.py +90 -0
- claude_supervisor-0.1.0/src/claude_supervisor/py.typed +0 -0
- claude_supervisor-0.1.0/src/claude_supervisor/resume/__init__.py +14 -0
- claude_supervisor-0.1.0/src/claude_supervisor/resume/clock.py +95 -0
- claude_supervisor-0.1.0/src/claude_supervisor/resume/planner.py +71 -0
- claude_supervisor-0.1.0/src/claude_supervisor/session/__init__.py +12 -0
- claude_supervisor-0.1.0/src/claude_supervisor/session/manager.py +95 -0
- claude_supervisor-0.1.0/src/claude_supervisor/state_machine/__init__.py +19 -0
- claude_supervisor-0.1.0/src/claude_supervisor/state_machine/machine.py +114 -0
- claude_supervisor-0.1.0/src/claude_supervisor/state_machine/states.py +62 -0
- claude_supervisor-0.1.0/src/claude_supervisor/storage/__init__.py +26 -0
- claude_supervisor-0.1.0/src/claude_supervisor/storage/base.py +136 -0
- claude_supervisor-0.1.0/src/claude_supervisor/storage/sqlite.py +224 -0
- claude_supervisor-0.1.0/src/claude_supervisor/terminal/__init__.py +26 -0
- claude_supervisor-0.1.0/src/claude_supervisor/terminal/backends.py +153 -0
- claude_supervisor-0.1.0/src/claude_supervisor/terminal/base.py +153 -0
- claude_supervisor-0.1.0/src/claude_supervisor/terminal/factory.py +46 -0
- claude_supervisor-0.1.0/src/claude_supervisor/terminal/threaded.py +134 -0
- claude_supervisor-0.1.0/tests/__init__.py +0 -0
- claude_supervisor-0.1.0/tests/integration/__init__.py +0 -0
- claude_supervisor-0.1.0/tests/integration/test_pty_integration.py +198 -0
- claude_supervisor-0.1.0/tests/test_cli.py +273 -0
- claude_supervisor-0.1.0/tests/test_clock.py +69 -0
- claude_supervisor-0.1.0/tests/test_config.py +125 -0
- claude_supervisor-0.1.0/tests/test_logging.py +48 -0
- claude_supervisor-0.1.0/tests/test_parser.py +124 -0
- claude_supervisor-0.1.0/tests/test_patterns.py +151 -0
- claude_supervisor-0.1.0/tests/test_permissions.py +57 -0
- claude_supervisor-0.1.0/tests/test_planner.py +48 -0
- claude_supervisor-0.1.0/tests/test_reset_time.py +82 -0
- claude_supervisor-0.1.0/tests/test_session.py +76 -0
- claude_supervisor-0.1.0/tests/test_state_machine.py +107 -0
- claude_supervisor-0.1.0/tests/test_storage.py +129 -0
- claude_supervisor-0.1.0/tests/test_supervisor.py +274 -0
- claude_supervisor-0.1.0/tests/test_terminal.py +222 -0
- claude_supervisor-0.1.0/tests/test_transcript.py +54 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Normalize line endings to LF in the repository across platforms.
|
|
2
|
+
* text=auto eol=lf
|
|
3
|
+
|
|
4
|
+
# Explicitly text
|
|
5
|
+
*.py text eol=lf
|
|
6
|
+
*.pyi text eol=lf
|
|
7
|
+
*.toml text eol=lf
|
|
8
|
+
*.yaml text eol=lf
|
|
9
|
+
*.yml text eol=lf
|
|
10
|
+
*.md text eol=lf
|
|
11
|
+
*.cfg text eol=lf
|
|
12
|
+
py.typed text eol=lf
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Something didn't work as expected
|
|
3
|
+
labels: [bug]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for trying Claude Supervisor (alpha). The single most useful thing
|
|
9
|
+
you can attach is a **`--capture` transcript** from the run — it records
|
|
10
|
+
exactly what Claude printed and what the supervisor detected.
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: what-happened
|
|
13
|
+
attributes:
|
|
14
|
+
label: What happened?
|
|
15
|
+
description: What did you expect, and what happened instead?
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: command
|
|
20
|
+
attributes:
|
|
21
|
+
label: Command you ran
|
|
22
|
+
render: shell
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: capture
|
|
27
|
+
attributes:
|
|
28
|
+
label: Capture transcript
|
|
29
|
+
description: |
|
|
30
|
+
Re-run with `--capture run.txt` and paste or attach the file. For any
|
|
31
|
+
detection problem (a prompt not answered, a limit not detected, a run
|
|
32
|
+
that didn't stop), this is the most important field.
|
|
33
|
+
render: text
|
|
34
|
+
- type: input
|
|
35
|
+
id: versions
|
|
36
|
+
attributes:
|
|
37
|
+
label: Versions
|
|
38
|
+
description: "OS, `python --version`, `claude --version`, `claude-supervisor version`"
|
|
39
|
+
placeholder: "Windows 11, Python 3.12.5, claude 1.x, claude-supervisor 0.1.0"
|
|
40
|
+
validations:
|
|
41
|
+
required: true
|
|
42
|
+
- type: textarea
|
|
43
|
+
id: logs
|
|
44
|
+
attributes:
|
|
45
|
+
label: Logs (optional)
|
|
46
|
+
description: "Output of `claude-supervisor logs -n 80`, if relevant."
|
|
47
|
+
render: shell
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest an idea or improvement
|
|
3
|
+
labels: [enhancement]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem / motivation
|
|
9
|
+
description: What are you trying to do that's hard or impossible today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: proposal
|
|
14
|
+
attributes:
|
|
15
|
+
label: Proposed solution
|
|
16
|
+
description: What would you like to see? Alternatives you've considered?
|
|
17
|
+
- type: checkboxes
|
|
18
|
+
id: scope
|
|
19
|
+
attributes:
|
|
20
|
+
label: Scope check
|
|
21
|
+
description: Claude Supervisor never bypasses limits, auth, or subscriptions, and never modifies Claude.
|
|
22
|
+
options:
|
|
23
|
+
- label: This request stays within that scope.
|
|
24
|
+
required: true
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# What & why
|
|
2
|
+
|
|
3
|
+
<!-- What does this change, and why? Link any related issue. -->
|
|
4
|
+
|
|
5
|
+
# Checklist
|
|
6
|
+
|
|
7
|
+
- [ ] Tests added/updated; `pytest` is green and coverage stays ≥ 90%
|
|
8
|
+
- [ ] `ruff check .`, `black --check .`, and `mypy src` are clean
|
|
9
|
+
- [ ] Docs and `CHANGELOG.md` updated where relevant
|
|
10
|
+
- [ ] Detection wording changes go in `parser/rules/claude.yaml` (not code) where possible
|
|
11
|
+
- [ ] Stays within scope: no bypassing limits/auth/subscriptions, no modifying Claude
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: "pip"
|
|
4
|
+
directory: "/"
|
|
5
|
+
schedule:
|
|
6
|
+
interval: "weekly"
|
|
7
|
+
groups:
|
|
8
|
+
python-dependencies:
|
|
9
|
+
patterns: ["*"]
|
|
10
|
+
labels: ["dependencies"]
|
|
11
|
+
|
|
12
|
+
- package-ecosystem: "github-actions"
|
|
13
|
+
directory: "/"
|
|
14
|
+
schedule:
|
|
15
|
+
interval: "weekly"
|
|
16
|
+
labels: ["dependencies", "ci"]
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: ${{ matrix.os }} / py${{ matrix.python }}
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, windows-latest]
|
|
20
|
+
python: ["3.12", "3.13", "3.14"]
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python }}
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python }}
|
|
28
|
+
|
|
29
|
+
- name: Install (with dev + platform PTY backend)
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
pip install -e ".[dev]"
|
|
33
|
+
|
|
34
|
+
- name: Lint (ruff)
|
|
35
|
+
run: ruff check .
|
|
36
|
+
|
|
37
|
+
- name: Format check (black)
|
|
38
|
+
run: black --check .
|
|
39
|
+
|
|
40
|
+
- name: Type check (mypy)
|
|
41
|
+
run: mypy src
|
|
42
|
+
|
|
43
|
+
- name: Test (with coverage; real-PTY integration included)
|
|
44
|
+
run: pytest
|
|
45
|
+
|
|
46
|
+
build:
|
|
47
|
+
name: build distribution
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v4
|
|
51
|
+
- uses: actions/setup-python@v5
|
|
52
|
+
with:
|
|
53
|
+
python-version: "3.12"
|
|
54
|
+
- name: Build wheel + sdist
|
|
55
|
+
run: |
|
|
56
|
+
python -m pip install --upgrade pip build
|
|
57
|
+
python -m build
|
|
58
|
+
- name: Verify metadata
|
|
59
|
+
run: |
|
|
60
|
+
python -m pip install twine
|
|
61
|
+
twine check dist/*
|
|
62
|
+
- uses: actions/upload-artifact@v4
|
|
63
|
+
with:
|
|
64
|
+
name: dist
|
|
65
|
+
path: dist/*
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when a version tag (v*) is pushed. Uses PyPI Trusted
|
|
4
|
+
# Publishing (OIDC) — no API token secret required once the publisher is
|
|
5
|
+
# configured on PyPI. See docs/RELEASING.md.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
- name: Build + check
|
|
23
|
+
run: |
|
|
24
|
+
python -m pip install --upgrade pip build twine
|
|
25
|
+
python -m build
|
|
26
|
+
twine check dist/*
|
|
27
|
+
- uses: actions/upload-artifact@v4
|
|
28
|
+
with:
|
|
29
|
+
name: dist
|
|
30
|
+
path: dist/*
|
|
31
|
+
|
|
32
|
+
publish:
|
|
33
|
+
needs: build
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
environment: pypi
|
|
36
|
+
permissions:
|
|
37
|
+
id-token: write # required for Trusted Publishing
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/download-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: dist
|
|
42
|
+
path: dist
|
|
43
|
+
- name: Publish to PyPI
|
|
44
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.eggs/
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
*.egg
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
|
|
15
|
+
# Tooling caches
|
|
16
|
+
.pytest_cache/
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
.coverage.*
|
|
21
|
+
htmlcov/
|
|
22
|
+
coverage.xml
|
|
23
|
+
|
|
24
|
+
# Runtime state (logs, database)
|
|
25
|
+
*.log
|
|
26
|
+
*.db
|
|
27
|
+
*.sqlite3
|
|
28
|
+
|
|
29
|
+
# Editors / OS
|
|
30
|
+
.idea/
|
|
31
|
+
.vscode/
|
|
32
|
+
.DS_Store
|
|
33
|
+
Thumbs.db
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Install once with: pre-commit install
|
|
2
|
+
# Run on all files: pre-commit run --all-files
|
|
3
|
+
# (mypy runs in CI rather than here to keep commits fast.)
|
|
4
|
+
repos:
|
|
5
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
6
|
+
rev: v5.0.0
|
|
7
|
+
hooks:
|
|
8
|
+
- id: trailing-whitespace
|
|
9
|
+
- id: end-of-file-fixer
|
|
10
|
+
- id: check-yaml
|
|
11
|
+
- id: check-toml
|
|
12
|
+
- id: check-merge-conflict
|
|
13
|
+
- id: check-added-large-files
|
|
14
|
+
|
|
15
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
16
|
+
rev: v0.6.9
|
|
17
|
+
hooks:
|
|
18
|
+
- id: ruff
|
|
19
|
+
args: [--fix]
|
|
20
|
+
|
|
21
|
+
- repo: https://github.com/psf/black
|
|
22
|
+
rev: 24.10.0
|
|
23
|
+
hooks:
|
|
24
|
+
- id: black
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres
|
|
5
|
+
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.1.0] — 2026-07-12
|
|
10
|
+
|
|
11
|
+
First public alpha.
|
|
12
|
+
|
|
13
|
+
### Validated
|
|
14
|
+
|
|
15
|
+
- **Runs against real Claude Code** (CLI 2.x). Confirmed end-to-end on Windows:
|
|
16
|
+
the supervisor launches `claude -p`, runs a task, detects the clean-exit
|
|
17
|
+
completion, and records the session. Live testing drove the fixes below.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **A clean process exit (code 0) now counts as completion in every mode.** Real
|
|
22
|
+
headless `claude -p` prints its answer and exits 0 with no "done" marker, so a
|
|
23
|
+
clean exit *is* success; only a non-zero exit is an unexpected exit. The
|
|
24
|
+
strict/heuristic distinction now governs only *idle* detection.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Default `resume_command` corrected from the invalid `claude resume` to
|
|
29
|
+
`claude --continue` (the real Claude Code flag for continuing a session).
|
|
30
|
+
- A failed process launch (e.g. `claude` not on PATH, or a wrong
|
|
31
|
+
`claude_command`) now raises a clear `TerminalError` with an actionable hint
|
|
32
|
+
and exits non-zero, instead of dumping a `FileNotFoundError` traceback.
|
|
33
|
+
- An explicitly provided `--config` path that does not exist now errors clearly
|
|
34
|
+
instead of being silently ignored (a typo'd path used to fall back to
|
|
35
|
+
defaults). A missing *default* location still uses defaults, as before.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **`claude-supervisor init`** writes a starter config using the validated
|
|
40
|
+
headless recipe (`claude -p --permission-mode acceptEdits`), so unattended
|
|
41
|
+
runs work out of the box.
|
|
42
|
+
- **`doctor` now checks for the `claude` CLI** on your PATH (informational),
|
|
43
|
+
with an install hint if it's missing.
|
|
44
|
+
- **Claude Code integration.** A `claude-supervisor statusline` command feeds a
|
|
45
|
+
live one-liner (`🛡 3 runs · 1 resume · 2.1h saved`) into Claude Code's status
|
|
46
|
+
bar, plus a `/supervisor` slash command — see
|
|
47
|
+
[docs/CLAUDE_CODE_INTEGRATION.md](docs/CLAUDE_CODE_INTEGRATION.md). The status
|
|
48
|
+
line forces UTF-8 output and is fully defensive so it can never disrupt the UI.
|
|
49
|
+
- **Release automation** (`.github/workflows/release.yml`): tag `vX.Y.Z` builds,
|
|
50
|
+
`twine check`s, and publishes to PyPI via Trusted Publishing. See
|
|
51
|
+
[docs/RELEASING.md](docs/RELEASING.md).
|
|
52
|
+
- **Contributor tooling:** `.pre-commit-config.yaml` (ruff/black/basic hooks)
|
|
53
|
+
and Dependabot for pip + GitHub Actions updates.
|
|
54
|
+
- **Public-readiness:** README badges (CI/license/Python/status), an honest
|
|
55
|
+
"Project status" section (alpha; not yet validated against live Claude),
|
|
56
|
+
a `status` demo, GitHub issue forms (bug report asks for a `--capture`
|
|
57
|
+
transcript) and a PR template, and CI stabilization (auto-retry the
|
|
58
|
+
timing-sensitive real-PTY tests).
|
|
59
|
+
- **Run capture / transcript** (`start --capture <file>`). Writes every
|
|
60
|
+
(ANSI-stripped) line Claude prints to a file, tagging the ones that triggered
|
|
61
|
+
a detected event. Makes a real run self-document exactly what Claude output
|
|
62
|
+
and what the supervisor saw — the fastest way to reconcile parser rules
|
|
63
|
+
against real Claude Code wording. Backed by a `LineListener` hook on the
|
|
64
|
+
parser and a `TranscriptWriter`; survives resumes.
|
|
65
|
+
- **Unattended task mode.** `claude-supervisor start --task "<task>"` runs a
|
|
66
|
+
task without you attached: it survives usage-limit resets, auto-answers the
|
|
67
|
+
repetitive prompts, detects completion, and reports. Task delivery is
|
|
68
|
+
configurable (`task_delivery`): `argument` appends it to the command
|
|
69
|
+
(`claude -p "<task>"` style, default) or `input` types it into an interactive
|
|
70
|
+
session. `--auto-approve` opts a single run into answering prompts
|
|
71
|
+
(active-task scope). Validated end-to-end on a real PTY for both modes.
|
|
72
|
+
- **Idle / prompt-return completion detection.** In heuristic completion mode,
|
|
73
|
+
a live-but-silent session (no output for `idle_completion_seconds`, default
|
|
74
|
+
30s) is treated as a finished turn — Claude idling at the prompt — so the
|
|
75
|
+
supervisor stops and hands control back. This covers the common case where
|
|
76
|
+
there is no literal "completed" marker. Strict mode (the default) is
|
|
77
|
+
unchanged. Idle time is accrued from read intervals (deterministic, no
|
|
78
|
+
busy-poll), and `ScriptedTerminal` gained a `TIMEOUT` marker to test it.
|
|
79
|
+
|
|
80
|
+
- **Storage** (`storage/`): a `Storage` protocol and `SqliteStorage` backend
|
|
81
|
+
persisting sessions and per-run events, plus a `Statistics` aggregate
|
|
82
|
+
(completed sessions, resumes, approvals, average runtime/wait, hours saved).
|
|
83
|
+
The layer speaks only primitives — it never imports the orchestration layer.
|
|
84
|
+
- **Session** (`session/`): `SessionManager` bridges a run onto storage —
|
|
85
|
+
records `RunStats`, logs every state transition as an event, and exposes
|
|
86
|
+
latest/recent sessions plus statistics.
|
|
87
|
+
- **CLI**: `status` (latest session + aggregate statistics) and `logs` (tail of
|
|
88
|
+
the log file) are now live. `start`/`resume` persist each run automatically.
|
|
89
|
+
- `RunStats` gained `total_wait_seconds` (unattended waiting absorbed), the
|
|
90
|
+
basis for the "hours saved" statistic.
|
|
91
|
+
|
|
92
|
+
- **Terminal** (`terminal/`): `TerminalManager` abstraction with a
|
|
93
|
+
timeout-capable `read`; a process-free `ScriptedTerminal`; a `ThreadedTerminal`
|
|
94
|
+
base that pumps blocking PTY reads on a background thread (event-driven, no
|
|
95
|
+
busy-polling); `pexpect` (POSIX) and `pywinpty` (Windows) backends, lazily
|
|
96
|
+
imported with a clear install hint; platform-aware `create_terminal` /
|
|
97
|
+
`terminal_factory`.
|
|
98
|
+
- **Permissions** (`permissions/`): `PermissionDecision`, a `PermissionEngine`
|
|
99
|
+
protocol, and `ActiveTaskPermissionEngine` — v1 approves repetitive prompts
|
|
100
|
+
only when the user opted in *and* a task is active; it never auto-rejects.
|
|
101
|
+
- **Resume** (`resume/`): an interruptible `Clock` (`RealClock` waits on an
|
|
102
|
+
event; `ManualClock` for deterministic tests) and a `ResumePlanner` that
|
|
103
|
+
prefers a parsed reset delay, then the last-known interval, then the default.
|
|
104
|
+
- **Core** (`core/`): the `Supervisor` run loop tying the subsystems together,
|
|
105
|
+
plus `RunStats`. Enforces the safety invariants structurally (completion is
|
|
106
|
+
terminal; waits are interruptible; auto-answer is scoped).
|
|
107
|
+
- **CLI**: `start` and `resume` are now live, with SIGINT-safe shutdown and a
|
|
108
|
+
run-summary table.
|
|
109
|
+
|
|
110
|
+
### Fixed
|
|
111
|
+
|
|
112
|
+
- Parser now emits at most one event per event type per line, so a single
|
|
113
|
+
usage-limit line can never trigger a duplicate resume.
|
|
114
|
+
- **Real-PTY hardening (found by integration testing against a live pseudo-
|
|
115
|
+
terminal):**
|
|
116
|
+
- The parser now strips ANSI/VT escape sequences before matching, so
|
|
117
|
+
detection is robust against Claude's coloured TUI output (`strip_ansi`).
|
|
118
|
+
- `send_line` now terminates input with a carriage return (`\r`), the actual
|
|
119
|
+
"Enter" key on a terminal. Previously it sent `\n`, which a Windows ConPTY
|
|
120
|
+
does not treat as Enter, leaving a child blocked on input forever.
|
|
121
|
+
|
|
122
|
+
### Changed
|
|
123
|
+
|
|
124
|
+
- **Permission answers are now configurable and menu-aware.** Real Claude Code
|
|
125
|
+
shows a numbered menu ("Do you want to proceed? / 1. Yes / …"), not a `(y/N)`
|
|
126
|
+
prompt. Terminals gained a raw `send(data)` (send arbitrary key sequences;
|
|
127
|
+
`send_line` is now `send(line + "\r")`), and `approve_response` /
|
|
128
|
+
`reject_response` config controls what is sent — defaulting to `"1\r"`
|
|
129
|
+
(select "Yes") and `"\x1b"` (Escape). Default detection patterns now match the
|
|
130
|
+
menu wording, keeping `(y/N)` support for classic prompts.
|
|
131
|
+
|
|
132
|
+
### Tests
|
|
133
|
+
|
|
134
|
+
- Added real-PTY integration tests (`tests/integration/`) that spawn an actual
|
|
135
|
+
subprocess in a pseudo-terminal via the platform backend, covering the full
|
|
136
|
+
usage-limit → wait → resume → permission → completion flow. Skipped cleanly
|
|
137
|
+
when no PTY backend is installed.
|
|
138
|
+
|
|
139
|
+
### Foundation (initial build)
|
|
140
|
+
|
|
141
|
+
The tested, dependency-light core.
|
|
142
|
+
|
|
143
|
+
### Added
|
|
144
|
+
|
|
145
|
+
- **Configuration** (`config/`): pydantic-validated `SupervisorConfig` loaded
|
|
146
|
+
from YAML, with backward-compatible flat spec keys (`log_level`, etc.) and
|
|
147
|
+
safe defaults (`auto_permissions` defaults to `false`).
|
|
148
|
+
- **Logging** (`logging/`): Rich console handler plus an optional rotating file
|
|
149
|
+
handler, behind an idempotent `configure_logging`.
|
|
150
|
+
- **Parser** (`parser/`): a streaming `ClaudeOutputParser` driven by an external
|
|
151
|
+
YAML **compatibility layer** (`PatternSet`), a small stable `EventType` set,
|
|
152
|
+
and reset-time extraction (relative `Try again in 4h 51m` and absolute
|
|
153
|
+
`Try again after 15:30`).
|
|
154
|
+
- **State machine** (`state_machine/`): explicit states and a validated
|
|
155
|
+
transition table with observers. Enforces the safety rule that
|
|
156
|
+
`TASK_COMPLETED` can only lead to `STOPPED`.
|
|
157
|
+
- **CLI** (`cli/`): `version`, `config`, and `doctor` commands; `start`,
|
|
158
|
+
`resume`, `status`, `logs` are declared as clear "not yet implemented" stubs.
|
|
159
|
+
- Test suite across all modules and project docs (README, ARCHITECTURE,
|
|
160
|
+
ROADMAP, SECURITY, CONTRIBUTING, CODE_OF_CONDUCT).
|
|
161
|
+
|
|
162
|
+
[Unreleased]: https://github.com/OnamSharma/claude-supervisor/compare/v0.1.0...HEAD
|
|
163
|
+
[0.1.0]: https://github.com/OnamSharma/claude-supervisor/releases/tag/v0.1.0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
|
10
|
+
orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment:
|
|
18
|
+
|
|
19
|
+
- Demonstrating empathy and kindness toward other people
|
|
20
|
+
- Being respectful of differing opinions, viewpoints, and experiences
|
|
21
|
+
- Giving and gracefully accepting constructive feedback
|
|
22
|
+
- Accepting responsibility and apologizing to those affected by our mistakes
|
|
23
|
+
- Focusing on what is best for the overall community
|
|
24
|
+
|
|
25
|
+
Examples of unacceptable behavior:
|
|
26
|
+
|
|
27
|
+
- The use of sexualized language or imagery, and sexual attention or advances
|
|
28
|
+
- Trolling, insulting or derogatory comments, and personal or political attacks
|
|
29
|
+
- Public or private harassment
|
|
30
|
+
- Publishing others' private information without explicit permission
|
|
31
|
+
- Other conduct which could reasonably be considered inappropriate
|
|
32
|
+
|
|
33
|
+
## Enforcement Responsibilities
|
|
34
|
+
|
|
35
|
+
Community leaders are responsible for clarifying and enforcing our standards and
|
|
36
|
+
will take appropriate and fair corrective action in response to any behavior
|
|
37
|
+
they deem inappropriate, threatening, offensive, or harmful.
|
|
38
|
+
|
|
39
|
+
## Scope
|
|
40
|
+
|
|
41
|
+
This Code of Conduct applies within all community spaces and also applies when
|
|
42
|
+
an individual is officially representing the community in public spaces.
|
|
43
|
+
|
|
44
|
+
## Enforcement
|
|
45
|
+
|
|
46
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
47
|
+
reported to the community leaders responsible for enforcement. All complaints
|
|
48
|
+
will be reviewed and investigated promptly and fairly.
|
|
49
|
+
|
|
50
|
+
## Attribution
|
|
51
|
+
|
|
52
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
53
|
+
version 2.1, available at
|
|
54
|
+
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
|
|
55
|
+
|
|
56
|
+
[homepage]: https://www.contributor-covenant.org
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Contributing to Claude Supervisor
|
|
2
|
+
|
|
3
|
+
Thanks for your interest! This project aims to be a clean, well-tested,
|
|
4
|
+
production-quality tool. Contributions of all sizes are welcome.
|
|
5
|
+
|
|
6
|
+
## Ground rules
|
|
7
|
+
|
|
8
|
+
1. **Stay within scope.** Contributions must not bypass usage limits,
|
|
9
|
+
authentication, or subscriptions, or modify/patch/impersonate Claude. See
|
|
10
|
+
[ROADMAP.md](ROADMAP.md) non-goals and [SECURITY.md](SECURITY.md).
|
|
11
|
+
2. **Safety over automation.** When behavior is uncertain, choose the safest
|
|
12
|
+
option and make the riskier one opt-in and logged.
|
|
13
|
+
3. **State-driven.** Lifecycle logic goes through the state machine, not ad-hoc
|
|
14
|
+
boolean flags.
|
|
15
|
+
|
|
16
|
+
## Development setup
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
python -m venv .venv
|
|
20
|
+
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
|
|
21
|
+
pip install -e ".[dev]"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires Python 3.12+.
|
|
25
|
+
|
|
26
|
+
Optionally install the git hooks so formatting/lint run on every commit:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pre-commit install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Before you open a PR
|
|
33
|
+
|
|
34
|
+
Run the full local check suite:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ruff check .
|
|
38
|
+
black --check .
|
|
39
|
+
mypy src
|
|
40
|
+
pytest
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- **Tests are required** for new behavior. Keep total coverage ≥ 90%.
|
|
44
|
+
- **Type hints and docstrings** on all public functions/classes (Google style).
|
|
45
|
+
- Keep modules single-responsibility and independently testable.
|
|
46
|
+
- Update [docs/TODO.md](docs/TODO.md), `CHANGELOG.md`, and relevant docs.
|
|
47
|
+
|
|
48
|
+
## Detection rules
|
|
49
|
+
|
|
50
|
+
Parser wording changes usually belong in
|
|
51
|
+
`src/claude_supervisor/parser/rules/claude.yaml`, **not** in Python. Prefer
|
|
52
|
+
under-matching over over-matching, especially for `permission` patterns — a
|
|
53
|
+
false permission match could auto-answer something.
|
|
54
|
+
|
|
55
|
+
## Commit / PR style
|
|
56
|
+
|
|
57
|
+
- Small, focused PRs aligned with a roadmap iteration are easiest to review.
|
|
58
|
+
- Describe the *why*, not just the *what*.
|
|
59
|
+
- Reference the iteration/issue you're addressing.
|
|
60
|
+
|
|
61
|
+
## Code of Conduct
|
|
62
|
+
|
|
63
|
+
Participation is governed by our [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Claude Supervisor 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.
|