cheaphelp 1.0.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.
- cheaphelp-1.0.0/AGENTS.md +1 -0
- cheaphelp-1.0.0/CHANGELOG.md +60 -0
- cheaphelp-1.0.0/CLAUDE.md +127 -0
- cheaphelp-1.0.0/CODE_OF_CONDUCT.md +84 -0
- cheaphelp-1.0.0/CONTRIBUTING.md +112 -0
- cheaphelp-1.0.0/LICENSE +21 -0
- cheaphelp-1.0.0/PKG-INFO +112 -0
- cheaphelp-1.0.0/README.md +82 -0
- cheaphelp-1.0.0/config/coverage.ini +25 -0
- cheaphelp-1.0.0/config/git-changelog.toml +9 -0
- cheaphelp-1.0.0/config/pytest.ini +16 -0
- cheaphelp-1.0.0/config/ruff.toml +102 -0
- cheaphelp-1.0.0/config/ty.toml +6 -0
- cheaphelp-1.0.0/config/vscode/launch.json +56 -0
- cheaphelp-1.0.0/config/vscode/settings.json +31 -0
- cheaphelp-1.0.0/config/vscode/tasks.json +97 -0
- cheaphelp-1.0.0/docs/.overrides/partials/comments.html +57 -0
- cheaphelp-1.0.0/docs/background-service.md +34 -0
- cheaphelp-1.0.0/docs/changelog.md +5 -0
- cheaphelp-1.0.0/docs/code_of_conduct.md +5 -0
- cheaphelp-1.0.0/docs/configuration.md +50 -0
- cheaphelp-1.0.0/docs/contributing.md +5 -0
- cheaphelp-1.0.0/docs/cost-tracking.md +17 -0
- cheaphelp-1.0.0/docs/credits.md +9 -0
- cheaphelp-1.0.0/docs/css/apidocs.css +21 -0
- cheaphelp-1.0.0/docs/dev-guide.md +48 -0
- cheaphelp-1.0.0/docs/getting-started.md +86 -0
- cheaphelp-1.0.0/docs/index.md +59 -0
- cheaphelp-1.0.0/docs/js/feedback.js +14 -0
- cheaphelp-1.0.0/docs/license.md +11 -0
- cheaphelp-1.0.0/docs/pipeline.md +67 -0
- cheaphelp-1.0.0/docs/reference/api.md +11 -0
- cheaphelp-1.0.0/docs/sandboxing.md +26 -0
- cheaphelp-1.0.0/docs/workspace.md +50 -0
- cheaphelp-1.0.0/duties.py +204 -0
- cheaphelp-1.0.0/pyproject.toml +109 -0
- cheaphelp-1.0.0/scripts/gen_credits.py +178 -0
- cheaphelp-1.0.0/scripts/get_version.py +31 -0
- cheaphelp-1.0.0/scripts/make +1 -0
- cheaphelp-1.0.0/scripts/make.py +227 -0
- cheaphelp-1.0.0/src/cheaphelp/__init__.py +10 -0
- cheaphelp-1.0.0/src/cheaphelp/__main__.py +14 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/__init__.py +0 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/cleanup.py +111 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/cli.py +372 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/commands.py +1025 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/config.py +326 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/conventions.py +21 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/debug.py +107 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/env.py +103 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/fixer.py +133 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/github.py +372 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/gitutil.py +216 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/lock.py +83 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/opencode.py +655 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/orchestrator.py +801 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/planner.py +187 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/pr_state.py +48 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/registry.py +147 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/responder.py +225 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/reviewer.py +322 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/rework.py +371 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/spend.py +107 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/systemd.py +302 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/tasks.py +263 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/templates/__init__.py +24 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/templates/fixer.md +50 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/templates/planner.md +64 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/templates/responder.md +154 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/templates/reviewer.md +53 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/templates/rework.md +61 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/templates/worker.md +49 -0
- cheaphelp-1.0.0/src/cheaphelp/_internal/worker.py +147 -0
- cheaphelp-1.0.0/src/cheaphelp/py.typed +0 -0
- cheaphelp-1.0.0/tests/__init__.py +7 -0
- cheaphelp-1.0.0/tests/conftest.py +242 -0
- cheaphelp-1.0.0/tests/test_api.py +163 -0
- cheaphelp-1.0.0/tests/test_cleanup.py +79 -0
- cheaphelp-1.0.0/tests/test_cli_basics.py +52 -0
- cheaphelp-1.0.0/tests/test_cli_clean.py +47 -0
- cheaphelp-1.0.0/tests/test_cli_config.py +297 -0
- cheaphelp-1.0.0/tests/test_cli_doctor.py +199 -0
- cheaphelp-1.0.0/tests/test_cli_logs.py +122 -0
- cheaphelp-1.0.0/tests/test_cli_repo.py +470 -0
- cheaphelp-1.0.0/tests/test_cli_retry.py +631 -0
- cheaphelp-1.0.0/tests/test_cli_run.py +514 -0
- cheaphelp-1.0.0/tests/test_cli_status.py +704 -0
- cheaphelp-1.0.0/tests/test_config.py +271 -0
- cheaphelp-1.0.0/tests/test_conventions.py +65 -0
- cheaphelp-1.0.0/tests/test_fixer.py +125 -0
- cheaphelp-1.0.0/tests/test_github.py +322 -0
- cheaphelp-1.0.0/tests/test_gitutil.py +85 -0
- cheaphelp-1.0.0/tests/test_opencode.py +714 -0
- cheaphelp-1.0.0/tests/test_orchestrator.py +1139 -0
- cheaphelp-1.0.0/tests/test_planner.py +238 -0
- cheaphelp-1.0.0/tests/test_responder.py +389 -0
- cheaphelp-1.0.0/tests/test_reviewer.py +384 -0
- cheaphelp-1.0.0/tests/test_rework.py +620 -0
- cheaphelp-1.0.0/tests/test_spend.py +95 -0
- cheaphelp-1.0.0/tests/test_systemd.py +515 -0
- cheaphelp-1.0.0/tests/test_tasks.py +299 -0
- cheaphelp-1.0.0/tests/test_worker.py +338 -0
- cheaphelp-1.0.0/zensical.toml +181 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
CLAUDE.md
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
6
|
+
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
<!-- insertion marker -->
|
|
9
|
+
## [1.0.0](https://github.com/jacotay7/cheaphelp/releases/tag/1.0.0) - 2026-06-14
|
|
10
|
+
|
|
11
|
+
<small>[Compare with first commit](https://github.com/jacotay7/cheaphelp/compare/4e6e0365dc8de03ebbfd97a3d418cb181608799d...1.0.0)</small>
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- `--linger` flag to enable lingering during install (#102) ([544c7d5](https://github.com/jacotay7/cheaphelp/commit/544c7d58a6f61bcba8bf9d2fe7fb6a9fe68baa15) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
16
|
+
- repair a failing quality gate with a fixer before replanning (#101) ([9210638](https://github.com/jacotay7/cheaphelp/commit/92106383bfae50347649e397dbbf66960c0063a4) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
17
|
+
- include per-issue cost breakdown in opened PR descriptions (#100) ([ada7503](https://github.com/jacotay7/cheaphelp/commit/ada7503da108be365431b35c579e97d7b4d9515b) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
18
|
+
- surface service run result in `systemd status` (#94) ([cecc993](https://github.com/jacotay7/cheaphelp/commit/cecc9930d8d5fe57ceac855b285d57834c813f39) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
19
|
+
- show today's spend vs daily budget footer (#95) ([29d8c5d](https://github.com/jacotay7/cheaphelp/commit/29d8c5df8db95c79b6b98a3855368e1d196eccbe) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
20
|
+
- persist unparseable agent output to last_unparsed_<role>.log (#93) ([4ca4aaa](https://github.com/jacotay7/cheaphelp/commit/4ca4aaa89cf12b7298f7ef153bed62c0cbbf6c16) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
21
|
+
- report systemd timer/service health in cheaphelp doctor (#92) ([f2958c2](https://github.com/jacotay7/cheaphelp/commit/f2958c248a77372561988b6cd5d3a17368d01cb2) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
22
|
+
- add daily spend budget guardrail with warn/exceeded comments (#74) ([728aaf6](https://github.com/jacotay7/cheaphelp/commit/728aaf60f61e27f18719b5a168cfdb7bad0431f5) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
23
|
+
- Label needs-human on comment; route back to responder on human reply (#73) ([3f3c493](https://github.com/jacotay7/cheaphelp/commit/3f3c49315b2a87f072edd588f986584ac07b5138) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
24
|
+
- Allow `cheaphelp run` for many ticks (`-n` / `--continuous`) (#75) ([5b52ed9](https://github.com/jacotay7/cheaphelp/commit/5b52ed9586b24c3c257982bf2cc8765ac854c2bc) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
25
|
+
- Add `cheaphelp retry` to un-stick issues labeled needs-human (#72) ([c1bead1](https://github.com/jacotay7/cheaphelp/commit/c1bead1fcabb762ee818fb1c257230af366eabe4) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
26
|
+
- Act on PR review feedback instead of leaving issues stuck in-review (#68) ([25f5f3f](https://github.com/jacotay7/cheaphelp/commit/25f5f3fdca0735b00a6c6d95f003660865670d56) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
27
|
+
- Add `cheaphelp config` subcommand (show/get/set) with auto-regen (#63) ([1d26895](https://github.com/jacotay7/cheaphelp/commit/1d26895af99eab3f8ea4af08b4ae118d140ff0bb) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>, Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
28
|
+
- track token usage and cost per tick, per role, and per issue (#64) ([e087550](https://github.com/jacotay7/cheaphelp/commit/e0875507cf49aa6fdca30315183296292e7fe6ec) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>, Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
29
|
+
- retry transient GitHub and OpenRouter failures with backoff (#62) ([2daca10](https://github.com/jacotay7/cheaphelp/commit/2daca1020f7ce4156e314d6b0927dd17d7594645) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
30
|
+
- add `cheaphelp logs` subcommand for viewing and following run activity (#61) ([f3e99a3](https://github.com/jacotay7/cheaphelp/commit/f3e99a30252320c1122909d1c90ca549947c1a86) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
31
|
+
- Blast-radius guardrail caps PR diff size (max files/lines) (#60) ([6037d91](https://github.com/jacotay7/cheaphelp/commit/6037d913867c2cb145e9928b97d0e8b98d47957a) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
32
|
+
- Let agents follow a project's own contribution conventions (#59) ([7a8e8be](https://github.com/jacotay7/cheaphelp/commit/7a8e8bed6f699d7fa755a032bcf061494f481328) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
33
|
+
- Prune build clones for closed issues; add `cheaphelp clean` (#45) ([302eec9](https://github.com/jacotay7/cheaphelp/commit/302eec9601892308fa0983f22660b8af0d2f7828) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
34
|
+
- Retry timed-out tasks; re-prompt agents that emit no decision (#44) ([17e8ab6](https://github.com/jacotay7/cheaphelp/commit/17e8ab6b7cf95f4cfccb1ec9d93ba2863fc85a67) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
35
|
+
- Hold issues until their dependencies close (#35 part 2) (#43) ([4aeb146](https://github.com/jacotay7/cheaphelp/commit/4aeb14659313a4b63ce8c2fa90226980024566e4) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
36
|
+
- Parallel ticks via per-issue locks (#35 part 1) (#42) ([0ba4a4e](https://github.com/jacotay7/cheaphelp/commit/0ba4a4ecc83cf14da46048247880464c4262fc7d) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
37
|
+
- Log each agent step as it starts; trim crash logs (#40) ([01efe1b](https://github.com/jacotay7/cheaphelp/commit/01efe1bb735bed7789245365522875dd7f6cbcd2) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
38
|
+
- Cap worker tasks run per issue per tick (max_tasks_per_tick) (#39) ([5c7b138](https://github.com/jacotay7/cheaphelp/commit/5c7b138c75ee543690ce33d39671202639dad488) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
39
|
+
- Cap issues processed per tick (--max-issues / max… (#38) ([a34dbfd](https://github.com/jacotay7/cheaphelp/commit/a34dbfd325067bb8ecbf20e72f9447cdfbd48251) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
40
|
+
- Add cheaphelp status command (#27) ([96e0cb6](https://github.com/jacotay7/cheaphelp/commit/96e0cb645b172b79d090a0327d4e92d7e76ccecc) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
41
|
+
- add workspace run-lock to serialise overlapping ticks (#25) ([bfc4778](https://github.com/jacotay7/cheaphelp/commit/bfc477837280eaa3aa82c923cc47dbfe6eff1fe2) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>, Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
42
|
+
- make opencode agent subprocess timeout configurable (#21) ([62a4e7a](https://github.com/jacotay7/cheaphelp/commit/62a4e7a81c2eb66c9bc2a7efd16bd6a50368b099) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
43
|
+
- add `cheaphelp repo set` to update checks/autofix in place (#19) ([6f66999](https://github.com/jacotay7/cheaphelp/commit/6f669994b642016ebbed484ff37a2ea665a927f7) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
44
|
+
- Prefix every GitHub message with a cheaphelp attribution header (#17) ([c001847](https://github.com/jacotay7/cheaphelp/commit/c0018477f42d4501ab3f230106da47de049e1671) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
45
|
+
- Hand the exact quality-gate commands to the worker (#12) ([a5ddec5](https://github.com/jacotay7/cheaphelp/commit/a5ddec5d42f291d998912893a24d5fa915cff2db) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
46
|
+
|
|
47
|
+
### Bug Fixes
|
|
48
|
+
|
|
49
|
+
- stop finalize replies promising a 'spec below' (#99) ([942db6e](https://github.com/jacotay7/cheaphelp/commit/942db6e1b54a8fa416d98be6198c1e89f8034a08) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
50
|
+
- balance-brace JSON extraction and retry unparseable clean exits (#98) ([1232a80](https://github.com/jacotay7/cheaphelp/commit/1232a805d58d6f22d254535f1cc0eca1572b541f) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
51
|
+
- Drop stale bot_login args from responder test call sites (#69) ([e9be0c0](https://github.com/jacotay7/cheaphelp/commit/e9be0c0f76105340d90af285821b9b5432cee62c) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
52
|
+
- Identify bot comments by marker only, not by author login (#67) ([e554d7b](https://github.com/jacotay7/cheaphelp/commit/e554d7bf5f43f0727ceb27fcd2705e43073534cc) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
53
|
+
- Route push failures to needs-human; require workflow PAT scope (#65) ([587b8d5](https://github.com/jacotay7/cheaphelp/commit/587b8d598ae80aeb1dd1e2db3ac3241c727d2ee1) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
54
|
+
- Re-validate issue state under its lock so overlapping ticks don't double-act (#58) ([24c279e](https://github.com/jacotay7/cheaphelp/commit/24c279e0ce4888f050b52a792ab34b17cd14aa1e) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
55
|
+
- distinguish `repo set` no-op from real update (#34) ([264cd6c](https://github.com/jacotay7/cheaphelp/commit/264cd6c8243821527ad208a64bb0982b9157e5f7) by Jacob Taylor). Co-authored-by: cheaphelp[bot] <cheaphelp@users.noreply.github.com>
|
|
56
|
+
- Keep the spec at requirements altitude, ask only material questions (#14) ([04a9010](https://github.com/jacotay7/cheaphelp/commit/04a9010a347e90c536bf4b8670b73cd2dcc35de5) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
57
|
+
|
|
58
|
+
### Code Refactoring
|
|
59
|
+
|
|
60
|
+
- Don't run the full quality gate after every task (#29) ([cf0de8e](https://github.com/jacotay7/cheaphelp/commit/cf0de8e5a3c658ee9b9987ffb6c52217ce11b340) by Jacob Taylor). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI agents working in this repository.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
|
|
7
|
+
`cheaphelp` is an AI software-engineer for GitHub repos. It installs as a
|
|
8
|
+
background service (systemd timer), watches registered repos, and runs a team of
|
|
9
|
+
narrow agents — via the **opencode** harness against cheap **OpenRouter** models
|
|
10
|
+
— to triage issues, plan, implement, and open PRs for human review.
|
|
11
|
+
|
|
12
|
+
The pipeline is a label-driven state machine. Each tick polls open issues and
|
|
13
|
+
dispatches by label:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
(no pipeline label) + human spoke last -> responder refine scope -> issues.md, label :ready
|
|
17
|
+
:ready / :needs-replan -> planner issues.md -> tasks, label :planned
|
|
18
|
+
:planned, tasks pending -> worker implement one task on the issue branch
|
|
19
|
+
:planned, all tasks done -> quality gate -> reviewer open PR (label :in-review) or replan
|
|
20
|
+
(gate fails -> fixer repairs + re-runs gate before replanning)
|
|
21
|
+
:in-review -> rework address new PR review feedback, or no-op
|
|
22
|
+
:needs-human, human replied -> responder re-engage a stuck issue
|
|
23
|
+
:needs-human, no new reply / :rejected -> (idle)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
A daily USD spend cap (`daily_budget_usd`, `spend.py`) can halt new agent turns
|
|
27
|
+
for the rest of the UTC day; see `orchestrator.tick` budget handling.
|
|
28
|
+
|
|
29
|
+
## Workflow (IMPORTANT: branch protection)
|
|
30
|
+
|
|
31
|
+
`main` is protected. **Never commit or push to `main` directly.** All changes
|
|
32
|
+
land through a pull request:
|
|
33
|
+
|
|
34
|
+
1. Branch off `main`: `git switch -c <type>-<short-name>` (e.g. `feat-json-output`).
|
|
35
|
+
2. Make the change with tests.
|
|
36
|
+
3. `make format && make check && make test` (all must pass).
|
|
37
|
+
4. Commit (see convention below), push the branch, open a PR.
|
|
38
|
+
|
|
39
|
+
## Dev commands
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
make setup # install deps (uv sync)
|
|
43
|
+
make format # auto-format (ruff format + ruff --fix)
|
|
44
|
+
make check # lint + types + docs + api checks
|
|
45
|
+
make test # pytest
|
|
46
|
+
make run cheaphelp [ARGS...] # run the CLI
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Direct equivalents (no direnv):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uv run ruff check src tests duties.py scripts --config config/ruff.toml
|
|
53
|
+
uv run ruff format src tests duties.py scripts --config config/ruff.toml
|
|
54
|
+
uv run python -m pytest -q
|
|
55
|
+
uv run cheaphelp <subcommand>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Lint is `ruff` with `select = ["ALL"]` (config in `config/ruff.toml`); it is
|
|
59
|
+
strict (e.g. COM812 trailing commas, ANN annotations, D docstrings). Run
|
|
60
|
+
`make format` before `make check`. Python target is 3.10+.
|
|
61
|
+
|
|
62
|
+
## Layout
|
|
63
|
+
|
|
64
|
+
All product code is under `src/cheaphelp/_internal/`:
|
|
65
|
+
|
|
66
|
+
| Module | Responsibility |
|
|
67
|
+
|--------|----------------|
|
|
68
|
+
| `config.py` | `Workspace` paths + `config.json` (`Config`) |
|
|
69
|
+
| `env.py` | `.env` secret parsing/writing (chmod 600) |
|
|
70
|
+
| `github.py` | minimal GitHub REST client (httpx) |
|
|
71
|
+
| `registry.py` | registered-repo store (`repos.json`) |
|
|
72
|
+
| `gitutil.py` | clones, commit, push, diff helpers |
|
|
73
|
+
| `lock.py` | per-repo file locks so concurrent ticks don't collide |
|
|
74
|
+
| `spend.py` | daily USD spend tracker for the budget guardrail |
|
|
75
|
+
| `conventions.py` | reads `CHEAPHELP.md`/`AGENTS.md`/`CONTRIBUTING.md` into agent context |
|
|
76
|
+
| `pr_state.py` | persists PR <-> issue link state for the rework stage |
|
|
77
|
+
| `opencode.py` | generate `opencode.json`, run agents headlessly, parse decisions |
|
|
78
|
+
| `templates/*.md` | bundled agent prompts (responder/planner/worker/reviewer/rework/fixer) |
|
|
79
|
+
| `tasks.py` | task manifest + per-issue task-state store |
|
|
80
|
+
| `responder.py` / `planner.py` / `worker.py` / `reviewer.py` / `rework.py` / `fixer.py` | per-role turn logic |
|
|
81
|
+
| `orchestrator.py` | one tick of the state machine (`tick()`, `classify()`, stage dispatch) |
|
|
82
|
+
| `cleanup.py` | prune build clones for closed issues / unregistered repos (keeps state) |
|
|
83
|
+
| `systemd.py` | user service + timer install (continuous-mode by default) |
|
|
84
|
+
| `commands.py` / `cli.py` | argparse CLI (`cmd_*` per subcommand) |
|
|
85
|
+
|
|
86
|
+
Tests live in `tests/`, one file per `src/cheaphelp/_internal/` module (plus
|
|
87
|
+
`test_cli_*.py` per CLI subcommand and `test_api.py`); shared fixtures in
|
|
88
|
+
`tests/conftest.py`.
|
|
89
|
+
|
|
90
|
+
## Key conventions & invariants
|
|
91
|
+
|
|
92
|
+
- **Agents communicate via a single final ```json block.** Each role parses the
|
|
93
|
+
last fenced JSON block from agent output (`opencode.extract_decision`). If you
|
|
94
|
+
change a role's output contract, update both its prompt in `templates/<role>.md`
|
|
95
|
+
and the parser/`apply_*` logic in the matching module.
|
|
96
|
+
- **Workspace is the source of truth at runtime**, default `~/.cheaphelp`
|
|
97
|
+
(override `CHEAPHELP_HOME`): `config.json`, `.env`, `repos.json`, `agents/`
|
|
98
|
+
(editable prompt overrides), `opencode/opencode.json` (generated),
|
|
99
|
+
`state/<owner>__<repo>/issue-<n>/` (issues.md, plan.md, tasks.json, tasks/,
|
|
100
|
+
cost.json, pr_state.json), `state/daily_spend.json`, `clones/`, `logs/`.
|
|
101
|
+
After editing models/prompts/sandbox, regenerate with `cheaphelp agents sync`.
|
|
102
|
+
- **`tasks.json` is authoritative; the `.md` files are readable mirrors.** Use
|
|
103
|
+
`TaskStore` for all task state transitions.
|
|
104
|
+
- **cheaphelp owns git remotes**: workers/reviewer never push; the orchestrator
|
|
105
|
+
does (`gitutil.push_branch`). Agent bash is sandboxed (see `opencode.py`
|
|
106
|
+
`_READER_BASH` / `_WORKER_BASH`); only `worker` may edit files.
|
|
107
|
+
- **Defaults live in `config.py`** (`DEFAULT_MODELS`, `DEFAULT_LABELS`,
|
|
108
|
+
`DEFAULT_VARIANTS`, `DEFAULT_SANDBOX`). `Config.from_dict` merges over them, so
|
|
109
|
+
new keys must be added to the defaults *and* `from_dict`/`to_dict`.
|
|
110
|
+
- **Network isolation in tests**: never make real network/API calls; mock the
|
|
111
|
+
GitHub client and the agent layer. Set `CHEAPHELP_AGENT_MOCK=/path/to/decision.json`
|
|
112
|
+
to make `run_agent` return canned output instead of invoking opencode.
|
|
113
|
+
- **Fake GitHub clients**: use `tests.conftest.FakeGitHubClient` (a real
|
|
114
|
+
`GitHubClient` subclass) instead of writing a new ad-hoc duck-typed class —
|
|
115
|
+
ad-hoc fakes don't satisfy `ty`'s `GitHubClient` parameter types and need
|
|
116
|
+
`# ty: ignore[invalid-argument-type]` on every call. Seed `.issues`,
|
|
117
|
+
`.comments`, `.labels`, etc. and build payloads with `make_issue`/
|
|
118
|
+
`make_comment`/`make_pr_state`, also in `tests/conftest.py`.
|
|
119
|
+
- **Per-issue failures must not abort a tick** — `_process_repo` guards each
|
|
120
|
+
stage; preserve that resilience.
|
|
121
|
+
|
|
122
|
+
## Commit messages
|
|
123
|
+
|
|
124
|
+
Angular/Karma convention: `<type>[(scope)]: Subject` (capitalized, no trailing
|
|
125
|
+
period). Types: `build`, `chore`, `ci`, `deps`, `docs`, `feat`, `fix`, `perf`,
|
|
126
|
+
`refactor`, `style`, `tests`. Don't update `CHANGELOG.md` (generated). Link the
|
|
127
|
+
related issue in the PR body (`Closes #<n>`).
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
|
|
6
|
+
|
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
|
8
|
+
|
|
9
|
+
## Our Standards
|
|
10
|
+
|
|
11
|
+
Examples of behavior that contributes to a positive environment for our community include:
|
|
12
|
+
|
|
13
|
+
* Demonstrating empathy and kindness toward other people
|
|
14
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
15
|
+
* Giving and gracefully accepting constructive feedback
|
|
16
|
+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
|
17
|
+
* Focusing on what is best not just for us as individuals, but for the overall community
|
|
18
|
+
|
|
19
|
+
Examples of unacceptable behavior include:
|
|
20
|
+
|
|
21
|
+
* The use of sexualized language or imagery, and sexual attention or advances of any kind
|
|
22
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
23
|
+
* Public or private harassment
|
|
24
|
+
* Publishing others' private information, such as a physical or email address, without their explicit permission
|
|
25
|
+
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
|
26
|
+
|
|
27
|
+
## Enforcement Responsibilities
|
|
28
|
+
|
|
29
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
|
30
|
+
|
|
31
|
+
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
|
32
|
+
|
|
33
|
+
## Scope
|
|
34
|
+
|
|
35
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
|
36
|
+
|
|
37
|
+
## Enforcement
|
|
38
|
+
|
|
39
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at jacobataylor7@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
|
|
40
|
+
|
|
41
|
+
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
|
42
|
+
|
|
43
|
+
## Enforcement Guidelines
|
|
44
|
+
|
|
45
|
+
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
|
46
|
+
|
|
47
|
+
### 1. Correction
|
|
48
|
+
|
|
49
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
|
50
|
+
|
|
51
|
+
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
|
52
|
+
|
|
53
|
+
### 2. Warning
|
|
54
|
+
|
|
55
|
+
**Community Impact**: A violation through a single incident or series of actions.
|
|
56
|
+
|
|
57
|
+
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
|
58
|
+
|
|
59
|
+
### 3. Temporary Ban
|
|
60
|
+
|
|
61
|
+
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
|
62
|
+
|
|
63
|
+
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
|
64
|
+
|
|
65
|
+
### 4. Permanent Ban
|
|
66
|
+
|
|
67
|
+
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
|
68
|
+
|
|
69
|
+
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
|
70
|
+
|
|
71
|
+
## Attribution
|
|
72
|
+
|
|
73
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
|
74
|
+
|
|
75
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
|
76
|
+
|
|
77
|
+
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
|
|
78
|
+
|
|
79
|
+
[homepage]: https://www.contributor-covenant.org
|
|
80
|
+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
81
|
+
[Mozilla CoC]: https://github.com/mozilla/diversity
|
|
82
|
+
[FAQ]: https://www.contributor-covenant.org/faq
|
|
83
|
+
[translations]: https://www.contributor-covenant.org/translations
|
|
84
|
+
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Contributions are welcome, and they are greatly appreciated. Every little bit helps, and credit will always be given.
|
|
4
|
+
|
|
5
|
+
**Please always create an issue before working on a new feature or a bug fix, so that we can discuss the implementation and make sure that your work will be merged.**
|
|
6
|
+
|
|
7
|
+
## Environment setup
|
|
8
|
+
|
|
9
|
+
Install [uv](https://github.com/astral-sh/uv) and [direnv](https://direnv.net/), fork and clone the repository, then:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
cd cheaphelp
|
|
13
|
+
direnv allow
|
|
14
|
+
make setup
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
You now have the dependencies installed.
|
|
18
|
+
|
|
19
|
+
You can run the application with `make run cheaphelp [ARGS...]`.
|
|
20
|
+
|
|
21
|
+
Run `make help` to see all the available actions!
|
|
22
|
+
|
|
23
|
+
## Tasks
|
|
24
|
+
|
|
25
|
+
The entry-point to run commands and tasks is the `make` Python script, located in the `scripts` directory. Try running `make` to show the available commands and tasks. The *commands* do not need the Python dependencies to be installed, while the *tasks* do. The cross-platform tasks are written in Python, thanks to [duty](https://github.com/pawamoy/duty).
|
|
26
|
+
|
|
27
|
+
If you work in VSCode, we provide [an action to configure VSCode](https://pawamoy.github.io/copier-uv/work/#vscode-setup) for the project.
|
|
28
|
+
|
|
29
|
+
## Development
|
|
30
|
+
|
|
31
|
+
As usual:
|
|
32
|
+
|
|
33
|
+
1. create a new branch: `git switch -c feature-or-bugfix-name`
|
|
34
|
+
1. edit the code and/or the documentation
|
|
35
|
+
|
|
36
|
+
**Before committing:**
|
|
37
|
+
|
|
38
|
+
1. run `make format` to auto-format the code
|
|
39
|
+
1. run `make check` to check everything (fix any warning)
|
|
40
|
+
1. run `make test` to run the tests (fix any issue)
|
|
41
|
+
1. if you updated the documentation or the project dependencies:
|
|
42
|
+
1. run `make docs`
|
|
43
|
+
1. go to http://localhost:8000 and check that everything looks good
|
|
44
|
+
1. follow our [commit message convention](#commit-message-convention)
|
|
45
|
+
|
|
46
|
+
If you are unsure about how to fix or ignore a warning, just let the continuous integration fail, and we will help you during review.
|
|
47
|
+
|
|
48
|
+
Don't bother updating the changelog, we will take care of this.
|
|
49
|
+
|
|
50
|
+
## Commit message convention
|
|
51
|
+
|
|
52
|
+
Commit messages must follow our convention based on the [Angular style](https://gist.github.com/stephenparish/9941e89d80e2bc58a153#format-of-the-commit-message) or the [Karma convention](https://karma-runner.github.io/4.0/dev/git-commit-msg.html):
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
<type>[(scope)]: Subject
|
|
56
|
+
|
|
57
|
+
[Body]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Subject and body must be valid Markdown.** Subject must have proper casing (uppercase for first letter if it makes sense), but no dot at the end, and no punctuation in general.
|
|
61
|
+
|
|
62
|
+
Scope and body are optional. Type can be:
|
|
63
|
+
|
|
64
|
+
- `build`: About packaging, building wheels, etc.
|
|
65
|
+
- `chore`: About packaging or repo/files management.
|
|
66
|
+
- `ci`: About Continuous Integration.
|
|
67
|
+
- `deps`: Dependencies update.
|
|
68
|
+
- `docs`: About documentation.
|
|
69
|
+
- `feat`: New feature.
|
|
70
|
+
- `fix`: Bug fix.
|
|
71
|
+
- `perf`: About performance.
|
|
72
|
+
- `refactor`: Changes that are not features or bug fixes.
|
|
73
|
+
- `style`: A change in code style/format.
|
|
74
|
+
- `tests`: About tests.
|
|
75
|
+
|
|
76
|
+
If you write a body, please add trailers at the end (for example issues and PR references, or co-authors), without relying on GitHub's flavored Markdown:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
Body.
|
|
80
|
+
|
|
81
|
+
Issue #10: https://github.com/namespace/project/issues/10
|
|
82
|
+
Related to PR namespace/other-project#15: https://github.com/namespace/other-project/pull/15
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
These "trailers" must appear at the end of the body, without any blank lines between them. The trailer title can contain any character except colons `:`. We expect a full URI for each trailer, not just GitHub autolinks (for example, full GitHub URLs for commits and issues, not the hash or the #issue-number).
|
|
86
|
+
|
|
87
|
+
We do not enforce a line length on commit messages summary and body, but please avoid very long summaries, and very long lines in the body, unless they are part of code blocks that must not be wrapped.
|
|
88
|
+
|
|
89
|
+
## Pull requests guidelines
|
|
90
|
+
|
|
91
|
+
Link to any related issue in the Pull Request message.
|
|
92
|
+
|
|
93
|
+
During the review, we recommend using fixups:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# SHA is the SHA of the commit you want to fix
|
|
97
|
+
git commit --fixup=SHA
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Once all the changes are approved, you can squash your commits:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
git rebase -i --autosquash main
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
And force-push:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git push -f
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
If this seems all too complicated, you can push or force-push each new commit, and we will squash them ourselves if needed, before merging.
|
cheaphelp-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jacob Taylor
|
|
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.
|
cheaphelp-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cheaphelp
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: An AI software-engineer that triages GitHub issues, plans, implements, and reviews changes on your repos using cheap OpenRouter models via the opencode harness.
|
|
5
|
+
Author-Email: Jacob Taylor <jacobataylor7@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Documentation
|
|
19
|
+
Classifier: Topic :: Software Development
|
|
20
|
+
Classifier: Topic :: Utilities
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Project-URL: Homepage, https://jacotay7.github.io/cheaphelp
|
|
23
|
+
Project-URL: Documentation, https://jacotay7.github.io/cheaphelp
|
|
24
|
+
Project-URL: Changelog, https://jacotay7.github.io/cheaphelp/changelog
|
|
25
|
+
Project-URL: Repository, https://github.com/jacotay7/cheaphelp
|
|
26
|
+
Project-URL: Issues, https://github.com/jacotay7/cheaphelp/issues
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: httpx>=0.27
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# cheaphelp
|
|
32
|
+
|
|
33
|
+
[](https://github.com/jacotay7/cheaphelp/actions/workflows/ci.yml)
|
|
34
|
+
[](https://jacotay7.github.io/cheaphelp/)
|
|
35
|
+
|
|
36
|
+
An AI software-engineer for your GitHub repositories. cheaphelp installs as a
|
|
37
|
+
background service on your machine, watches the repos you register, and runs a
|
|
38
|
+
team of narrow AI agents — powered by **cheap [OpenRouter](https://openrouter.ai)
|
|
39
|
+
models** through the **[opencode](https://opencode.ai)** terminal harness — to
|
|
40
|
+
triage issues, plan work, implement it, and open pull requests for human review.
|
|
41
|
+
|
|
42
|
+
> **Status: full pipeline wired and exercised live.** All roles run end-to-end
|
|
43
|
+
> against a real repository; expect to keep tuning prompts and hardening edge
|
|
44
|
+
> cases.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
The recommended way to install the `cheaphelp` CLI on your machine:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pipx install cheaphelp
|
|
52
|
+
# or, if you don't use pipx:
|
|
53
|
+
pip install --user cheaphelp
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For development (running from a clone, contributing, or testing unreleased
|
|
57
|
+
changes), use `uv sync` inside the clone and invoke the CLI as
|
|
58
|
+
`uv run cheaphelp …` — see [Quick start](#quick-start) step 1.
|
|
59
|
+
|
|
60
|
+
## Quick start
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# 1. (Development install — end users should `pipx install cheaphelp`, see
|
|
64
|
+
# the Install section above.) Clone, sync deps, and install the
|
|
65
|
+
# `cheaphelp` command globally.
|
|
66
|
+
git clone https://github.com/jacotay7/cheaphelp.git
|
|
67
|
+
cd cheaphelp
|
|
68
|
+
uv sync # install deps (needed before tool install)
|
|
69
|
+
uv tool install --from . cheaphelp # puts `cheaphelp` on $PATH
|
|
70
|
+
|
|
71
|
+
# 2. Create your machine-local workspace (~/.cheaphelp) and store secrets.
|
|
72
|
+
# Prompts for your tokens, or pass them as flags / set them later.
|
|
73
|
+
cheaphelp init
|
|
74
|
+
|
|
75
|
+
# 3. Check everything is wired up.
|
|
76
|
+
cheaphelp doctor
|
|
77
|
+
|
|
78
|
+
# 4. Register a repo to work on.
|
|
79
|
+
cheaphelp repo add owner/name
|
|
80
|
+
cheaphelp repo list
|
|
81
|
+
|
|
82
|
+
# 5. Dry-run one tick (shows what it *would* do, no changes).
|
|
83
|
+
cheaphelp run --dry-run
|
|
84
|
+
|
|
85
|
+
# 6. Run it for real (responder engages open issues).
|
|
86
|
+
cheaphelp run
|
|
87
|
+
|
|
88
|
+
# 7. Or drain the whole backlog now: repeat ticks until one is idle.
|
|
89
|
+
cheaphelp run --continuous
|
|
90
|
+
|
|
91
|
+
# 8. Install the background timer (default every 10 minutes; each firing
|
|
92
|
+
# runs `cheaphelp run --continuous` by default, see the docs).
|
|
93
|
+
cheaphelp systemd install --interval 10m
|
|
94
|
+
cheaphelp systemd status
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> **Upgrading.** After pulling new code, re-run `uv tool install --from . --reinstall cheaphelp` to refresh the global command. A plain `git pull` updates the source tree but does NOT refresh the installed binary, and `uv run cheaphelp` would then diverge from your checkout.
|
|
98
|
+
|
|
99
|
+
## Documentation
|
|
100
|
+
|
|
101
|
+
- [Getting started](docs/getting-started.md) — install, requirements, running modes
|
|
102
|
+
- [Pipeline](docs/pipeline.md) — how the agents collaborate and the quality gate
|
|
103
|
+
- [Configuration](docs/configuration.md) — `config.json` fields, models, budget knobs
|
|
104
|
+
- [Workspace](docs/workspace.md) — files cheaphelp writes to disk
|
|
105
|
+
- [Sandboxing](docs/sandboxing.md) — how agents are isolated and its limits
|
|
106
|
+
- [Cost tracking](docs/cost-tracking.md) — daily budget and per-issue cost reporting
|
|
107
|
+
- [Background service](docs/background-service.md) — running under the systemd timer
|
|
108
|
+
- [Dev guide](docs/dev-guide.md) — for contributors (testing, source layout, mocking opencode)
|
|
109
|
+
|
|
110
|
+
## For contributors
|
|
111
|
+
|
|
112
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) and the [Dev guide](docs/dev-guide.md).
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# cheaphelp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/jacotay7/cheaphelp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://jacotay7.github.io/cheaphelp/)
|
|
5
|
+
|
|
6
|
+
An AI software-engineer for your GitHub repositories. cheaphelp installs as a
|
|
7
|
+
background service on your machine, watches the repos you register, and runs a
|
|
8
|
+
team of narrow AI agents — powered by **cheap [OpenRouter](https://openrouter.ai)
|
|
9
|
+
models** through the **[opencode](https://opencode.ai)** terminal harness — to
|
|
10
|
+
triage issues, plan work, implement it, and open pull requests for human review.
|
|
11
|
+
|
|
12
|
+
> **Status: full pipeline wired and exercised live.** All roles run end-to-end
|
|
13
|
+
> against a real repository; expect to keep tuning prompts and hardening edge
|
|
14
|
+
> cases.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
The recommended way to install the `cheaphelp` CLI on your machine:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pipx install cheaphelp
|
|
22
|
+
# or, if you don't use pipx:
|
|
23
|
+
pip install --user cheaphelp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For development (running from a clone, contributing, or testing unreleased
|
|
27
|
+
changes), use `uv sync` inside the clone and invoke the CLI as
|
|
28
|
+
`uv run cheaphelp …` — see [Quick start](#quick-start) step 1.
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# 1. (Development install — end users should `pipx install cheaphelp`, see
|
|
34
|
+
# the Install section above.) Clone, sync deps, and install the
|
|
35
|
+
# `cheaphelp` command globally.
|
|
36
|
+
git clone https://github.com/jacotay7/cheaphelp.git
|
|
37
|
+
cd cheaphelp
|
|
38
|
+
uv sync # install deps (needed before tool install)
|
|
39
|
+
uv tool install --from . cheaphelp # puts `cheaphelp` on $PATH
|
|
40
|
+
|
|
41
|
+
# 2. Create your machine-local workspace (~/.cheaphelp) and store secrets.
|
|
42
|
+
# Prompts for your tokens, or pass them as flags / set them later.
|
|
43
|
+
cheaphelp init
|
|
44
|
+
|
|
45
|
+
# 3. Check everything is wired up.
|
|
46
|
+
cheaphelp doctor
|
|
47
|
+
|
|
48
|
+
# 4. Register a repo to work on.
|
|
49
|
+
cheaphelp repo add owner/name
|
|
50
|
+
cheaphelp repo list
|
|
51
|
+
|
|
52
|
+
# 5. Dry-run one tick (shows what it *would* do, no changes).
|
|
53
|
+
cheaphelp run --dry-run
|
|
54
|
+
|
|
55
|
+
# 6. Run it for real (responder engages open issues).
|
|
56
|
+
cheaphelp run
|
|
57
|
+
|
|
58
|
+
# 7. Or drain the whole backlog now: repeat ticks until one is idle.
|
|
59
|
+
cheaphelp run --continuous
|
|
60
|
+
|
|
61
|
+
# 8. Install the background timer (default every 10 minutes; each firing
|
|
62
|
+
# runs `cheaphelp run --continuous` by default, see the docs).
|
|
63
|
+
cheaphelp systemd install --interval 10m
|
|
64
|
+
cheaphelp systemd status
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
> **Upgrading.** After pulling new code, re-run `uv tool install --from . --reinstall cheaphelp` to refresh the global command. A plain `git pull` updates the source tree but does NOT refresh the installed binary, and `uv run cheaphelp` would then diverge from your checkout.
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
- [Getting started](docs/getting-started.md) — install, requirements, running modes
|
|
72
|
+
- [Pipeline](docs/pipeline.md) — how the agents collaborate and the quality gate
|
|
73
|
+
- [Configuration](docs/configuration.md) — `config.json` fields, models, budget knobs
|
|
74
|
+
- [Workspace](docs/workspace.md) — files cheaphelp writes to disk
|
|
75
|
+
- [Sandboxing](docs/sandboxing.md) — how agents are isolated and its limits
|
|
76
|
+
- [Cost tracking](docs/cost-tracking.md) — daily budget and per-issue cost reporting
|
|
77
|
+
- [Background service](docs/background-service.md) — running under the systemd timer
|
|
78
|
+
- [Dev guide](docs/dev-guide.md) — for contributors (testing, source layout, mocking opencode)
|
|
79
|
+
|
|
80
|
+
## For contributors
|
|
81
|
+
|
|
82
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) and the [Dev guide](docs/dev-guide.md).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[coverage:run]
|
|
2
|
+
branch = true
|
|
3
|
+
parallel = true
|
|
4
|
+
source =
|
|
5
|
+
src/
|
|
6
|
+
tests/
|
|
7
|
+
|
|
8
|
+
[coverage:paths]
|
|
9
|
+
equivalent =
|
|
10
|
+
src/
|
|
11
|
+
.venv/lib/*/site-packages/
|
|
12
|
+
.venvs/*/lib/*/site-packages/
|
|
13
|
+
|
|
14
|
+
[coverage:report]
|
|
15
|
+
precision = 2
|
|
16
|
+
omit =
|
|
17
|
+
src/*/__init__.py
|
|
18
|
+
src/*/__main__.py
|
|
19
|
+
tests/__init__.py
|
|
20
|
+
exclude_lines =
|
|
21
|
+
pragma: no cover
|
|
22
|
+
if TYPE_CHECKING
|
|
23
|
+
|
|
24
|
+
[coverage:json]
|
|
25
|
+
output = htmlcov/coverage.json
|