lemming-cli 0.4.2__tar.gz → 0.4.4__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 (201) hide show
  1. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/.github/workflows/ci.yml +9 -9
  2. lemming_cli-0.4.4/.prettierignore +13 -0
  3. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/Dockerfile +4 -2
  4. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/PKG-INFO +81 -78
  5. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/README.md +78 -75
  6. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/SKILL.md +39 -32
  7. lemming_cli-0.4.4/biome.json +42 -0
  8. lemming_cli-0.4.4/docs/EVALS.md +185 -0
  9. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/docs/HOOKS.md +29 -29
  10. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/package-lock.json +54 -38
  11. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/package.json +3 -2
  12. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/pyproject.toml +15 -3
  13. lemming_cli-0.4.4/pyrefly.toml +21 -0
  14. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/config_test.py +1 -1
  15. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/config.py +1 -1
  16. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/main.py +3 -0
  17. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/main_test.py +9 -0
  18. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/readability_cli_test.py +5 -4
  19. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/cli.py +124 -16
  20. lemming_cli-0.4.4/src/lemming/evals/cli_test.py +273 -0
  21. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/container.py +3 -4
  22. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/container_test.py +1 -2
  23. lemming_cli-0.4.4/src/lemming/evals/fixtures.py +197 -0
  24. lemming_cli-0.4.4/src/lemming/evals/fixtures_test.py +149 -0
  25. lemming_cli-0.4.4/src/lemming/evals/harness.py +445 -0
  26. lemming_cli-0.4.4/src/lemming/evals/harness_test.py +430 -0
  27. lemming_cli-0.4.4/src/lemming/evals/metrics.py +211 -0
  28. lemming_cli-0.4.4/src/lemming/evals/metrics_test.py +215 -0
  29. lemming_cli-0.4.4/src/lemming/evals/projects/readability/base/README.md +1 -0
  30. lemming_cli-0.4.4/src/lemming/evals/projects/readability/base/calc/__init__.py +0 -0
  31. lemming_cli-0.4.4/src/lemming/evals/projects/readability/base/calc/legacy.py +21 -0
  32. lemming_cli-0.4.4/src/lemming/evals/projects/readability/base/calc/ops.py +6 -0
  33. lemming_cli-0.4.4/src/lemming/evals/projects/readability/base/calc/ops_test.py +8 -0
  34. lemming_cli-0.4.4/src/lemming/evals/projects/readability/clean/calc/ops.py +11 -0
  35. lemming_cli-0.4.4/src/lemming/evals/projects/readability/clean/calc/ops_test.py +11 -0
  36. lemming_cli-0.4.4/src/lemming/evals/projects/readability/dead-code/calc/ops.py +16 -0
  37. lemming_cli-0.4.4/src/lemming/evals/projects/readability/dead-code/calc/ops_test.py +11 -0
  38. lemming_cli-0.4.4/src/lemming/evals/projects/readability/duplicated-behavior/calc/ops.py +29 -0
  39. lemming_cli-0.4.4/src/lemming/evals/projects/readability/duplicated-behavior/calc/ops_test.py +23 -0
  40. lemming_cli-0.4.4/src/lemming/evals/projects/readability/false-reuse/calc/limits.py +27 -0
  41. lemming_cli-0.4.4/src/lemming/evals/projects/readability/false-reuse/calc/limits_test.py +15 -0
  42. lemming_cli-0.4.4/src/lemming/evals/projects/readability/lint-debt/calc/ops.py +18 -0
  43. lemming_cli-0.4.4/src/lemming/evals/projects/readability/lint-debt/calc/ops_test.py +17 -0
  44. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/add-only/README.md +1 -0
  45. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/add-only/calc/__init__.py +0 -0
  46. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/add-only/calc/ops.py +6 -0
  47. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/add-only/calc/ops_test.py +8 -0
  48. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/buggy-subtract/README.md +1 -0
  49. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/buggy-subtract/calc/__init__.py +0 -0
  50. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/buggy-subtract/calc/ops.py +16 -0
  51. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/buggy-subtract/calc/ops_test.py +8 -0
  52. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/full-ops/README.md +1 -0
  53. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/full-ops/calc/__init__.py +0 -0
  54. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/full-ops/calc/ops.py +16 -0
  55. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/full-ops/calc/ops_test.py +8 -0
  56. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/unwired-cli/README.md +1 -0
  57. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/unwired-cli/calc/__init__.py +0 -0
  58. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/unwired-cli/calc/cli.py +14 -0
  59. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/unwired-cli/calc/cli_test.py +14 -0
  60. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/unwired-cli/calc/ops.py +16 -0
  61. lemming_cli-0.4.4/src/lemming/evals/projects/roadmap/unwired-cli/calc/ops_test.py +14 -0
  62. lemming_cli-0.4.4/src/lemming/evals/projects/task/hidden/stats/summary_hidden_test.py +22 -0
  63. lemming_cli-0.4.4/src/lemming/evals/projects/task/summary/README.md +1 -0
  64. lemming_cli-0.4.4/src/lemming/evals/projects/task/summary/stats/__init__.py +1 -0
  65. lemming_cli-0.4.4/src/lemming/evals/projects/task/summary/stats/summary.py +25 -0
  66. lemming_cli-0.4.4/src/lemming/evals/projects/task/summary/stats/summary_test.py +15 -0
  67. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/readability.py +155 -172
  68. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/readability_test.py +134 -13
  69. lemming_cli-0.4.4/src/lemming/evals/report.py +223 -0
  70. lemming_cli-0.4.4/src/lemming/evals/report_test.py +211 -0
  71. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/roadmap.py +12 -135
  72. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/roadmap_test.py +1 -2
  73. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/scenarios.py +18 -8
  74. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/suites.py +2 -1
  75. lemming_cli-0.4.4/src/lemming/evals/task.py +234 -0
  76. lemming_cli-0.4.4/src/lemming/evals/task_test.py +243 -0
  77. lemming_cli-0.4.4/src/lemming/evals/trial.py +250 -0
  78. lemming_cli-0.4.4/src/lemming/evals/trial_test.py +306 -0
  79. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/models.py +1 -1
  80. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/orchestrator.py +6 -1
  81. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/orchestrator_test.py +28 -0
  82. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/runner.py +70 -8
  83. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/runner_test.py +103 -2
  84. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/dashboard.spec.js +3 -6
  85. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/dashboard.test.js +7 -17
  86. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/favicon.spec.js +1 -1
  87. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/files.html +11 -5
  88. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/index.html +37 -25
  89. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/logs.html +5 -1
  90. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/screenshots.spec.js +3 -3
  91. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/uv.lock +34 -5
  92. lemming_cli-0.4.2/.prettierignore +0 -5
  93. lemming_cli-0.4.2/biome.json +0 -32
  94. lemming_cli-0.4.2/docs/EVALS.md +0 -89
  95. lemming_cli-0.4.2/src/lemming/evals/cli_test.py +0 -136
  96. lemming_cli-0.4.2/src/lemming/evals/fixtures.py +0 -90
  97. lemming_cli-0.4.2/src/lemming/evals/fixtures_test.py +0 -60
  98. lemming_cli-0.4.2/src/lemming/evals/harness.py +0 -239
  99. lemming_cli-0.4.2/src/lemming/evals/harness_test.py +0 -187
  100. lemming_cli-0.4.2/src/lemming/evals/trial.py +0 -86
  101. lemming_cli-0.4.2/src/lemming/evals/trial_test.py +0 -133
  102. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/.dockerignore +0 -0
  103. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/.github/workflows/publish.yml +0 -0
  104. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/.github/workflows/screenshots.yml +0 -0
  105. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/.gitignore +0 -0
  106. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/.prettierrc +0 -0
  107. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/LICENSE +0 -0
  108. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/docker-compose.yml +0 -0
  109. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/docs/screenshots/dashboard-desktop.png +0 -0
  110. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/docs/screenshots/dashboard-mobile.png +0 -0
  111. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/docs/screenshots/task-log-desktop.png +0 -0
  112. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/docs/screenshots/task-log-mobile.png +0 -0
  113. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/playwright.config.js +0 -0
  114. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/__init__.py +0 -0
  115. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/__init__.py +0 -0
  116. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/auth.py +0 -0
  117. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/auth_test.py +0 -0
  118. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/config.py +0 -0
  119. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/conftest.py +0 -0
  120. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/context.py +0 -0
  121. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/context_test.py +0 -0
  122. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/directories.py +0 -0
  123. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/directories_test.py +0 -0
  124. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/files.py +0 -0
  125. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/files_test.py +0 -0
  126. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/hooks.py +0 -0
  127. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/hooks_test.py +0 -0
  128. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/logging.py +0 -0
  129. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/logging_test.py +0 -0
  130. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/loop.py +0 -0
  131. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/loop_test.py +0 -0
  132. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/main.py +0 -0
  133. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/main_test.py +0 -0
  134. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/tasks.py +0 -0
  135. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api/tasks_test.py +0 -0
  136. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/api_test.py +0 -0
  137. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/brief_test.py +0 -0
  138. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/__init__.py +0 -0
  139. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/brief.py +0 -0
  140. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/config_test.py +0 -0
  141. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/exec_cli.py +0 -0
  142. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/exec_cli_test.py +0 -0
  143. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/goal.py +0 -0
  144. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/goal_test.py +0 -0
  145. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/hooks.py +0 -0
  146. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/hooks_test.py +0 -0
  147. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/machine_output_test.py +0 -0
  148. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/operations.py +0 -0
  149. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/operations_test.py +0 -0
  150. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/progress.py +0 -0
  151. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/progress_test.py +0 -0
  152. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/readability_cli.py +0 -0
  153. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/skill.py +0 -0
  154. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/skill_test.py +0 -0
  155. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/stop_test.py +0 -0
  156. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/tasks.py +0 -0
  157. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli/tasks_test.py +0 -0
  158. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/cli_test.py +0 -0
  159. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/conftest.py +0 -0
  160. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/__init__.py +0 -0
  161. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/__main__.py +0 -0
  162. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/evals/scenarios_test.py +0 -0
  163. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/hooks.py +0 -0
  164. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/hooks_test.py +0 -0
  165. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/integration_test.py +0 -0
  166. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/main.py +0 -0
  167. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/main_test.py +0 -0
  168. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/models_test.py +0 -0
  169. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/paths.py +0 -0
  170. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/paths_test.py +0 -0
  171. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/persistence.py +0 -0
  172. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/persistence_test.py +0 -0
  173. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/prompts/hooks/50-readability.md +0 -0
  174. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/prompts/hooks/60-testing.md +0 -0
  175. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/prompts/hooks/70-ux.md +0 -0
  176. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/prompts/hooks/90-roadmap.md +0 -0
  177. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/prompts/taskrunner.md +0 -0
  178. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/prompts.py +0 -0
  179. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/prompts_test.py +0 -0
  180. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/providers.py +0 -0
  181. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/providers_test.py +0 -0
  182. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/scope.py +0 -0
  183. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/scope_test.py +0 -0
  184. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/shutdown.py +0 -0
  185. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/shutdown_integration_test.py +0 -0
  186. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/shutdown_test.py +0 -0
  187. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/__init__.py +0 -0
  188. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/lifecycle.py +0 -0
  189. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/lifecycle_test.py +0 -0
  190. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/limits.py +0 -0
  191. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/operations.py +0 -0
  192. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/operations_test.py +0 -0
  193. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/progress.py +0 -0
  194. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/progress_test.py +0 -0
  195. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/queries.py +0 -0
  196. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/tasks/queries_test.py +0 -0
  197. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/favicon.js +0 -0
  198. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/files.spec.js +0 -0
  199. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/index.js +0 -0
  200. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/logs.test.js +0 -0
  201. {lemming_cli-0.4.2 → lemming_cli-0.4.4}/src/lemming/web/mancha.js +0 -0
