whiletrue 0.1.0__tar.gz → 0.1.1__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 (199) hide show
  1. {whiletrue-0.1.0 → whiletrue-0.1.1}/CHANGELOG.md +5 -0
  2. whiletrue-0.1.1/PKG-INFO +268 -0
  3. whiletrue-0.1.1/README.md +243 -0
  4. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/README.md +1 -0
  5. whiletrue-0.1.1/docs/assets/architecture.svg +48 -0
  6. whiletrue-0.1.1/docs/assets/demo-real.svg +1 -0
  7. whiletrue-0.1.1/docs/assets/issue-loop.svg +17 -0
  8. whiletrue-0.1.1/docs/assets/logo.svg +7 -0
  9. whiletrue-0.1.1/docs/assets/ralph-loop.svg +17 -0
  10. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/getting-started.md +2 -0
  11. whiletrue-0.1.1/docs/tutorial.md +250 -0
  12. {whiletrue-0.1.0 → whiletrue-0.1.1}/pyproject.toml +3 -3
  13. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/tmux/test_controller.py +37 -0
  14. {whiletrue-0.1.0 → whiletrue-0.1.1}/uv.lock +1 -1
  15. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/tmux/controller.py +13 -0
  16. whiletrue-0.1.0/PKG-INFO +0 -48
  17. whiletrue-0.1.0/README.md +0 -23
  18. {whiletrue-0.1.0 → whiletrue-0.1.1}/.editorconfig +0 -0
  19. {whiletrue-0.1.0 → whiletrue-0.1.1}/.envrc +0 -0
  20. {whiletrue-0.1.0 → whiletrue-0.1.1}/.github/ISSUE_TEMPLATE/task.md +0 -0
  21. {whiletrue-0.1.0 → whiletrue-0.1.1}/.github/pull_request_template.md +0 -0
  22. {whiletrue-0.1.0 → whiletrue-0.1.1}/.github/workflows/ci.yml +0 -0
  23. {whiletrue-0.1.0 → whiletrue-0.1.1}/.github/workflows/release.yml +0 -0
  24. {whiletrue-0.1.0 → whiletrue-0.1.1}/.gitignore +0 -0
  25. {whiletrue-0.1.0 → whiletrue-0.1.1}/CLAUDE.md +0 -0
  26. {whiletrue-0.1.0 → whiletrue-0.1.1}/LICENSE +0 -0
  27. {whiletrue-0.1.0 → whiletrue-0.1.1}/devenv.lock +0 -0
  28. {whiletrue-0.1.0 → whiletrue-0.1.1}/devenv.nix +0 -0
  29. {whiletrue-0.1.0 → whiletrue-0.1.1}/devenv.yaml +0 -0
  30. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/architecture.md +0 -0
  31. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/authoring.md +0 -0
  32. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/cli.md +0 -0
  33. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/conventions.md +0 -0
  34. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/developing.md +0 -0
  35. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/m0-smoke.md +0 -0
  36. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/open-questions.md +0 -0
  37. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/plan.md +0 -0
  38. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/plugins.md +0 -0
  39. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/reference.md +0 -0
  40. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/spike-interactive.md +0 -0
  41. {whiletrue-0.1.0 → whiletrue-0.1.1}/docs/todo.md +0 -0
  42. {whiletrue-0.1.0 → whiletrue-0.1.1}/examples/issue-loop/README.md +0 -0
  43. {whiletrue-0.1.0 → whiletrue-0.1.1}/examples/issue-loop/agents/fix.md +0 -0
  44. {whiletrue-0.1.0 → whiletrue-0.1.1}/examples/issue-loop/agents/implement.md +0 -0
  45. {whiletrue-0.1.0 → whiletrue-0.1.1}/examples/issue-loop/agents/respond.md +0 -0
  46. {whiletrue-0.1.0 → whiletrue-0.1.1}/examples/issue-loop/whiletrue.yaml +0 -0
  47. {whiletrue-0.1.0 → whiletrue-0.1.1}/scripts/docs_check.py +0 -0
  48. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/conftest.py +0 -0
  49. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/fixtures/fake_interactive_claude.py +0 -0
  50. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_cli.py +0 -0
  51. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_cli_surface.py +0 -0
  52. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_gates_cli.py +0 -0
  53. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_interactive_run.py +0 -0
  54. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_issue_loop.py +0 -0
  55. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_m3_exit.py +0 -0
  56. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_ops_cli.py +0 -0
  57. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/integration/test_recipes.py +0 -0
  58. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/live/test_live_backends.py +0 -0
  59. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_agent.py +0 -0
  60. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_exec.py +0 -0
  61. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_gates.py +0 -0
  62. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_history.py +0 -0
  63. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_human.py +0 -0
  64. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_json_source.py +0 -0
  65. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_markdown_source.py +0 -0
  66. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_plugin.py +0 -0
  67. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_process.py +0 -0
  68. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_sessions.py +0 -0
  69. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/basics/test_shell.py +0 -0
  70. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/claude_code/test_endpoint.py +0 -0
  71. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/claude_code/test_headless.py +0 -0
  72. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/claude_code/test_interactive.py +0 -0
  73. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/claude_code/test_panes.py +0 -0
  74. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/claude_code/test_plugin_scripts.py +0 -0
  75. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/claude_code/test_session.py +0 -0
  76. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/claude_code/test_transcript.py +0 -0
  77. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/codex/test_runner.py +0 -0
  78. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/control/test_control.py +0 -0
  79. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_cache.py +0 -0
  80. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_caps.py +0 -0
  81. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_composite.py +0 -0
  82. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_config.py +0 -0
  83. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_context.py +0 -0
  84. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_duration.py +0 -0
  85. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_events.py +0 -0
  86. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_expr.py +0 -0
  87. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_history_store.py +0 -0
  88. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_lock.py +0 -0
  89. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_memory_store.py +0 -0
  90. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_module.py +0 -0
  91. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_outcomes.py +0 -0
  92. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_registry.py +0 -0
  93. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_replay.py +0 -0
  94. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_runtime.py +0 -0
  95. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_template.py +0 -0
  96. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_validate.py +0 -0
  97. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/core/test_wake.py +0 -0
  98. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/git/test_git.py +0 -0
  99. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/github/test_client.py +0 -0
  100. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/github/test_filebacked.py +0 -0
  101. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/github/test_plugin.py +0 -0
  102. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/github/test_specs.py +0 -0
  103. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/opencode/test_runner.py +0 -0
  104. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/store_sqlite/test_sqlite_store.py +0 -0
  105. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/test_abort.py +0 -0
  106. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/test_architecture.py +0 -0
  107. {whiletrue-0.1.0 → whiletrue-0.1.1}/tests/unit/test_panel.py +0 -0
  108. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/__init__.py +0 -0
  109. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/__main__.py +0 -0
  110. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/abort.py +0 -0
  111. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/__init__.py +0 -0
  112. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/agent.py +0 -0
  113. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/comments.py +0 -0
  114. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/diff_size.py +0 -0
  115. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/exec_.py +0 -0
  116. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/history.py +0 -0
  117. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/human.py +0 -0
  118. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/json_source.py +0 -0
  119. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/markdown_source.py +0 -0
  120. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/process.py +0 -0
  121. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/sessions.py +0 -0
  122. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/set_.py +0 -0
  123. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/shell.py +0 -0
  124. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/basics/wake.py +0 -0
  125. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/__init__.py +0 -0
  126. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/endpoint.py +0 -0
  127. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/headless.py +0 -0
  128. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/interactive.py +0 -0
  129. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/learnings.py +0 -0
  130. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/panes.py +0 -0
  131. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/plugin/.claude-plugin/plugin.json +0 -0
  132. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/plugin/hook.py +0 -0
  133. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/plugin/hooks/hooks.json +0 -0
  134. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/plugin/mcp_server.py +0 -0
  135. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/session.py +0 -0
  136. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/claude_code/transcript.py +0 -0
  137. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/__init__.py +0 -0
  138. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/__main__.py +0 -0
  139. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/app.py +0 -0
  140. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/common.py +0 -0
  141. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/gates.py +0 -0
  142. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/ops.py +0 -0
  143. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/panel.py +0 -0
  144. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/registry.py +0 -0
  145. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/cli/templates.py +0 -0
  146. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/codex/__init__.py +0 -0
  147. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/codex/runner.py +0 -0
  148. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/__init__.py +0 -0
  149. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/chain.py +0 -0
  150. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/loop.py +0 -0
  151. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/map_.py +0 -0
  152. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/parallel.py +0 -0
  153. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/retry.py +0 -0
  154. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/sequence.py +0 -0
  155. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/control/switch.py +0 -0
  156. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/__init__.py +0 -0
  157. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/caps.py +0 -0
  158. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/comments.py +0 -0
  159. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/composite.py +0 -0
  160. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/config.py +0 -0
  161. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/context.py +0 -0
  162. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/duration.py +0 -0
  163. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/events.py +0 -0
  164. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/expr.py +0 -0
  165. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/history.py +0 -0
  166. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/lock.py +0 -0
  167. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/memory_store.py +0 -0
  168. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/module.py +0 -0
  169. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/outcomes.py +0 -0
  170. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/registry.py +0 -0
  171. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/replay.py +0 -0
  172. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/runner.py +0 -0
  173. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/runtime.py +0 -0
  174. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/source.py +0 -0
  175. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/store.py +0 -0
  176. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/template.py +0 -0
  177. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/validate.py +0 -0
  178. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/wake.py +0 -0
  179. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/core/workspace.py +0 -0
  180. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/git/__init__.py +0 -0
  181. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/git/modules.py +0 -0
  182. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/git/workspaces.py +0 -0
  183. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/github/__init__.py +0 -0
  184. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/github/client.py +0 -0
  185. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/github/filebacked.py +0 -0
  186. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/github/memory.py +0 -0
  187. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/github/plugin.py +0 -0
  188. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/github/specs.py +0 -0
  189. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/opencode/__init__.py +0 -0
  190. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/opencode/runner.py +0 -0
  191. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/py.typed +0 -0
  192. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/recipes/issue-loop.yaml +0 -0
  193. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/recipes/ralph.yaml +0 -0
  194. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/recipes/review-pass.yaml +0 -0
  195. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/recipes/review-respond.yaml +0 -0
  196. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/store_sqlite/__init__.py +0 -0
  197. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/store_sqlite/migrations.py +0 -0
  198. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/store_sqlite/sqlite_store.py +0 -0
  199. {whiletrue-0.1.0 → whiletrue-0.1.1}/whiletrue/tmux/__init__.py +0 -0
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1
4
+
5
+ - Fixed: parallel interactive items raced to create the tmux session. The loser failed with `duplicate session` and that error was fed to the agent as its previous failure. Session and pane creation now run one at a time, and parallel agents share one window grid.
6
+ - Docs: a new README with a recording of a real run, architecture and flow diagrams, and a step-by-step tutorial (`docs/tutorial.md`).
7
+
3
8
  ## 0.1.0 (first release)
