dev-autopilot 0.4.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 (146) hide show
  1. dev_autopilot-0.4.0/LICENSE +21 -0
  2. dev_autopilot-0.4.0/PKG-INFO +148 -0
  3. dev_autopilot-0.4.0/README.md +121 -0
  4. dev_autopilot-0.4.0/autopilot/__init__.py +4 -0
  5. dev_autopilot-0.4.0/autopilot/__main__.py +6 -0
  6. dev_autopilot-0.4.0/autopilot/backends/__init__.py +159 -0
  7. dev_autopilot-0.4.0/autopilot/backends/claude_cli.py +368 -0
  8. dev_autopilot-0.4.0/autopilot/backends/command.py +90 -0
  9. dev_autopilot-0.4.0/autopilot/cli.py +1614 -0
  10. dev_autopilot-0.4.0/autopilot/commands/__init__.py +0 -0
  11. dev_autopilot-0.4.0/autopilot/commands/preflight.py +131 -0
  12. dev_autopilot-0.4.0/autopilot/config.py +155 -0
  13. dev_autopilot-0.4.0/autopilot/context.py +414 -0
  14. dev_autopilot-0.4.0/autopilot/dash_term.py +493 -0
  15. dev_autopilot-0.4.0/autopilot/dash_web.py +347 -0
  16. dev_autopilot-0.4.0/autopilot/dashboard.py +410 -0
  17. dev_autopilot-0.4.0/autopilot/decisions.py +85 -0
  18. dev_autopilot-0.4.0/autopilot/deploy.py +67 -0
  19. dev_autopilot-0.4.0/autopilot/docs.py +301 -0
  20. dev_autopilot-0.4.0/autopilot/doctor.py +478 -0
  21. dev_autopilot-0.4.0/autopilot/gate.py +383 -0
  22. dev_autopilot-0.4.0/autopilot/github_util.py +42 -0
  23. dev_autopilot-0.4.0/autopilot/gitops.py +251 -0
  24. dev_autopilot-0.4.0/autopilot/growth.py +85 -0
  25. dev_autopilot-0.4.0/autopilot/handoff.py +27 -0
  26. dev_autopilot-0.4.0/autopilot/layers.py +134 -0
  27. dev_autopilot-0.4.0/autopilot/log_scrub.py +11 -0
  28. dev_autopilot-0.4.0/autopilot/mcp.py +104 -0
  29. dev_autopilot-0.4.0/autopilot/notify.py +98 -0
  30. dev_autopilot-0.4.0/autopilot/orchestrator.py +2214 -0
  31. dev_autopilot-0.4.0/autopilot/plain.py +238 -0
  32. dev_autopilot-0.4.0/autopilot/plan.py +320 -0
  33. dev_autopilot-0.4.0/autopilot/proc.py +176 -0
  34. dev_autopilot-0.4.0/autopilot/prompts/auditor.md +39 -0
  35. dev_autopilot-0.4.0/autopilot/prompts/decide.md +38 -0
  36. dev_autopilot-0.4.0/autopilot/prompts/docs.md +48 -0
  37. dev_autopilot-0.4.0/autopilot/prompts/fixer.md +26 -0
  38. dev_autopilot-0.4.0/autopilot/prompts/onboard.md +43 -0
  39. dev_autopilot-0.4.0/autopilot/prompts/plan_writer.md +40 -0
  40. dev_autopilot-0.4.0/autopilot/prompts/replanner.md +42 -0
  41. dev_autopilot-0.4.0/autopilot/prompts/research.md +25 -0
  42. dev_autopilot-0.4.0/autopilot/prompts/resume.md +10 -0
  43. dev_autopilot-0.4.0/autopilot/prompts/retry.md +8 -0
  44. dev_autopilot-0.4.0/autopilot/prompts/review.md +40 -0
  45. dev_autopilot-0.4.0/autopilot/prompts/system.md +16 -0
  46. dev_autopilot-0.4.0/autopilot/prompts/task.md +78 -0
  47. dev_autopilot-0.4.0/autopilot/prompts/triage.md +30 -0
  48. dev_autopilot-0.4.0/autopilot/prompts/unstick.md +37 -0
  49. dev_autopilot-0.4.0/autopilot/prompts/verify.md +32 -0
  50. dev_autopilot-0.4.0/autopilot/repomap.py +71 -0
  51. dev_autopilot-0.4.0/autopilot/report.py +633 -0
  52. dev_autopilot-0.4.0/autopilot/rights.py +184 -0
  53. dev_autopilot-0.4.0/autopilot/schemas.py +42 -0
  54. dev_autopilot-0.4.0/autopilot/state.py +298 -0
  55. dev_autopilot-0.4.0/autopilot/templates/__pycache__/cloudflare_apply.cpython-313.pyc +0 -0
  56. dev_autopilot-0.4.0/autopilot/templates/agent/BRAIN.md +21 -0
  57. dev_autopilot-0.4.0/autopilot/templates/agent/CLAUDE.md.snippet +10 -0
  58. dev_autopilot-0.4.0/autopilot/templates/agent/DECISIONS.md +5 -0
  59. dev_autopilot-0.4.0/autopilot/templates/agent/HANDOFF.md +3 -0
  60. dev_autopilot-0.4.0/autopilot/templates/agent/gitignore +10 -0
  61. dev_autopilot-0.4.0/autopilot/templates/agent/ide_rules.md +8 -0
  62. dev_autopilot-0.4.0/autopilot/templates/agent/plan.yaml +48 -0
  63. dev_autopilot-0.4.0/autopilot/templates/agent/project.yaml +259 -0
  64. dev_autopilot-0.4.0/autopilot/templates/cloudflare_apply.py +211 -0
  65. dev_autopilot-0.4.0/autopilot/templates/deploy.sh +72 -0
  66. dev_autopilot-0.4.0/autopilot/templates/email_verify.py +144 -0
  67. dev_autopilot-0.4.0/autopilot/templates/infra/cloudflare.yaml +11 -0
  68. dev_autopilot-0.4.0/autopilot/templates/presets/docker.yaml +4 -0
  69. dev_autopilot-0.4.0/autopilot/templates/presets/generic.yaml +3 -0
  70. dev_autopilot-0.4.0/autopilot/templates/presets/go.yaml +6 -0
  71. dev_autopilot-0.4.0/autopilot/templates/presets/java.yaml +4 -0
  72. dev_autopilot-0.4.0/autopilot/templates/presets/node.yaml +7 -0
  73. dev_autopilot-0.4.0/autopilot/templates/presets/python.yaml +6 -0
  74. dev_autopilot-0.4.0/autopilot/templates/presets/rust.yaml +5 -0
  75. dev_autopilot-0.4.0/autopilot/templates/presets/static.yaml +3 -0
  76. dev_autopilot-0.4.0/autopilot/upgrade.py +192 -0
  77. dev_autopilot-0.4.0/dev_autopilot.egg-info/PKG-INFO +148 -0
  78. dev_autopilot-0.4.0/dev_autopilot.egg-info/SOURCES.txt +144 -0
  79. dev_autopilot-0.4.0/dev_autopilot.egg-info/dependency_links.txt +1 -0
  80. dev_autopilot-0.4.0/dev_autopilot.egg-info/entry_points.txt +3 -0
  81. dev_autopilot-0.4.0/dev_autopilot.egg-info/requires.txt +7 -0
  82. dev_autopilot-0.4.0/dev_autopilot.egg-info/top_level.txt +1 -0
  83. dev_autopilot-0.4.0/pyproject.toml +45 -0
  84. dev_autopilot-0.4.0/setup.cfg +4 -0
  85. dev_autopilot-0.4.0/tests/test_adopt.py +221 -0
  86. dev_autopilot-0.4.0/tests/test_autofix.py +119 -0
  87. dev_autopilot-0.4.0/tests/test_autopilot.py +353 -0
  88. dev_autopilot-0.4.0/tests/test_backend.py +169 -0
  89. dev_autopilot-0.4.0/tests/test_cache.py +48 -0
  90. dev_autopilot-0.4.0/tests/test_chat.py +167 -0
  91. dev_autopilot-0.4.0/tests/test_conflicts.py +42 -0
  92. dev_autopilot-0.4.0/tests/test_consolidate.py +53 -0
  93. dev_autopilot-0.4.0/tests/test_dash_term.py +564 -0
  94. dev_autopilot-0.4.0/tests/test_dash_web.py +175 -0
  95. dev_autopilot-0.4.0/tests/test_dashboard.py +124 -0
  96. dev_autopilot-0.4.0/tests/test_dashboard_rows.py +82 -0
  97. dev_autopilot-0.4.0/tests/test_dashboard_time.py +58 -0
  98. dev_autopilot-0.4.0/tests/test_decide.py +103 -0
  99. dev_autopilot-0.4.0/tests/test_deploy.py +77 -0
  100. dev_autopilot-0.4.0/tests/test_deps.py +187 -0
  101. dev_autopilot-0.4.0/tests/test_docs_session.py +59 -0
  102. dev_autopilot-0.4.0/tests/test_doctor.py +134 -0
  103. dev_autopilot-0.4.0/tests/test_functional.py +158 -0
  104. dev_autopilot-0.4.0/tests/test_gate.py +349 -0
  105. dev_autopilot-0.4.0/tests/test_github_identity.py +43 -0
  106. dev_autopilot-0.4.0/tests/test_handoff.py +81 -0
  107. dev_autopilot-0.4.0/tests/test_heal.py +299 -0
  108. dev_autopilot-0.4.0/tests/test_ide_rules.py +88 -0
  109. dev_autopilot-0.4.0/tests/test_infra_templates.py +212 -0
  110. dev_autopilot-0.4.0/tests/test_intake.py +182 -0
  111. dev_autopilot-0.4.0/tests/test_killed_usage.py +65 -0
  112. dev_autopilot-0.4.0/tests/test_layers.py +44 -0
  113. dev_autopilot-0.4.0/tests/test_lean.py +95 -0
  114. dev_autopilot-0.4.0/tests/test_lifecycle.py +231 -0
  115. dev_autopilot-0.4.0/tests/test_mcp.py +40 -0
  116. dev_autopilot-0.4.0/tests/test_needs_you.py +290 -0
  117. dev_autopilot-0.4.0/tests/test_new_file_gate.py +301 -0
  118. dev_autopilot-0.4.0/tests/test_opening.py +51 -0
  119. dev_autopilot-0.4.0/tests/test_orchestrator.py +269 -0
  120. dev_autopilot-0.4.0/tests/test_parallel.py +253 -0
  121. dev_autopilot-0.4.0/tests/test_plan_source.py +55 -0
  122. dev_autopilot-0.4.0/tests/test_preflight.py +113 -0
  123. dev_autopilot-0.4.0/tests/test_presets.py +181 -0
  124. dev_autopilot-0.4.0/tests/test_proc.py +60 -0
  125. dev_autopilot-0.4.0/tests/test_prompt_contract_task.py +8 -0
  126. dev_autopilot-0.4.0/tests/test_quality.py +50 -0
  127. dev_autopilot-0.4.0/tests/test_quickstart.py +447 -0
  128. dev_autopilot-0.4.0/tests/test_reliability.py +283 -0
  129. dev_autopilot-0.4.0/tests/test_repomap.py +46 -0
  130. dev_autopilot-0.4.0/tests/test_research.py +80 -0
  131. dev_autopilot-0.4.0/tests/test_review.py +133 -0
  132. dev_autopilot-0.4.0/tests/test_rights.py +121 -0
  133. dev_autopilot-0.4.0/tests/test_roadmap.py +104 -0
  134. dev_autopilot-0.4.0/tests/test_routing.py +179 -0
  135. dev_autopilot-0.4.0/tests/test_runner_detect.py +309 -0
  136. dev_autopilot-0.4.0/tests/test_sandbox.py +60 -0
  137. dev_autopilot-0.4.0/tests/test_simple_view.py +331 -0
  138. dev_autopilot-0.4.0/tests/test_stats.py +144 -0
  139. dev_autopilot-0.4.0/tests/test_status_line.py +230 -0
  140. dev_autopilot-0.4.0/tests/test_status_page.py +153 -0
  141. dev_autopilot-0.4.0/tests/test_sync.py +176 -0
  142. dev_autopilot-0.4.0/tests/test_three_actions.py +116 -0
  143. dev_autopilot-0.4.0/tests/test_upgrade.py +163 -0
  144. dev_autopilot-0.4.0/tests/test_usage.py +114 -0
  145. dev_autopilot-0.4.0/tests/test_version.py +42 -0
  146. dev_autopilot-0.4.0/tests/test_window.py +117 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Manish Kumar
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,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: dev-autopilot
3
+ Version: 0.4.0
4
+ Summary: Autopilot builds your software project while you are away. You write what you want in plain words and start it once. You get working software, tested, with a record of every step.
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/manishjnv/AutoPilot
7
+ Project-URL: Documentation, https://github.com/manishjnv/AutoPilot#readme
8
+ Project-URL: Changelog, https://github.com/manishjnv/AutoPilot/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/manishjnv/AutoPilot/issues
10
+ Keywords: autonomous,coding-agent,claude-code,developer-tools
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Software Development :: Build Tools
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: PyYAML>=6.0
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=7; extra == "dev"
24
+ Provides-Extra: aws
25
+ Requires-Dist: boto3>=1.26; extra == "aws"
26
+ Dynamic: license-file
27
+
28
+ # Autopilot
29
+
30
+ Autopilot builds your software project while you are away. You write what you want in plain words and start it once. You get working software, tested, with a record of every step.
31
+ It is for one developer, or for a person with an idea and a developer friend.
32
+
33
+ **Give it a plan tonight. Wake up to a working app, and proof that it works.** Claude Code (the coding agent) writes the code; Python code decides when a task is complete.
34
+
35
+ [![CI](https://github.com/manishjnv/AutoPilot/actions/workflows/ci.yml/badge.svg)](https://github.com/manishjnv/AutoPilot/actions/workflows/ci.yml)
36
+ ![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)
37
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
38
+
39
+ ## Claude Code alone and with Autopilot
40
+
41
+ | | Claude Code alone | With Autopilot |
42
+ |---|---|---|
43
+ | Direction | Claude can choose the design as it works. | Your plan sets the design. The gate refuses plan changes. |
44
+ | Checks | The model can say that work is done. | Autopilot runs your build, lint and test commands. A task merges only if they pass. |
45
+ | Failures | You find and repair a problem. | A stronger model tries again. Autopilot repairs a missing tool or a red main branch. |
46
+ | Questions | The chat waits for you. | That task waits. Other tasks continue. |
47
+ | Status | You scroll the chat. | `ap watch` shows tasks, output, progress and usage. |
48
+
49
+ The [full comparison](ARCHITECTURE.md#13-claude-code-alone-and-with-autopilot) has ten rows. Use Claude Code alone
50
+ for a small change, a question, or an open design.
51
+
52
+ ## How it works
53
+
54
+ ![The loop: plan, task, Claude Code session, the gate, then main. Work that fails goes back to a stronger model.](assets/loop.gif)
55
+
56
+ ```mermaid
57
+ flowchart LR
58
+ accTitle: How Autopilot builds a plan
59
+ accDescr: Each task runs in a new Claude Code session. Python runs the checks. A pass merges to main, a fail retries on a stronger model, and a blocked task becomes a question while the other tasks continue. At the end, a completion audit adds tasks for gaps.
60
+ plan["Plan"] --> task["Next task"]
61
+ task --> session["New Claude Code<br/>session"]
62
+ session --> gate{"Python runs<br/>the checks"}
63
+ gate -->|pass| merge["Merge to main"]
64
+ gate -->|fail| retry["Retry on a<br/>stronger model"]
65
+ retry --> session
66
+ retry -->|blocked| park["Question in NEEDS-YOU.md,<br/>build the other tasks"]
67
+ park --> task
68
+ merge --> task
69
+ merge -->|plan done| audit{"Completion<br/>audit"}
70
+ audit -->|gaps| task
71
+ audit -->|complete| app["Working app"]
72
+ ```
73
+
74
+ ## Follow the build
75
+
76
+ `ap watch` shows the build in the terminal; the status page shows the same data in your browser (sample data).
77
+
78
+ ![The terminal window of the watch command: panels for the project, the tasks, the live output, the progress, the usage, the files and the issues.](assets/dashboard-terminal.png)
79
+
80
+ ![The status page in the browser: the question for you at the top, then the same panels as the terminal window.](assets/dashboard-browser.png)
81
+
82
+ ## Real results
83
+
84
+ Two real projects built from a plan:
85
+
86
+ - **SecretScan** finds leaked secrets in a repository.
87
+ - **envguard** checks `.env` files against a schema and finds secrets in the git history.
88
+
89
+ | Measure | SecretScan | envguard |
90
+ |---|---|---|
91
+ | Tasks merged | **27 of 27**: 13 from the plan, 14 from the audits | **21 of 21**: 11 from the plan, 10 from the audits |
92
+ | Blocked tasks | **0** | **0** |
93
+ | Passed on the first attempt | 25 of 27 | 17 of 21 |
94
+ | Decisions that needed a person | **0** | **0** |
95
+ | Agent time | 2.2 hours, 38 sessions | 1.4 hours, 42 sessions |
96
+ | Cost at API prices | $17.13 | $19.01 |
97
+
98
+ Both runs used a subscription. The envguard audits found 8 real bugs; Autopilot fixed all. envguard is private; numbers come from the run log. A lean rerun of envguard used 39.5 percent fewer tokens per task.
99
+
100
+ ## Install
101
+
102
+ One line. It installs what is missing for your user, with no administrator prompt.
103
+ Windows (PowerShell):
104
+
105
+ ```powershell
106
+ irm https://raw.githubusercontent.com/manishjnv/AutoPilot/main/install.ps1 | iex
107
+ ```
108
+
109
+ macOS, Linux or WSL:
110
+
111
+ ```bash
112
+ curl -fsSL https://raw.githubusercontent.com/manishjnv/AutoPilot/main/install.sh | bash
113
+ ```
114
+
115
+ On Windows pick Windows or WSL, not both; WSL only for the sandbox. With [uv](https://docs.astral.sh/uv/) already
116
+ installed, `uv tool install dev-autopilot` is the same.
117
+ Open a project folder and type `ap`. The first run logs you in to Claude (a paid plan, Pro or Max), then starts.
118
+ See [What `ap` does](HOWTO.md#what-ap-does-in-a-folder). After a release, run `ap upgrade`. For a repair or a
119
+ second machine, run `ap install`. Checksums and each step: [Install with one script](HOWTO.md#install-with-one-script).
120
+
121
+ ## Example output
122
+
123
+ Shortened real output:
124
+
125
+ ```text
126
+ task P02-T01 attempt 1 failed: PROBLEM: skip/focus marker added in tests/test_walker.py
127
+ session #10 task P02-T01 model=sonnet attempt=2
128
+ task P02-T01 done (sonnet, $0.39)
129
+ audit: completion audit: 92% complete, 8 corrective tasks (FIX001)
130
+ ```
131
+
132
+ ## Documentation
133
+
134
+ | To | Read |
135
+ |---|---|
136
+ | Build your first project | [Tutorial](GUIDE.md) |
137
+ | Do one job: a server, phone alerts, an existing project | [How-to guides](HOWTO.md) |
138
+ | Look up a command, setting, file or term | [Reference](REFERENCE.md) |
139
+ | How Autopilot works and why | [Architecture](ARCHITECTURE.md) |
140
+
141
+ ## Good to know
142
+
143
+ > [!WARNING]
144
+ > Use a sandbox on a server: sessions run without permission prompts. See
145
+ > [Run Autopilot on a server](HOWTO.md#run-autopilot-on-a-server).
146
+
147
+ - Version 0.3.0, an early release. [MIT license](LICENSE).
148
+ - One CLI agent per session. See [limits and runners](HOWTO.md#limits-and-supported-agent-clis).
@@ -0,0 +1,121 @@
1
+ # Autopilot
2
+
3
+ Autopilot builds your software project while you are away. You write what you want in plain words and start it once. You get working software, tested, with a record of every step.
4
+ It is for one developer, or for a person with an idea and a developer friend.
5
+
6
+ **Give it a plan tonight. Wake up to a working app, and proof that it works.** Claude Code (the coding agent) writes the code; Python code decides when a task is complete.
7
+
8
+ [![CI](https://github.com/manishjnv/AutoPilot/actions/workflows/ci.yml/badge.svg)](https://github.com/manishjnv/AutoPilot/actions/workflows/ci.yml)
9
+ ![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)
10
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
11
+
12
+ ## Claude Code alone and with Autopilot
13
+
14
+ | | Claude Code alone | With Autopilot |
15
+ |---|---|---|
16
+ | Direction | Claude can choose the design as it works. | Your plan sets the design. The gate refuses plan changes. |
17
+ | Checks | The model can say that work is done. | Autopilot runs your build, lint and test commands. A task merges only if they pass. |
18
+ | Failures | You find and repair a problem. | A stronger model tries again. Autopilot repairs a missing tool or a red main branch. |
19
+ | Questions | The chat waits for you. | That task waits. Other tasks continue. |
20
+ | Status | You scroll the chat. | `ap watch` shows tasks, output, progress and usage. |
21
+
22
+ The [full comparison](ARCHITECTURE.md#13-claude-code-alone-and-with-autopilot) has ten rows. Use Claude Code alone
23
+ for a small change, a question, or an open design.
24
+
25
+ ## How it works
26
+
27
+ ![The loop: plan, task, Claude Code session, the gate, then main. Work that fails goes back to a stronger model.](assets/loop.gif)
28
+
29
+ ```mermaid
30
+ flowchart LR
31
+ accTitle: How Autopilot builds a plan
32
+ accDescr: Each task runs in a new Claude Code session. Python runs the checks. A pass merges to main, a fail retries on a stronger model, and a blocked task becomes a question while the other tasks continue. At the end, a completion audit adds tasks for gaps.
33
+ plan["Plan"] --> task["Next task"]
34
+ task --> session["New Claude Code<br/>session"]
35
+ session --> gate{"Python runs<br/>the checks"}
36
+ gate -->|pass| merge["Merge to main"]
37
+ gate -->|fail| retry["Retry on a<br/>stronger model"]
38
+ retry --> session
39
+ retry -->|blocked| park["Question in NEEDS-YOU.md,<br/>build the other tasks"]
40
+ park --> task
41
+ merge --> task
42
+ merge -->|plan done| audit{"Completion<br/>audit"}
43
+ audit -->|gaps| task
44
+ audit -->|complete| app["Working app"]
45
+ ```
46
+
47
+ ## Follow the build
48
+
49
+ `ap watch` shows the build in the terminal; the status page shows the same data in your browser (sample data).
50
+
51
+ ![The terminal window of the watch command: panels for the project, the tasks, the live output, the progress, the usage, the files and the issues.](assets/dashboard-terminal.png)
52
+
53
+ ![The status page in the browser: the question for you at the top, then the same panels as the terminal window.](assets/dashboard-browser.png)
54
+
55
+ ## Real results
56
+
57
+ Two real projects built from a plan:
58
+
59
+ - **SecretScan** finds leaked secrets in a repository.
60
+ - **envguard** checks `.env` files against a schema and finds secrets in the git history.
61
+
62
+ | Measure | SecretScan | envguard |
63
+ |---|---|---|
64
+ | Tasks merged | **27 of 27**: 13 from the plan, 14 from the audits | **21 of 21**: 11 from the plan, 10 from the audits |
65
+ | Blocked tasks | **0** | **0** |
66
+ | Passed on the first attempt | 25 of 27 | 17 of 21 |
67
+ | Decisions that needed a person | **0** | **0** |
68
+ | Agent time | 2.2 hours, 38 sessions | 1.4 hours, 42 sessions |
69
+ | Cost at API prices | $17.13 | $19.01 |
70
+
71
+ Both runs used a subscription. The envguard audits found 8 real bugs; Autopilot fixed all. envguard is private; numbers come from the run log. A lean rerun of envguard used 39.5 percent fewer tokens per task.
72
+
73
+ ## Install
74
+
75
+ One line. It installs what is missing for your user, with no administrator prompt.
76
+ Windows (PowerShell):
77
+
78
+ ```powershell
79
+ irm https://raw.githubusercontent.com/manishjnv/AutoPilot/main/install.ps1 | iex
80
+ ```
81
+
82
+ macOS, Linux or WSL:
83
+
84
+ ```bash
85
+ curl -fsSL https://raw.githubusercontent.com/manishjnv/AutoPilot/main/install.sh | bash
86
+ ```
87
+
88
+ On Windows pick Windows or WSL, not both; WSL only for the sandbox. With [uv](https://docs.astral.sh/uv/) already
89
+ installed, `uv tool install dev-autopilot` is the same.
90
+ Open a project folder and type `ap`. The first run logs you in to Claude (a paid plan, Pro or Max), then starts.
91
+ See [What `ap` does](HOWTO.md#what-ap-does-in-a-folder). After a release, run `ap upgrade`. For a repair or a
92
+ second machine, run `ap install`. Checksums and each step: [Install with one script](HOWTO.md#install-with-one-script).
93
+
94
+ ## Example output
95
+
96
+ Shortened real output:
97
+
98
+ ```text
99
+ task P02-T01 attempt 1 failed: PROBLEM: skip/focus marker added in tests/test_walker.py
100
+ session #10 task P02-T01 model=sonnet attempt=2
101
+ task P02-T01 done (sonnet, $0.39)
102
+ audit: completion audit: 92% complete, 8 corrective tasks (FIX001)
103
+ ```
104
+
105
+ ## Documentation
106
+
107
+ | To | Read |
108
+ |---|---|
109
+ | Build your first project | [Tutorial](GUIDE.md) |
110
+ | Do one job: a server, phone alerts, an existing project | [How-to guides](HOWTO.md) |
111
+ | Look up a command, setting, file or term | [Reference](REFERENCE.md) |
112
+ | How Autopilot works and why | [Architecture](ARCHITECTURE.md) |
113
+
114
+ ## Good to know
115
+
116
+ > [!WARNING]
117
+ > Use a sandbox on a server: sessions run without permission prompts. See
118
+ > [Run Autopilot on a server](HOWTO.md#run-autopilot-on-a-server).
119
+
120
+ - Version 0.3.0, an early release. [MIT license](LICENSE).
121
+ - One CLI agent per session. See [limits and runners](HOWTO.md#limits-and-supported-agent-clis).
@@ -0,0 +1,4 @@
1
+ """Autopilot — autonomous, plan-driven development orchestrator for Claude Code."""
2
+
3
+ __version__ = "0.4.0"
4
+ AGENT_DIR = ".agent"
@@ -0,0 +1,6 @@
1
+ """`python -m autopilot`: works even when the `autopilot` command is not on PATH."""
2
+ import sys
3
+
4
+ from .cli import main
5
+
6
+ sys.exit(main())
@@ -0,0 +1,159 @@
1
+ """Agent backends. Each runs ONE fresh session and returns a SessionResult."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import re
6
+ from dataclasses import dataclass, field
7
+ from datetime import datetime, timedelta
8
+
9
+ # Anchored to a line start: the CLI prints these as its own message, so prose inside a failed session doesn't count.
10
+ LIMIT_RX = re.compile(r"^\s*(?:you've|you have) hit your (?:[\w-]+ ){0,3}limit"
11
+ r"(?:\s*[·•|\-–—,.]*\s*resets?\s+(?P<reset>[^\n]+))?", re.I | re.M)
12
+ API_LIMIT_RX = re.compile(r"^\s*API Error: (?:429|529)\b|^\s*API Error:.*(?:rate_limit_error|overloaded_error)", re.I | re.M)
13
+ _RESET_RX = re.compile(r"^(?:(?P<mon>[a-z]{3,9})\.?\s+(?P<day>\d{1,2})\s*(?:,|at)?\s*)?(?P<h>\d{1,2})(?::(?P<m>\d{2}))?"
14
+ r"\s*(?P<ap>am|pm)?\s*(?:\((?P<tz>[^)]+)\))?$", re.I)
15
+ _MONTHS = {m: i + 1 for i, m in enumerate("jan feb mar apr may jun jul aug sep oct nov dec".split())}
16
+
17
+
18
+ def parse_reset(s: str, now: datetime) -> float | None:
19
+ """Next future occurrence of a CLI reset time like `3:45pm`, `Oct 3, 9am (Asia/Calcutta)`; None if unparseable."""
20
+ try:
21
+ m = _RESET_RX.match((s or "").strip().rstrip(".").strip())
22
+ if not m or not (m["ap"] or m["m"]):
23
+ return None
24
+ tz = now.tzinfo
25
+ if m["tz"]:
26
+ try:
27
+ from zoneinfo import ZoneInfo
28
+ tz = ZoneInfo(m["tz"].strip())
29
+ except Exception: # noqa: BLE001 no tzdata / unknown zone: fall back to local time
30
+ pass
31
+ if now.tzinfo:
32
+ now = now.astimezone(tz)
33
+ h, mi = int(m["h"]), int(m["m"] or 0)
34
+ if m["ap"]:
35
+ if not 1 <= h <= 12:
36
+ return None
37
+ h = h % 12 + (12 if m["ap"].lower() == "pm" else 0)
38
+ if m["mon"]:
39
+ mon = _MONTHS.get(m["mon"][:3].lower())
40
+ if not mon:
41
+ return None
42
+ t = now.replace(month=mon, day=int(m["day"]), hour=h, minute=mi, second=0, microsecond=0)
43
+ if t <= now:
44
+ t = t.replace(year=t.year + 1)
45
+ else:
46
+ t = now.replace(hour=h, minute=mi, second=0, microsecond=0)
47
+ if t <= now:
48
+ t += timedelta(days=1)
49
+ return t.timestamp()
50
+ except Exception: # noqa: BLE001
51
+ return None
52
+
53
+
54
+ def detect_limit(text: str, now: datetime | None = None) -> tuple[bool, float | None]:
55
+ """(limited, reset_at epoch). Only the CLI's subscription message or API 429/529 errors count, never agent prose."""
56
+ text = text or ""
57
+ m = LIMIT_RX.search(text)
58
+ if m:
59
+ return True, (parse_reset(m["reset"], now or datetime.now().astimezone()) if m["reset"] else None)
60
+ return bool(API_LIMIT_RX.search(text)), None
61
+
62
+
63
+ # Failures of the machinery, not of the work: retried by the orchestrator, never counted as a task attempt.
64
+ # Anchored to a line start like LIMIT_RX, so the agent's own prose about these words never counts.
65
+ _AUTH_RX = re.compile(r"^\s*(?:Invalid API key|Please run /login|OAuth token (?:has )?expired|API Error: 401\b)",
66
+ re.I | re.M)
67
+ # Node's own error shapes ("reason: getaddrinfo ENOTFOUND", "Error: connect ECONNREFUSED"), not a bare code in prose
68
+ _NET_RX = re.compile(r"^\s*API Error: (?:Connection error|Request timed out|50[0234]\b)|"
69
+ r"(?:reason:|Error:)\s+(?:getaddrinfo |connect |read |write )?"
70
+ r"(?:ENOTFOUND|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN)\b", re.I | re.M)
71
+
72
+
73
+ def detect_infra(text: str) -> str:
74
+ """'auth' (not logged in / key rejected), 'network' (connection, timeout, server 5xx) or ''."""
75
+ text = text or ""
76
+ return "auth" if _AUTH_RX.search(text) else "network" if _NET_RX.search(text) else ""
77
+
78
+
79
+ @dataclass
80
+ class SessionRequest:
81
+ prompt: str
82
+ model: str
83
+ cwd: str
84
+ timeout_sec: int = 3600
85
+ budget_usd: float | None = None
86
+ system_append: str = ""
87
+ read_only: bool = False
88
+ log_path: str = ""
89
+ resume: str = "" # continue this CLI session instead of starting fresh
90
+ resume_totals: dict = field(default_factory=dict) # that session's totals so far (see SessionResult.totals)
91
+ schema: dict | None = None # JSON Schema of the final report (schemas.REPORTS)
92
+ effort: str = "" # overrides agent.effort for this session
93
+ web_only: bool = False # research: only web search/fetch and reading files
94
+ mcp_config: str = "" # MCP servers for this session only (e.g. Playwright)
95
+ no_tools: bool = False # triage of untrusted text: no file, shell, web or MCP tools
96
+ label: str = "" # live progress lines: "P01-T01 Project skeleton [haiku]"
97
+ on_context: object = None # J5: called with the session's context size (tokens)
98
+ on_tokens: object = None # G8: called with the session's running token total
99
+
100
+
101
+ @dataclass
102
+ class SessionResult:
103
+ ok: bool
104
+ text: str = ""
105
+ cost: float = 0.0
106
+ session_id: str = ""
107
+ report: dict = field(default_factory=dict)
108
+ error: str = ""
109
+ rate_limited: bool = False
110
+ reset_at: float | None = None
111
+ timed_out: bool = False
112
+ stuck: bool = False # killed for repeating the same action (stream-json watch)
113
+ usage: dict = field(default_factory=dict) # model -> {input, output, cache_read, cache_write, cost}
114
+ num_turns: int = 0
115
+ duration_ms: int = 0
116
+ totals: dict = field(default_factory=dict) # whole-session {cost, usage, num_turns, duration_ms}, for a later resume
117
+ infra: str = "" # 'cli' | 'auth' | 'network': the machinery failed, not the work
118
+ window: dict = field(default_factory=dict) # G1: the CLI's own usage figure {five_hour: {pct, reset}, seven_day, status}
119
+ config: dict = field(default_factory=dict) # I1: what the session loaded from the user's Claude config (names, counts)
120
+
121
+
122
+ def since(totals: dict, base: dict) -> dict:
123
+ """A resumed CLI session reports whole-session totals; keep only what this run added (never below zero)."""
124
+ def sub(a, b):
125
+ return max(0, (a or 0) - (b or 0))
126
+ bu = base.get("usage") or {}
127
+ usage = {m: {k: sub(v, (bu.get(m) or {}).get(k)) for k, v in u.items()} for m, u in (totals.get("usage") or {}).items()}
128
+ return {"cost": sub(totals.get("cost"), base.get("cost")), "usage": usage,
129
+ "num_turns": sub(totals.get("num_turns"), base.get("num_turns")),
130
+ "duration_ms": sub(totals.get("duration_ms"), base.get("duration_ms"))}
131
+
132
+
133
+ def parse_report(text: str) -> dict:
134
+ """Extract the last ```json block (or bare JSON object) from the agent's final message."""
135
+ blocks = re.findall(r"```(?:json)?\s*(\{.*?\})\s*```", text or "", re.S)
136
+ candidates = list(reversed(blocks))
137
+ if not candidates:
138
+ m = re.search(r"(\{[^{}]*\"status\".*\})\s*$", text or "", re.S)
139
+ if m:
140
+ candidates = [m.group(1)]
141
+ for c in candidates:
142
+ try:
143
+ data = json.loads(c)
144
+ if isinstance(data, dict):
145
+ return data
146
+ except json.JSONDecodeError:
147
+ continue
148
+ return {}
149
+
150
+
151
+ def get_backend(cfg):
152
+ kind = cfg.get("agent.backend", "claude_cli")
153
+ if kind == "claude_cli":
154
+ from .claude_cli import ClaudeCLIBackend
155
+ return ClaudeCLIBackend(cfg)
156
+ if kind == "command":
157
+ from .command import CommandBackend
158
+ return CommandBackend(cfg)
159
+ raise ValueError(f"unknown backend {kind}")