@@ -21,23 +21,23 @@ jobs:
21
21
  - name: Install Python dependencies
22
22
  run: uv sync --locked
23
23
 
24
- - name: Run Python linting
25
- run: uv run ruff check .
26
-
27
- - name: Run Python formatting check
28
- run: uv run ruff format --check .
29
-
30
- - name: Run Python tests
31
- run: uv run pytest
32
-
33
24
  - name: Set up Node.js
34
25
  uses: actions/setup-node@v6
35
26
  with:
36
27
  node-version: '20'
37
28
 
29
+ # Before the Python tests: they invoke readability, which runs this.
38
30
  - name: Install Node.js dependencies
39
31
  run: npm install
40
32
 
33
+ # Runs ruff and ruff format as before, and adds the type and prose
34
+ # checks the separate steps never covered.
35
+ - name: Run linting
36
+ run: uv run readability check .
37
+
38
+ - name: Run Python tests
39
+ run: uv run pytest
40
+
41
41
  - name: Run Web linting
42
42
  run: npm run lint
43
43
 
@@ -0,0 +1,13 @@
1
+ .venv
2
+ node_modules
3
+ dist
4
+ src/lemming/web/mancha.js
5
+ test-results
6
+
7
+ # Prompt templates and web views are rendered, not read as markdown or HTML.
8
+ # Prettier is not template-aware: it joined a {{placeholder}} that expands to
9
+ # a multi-line section onto the end of a sentence, and moved a mancha binding
10
+ # onto its own line inside a <button>, changing the rendered whitespace. Both
11
+ # are product behaviour, so neither file set is prettier's to reflow.
12
+ src/lemming/prompts/
13
+ src/lemming/web/
@@ -11,7 +11,8 @@ RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \
11
11
  && rm -rf /var/lib/apt/lists/*
12
12
 
13
13
  # Install AI coding CLIs (antigravity ships a native binary, not an npm package)
14
- RUN npm install -g @openai/codex @anthropic-ai/claude-code \
14
+ RUN npm install -g --allow-scripts=opencode-ai \
15
+ @openai/codex @anthropic-ai/claude-code opencode-ai \
15
16
  && curl -fsSL https://antigravity.google/cli/install.sh | bash -s -- --dir /usr/local/bin
16
17
 
17
18
  # Copy cloudflared and uv binaries directly from their official images
@@ -20,7 +21,8 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
20
21
 
21
22
  WORKDIR /opt/lemming
22
23
  COPY . .
23
- RUN uv sync --no-dev --frozen
24
+ # The evals group carries the linters readability shells out to.
25
+ RUN uv sync --no-dev --group evals --frozen
24
26
 
25
27
  # Frontend dependencies are always needed: postinstall vendors mancha into
26
28
  # the web assets. The browsers are not, and they are more than half the
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: lemming-cli
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: An autonomous, iterative task runner for AI coding agents.
5
5
  Project-URL: Homepage, https://github.com/owahltinez/lemming
6
6
  Project-URL: Repository, https://github.com/owahltinez/lemming
7
7
  Author: Lemming Contributors
8
8
  License: MIT
9
9
  License-File: LICENSE
10
- Keywords: agents,ai,aider,antigravity,automation,claude
10
+ Keywords: agents,ai,antigravity,automation,claude,opencode
11
11
  Requires-Python: >=3.12
12
12
  Requires-Dist: beautifulsoup4>=4.13.3
13
13
  Requires-Dist: click>=8.0.0
@@ -15,7 +15,7 @@ Requires-Dist: fastapi>=0.124.4
15
15
  Requires-Dist: markdownify>=0.14.1
16
16
  Requires-Dist: pydantic>=2.12.5
17
17
  Requires-Dist: pyyaml>=6.0.3
18
- Requires-Dist: readability-cli>=0.7.0
18
+ Requires-Dist: readability-cli>=0.8.5
19
19
  Requires-Dist: requests>=2.32.3
20
20
  Requires-Dist: uvicorn>=0.33.0
21
21
  Description-Content-Type: text/markdown
@@ -38,8 +38,8 @@ human-readable `tasks.yml` file.
38
38
  update is recorded in a human-readable `tasks.yml` file. You can step in,
39
39
  adjust the roadmap, or swap agents at any time.
40
40
  - **Tool Agnostic**: Lemming doesn't care which agent you use. It works
41
- out-of-the-box with `agy`, `aider`, `claude`, `codex`, or even your own custom
42
- scripts.
41
+ out-of-the-box with `agy`, `opencode`, `claude`, `codex`, or even your own
42
+ custom scripts.
43
43
  - **Resilient Execution**: With built-in heartbeat monitoring, automatic
44
44
  retries, and progress tracking, Lemming handles process crashes and rate
45
45
  limits gracefully.
@@ -93,7 +93,7 @@ Start the autonomous loop.
93
93
 
94
94
  ```bash
95
95
  # Run using the project's configured agent (defaults to the first
96
- # supported runner found on PATH: agy, aider, claude, or codex)
96
+ # supported runner found on PATH: agy, opencode, claude, or codex)
97
97
  lemming run
98
98
 
99
99
  # Flags passed after -- are sent directly to the underlying runner
@@ -137,28 +137,29 @@ to the whole tree outside a git repository.
137
137
  Each run is self-contained: nothing is read from the project's roadmap or its
138
138
  local hooks, one agent run is attempted, and the run's state directory is
139
139
  removed unless it failed — in which case it is kept, and its path printed, so
140
- the log can be read. Kept directories live in `~/.local/lemming/exec-*` and
141
- are retired automatically a week later, so a recent failure is always still
142
- there to inspect. Stdout carries the agent's message alone and everything
143
- else goes to stderr, so the output can be consumed directly. Stderr reports
144
- the ephemeral tasks file and task ID at startup; pass those to `lemming
145
- --tasks-file <path> status <id>` or `logs <id>` to inspect an active run. Use
146
- the global verbose flag (`lemming -v exec ...`) to stream runner activity.
140
+ the log can be read. Kept directories live in `~/.local/lemming/exec-*` and are
141
+ retired automatically a week later, so a recent failure is always still there to
142
+ inspect. Stdout carries the agent's message alone and everything else goes to
143
+ stderr, so the output can be consumed directly. Stderr reports the ephemeral
144
+ tasks file and task ID at startup; pass those to
145
+ `lemming --tasks-file <path> status <id>` or `logs <id>` to inspect an active
146
+ run. Use the global verbose flag (`lemming -v exec ...`) to stream runner
147
+ activity.
147
148
 
148
149
  Note that the agent runs unattended (`--yolo` by default), so it does not
149
150
  inherit the permission prompts of whatever launched it.
150
151
 
151
152
  ### Teaching Your Agent to Use It
152
153
 
153
- Lemming ships an Agent Skill so that an agent already running — Claude Code,
154
- Gemini CLI, Cursor — can reach any other agent CLI without knowing how each
155
- one spells its flags. Install it once:
154
+ Lemming ships an Agent Skill so that an agent already running — Codex, Claude
155
+ Code, Gemini CLI, Cursor — can reach any other agent CLI without knowing how
156
+ each one spells its flags. Install it once:
156
157
 
157
158
  ```bash
158
159
  # Cross-tool location (~/.agents/skills), and report any tool-specific ones
159
160
  lemming skill install
160
161
 
161
- # Cover every agent tool detected on this machine
162
+ # Cover detected tools that require their own skill directory too
162
163
  lemming skill install --all
163
164
 
164
165
  # This repository only
@@ -226,17 +227,16 @@ tasks may not fully achieve the stated goal. **Orchestrator Hooks** address this
226
227
  by running custom agents or scripts after each task execution to evaluate
227
228
  results and adapt the roadmap.
228
229
 
229
- Lemming runs every hook it discovers on the filesystem (including the
230
- built-in `roadmap` hook). Hooks are plain Markdown files, and udev-style
231
- filename conventions control their behavior:
230
+ Lemming runs every hook it discovers on the filesystem (including the built-in
231
+ `roadmap` hook). Hooks are plain Markdown files, and udev-style filename
232
+ conventions control their behavior:
232
233
 
233
- - **Ordering**: A numeric prefix sets the execution order (e.g.
234
- `10-lint.md` runs before `90-roadmap.md`); files without a prefix
235
- default to priority 50.
236
- - **Failure hooks**: Hooks at priority 90 and above also run when a task
237
- fails; all others only run on success.
238
- - **Disabling**: An empty file masks (disables) the hook of the same name
239
- from a lower-precedence layer.
234
+ - **Ordering**: A numeric prefix sets the execution order (e.g. `10-lint.md`
235
+ runs before `90-roadmap.md`); files without a prefix default to priority 50.
236
+ - **Failure hooks**: Hooks at priority 90 and above also run when a task fails;
237
+ all others only run on success.
238
+ - **Disabling**: An empty file masks (disables) the hook of the same name from a
239
+ lower-precedence layer.
240
240
 
241
241
  ```bash
242
242
  # Disable a hook for this project (writes an empty .lemming/hooks/50-lint.md)
@@ -255,16 +255,16 @@ Lemming comes with several built-in hooks to help manage your project:
255
255
  needs to be adjusted (e.g., adding a missing prerequisite, skipping obsolete
256
256
  tasks, or breaking down a broad task).
257
257
  - **`readability`**: A code quality and simplification hook that challenges
258
- unnecessary complexity and duplicate implementations, then reviews changes
259
- for adherence to the Google Style Guide and general readability using the
258
+ unnecessary complexity and duplicate implementations, then reviews changes for
259
+ adherence to the Google Style Guide and general readability using the
260
260
  [readability](https://github.com/owahltinez/readability) tool (exposed as
261
261
  `lemming readability`). It can record findings as task progress or suggest
262
262
  follow-up refactoring tasks.
263
263
  - **`testing`**: Verifies that changed behavior has focused test coverage and
264
264
  that the relevant tests pass.
265
- - **`ux`**: Reviews at most one critical user journey affected by a
266
- user-visible change. It reports only concrete, reproducible continuity gaps
267
- and exits immediately for non-user-facing tasks.
265
+ - **`ux`**: Reviews at most one critical user journey affected by a user-visible
266
+ change. It reports only concrete, reproducible continuity gaps and exits
267
+ immediately for non-user-facing tasks.
268
268
 
269
269
  ### Custom and Global Hooks
270
270
 
@@ -273,10 +273,10 @@ You can create your own hooks by adding Markdown files to:
273
273
  1. **Project-specific**: `.lemming/hooks/*.md`
274
274
  2. **Global**: `~/.local/lemming/hooks/*.md`
275
275
 
276
- To **override** a built-in hook, create a file with the same logical name
277
- (the numeric prefix is not part of the name, so `20-roadmap.md` overrides
278
- the built-in `90-roadmap.md` and also moves it to priority 20); delete the
279
- file to restore the built-in version.
276
+ To **override** a built-in hook, create a file with the same logical name (the
277
+ numeric prefix is not part of the name, so `20-roadmap.md` overrides the
278
+ built-in `90-roadmap.md` and also moves it to priority 20); delete the file to
279
+ restore the built-in version.
280
280
 
281
281
  Hooks follow a specific discovery precedence: **Project > Global > Built-in**.
282
282
  See [docs/HOOKS.md](docs/HOOKS.md) for more details.
@@ -293,7 +293,7 @@ lemming hooks list
293
293
  lemming config list
294
294
 
295
295
  # Persist configuration to tasks.yml
296
- lemming config set runner aider
296
+ lemming config set runner opencode
297
297
  ```
298
298
 
299
299
  ### Evaluating Prompt Changes
@@ -316,22 +316,23 @@ See [docs/EVALS.md](docs/EVALS.md) for details.
316
316
 
317
317
  These come before the subcommand and apply to all of them.
318
318
 
319
- - **`-C, --project-dir <dir>`**: Run as if invoked from `<dir>`, addressing
320
- that project's roadmap. Relative paths in other options resolve against it.
321
- See [Working across projects](#working-across-projects).
319
+ - **`-C, --project-dir <dir>`**: Run as if invoked from `<dir>`, addressing that
320
+ project's roadmap. Relative paths in other options resolve against it. See
321
+ [Working across projects](#working-across-projects).
322
322
  - **`--tasks-file <path>`**: Point at a specific tasks file instead of the one
323
323
  derived from the current directory.
324
324
  - **`-v, --verbose`**: Show verbose output.
325
+ - **`--version`**: Print the installed version and exit.
325
326
 
326
327
  ### Roadmap Management
327
328
 
328
- - **`status [<id>]`**: Queue/history overview or deep-dive into a specific
329
- task, including supersession lineage, the last resolved runner command, and
330
- runner/orchestrator-hook execution times. Superseded and failed history
331
- stays visible in the default overview; `--verbose` also shows routine
329
+ - **`status [<id>]`**: Queue/history overview or deep-dive into a specific task,
330
+ including supersession lineage, the last resolved runner command, and
331
+ runner/orchestrator-hook execution times. Superseded and failed history stays
332
+ visible in the default overview; `--verbose` also shows routine
332
333
  completed/cancelled history.
333
- - `--json`: Emit machine-readable JSON instead of formatted text, so
334
- scripts never have to parse the internal state file.
334
+ - `--json`: Emit machine-readable JSON instead of formatted text, so scripts
335
+ never have to parse the internal state file.
335
336
  - `--brief`: Omit task descriptions, which otherwise dominate the output.
336
337
  - **`goal [<text>]`**: Set or view the long-term goal shared by all tasks.
337
338
  Supports `-f/--file`.
@@ -340,8 +341,8 @@ These come before the subcommand and apply to all of them.
340
341
  - **`edit <id>`**: Modify a task's description, runner, model, or position.
341
342
  - **`brief <id> [text]`**: View or set a task's long-form brief. Unlike the
342
343
  description it has no length cap, and it is appended to the runner prompt
343
- automatically — the right home for measured timings, exact failing
344
- selectors, or why a previous attempt was wrong. Supports `-f/--file`.
344
+ automatically — the right home for measured timings, exact failing selectors,
345
+ or why a previous attempt was wrong. Supports `-f/--file`.
345
346
  - **`delete <id>`**: Remove an unstarted task while retaining its runner log.
346
347
  Tasks with execution history require `--force`; autonomous restructuring
347
348
  should use `supersede`. Supports `--all` and `--completed` for bulk cleanup,
@@ -353,11 +354,11 @@ These come before the subcommand and apply to all of them.
353
354
  - `add <id> <finding>`: Record a new technical detail.
354
355
  - `edit <id> <index> <text>`: Modify an existing progress entry.
355
356
  - `delete <id> <index>`: Remove a progress entry.
356
- - **`config`**: Manage project configuration (runner, model, retries,
357
- time limit).
357
+ - **`config`**: Manage project configuration (runner, model, retries, time
358
+ limit).
358
359
  - `list`: View current configuration.
359
- - `set <key> <value>`: Update a setting. `set model default` clears a
360
- pinned model without touching the runner.
360
+ - `set <key> <value>`: Update a setting. `set model default` clears a pinned
361
+ model without touching the runner.
361
362
  - **`hooks`**: Manage orchestrator hooks.
362
363
  - `list`: View available and active hooks.
363
364
  - `install`: Install built-in hooks to the global directory.
@@ -380,12 +381,12 @@ These come before the subcommand and apply to all of them.
380
381
  - **`fail <id>`**: Mark a task as a terminal failure (will not be retried).
381
382
  - **`cancel <id>`**: Stop an in-progress task (kills the runner process).
382
383
  - **`reset <id>`**: Clear attempts and progress to start a task fresh.
383
- - Superseded tasks remain visible as non-failing history; replacement tasks
384
- link back through their parent task ID.
384
+ - Superseded tasks remain visible as non-failing history; replacement tasks link
385
+ back through their parent task ID.
385
386
  - **`logs [<id>]`**: Print a task's execution log to stdout, including retained
386
387
  logs for removed tasks. If no ID is provided, it defaults to the active or
387
- most recent task. Orchestrator hook output is automatically appended.
388
- Supports `--json` to wrap the log with its task ID and path.
388
+ most recent task. Orchestrator hook output is automatically appended. Supports
389
+ `--json` to wrap the log with its task ID and path.
389
390
 
390
391
  ### Execution
391
392
 
@@ -398,17 +399,17 @@ These come before the subcommand and apply to all of them.
398
399
  per-task `--runner`/`--model` overrides anything passed here.
399
400
  - **`exec [<description>]`**: Run one task, or one set of reviews, outside any
400
401
  roadmap. Prints the agent's closing message to stdout and everything else to
401
- stderr, including its tasks file and task ID at startup. Use `lemming -v
402
- exec ...` to stream runner activity. Exits non-zero if the task did not
403
- complete. See [One-off tasks](#one-off-tasks-without-a-roadmap).
402
+ stderr, including its tasks file and task ID at startup. Use
403
+ `lemming -v exec ...` to stream runner activity. Exits non-zero if the task
404
+ did not complete. See [One-off tasks](#one-off-tasks-without-a-roadmap).
404
405
  - `-f/--file`: Read the description from a file, or `-` for stdin. Unlike
405
406
  `add`, there is no length cap.
406
407
  - `--review <names>`: Reviews to run after the task, comma-separated or
407
408
  repeated; `all` selects every one. With no description, only the reviews
408
409
  run. Hooks that revise the roadmap cannot be selected.
409
- - `--scope <path|range>`: What the reviews look at. Paths pass through; a
410
- git revision range is resolved to the files it changed. Defaults to
411
- uncommitted work, or the whole tree outside a repository.
410
+ - `--scope <path|range>`: What the reviews look at. Paths pass through; a git
411
+ revision range is resolved to the files it changed. Defaults to uncommitted
412
+ work, or the whole tree outside a repository.
412
413
  - `--runner`, `--model`: Which agent CLI and model to use.
413
414
  - `--time-limit`: Minutes before the agent is killed (default 60, 0 for no
414
415
  limit).
@@ -422,12 +423,11 @@ These come before the subcommand and apply to all of them.
422
423
  - `--link`: Symlink instead of copying, so upgrades take effect immediately.
423
424
  - `--force`: Replace an existing installation of this skill.
424
425
  - `--dry-run`: Print what would happen, refusals included.
425
- - **`skill uninstall`**: Remove it again. Same `--to`, `--all`, and
426
- `--dry-run`.
426
+ - **`skill uninstall`**: Remove it again. Same `--to`, `--all`, and `--dry-run`.
427
427
  - **`stop`**: Stop the running loop and its runner.
428
428
  - `--after-current-task`: Drain instead — let the running task finish, then
429
- stop before claiming another. This is the safe way to change the runner
430
- or model without stranding work in flight.
429
+ stop before claiming another. This is the safe way to change the runner or
430
+ model without stranding work in flight.
431
431
  - **`serve`**: Launch the interactive Web UI.
432
432
  - `--port`: The port to bind the server to (default: 8999).
433
433
  - `--host`: The host address to bind the server to (default: 127.0.0.1).
@@ -440,10 +440,10 @@ These come before the subcommand and apply to all of them.
440
440
 
441
441
  ## Working across projects
442
442
 
443
- When work on one project turns up something that belongs to another — a bug in
444
- a dependency you also maintain, a doc fix in a sibling repo — file it directly
445
- on that project's roadmap with `-C` instead of routing it through an external
446
- issue tracker:
443
+ When work on one project turns up something that belongs to another — a bug in a
444
+ dependency you also maintain, a doc fix in a sibling repo — file it directly on
445
+ that project's roadmap with `-C` instead of routing it through an external issue
446
+ tracker:
447
447
 
448
448
  ```bash
449
449
  # From inside project A, queue work on project B
@@ -473,9 +473,12 @@ describing why the work was requested, so the report doesn't lose its origin.
473
473
  Lemming uses **fuzzy matching** to automatically inject the correct "YOLO"
474
474
  (auto-approve) and "Quiet" flags for popular tools:
475
475
 
476
- - **Antigravity (`agy`)**: Adds `--dangerously-skip-permissions` and exposes
477
- the project workspace with `--add-dir`
478
- - **Aider**: Adds `--yes --quiet`
476
+ - **Antigravity (`agy`)**: Adds `--dangerously-skip-permissions` and exposes the
477
+ project workspace with `--add-dir`
478
+ - **OpenCode**: Runs non-interactively via `opencode run`, adds `--format json`,
479
+ and, in YOLO mode, adds `--auto`. For its Google provider, Lemming makes an
480
+ existing `GOOGLE_API_KEY` or `GEMINI_API_KEY` available under OpenCode's
481
+ native `GOOGLE_GENERATIVE_AI_API_KEY` name.
479
482
  - **Claude**: Adds `--dangerously-skip-permissions`
480
483
  - **Codex**: Runs non-interactively via `codex exec`, adds `--json`, and, in
481
484
  YOLO mode, adds `--dangerously-bypass-approvals-and-sandbox`
@@ -493,14 +496,14 @@ lemming config set model default # let the runner decide
493
496
 
494
497
  Precedence, highest first: an explicit `--model` inside a runner string, the
495
498
  task's `--model`, the project's `config model`, then anything passed after
496
- `lemming run --`. A per-task setting always wins over the loop-wide
497
- passthrough — the conflicting global flag is dropped rather than duplicated
498
- on the command line.
499
+ `lemming run --`. A per-task setting always wins over the loop-wide passthrough
500
+ — the conflicting global flag is dropped rather than duplicated on the command
501
+ line.
499
502
 
500
503
  ### Runner strings
501
504
 
502
- A runner is not limited to a binary name: any extra arguments in the string
503
- are appended to the command, which is another way to pin per-task behaviour.
505
+ A runner is not limited to a binary name: any extra arguments in the string are
506
+ appended to the command, which is another way to pin per-task behaviour.
504
507
 
505
508
  ```bash
506
509
  lemming add "Try the fast model" --runner "agy --model fast"