4
9
 
5
10
  whiletrue runs configurable pipelines of agentic and deterministic steps around coding agents.
@@ -0,0 +1,268 @@
1
+ Metadata-Version: 2.5
2
+ Name: whiletrue
3
+ Version: 0.1.1
4
+ Summary: Local orchestrator that runs pipelines of agent and deterministic steps around Claude Code, opencode and Codex, with gates, human approval, parallel git worktrees and crash-safe resume.
5
+ Project-URL: Repository, https://github.com/dariussingh/whiletrue
6
+ Project-URL: Changelog, https://github.com/dariussingh/whiletrue/blob/main/CHANGELOG.md
7
+ Project-URL: Documentation, https://github.com/dariussingh/whiletrue/tree/main/docs
8
+ Author: Darius Singh
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,ai-agents,claude-code,codex,coding-agents,git-worktree,human-in-the-loop,opencode,orchestration,pipelines,ralph,tmux
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: POSIX
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Build Tools
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.12
21
+ Requires-Dist: common-expression-language<1,>=0.10
22
+ Requires-Dist: pydantic<3,>=2.9
23
+ Requires-Dist: pyyaml<7,>=6
24
+ Description-Content-Type: text/markdown
25
+
26
+ <div align="center">
27
+
28
+ <img src="docs/assets/logo.svg" alt="whiletrue logo" width="96" height="96">
29
+
30
+ # whiletrue
31
+
32
+ **The loop around your coding agents.**
33
+
34
+ Run pipelines of agentic and deterministic steps around Claude Code, opencode and Codex, locally, with gates, humans in the loop, and crash-safe resume.
35
+
36
+ [![PyPI](https://img.shields.io/pypi/v/whiletrue?logo=pypi&logoColor=white)](https://pypi.org/project/whiletrue/)
37
+ [![Python](https://img.shields.io/pypi/pyversions/whiletrue?logo=python&logoColor=white)](https://pypi.org/project/whiletrue/)
38
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
39
+ [![Docs](https://img.shields.io/badge/docs-docs%2F-informational)](docs/README.md)
40
+
41
+ </div>
42
+
43
+ > LangGraph builds the agent; whiletrue runs the loop around agents you already have.
44
+
45
+ <div align="center">
46
+
47
+ <img src="docs/assets/demo-real.svg" alt="Recording of a real run: two Claude Code agents work in parallel in tmux panes while a control panel and shell show status, both items pass their pytest gate and park for human approval, then approve and resume finish them" width="900">
48
+
49
+ <sub>A real run, not a mock-up: two Claude Code agents in parallel, a pytest gate, a human approval and a resume, about $0.23 in total. Captured from the live tmux panes; the two tmux windows are drawn side by side.</sub>
50
+
51
+ </div>
52
+
53
+ ```bash
54
+ uvx whiletrue init # scaffold a Ralph loop
55
+ uvx whiletrue run # agent -> pytest gate -> repeat until green
56
+ ```
57
+
58
+ ## Overview
59
+
60
+ Coding agents are good at one task and bad at finishing a backlog unattended. whiletrue is the orchestrator you put around them. You describe the loop in a single `whiletrue.yaml`: which agent does the work, which deterministic gate checks it, when to retry, when to ask a person. whiletrue validates the config before spending a token, runs it, and records every step so you can inspect, replay or resume it.
61
+
62
+ - **Pipelines, not prompts.** Agent steps, shell and git steps, and gates compose with `sequence`, `loop`, `map`, `parallel`, `switch`, `retry`, `try` and `human.approve`. Every loop is bounded.
63
+ - **Any backend.** `claude-code-headless`, `claude-code` (the real interactive CLI in a tmux pane you can type into), `opencode` and `codex`. Mix them in one pipeline.
64
+ - **Many items at once.** One item per task or GitHub issue, each in its own git worktree, with `parallel: N` and a cap on live agent sessions.
65
+ - **Humans in the loop.** A gate parks an item until a person approves, rejects or comments; other items keep running. Every review comment gets an answer.
66
+ - **Durable.** State lives in SQLite. Kill the process at any point and `whiletrue resume` replays finished steps instead of redoing them; side effects (PRs, merges, replies) happen exactly once.
67
+ - **Local.** One machine, no server, no account. Everything is a file in your repo plus `.whiletrue/`.
68
+
69
+ ## Contents
70
+
71
+ - [Install](#install)
72
+ - [Quickstart](#quickstart)
73
+ - [Architecture](#architecture)
74
+ - [Concepts](#concepts)
75
+ - [Examples](#examples)
76
+ - [Backends](#backends)
77
+ - [CLI](#cli)
78
+ - [Documentation](#documentation)
79
+ - [Development](#development)
80
+ - [License](#license)
81
+
82
+ ## Install
83
+
84
+ Requires Python 3.12+ and at least one agent CLI on your `PATH` ([Claude Code](https://claude.com/claude-code), [opencode](https://opencode.ai) or [Codex](https://github.com/openai/codex)). `git` is needed for worktrees, `tmux` for interactive agents, and `gh` for the GitHub integration.
85
+
86
+ ```bash
87
+ uv tool install whiletrue # or: pip install whiletrue
88
+ whiletrue --help
89
+
90
+ uvx whiletrue --help # or run it without installing
91
+ ```
92
+
93
+ If an agent CLI is not on `PATH`, set `WHILETRUE_CLAUDE_BIN`, `WHILETRUE_OPENCODE_BIN` or `WHILETRUE_CODEX_BIN`.
94
+
95
+ ## Quickstart
96
+
97
+ ```bash
98
+ cd my-project
99
+ whiletrue init # writes whiletrue.yaml and agents/ralph.md
100
+ whiletrue validate # config, wiring, limits and safety rules; spends nothing
101
+ whiletrue plan # prints the expanded step tree; spends nothing
102
+ whiletrue run # runs it
103
+ whiletrue status # steps, outcomes and cost of the latest run
104
+ ```
105
+
106
+ The scaffold is a Ralph loop. The agent runs in a fresh context, a deterministic `pytest` gate checks the result, and the loop repeats (at most 5 times) until the gate is green:
107
+
108
+ ```yaml
109
+ # whiletrue.yaml
110
+ name: ralph
111
+ pipeline:
112
+ loop:
113
+ max: 5 # every loop is bounded; `max: unbounded` is an explicit opt-out
114
+ do:
115
+ - agent: { uses: ./agents/ralph.md }
116
+ - gate.shell: { run: "pytest" }
117
+ ```
118
+
119
+ ```markdown
120
+ ---
121
+ # agents/ralph.md
122
+ agent: ralph
123
+ runner: claude-code-headless
124
+ permission_mode: acceptEdits
125
+ tools: [Read, Edit, Write, "Bash(pytest*)", "Bash(git *)"]
126
+ limits: { budget_usd: 2, turns: 40, wall: 20m }
127
+ ---
128
+ Work through the next unfinished item in TODO.md. Make the tests pass.
129
+
130
+ Failure output from the previous attempt (empty on the first try):
131
+ {{iter.previous}}
132
+ ```
133
+
134
+ Every agent must declare `limits`; `validate` refuses the config otherwise.
135
+
136
+ ## Architecture
137
+
138
+ <img src="docs/assets/architecture.svg" alt="Architecture: whiletrue.yaml and the CLI drive the core engine (loader, scheduler, pipeline runtime, park and resume, plugin registry, SQLite store); built-in plugins connect it to agent CLIs, git, GitHub and tmux" width="900">
139
+
140
+ The core knows nothing about git, GitHub, tmux or any agent. Every integration is a plugin built on the public plugin API, so you can add your own ([plugins](docs/plugins.md), [architecture](docs/architecture.md)).
141
+
142
+ ## Concepts
143
+
144
+ | Concept | What it is |
145
+ | --- | --- |
146
+ | **Pipeline** | A list of steps, or one strategy, in `whiletrue.yaml`. |
147
+ | **Step** | An action: `agent`, a shell command, a git or GitHub operation, a gate. Pure, deterministic, agentic or side-effecting. |
148
+ | **Strategy** | Control flow over steps: `sequence`, `tap`, `loop`, `map`, `parallel`, `switch`, `retry`, `try`, `human.approve`. |
149
+ | **Outcome ports** | Every step ends on `ok`, `fail`, `needs_human`, `skip` or `rejected`. `wires:` routes a port to another step; back-wires make loops. |
150
+ | **Item** | One unit of work from a `source:` (`json`, `markdown_tasks`, `github_issues`). Items run in parallel, in dependency order. |
151
+ | **Workspace** | Per-item checkout: `git-worktree`, `dir-copy` or `none`. |
152
+ | **Gate** | A deterministic check, or a human decision, that an item must pass. |
153
+ | **Recipe** | A ready-made composite: `ralph`, `review-pass`, `review-respond`, `issue-loop`. |
154
+ | **Run record** | The SQLite log of steps, parks, effects, comments and cost that makes replay and resume possible. |
155
+
156
+ Details: [reference](docs/reference.md), [authoring guide](docs/authoring.md), [architecture](docs/architecture.md).
157
+
158
+ ## Examples
159
+
160
+ ### A Ralph loop
161
+
162
+ <img src="docs/assets/ralph-loop.svg" alt="Ralph loop: agent in a fresh context, then a pytest gate; green ends the loop, red feeds the output back to the agent" width="900">
163
+
164
+ This is what `whiletrue init` scaffolds. See the YAML under [Quickstart](#quickstart).
165
+
166
+ ### Review loop with a read-only reviewer
167
+
168
+ ```yaml
169
+ pipeline:
170
+ composite:
171
+ uses: "recipe:review-pass"
172
+ params: { reviewer: ./agents/review.md, fixer: ./agents/fix.md, max_rounds: 3 }
173
+ ```
174
+
175
+ ### A backlog in parallel worktrees
176
+
177
+ ```yaml
178
+ parallel: 4
179
+ max_agents: 4
180
+ source: { markdown_tasks: { path: TASKS.md } } # - [ ] Title {#id after=other}
181
+ workspace: { git-worktree: { branch: "wt/{{item.id}}" } }
182
+ pipeline:
183
+ loop:
184
+ max: 5
185
+ do:
186
+ - agent: { uses: ./agents/implement.md }
187
+ - gate.shell: { run: "pytest" }
188
+ ```
189
+
190
+ ### A human gate on a pull request
191
+
192
+ ```yaml
193
+ - id: review
194
+ human.approve:
195
+ what: pr
196
+ wake: { any: [cli, { github.pr_review: any }] }
197
+ do:
198
+ - composite: { uses: "recipe:review-respond", params: { responder: ./agents/respond.md } }
199
+ wires: { rejected: fix }
200
+ ```
201
+
202
+ ```bash
203
+ whiletrue run # parks at the gate and exits with code 2
204
+ whiletrue status # lists what is waiting
205
+ whiletrue approve 12 # or: reject 12 --note "what to change"
206
+ whiletrue resume # finished steps are replayed, never redone
207
+ ```
208
+
209
+ ### The reference pipeline: issues with a human in the loop
210
+
211
+ [`examples/issue-loop`](examples/issue-loop/README.md) takes every issue in a GitHub milestone from open to merged: implement in a worktree, run the gate, open a PR, answer review comments, merge, close. You review every PR, and every comment you leave gets an answer.
212
+
213
+ <img src="docs/assets/issue-loop.svg" alt="Issue loop flow: implement with retry and a gate, open a PR, a human review gate with comment replies and a fix branch on rejection, then sync, a merge approval and the merge" width="900">
214
+
215
+ ## Backends
216
+
217
+ Choose per agent with `runner:`.
218
+
219
+ | Runner | Runs | Notes |
220
+ | --- | --- | --- |
221
+ | `claude-code-headless` | `claude -p` | Default. Budget, turns and wall limits enforced. |
222
+ | `claude-code` | Interactive Claude Code in a tmux pane | Watch it, type into it (recorded as a *steer*). Submits through a bundled MCP tool and hooks. |
223
+ | `opencode` | `opencode run` | Structured output checked against the step's cap. |
224
+ | `codex` | `codex exec` | Sandbox derived from `permission_mode`. No budget enforcement. |
225
+
226
+ Structured `outputs:` work on all of them. See [choosing a backend](docs/authoring.md#choosing-a-backend).
227
+
228
+ ## CLI
229
+
230
+ | Command | Purpose |
231
+ | --- | --- |
232
+ | `init`, `validate`, `plan` | Scaffold, check and preview a pipeline without spending tokens. |
233
+ | `run`, `resume`, `rerun`, `cancel` | Start, continue after a park or crash, redo, or stop items. |
234
+ | `status`, `logs`, `cost`, `replay` | Inspect runs, steps and spend; replay a recorded run. |
235
+ | `approve`, `reject`, `comment` | Decide human gates and talk to waiting items. |
236
+ | `attach`, `panel` | Open the tmux session and the live control panel. |
237
+ | `history`, `learnings` | Audit trail and approved lessons for future agents. |
238
+ | `lock` | Show or clear the run lock. |
239
+
240
+ Full reference: [docs/cli.md](docs/cli.md). New here? Follow the [tutorial](docs/tutorial.md).
241
+
242
+ ## Documentation
243
+
244
+ Start at [docs/README.md](docs/README.md).
245
+
246
+ - [Tutorial](docs/tutorial.md): from an empty folder to your own loop with gates, a reviewer, parallel tasks and a human approval.
247
+ - [Getting started](docs/getting-started.md): a longer walkthrough, including interactive agents, gates and parallel items.
248
+ - [Authoring guide](docs/authoring.md): writing pipelines and agents.
249
+ - [Reference](docs/reference.md): every module, strategy, provider and config key.
250
+ - [CLI](docs/cli.md) and [plugins](docs/plugins.md): the command line and extending whiletrue.
251
+ - [Architecture](docs/architecture.md), [plan](docs/plan.md), [todo](docs/todo.md) and [changelog](CHANGELOG.md).
252
+
253
+ ## Development
254
+
255
+ Requires [devenv](https://devenv.sh) (or Python 3.12 + [uv](https://docs.astral.sh/uv/)). See [developing.md](docs/developing.md).
256
+
257
+ ```bash
258
+ git clone https://github.com/dariussingh/whiletrue && cd whiletrue
259
+ direnv allow # or: devenv shell
260
+ poe check # format check, lint, pyright, tests + coverage, docs check
261
+ whiletrue --help # installed editable into .devenv/state/venv
262
+ ```
263
+
264
+ Live tests against real agent CLIs are opt-in: `WHILETRUE_LIVE=1 uv run pytest tests/live -v`.
265
+
266
+ ## License
267
+
268
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,243 @@
1
+ <div align="center">
2
+
3
+ <img src="docs/assets/logo.svg" alt="whiletrue logo" width="96" height="96">
4
+
5
+ # whiletrue
6
+
7
+ **The loop around your coding agents.**
8
+
9
+ Run pipelines of agentic and deterministic steps around Claude Code, opencode and Codex, locally, with gates, humans in the loop, and crash-safe resume.
10
+
11
+ [![PyPI](https://img.shields.io/pypi/v/whiletrue?logo=pypi&logoColor=white)](https://pypi.org/project/whiletrue/)
12
+ [![Python](https://img.shields.io/pypi/pyversions/whiletrue?logo=python&logoColor=white)](https://pypi.org/project/whiletrue/)
13
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
14
+ [![Docs](https://img.shields.io/badge/docs-docs%2F-informational)](docs/README.md)
15
+
16
+ </div>
17
+
18
+ > LangGraph builds the agent; whiletrue runs the loop around agents you already have.
19
+
20
+ <div align="center">
21
+
22
+ <img src="docs/assets/demo-real.svg" alt="Recording of a real run: two Claude Code agents work in parallel in tmux panes while a control panel and shell show status, both items pass their pytest gate and park for human approval, then approve and resume finish them" width="900">
23
+
24
+ <sub>A real run, not a mock-up: two Claude Code agents in parallel, a pytest gate, a human approval and a resume, about $0.23 in total. Captured from the live tmux panes; the two tmux windows are drawn side by side.</sub>
25
+
26
+ </div>
27
+
28
+ ```bash
29
+ uvx whiletrue init # scaffold a Ralph loop
30
+ uvx whiletrue run # agent -> pytest gate -> repeat until green
31
+ ```
32
+
33
+ ## Overview
34
+
35
+ Coding agents are good at one task and bad at finishing a backlog unattended. whiletrue is the orchestrator you put around them. You describe the loop in a single `whiletrue.yaml`: which agent does the work, which deterministic gate checks it, when to retry, when to ask a person. whiletrue validates the config before spending a token, runs it, and records every step so you can inspect, replay or resume it.
36
+
37
+ - **Pipelines, not prompts.** Agent steps, shell and git steps, and gates compose with `sequence`, `loop`, `map`, `parallel`, `switch`, `retry`, `try` and `human.approve`. Every loop is bounded.
38
+ - **Any backend.** `claude-code-headless`, `claude-code` (the real interactive CLI in a tmux pane you can type into), `opencode` and `codex`. Mix them in one pipeline.
39
+ - **Many items at once.** One item per task or GitHub issue, each in its own git worktree, with `parallel: N` and a cap on live agent sessions.
40
+ - **Humans in the loop.** A gate parks an item until a person approves, rejects or comments; other items keep running. Every review comment gets an answer.
41
+ - **Durable.** State lives in SQLite. Kill the process at any point and `whiletrue resume` replays finished steps instead of redoing them; side effects (PRs, merges, replies) happen exactly once.
42
+ - **Local.** One machine, no server, no account. Everything is a file in your repo plus `.whiletrue/`.
43
+
44
+ ## Contents
45
+
46
+ - [Install](#install)
47
+ - [Quickstart](#quickstart)
48
+ - [Architecture](#architecture)
49
+ - [Concepts](#concepts)
50
+ - [Examples](#examples)
51
+ - [Backends](#backends)
52
+ - [CLI](#cli)
53
+ - [Documentation](#documentation)
54
+ - [Development](#development)
55
+ - [License](#license)
56
+
57
+ ## Install
58
+
59
+ Requires Python 3.12+ and at least one agent CLI on your `PATH` ([Claude Code](https://claude.com/claude-code), [opencode](https://opencode.ai) or [Codex](https://github.com/openai/codex)). `git` is needed for worktrees, `tmux` for interactive agents, and `gh` for the GitHub integration.
60
+
61
+ ```bash
62
+ uv tool install whiletrue # or: pip install whiletrue
63
+ whiletrue --help
64
+
65
+ uvx whiletrue --help # or run it without installing
66
+ ```
67
+
68
+ If an agent CLI is not on `PATH`, set `WHILETRUE_CLAUDE_BIN`, `WHILETRUE_OPENCODE_BIN` or `WHILETRUE_CODEX_BIN`.
69
+
70
+ ## Quickstart
71
+
72
+ ```bash
73
+ cd my-project
74
+ whiletrue init # writes whiletrue.yaml and agents/ralph.md
75
+ whiletrue validate # config, wiring, limits and safety rules; spends nothing
76
+ whiletrue plan # prints the expanded step tree; spends nothing
77
+ whiletrue run # runs it
78
+ whiletrue status # steps, outcomes and cost of the latest run
79
+ ```
80
+
81
+ The scaffold is a Ralph loop. The agent runs in a fresh context, a deterministic `pytest` gate checks the result, and the loop repeats (at most 5 times) until the gate is green:
82
+
83
+ ```yaml
84
+ # whiletrue.yaml
85
+ name: ralph
86
+ pipeline:
87
+ loop:
88
+ max: 5 # every loop is bounded; `max: unbounded` is an explicit opt-out
89
+ do:
90
+ - agent: { uses: ./agents/ralph.md }
91
+ - gate.shell: { run: "pytest" }
92
+ ```
93
+
94
+ ```markdown
95
+ ---
96
+ # agents/ralph.md
97
+ agent: ralph
98
+ runner: claude-code-headless
99
+ permission_mode: acceptEdits
100
+ tools: [Read, Edit, Write, "Bash(pytest*)", "Bash(git *)"]
101
+ limits: { budget_usd: 2, turns: 40, wall: 20m }
102
+ ---
103
+ Work through the next unfinished item in TODO.md. Make the tests pass.
104
+
105
+ Failure output from the previous attempt (empty on the first try):
106
+ {{iter.previous}}
107
+ ```
108
+
109
+ Every agent must declare `limits`; `validate` refuses the config otherwise.
110
+
111
+ ## Architecture
112
+
113
+ <img src="docs/assets/architecture.svg" alt="Architecture: whiletrue.yaml and the CLI drive the core engine (loader, scheduler, pipeline runtime, park and resume, plugin registry, SQLite store); built-in plugins connect it to agent CLIs, git, GitHub and tmux" width="900">
114
+
115
+ The core knows nothing about git, GitHub, tmux or any agent. Every integration is a plugin built on the public plugin API, so you can add your own ([plugins](docs/plugins.md), [architecture](docs/architecture.md)).
116
+
117
+ ## Concepts
118
+
119
+ | Concept | What it is |
120
+ | --- | --- |
121
+ | **Pipeline** | A list of steps, or one strategy, in `whiletrue.yaml`. |
122
+ | **Step** | An action: `agent`, a shell command, a git or GitHub operation, a gate. Pure, deterministic, agentic or side-effecting. |
123
+ | **Strategy** | Control flow over steps: `sequence`, `tap`, `loop`, `map`, `parallel`, `switch`, `retry`, `try`, `human.approve`. |
124
+ | **Outcome ports** | Every step ends on `ok`, `fail`, `needs_human`, `skip` or `rejected`. `wires:` routes a port to another step; back-wires make loops. |
125
+ | **Item** | One unit of work from a `source:` (`json`, `markdown_tasks`, `github_issues`). Items run in parallel, in dependency order. |
126
+ | **Workspace** | Per-item checkout: `git-worktree`, `dir-copy` or `none`. |
127
+ | **Gate** | A deterministic check, or a human decision, that an item must pass. |
128
+ | **Recipe** | A ready-made composite: `ralph`, `review-pass`, `review-respond`, `issue-loop`. |
129
+ | **Run record** | The SQLite log of steps, parks, effects, comments and cost that makes replay and resume possible. |
130
+
131
+ Details: [reference](docs/reference.md), [authoring guide](docs/authoring.md), [architecture](docs/architecture.md).
132
+
133
+ ## Examples
134
+
135
+ ### A Ralph loop
136
+
137
+ <img src="docs/assets/ralph-loop.svg" alt="Ralph loop: agent in a fresh context, then a pytest gate; green ends the loop, red feeds the output back to the agent" width="900">
138
+
139
+ This is what `whiletrue init` scaffolds. See the YAML under [Quickstart](#quickstart).
140
+
141
+ ### Review loop with a read-only reviewer
142
+
143
+ ```yaml
144
+ pipeline:
145
+ composite:
146
+ uses: "recipe:review-pass"
147
+ params: { reviewer: ./agents/review.md, fixer: ./agents/fix.md, max_rounds: 3 }
148
+ ```
149
+
150
+ ### A backlog in parallel worktrees
151
+
152
+ ```yaml
153
+ parallel: 4
154
+ max_agents: 4
155
+ source: { markdown_tasks: { path: TASKS.md } } # - [ ] Title {#id after=other}
156
+ workspace: { git-worktree: { branch: "wt/{{item.id}}" } }
157
+ pipeline:
158
+ loop:
159
+ max: 5
160
+ do:
161
+ - agent: { uses: ./agents/implement.md }
162
+ - gate.shell: { run: "pytest" }
163
+ ```
164
+
165
+ ### A human gate on a pull request
166
+
167
+ ```yaml
168
+ - id: review
169
+ human.approve:
170
+ what: pr
171
+ wake: { any: [cli, { github.pr_review: any }] }
172
+ do:
173
+ - composite: { uses: "recipe:review-respond", params: { responder: ./agents/respond.md } }
174
+ wires: { rejected: fix }
175
+ ```
176
+
177
+ ```bash
178
+ whiletrue run # parks at the gate and exits with code 2
179
+ whiletrue status # lists what is waiting
180
+ whiletrue approve 12 # or: reject 12 --note "what to change"
181
+ whiletrue resume # finished steps are replayed, never redone
182
+ ```
183
+
184
+ ### The reference pipeline: issues with a human in the loop
185
+
186
+ [`examples/issue-loop`](examples/issue-loop/README.md) takes every issue in a GitHub milestone from open to merged: implement in a worktree, run the gate, open a PR, answer review comments, merge, close. You review every PR, and every comment you leave gets an answer.
187
+
188
+ <img src="docs/assets/issue-loop.svg" alt="Issue loop flow: implement with retry and a gate, open a PR, a human review gate with comment replies and a fix branch on rejection, then sync, a merge approval and the merge" width="900">
189
+
190
+ ## Backends
191
+
192
+ Choose per agent with `runner:`.
193
+
194
+ | Runner | Runs | Notes |
195
+ | --- | --- | --- |
196
+ | `claude-code-headless` | `claude -p` | Default. Budget, turns and wall limits enforced. |
197
+ | `claude-code` | Interactive Claude Code in a tmux pane | Watch it, type into it (recorded as a *steer*). Submits through a bundled MCP tool and hooks. |
198
+ | `opencode` | `opencode run` | Structured output checked against the step's cap. |
199
+ | `codex` | `codex exec` | Sandbox derived from `permission_mode`. No budget enforcement. |
200
+
201
+ Structured `outputs:` work on all of them. See [choosing a backend](docs/authoring.md#choosing-a-backend).
202
+
203
+ ## CLI
204
+
205
+ | Command | Purpose |
206
+ | --- | --- |
207
+ | `init`, `validate`, `plan` | Scaffold, check and preview a pipeline without spending tokens. |
208
+ | `run`, `resume`, `rerun`, `cancel` | Start, continue after a park or crash, redo, or stop items. |
209
+ | `status`, `logs`, `cost`, `replay` | Inspect runs, steps and spend; replay a recorded run. |
210
+ | `approve`, `reject`, `comment` | Decide human gates and talk to waiting items. |
211
+ | `attach`, `panel` | Open the tmux session and the live control panel. |
212
+ | `history`, `learnings` | Audit trail and approved lessons for future agents. |
213
+ | `lock` | Show or clear the run lock. |
214
+
215
+ Full reference: [docs/cli.md](docs/cli.md). New here? Follow the [tutorial](docs/tutorial.md).
216
+
217
+ ## Documentation
218
+
219
+ Start at [docs/README.md](docs/README.md).
220
+
221
+ - [Tutorial](docs/tutorial.md): from an empty folder to your own loop with gates, a reviewer, parallel tasks and a human approval.
222
+ - [Getting started](docs/getting-started.md): a longer walkthrough, including interactive agents, gates and parallel items.
223
+ - [Authoring guide](docs/authoring.md): writing pipelines and agents.
224
+ - [Reference](docs/reference.md): every module, strategy, provider and config key.
225
+ - [CLI](docs/cli.md) and [plugins](docs/plugins.md): the command line and extending whiletrue.
226
+ - [Architecture](docs/architecture.md), [plan](docs/plan.md), [todo](docs/todo.md) and [changelog](CHANGELOG.md).
227
+
228
+ ## Development
229
+
230
+ Requires [devenv](https://devenv.sh) (or Python 3.12 + [uv](https://docs.astral.sh/uv/)). See [developing.md](docs/developing.md).
231
+
232
+ ```bash
233
+ git clone https://github.com/dariussingh/whiletrue && cd whiletrue
234
+ direnv allow # or: devenv shell
235
+ poe check # format check, lint, pyright, tests + coverage, docs check
236
+ whiletrue --help # installed editable into .devenv/state/venv
237
+ ```
238
+
239
+ Live tests against real agent CLIs are opt-in: `WHILETRUE_LIVE=1 uv run pytest tests/live -v`.
240
+
241
+ ## License
242
+
243
+ MIT. See [LICENSE](LICENSE).
@@ -4,6 +4,7 @@
4
4
  | -------------------------------------- | --------------------------------------------------------------------------------- |
5
5
  | [architecture.md](architecture.md) | Full design: core model, runtime, state, agents, human gates, packages |
6
6
  | [getting-started.md](getting-started.md) | User guide: install, first loop, commands, exit codes, safety defaults |
7
+ | [tutorial.md](tutorial.md) | Tutorial: install, first loop, then build your own gates, review, parallel and human steps |
7
8
  | [authoring.md](authoring.md) | Authoring guide: pipelines, composites, agents, choosing a backend |
8
9
  | [cli.md](cli.md) | CLI reference: every command, option, exit code and environment variable |
9
10
  | [reference.md](reference.md) | User reference: modules, control flow, expressions, composites, recipes, replay |
@@ -0,0 +1,48 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 600" width="960" height="600" role="img" aria-label="whiletrue architecture: CLI and whiletrue.yaml feed the core engine, which uses plugins to drive agent CLIs, git, GitHub and tmux, with state in SQLite">
2
+ <style>
3
+ text{font:13px ui-monospace,SFMono-Regular,Menlo,Consolas,'DejaVu Sans Mono',monospace;fill:#d5dbe3}
4
+ .t{font-size:15px;font-weight:700}.d{fill:#7d8896}.b{fill:#151b23;stroke:#2b3440;stroke-width:1.5}
5
+ .g{fill:#12251a;stroke:#3f7a50;stroke-width:1.5}.c{fill:#10222b;stroke:#3a7f96;stroke-width:1.5}.o{fill:#2a1f14;stroke:#a8683a;stroke-width:1.5}
6
+ .l{stroke:#7d8896;stroke-width:1.5;fill:none;marker-end:url(#a)}
7
+ </style>
8
+ <defs><marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto"><path d="M0 0L10 5L0 10z" fill="#7d8896"/></marker></defs>
9
+ <rect width="960" height="600" rx="10" fill="#0f1419"/>
10
+
11
+ <rect class="b" x="30" y="24" width="900" height="64" rx="6"/>
12
+ <text class="t" x="48" y="50">You</text>
13
+ <text class="d" x="48" y="72">whiletrue.yaml · agents/*.md · whiletrue CLI (run resume approve status panel)</text>
14
+
15
+ <path class="l" d="M480 88V112"/>
16
+
17
+ <rect class="g" x="30" y="114" width="900" height="206" rx="6"/>
18
+ <text class="t" x="48" y="140">whiletrue.core (knows no git, GitHub, tmux or agent)</text>
19
+ <rect class="b" x="48" y="156" width="196" height="64" rx="5"/>
20
+ <text x="62" y="182">Loader + validator</text><text class="d" x="62" y="202">config, wiring, limits</text>
21
+ <rect class="b" x="260" y="156" width="196" height="64" rx="5"/>
22
+ <text x="274" y="182">Scheduler</text><text class="d" x="274" y="202">items, parallel, deps</text>
23
+ <rect class="b" x="472" y="156" width="196" height="64" rx="5"/>
24
+ <text x="486" y="182">Pipeline runtime</text><text class="d" x="486" y="202">strategies, journal</text>
25
+ <rect class="b" x="684" y="156" width="228" height="64" rx="5"/>
26
+ <text x="698" y="182">Park / resume / replay</text><text class="d" x="698" y="202">gates, crash recovery</text>
27
+ <rect class="b" x="48" y="236" width="420" height="64" rx="5"/>
28
+ <text x="62" y="262">Plugin API + registry</text><text class="d" x="62" y="282">action modules · strategies · providers · runners</text>
29
+ <rect class="b" x="484" y="236" width="428" height="64" rx="5"/>
30
+ <text x="498" y="262">State store (SQLite, .whiletrue/)</text><text class="d" x="498" y="282">steps · parks · effects · comments · cost</text>
31
+
32
+ <path class="l" d="M480 320V346"/>
33
+
34
+ <rect class="c" x="30" y="348" width="900" height="122" rx="6"/>
35
+ <text class="t" x="48" y="374">Built-in plugins (public plugin API only)</text>
36
+ <rect class="b" x="48" y="388" width="140" height="64" rx="5"/><text x="60" y="414">control</text><text class="d" x="60" y="434">loop map switch</text>
37
+ <rect class="b" x="200" y="388" width="140" height="64" rx="5"/><text x="212" y="414">basics</text><text class="d" x="212" y="434">agent shell</text>
38
+ <rect class="b" x="352" y="388" width="140" height="64" rx="5"/><text x="364" y="414">git</text><text class="d" x="364" y="434">worktrees</text>
39
+ <rect class="b" x="504" y="388" width="140" height="64" rx="5"/><text x="516" y="414">github</text><text class="d" x="516" y="434">issues, PRs</text>
40
+ <rect class="b" x="656" y="388" width="130" height="64" rx="5"/><text x="668" y="414">claude_code</text><text class="d" x="668" y="434">headless tmux</text>
41
+ <rect class="b" x="798" y="388" width="114" height="64" rx="5"/><text x="810" y="414">opencode</text><text class="d" x="810" y="434">codex</text>
42
+
43
+ <path class="l" d="M480 470V496"/>
44
+
45
+ <rect class="o" x="30" y="498" width="900" height="74" rx="6"/>
46
+ <text class="t" x="48" y="524">Outside world</text>
47
+ <text class="d" x="48" y="546">claude · opencode · codex CLIs | git | gh (GitHub) | tmux | your tests and scripts</text>
48
+ </svg>