marim-harness 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (730) hide show
  1. marim_harness-0.1.0/.env.example +178 -0
  2. marim_harness-0.1.0/.gitea/workflows/ci.yml +71 -0
  3. marim_harness-0.1.0/.gitea/workflows/release.yml +55 -0
  4. marim_harness-0.1.0/.gitignore +56 -0
  5. marim_harness-0.1.0/CHANGELOG.md +39 -0
  6. marim_harness-0.1.0/CLAUDE.md +234 -0
  7. marim_harness-0.1.0/CONTRIBUTING.md +87 -0
  8. marim_harness-0.1.0/LICENSE +21 -0
  9. marim_harness-0.1.0/PKG-INFO +362 -0
  10. marim_harness-0.1.0/README.md +301 -0
  11. marim_harness-0.1.0/SECURITY.md +46 -0
  12. marim_harness-0.1.0/coding-guidelines.md +92 -0
  13. marim_harness-0.1.0/docs/README.md +52 -0
  14. marim_harness-0.1.0/docs/architecture.md +169 -0
  15. marim_harness-0.1.0/docs/assets/demo.gif +0 -0
  16. marim_harness-0.1.0/docs/embedding.md +89 -0
  17. marim_harness-0.1.0/docs/examples/agents/cli-worker.md +9 -0
  18. marim_harness-0.1.0/docs/guides/headless.md +322 -0
  19. marim_harness-0.1.0/docs/guides/hooks.md +322 -0
  20. marim_harness-0.1.0/docs/guides/mcp.md +254 -0
  21. marim_harness-0.1.0/docs/guides/sessions.md +246 -0
  22. marim_harness-0.1.0/docs/guides/skills-and-memory.md +236 -0
  23. marim_harness-0.1.0/docs/guides/subagents.md +269 -0
  24. marim_harness-0.1.0/docs/guides/trust.md +259 -0
  25. marim_harness-0.1.0/docs/guides/tui.md +343 -0
  26. marim_harness-0.1.0/docs/guides/workflows.md +240 -0
  27. marim_harness-0.1.0/docs/internal/context-management-report.md +415 -0
  28. marim_harness-0.1.0/docs/internal/review-coding-guidelines-2026-03-23.md +186 -0
  29. marim_harness-0.1.0/docs/internal/reviews/2026-07-03-codebase-review-no-interfaces.md +131 -0
  30. marim_harness-0.1.0/docs/internal/reviews/2026-07-03-codebase-review.md +192 -0
  31. marim_harness-0.1.0/docs/internal/reviews/2026-07-03-review-parallel-agents-3ef6c46.md +149 -0
  32. marim_harness-0.1.0/docs/internal/reviews/2026-07-21-full-codebase-review.md +223 -0
  33. marim_harness-0.1.0/docs/lsp-plugins.md +109 -0
  34. marim_harness-0.1.0/docs/plugins.md +75 -0
  35. marim_harness-0.1.0/docs/reference/configuration.md +330 -0
  36. marim_harness-0.1.0/docs/reference/serve-api.md +568 -0
  37. marim_harness-0.1.0/docs/sdk/README.md +94 -0
  38. marim_harness-0.1.0/docs/sdk/builder.md +153 -0
  39. marim_harness-0.1.0/docs/sdk/custom-tools.md +103 -0
  40. marim_harness-0.1.0/docs/sdk/getting-started.md +115 -0
  41. marim_harness-0.1.0/docs/sdk/integrations.md +108 -0
  42. marim_harness-0.1.0/docs/sdk/sessions-and-state.md +83 -0
  43. marim_harness-0.1.0/docs/sdk/subagents.md +84 -0
  44. marim_harness-0.1.0/docs/sdk/testing.md +128 -0
  45. marim_harness-0.1.0/docs/sdk/turns.md +123 -0
  46. marim_harness-0.1.0/docs/sdk/tutorial-daily-report.md +320 -0
  47. marim_harness-0.1.0/docs/superpowers/plans/2025-07-19-deps-refactor.md +386 -0
  48. marim_harness-0.1.0/docs/superpowers/plans/2026-03-23-coding-guidelines.md +178 -0
  49. marim_harness-0.1.0/docs/superpowers/plans/2026-06-15-marim-harness.md +1596 -0
  50. marim_harness-0.1.0/docs/superpowers/plans/2026-06-16-agent-refactor.md +988 -0
  51. marim_harness-0.1.0/docs/superpowers/plans/2026-06-16-multi-provider.md +1126 -0
  52. marim_harness-0.1.0/docs/superpowers/plans/2026-06-16-subagent-mcp.md +793 -0
  53. marim_harness-0.1.0/docs/superpowers/plans/2026-06-16-tui-aesthetics.md +777 -0
  54. marim_harness-0.1.0/docs/superpowers/plans/2026-06-17-lsp-integration.md +1568 -0
  55. marim_harness-0.1.0/docs/superpowers/plans/2026-06-17-marim-hooks-engine.md +1499 -0
  56. marim_harness-0.1.0/docs/superpowers/plans/2026-06-18-ask-user-tool.md +853 -0
  57. marim_harness-0.1.0/docs/superpowers/plans/2026-06-18-background-subagents-wake.md +859 -0
  58. marim_harness-0.1.0/docs/superpowers/plans/2026-06-18-decouple-claude-skill-roots.md +307 -0
  59. marim_harness-0.1.0/docs/superpowers/plans/2026-06-18-worktree-workflow.md +751 -0
  60. marim_harness-0.1.0/docs/superpowers/plans/2026-06-19-cli-lazy-imports.md +316 -0
  61. marim_harness-0.1.0/docs/superpowers/plans/2026-06-19-decompose-harnessapp.md +344 -0
  62. marim_harness-0.1.0/docs/superpowers/plans/2026-06-19-image-input.md +1382 -0
  63. marim_harness-0.1.0/docs/superpowers/plans/2026-06-19-output-offload.md +707 -0
  64. marim_harness-0.1.0/docs/superpowers/plans/2026-06-22-agentmemory-missing-hooks.md +730 -0
  65. marim_harness-0.1.0/docs/superpowers/plans/2026-06-22-plugin-system.md +2829 -0
  66. marim_harness-0.1.0/docs/superpowers/plans/2026-06-22-review-recommendations.md +988 -0
  67. marim_harness-0.1.0/docs/superpowers/plans/2026-06-22-review-refactor.md +68 -0
  68. marim_harness-0.1.0/docs/superpowers/plans/2026-06-22-token-efficiency-prompt-caching.md +346 -0
  69. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-checkpoint-rewind.md +1215 -0
  70. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-deps-services-split.md +324 -0
  71. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-harness-bind-ui.md +180 -0
  72. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-harness-init-extraction.md +252 -0
  73. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-message-queueing.md +640 -0
  74. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-message-steering.md +552 -0
  75. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-review-followups-2.md +98 -0
  76. marim_harness-0.1.0/docs/superpowers/plans/2026-06-23-steer-fallback-key.md +130 -0
  77. marim_harness-0.1.0/docs/superpowers/plans/2026-06-24-detached-card-fill.md +464 -0
  78. marim_harness-0.1.0/docs/superpowers/plans/2026-06-24-detached-fanout.md +538 -0
  79. marim_harness-0.1.0/docs/superpowers/plans/2026-06-24-harnessapp-decomposition.md +742 -0
  80. marim_harness-0.1.0/docs/superpowers/plans/2026-06-24-scrollable-panels.md +180 -0
  81. marim_harness-0.1.0/docs/superpowers/plans/2026-06-24-slash-command-autocomplete.md +798 -0
  82. marim_harness-0.1.0/docs/superpowers/plans/2026-06-24-subagents-screen.md +1472 -0
  83. marim_harness-0.1.0/docs/superpowers/plans/2026-06-24-tool-rendering-redesign.md +695 -0
  84. marim_harness-0.1.0/docs/superpowers/plans/2026-06-25-ask-user-chat-display.md +453 -0
  85. marim_harness-0.1.0/docs/superpowers/plans/2026-06-25-claude-cli-subagent.md +1161 -0
  86. marim_harness-0.1.0/docs/superpowers/plans/2026-06-25-marim-mcp-cli.md +718 -0
  87. marim_harness-0.1.0/docs/superpowers/plans/2026-06-25-resumable-subagent-transcripts.md +838 -0
  88. marim_harness-0.1.0/docs/superpowers/plans/2026-06-25-subagents-live-streaming.md +496 -0
  89. marim_harness-0.1.0/docs/superpowers/plans/2026-06-26-multi-provider-model-picker.md +730 -0
  90. marim_harness-0.1.0/docs/superpowers/plans/2026-06-26-native-deep-research.md +442 -0
  91. marim_harness-0.1.0/docs/superpowers/plans/2026-06-26-turn-controller-extraction.md +439 -0
  92. marim_harness-0.1.0/docs/superpowers/plans/2026-06-28-plan-mode.md +948 -0
  93. marim_harness-0.1.0/docs/superpowers/plans/2026-06-28-tool-catalog.md +451 -0
  94. marim_harness-0.1.0/docs/superpowers/plans/2026-06-28-tool-search.md +892 -0
  95. marim_harness-0.1.0/docs/superpowers/plans/2026-06-29-claude-cli-provider.md +1283 -0
  96. marim_harness-0.1.0/docs/superpowers/plans/2026-06-29-mcp-instructions-on-discovery.md +389 -0
  97. marim_harness-0.1.0/docs/superpowers/plans/2026-06-29-mcp-instructions-v2-cacheable.md +364 -0
  98. marim_harness-0.1.0/docs/superpowers/plans/2026-06-30-settings-screen-ux.md +565 -0
  99. marim_harness-0.1.0/docs/superpowers/plans/2026-06-30-subagent-hierarchy.md +663 -0
  100. marim_harness-0.1.0/docs/superpowers/plans/2026-07-01-inline-interaction-panels.md +807 -0
  101. marim_harness-0.1.0/docs/superpowers/plans/2026-07-01-shell-passthrough.md +898 -0
  102. marim_harness-0.1.0/docs/superpowers/plans/2026-07-01-stringified-tool-args-coercion.md +667 -0
  103. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-after-deps-tui.md +591 -0
  104. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-cli-subagent-demux.md +1530 -0
  105. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-context-window-budget.md +1151 -0
  106. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-job-poll-guard.md +399 -0
  107. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-paste-collapsing.md +484 -0
  108. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-scraper-gen-plugin.md +631 -0
  109. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-spawn-after-dependencies.md +751 -0
  110. marim_harness-0.1.0/docs/superpowers/plans/2026-07-02-subagent-context-masking.md +962 -0
  111. marim_harness-0.1.0/docs/superpowers/plans/2026-07-03-claude-md-fallback.md +284 -0
  112. marim_harness-0.1.0/docs/superpowers/plans/2026-07-03-cli-subagent-resume.md +691 -0
  113. marim_harness-0.1.0/docs/superpowers/plans/2026-07-03-subagent-resume.md +1413 -0
  114. marim_harness-0.1.0/docs/superpowers/plans/2026-07-06-marim-serve.md +2831 -0
  115. marim_harness-0.1.0/docs/superpowers/plans/2026-07-06-plan-presentation-tui.md +953 -0
  116. marim_harness-0.1.0/docs/superpowers/plans/2026-07-07-forge-tea-toolset.md +1338 -0
  117. marim_harness-0.1.0/docs/superpowers/plans/2026-07-07-lsp-toolset-deferral.md +491 -0
  118. marim_harness-0.1.0/docs/superpowers/plans/2026-07-07-plancard-feedback.md +424 -0
  119. marim_harness-0.1.0/docs/superpowers/plans/2026-07-08-embeddable-sdk-builder.md +1276 -0
  120. marim_harness-0.1.0/docs/superpowers/plans/2026-07-10-codemode-experiment.md +1415 -0
  121. marim_harness-0.1.0/docs/superpowers/plans/2026-07-10-decompose-runner-controller.md +579 -0
  122. marim_harness-0.1.0/docs/superpowers/plans/2026-07-11-cyclomatic-complexity-reduction.md +521 -0
  123. marim_harness-0.1.0/docs/superpowers/plans/2026-07-11-dynamic-workflows.md +1479 -0
  124. marim_harness-0.1.0/docs/superpowers/plans/2026-07-11-providers-settings.md +1352 -0
  125. marim_harness-0.1.0/docs/superpowers/plans/2026-07-11-scratchpad-directory.md +1160 -0
  126. marim_harness-0.1.0/docs/superpowers/plans/2026-07-11-tui-regroup.md +186 -0
  127. marim_harness-0.1.0/docs/superpowers/plans/2026-07-11-workflows-polish.md +1311 -0
  128. marim_harness-0.1.0/docs/superpowers/plans/2026-07-12-deep-research-workflows.md +810 -0
  129. marim_harness-0.1.0/docs/superpowers/plans/2026-07-12-workflow-resume-journal.md +1078 -0
  130. marim_harness-0.1.0/docs/superpowers/plans/2026-07-13-subagent-model-tiers.md +1017 -0
  131. marim_harness-0.1.0/docs/superpowers/plans/2026-07-21-advisor-tool.md +1780 -0
  132. marim_harness-0.1.0/docs/superpowers/plans/2026-07-21-compaction-pipeline.md +1292 -0
  133. marim_harness-0.1.0/docs/superpowers/plans/2026-07-21-lsp-plugins.md +1558 -0
  134. marim_harness-0.1.0/docs/superpowers/plans/2026-07-22-memory-gaps.md +616 -0
  135. marim_harness-0.1.0/docs/superpowers/plans/2026-07-22-thinking-level.md +2203 -0
  136. marim_harness-0.1.0/docs/superpowers/specs/2025-07-19-deps-refactor-design.md +195 -0
  137. marim_harness-0.1.0/docs/superpowers/specs/2026-06-15-marim-harness-design.md +219 -0
  138. marim_harness-0.1.0/docs/superpowers/specs/2026-06-16-agent-refactor-design.md +151 -0
  139. marim_harness-0.1.0/docs/superpowers/specs/2026-06-16-subagent-mcp-design.md +184 -0
  140. marim_harness-0.1.0/docs/superpowers/specs/2026-06-16-tui-aesthetics-design.md +175 -0
  141. marim_harness-0.1.0/docs/superpowers/specs/2026-06-17-lsp-integration-design.md +161 -0
  142. marim_harness-0.1.0/docs/superpowers/specs/2026-06-17-marim-hooks-engine-design.md +233 -0
  143. marim_harness-0.1.0/docs/superpowers/specs/2026-06-18-ask-user-tool-design.md +215 -0
  144. marim_harness-0.1.0/docs/superpowers/specs/2026-06-18-background-subagents-wake-design.md +270 -0
  145. marim_harness-0.1.0/docs/superpowers/specs/2026-06-18-decouple-claude-skill-roots-design.md +165 -0
  146. marim_harness-0.1.0/docs/superpowers/specs/2026-06-18-worktree-subagent-isolation-notes.md +110 -0
  147. marim_harness-0.1.0/docs/superpowers/specs/2026-06-18-worktree-workflow-design.md +290 -0
  148. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-cli-lazy-imports-design.md +175 -0
  149. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-decompose-harnessapp-design.md +138 -0
  150. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-edit-diff-rendering-design.md +111 -0
  151. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-grep-optimization-design.md +99 -0
  152. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-image-input-design.md +205 -0
  153. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-output-offload-design.md +164 -0
  154. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-session-turn-duration-design.md +88 -0
  155. marim_harness-0.1.0/docs/superpowers/specs/2026-06-19-title-idle-working-design.md +76 -0
  156. marim_harness-0.1.0/docs/superpowers/specs/2026-06-20-compaction-summary-widget-design.md +96 -0
  157. marim_harness-0.1.0/docs/superpowers/specs/2026-06-22-agentmemory-missing-hooks-design.md +153 -0
  158. marim_harness-0.1.0/docs/superpowers/specs/2026-06-22-plugin-system-design.md +314 -0
  159. marim_harness-0.1.0/docs/superpowers/specs/2026-06-22-token-efficiency-prompt-caching-design.md +175 -0
  160. marim_harness-0.1.0/docs/superpowers/specs/2026-06-23-message-queueing-design.md +82 -0
  161. marim_harness-0.1.0/docs/superpowers/specs/2026-06-23-message-steering-design.md +81 -0
  162. marim_harness-0.1.0/docs/superpowers/specs/2026-06-23-steer-fallback-key-design.md +42 -0
  163. marim_harness-0.1.0/docs/superpowers/specs/2026-06-24-detached-card-fill-design.md +119 -0
  164. marim_harness-0.1.0/docs/superpowers/specs/2026-06-24-detached-fanout-design.md +180 -0
  165. marim_harness-0.1.0/docs/superpowers/specs/2026-06-24-harnessapp-decomposition-design.md +159 -0
  166. marim_harness-0.1.0/docs/superpowers/specs/2026-06-24-slash-command-autocomplete-design.md +194 -0
  167. marim_harness-0.1.0/docs/superpowers/specs/2026-06-24-subagents-screen-design.md +205 -0
  168. marim_harness-0.1.0/docs/superpowers/specs/2026-06-24-tool-rendering-redesign-design.md +154 -0
  169. marim_harness-0.1.0/docs/superpowers/specs/2026-06-25-ask-user-chat-display-design.md +169 -0
  170. marim_harness-0.1.0/docs/superpowers/specs/2026-06-25-claude-cli-subagent-design.md +196 -0
  171. marim_harness-0.1.0/docs/superpowers/specs/2026-06-25-marim-mcp-cli-design.md +126 -0
  172. marim_harness-0.1.0/docs/superpowers/specs/2026-06-25-resumable-subagent-transcripts-design.md +194 -0
  173. marim_harness-0.1.0/docs/superpowers/specs/2026-06-25-subagents-live-streaming-design.md +117 -0
  174. marim_harness-0.1.0/docs/superpowers/specs/2026-06-26-multi-provider-model-picker-design.md +165 -0
  175. marim_harness-0.1.0/docs/superpowers/specs/2026-06-26-native-deep-research-design.md +185 -0
  176. marim_harness-0.1.0/docs/superpowers/specs/2026-06-28-plan-mode-design.md +156 -0
  177. marim_harness-0.1.0/docs/superpowers/specs/2026-06-28-tool-catalog-design.md +131 -0
  178. marim_harness-0.1.0/docs/superpowers/specs/2026-06-28-tool-search-design.md +143 -0
  179. marim_harness-0.1.0/docs/superpowers/specs/2026-06-29-claude-cli-provider-design.md +227 -0
  180. marim_harness-0.1.0/docs/superpowers/specs/2026-06-29-mcp-instructions-on-discovery-design.md +134 -0
  181. marim_harness-0.1.0/docs/superpowers/specs/2026-06-29-mcp-instructions-v2-cacheable-design.md +141 -0
  182. marim_harness-0.1.0/docs/superpowers/specs/2026-06-29-nested-subagents-design.md +141 -0
  183. marim_harness-0.1.0/docs/superpowers/specs/2026-06-30-settings-screen-ux-design.md +181 -0
  184. marim_harness-0.1.0/docs/superpowers/specs/2026-06-30-subagent-hierarchy-design.md +174 -0
  185. marim_harness-0.1.0/docs/superpowers/specs/2026-07-01-inline-interaction-panels-design.md +111 -0
  186. marim_harness-0.1.0/docs/superpowers/specs/2026-07-01-shell-passthrough-design.md +117 -0
  187. marim_harness-0.1.0/docs/superpowers/specs/2026-07-01-stringified-tool-args-coercion-design.md +117 -0
  188. marim_harness-0.1.0/docs/superpowers/specs/2026-07-02-after-deps-tui-design.md +129 -0
  189. marim_harness-0.1.0/docs/superpowers/specs/2026-07-02-context-window-budget-design.md +162 -0
  190. marim_harness-0.1.0/docs/superpowers/specs/2026-07-02-job-poll-guard-design.md +133 -0
  191. marim_harness-0.1.0/docs/superpowers/specs/2026-07-02-paste-collapsing-design.md +85 -0
  192. marim_harness-0.1.0/docs/superpowers/specs/2026-07-02-scraper-gen-plugin-design.md +165 -0
  193. marim_harness-0.1.0/docs/superpowers/specs/2026-07-02-spawn-after-dependencies-design.md +163 -0
  194. marim_harness-0.1.0/docs/superpowers/specs/2026-07-03-claude-md-fallback-design.md +101 -0
  195. marim_harness-0.1.0/docs/superpowers/specs/2026-07-03-cli-subagent-resume-design.md +167 -0
  196. marim_harness-0.1.0/docs/superpowers/specs/2026-07-03-subagent-resume-design.md +211 -0
  197. marim_harness-0.1.0/docs/superpowers/specs/2026-07-06-marim-serve-design.md +239 -0
  198. marim_harness-0.1.0/docs/superpowers/specs/2026-07-06-plan-presentation-tui-design.md +182 -0
  199. marim_harness-0.1.0/docs/superpowers/specs/2026-07-07-gitea-tea-toolset-design.md +156 -0
  200. marim_harness-0.1.0/docs/superpowers/specs/2026-07-07-lsp-toolset-deferral-design.md +145 -0
  201. marim_harness-0.1.0/docs/superpowers/specs/2026-07-07-plancard-feedback-design.md +171 -0
  202. marim_harness-0.1.0/docs/superpowers/specs/2026-07-08-embeddable-sdk-builder-design.md +207 -0
  203. marim_harness-0.1.0/docs/superpowers/specs/2026-07-10-acp-interface-design.md +226 -0
  204. marim_harness-0.1.0/docs/superpowers/specs/2026-07-10-codemode-experiment-design.md +155 -0
  205. marim_harness-0.1.0/docs/superpowers/specs/2026-07-11-dynamic-workflows-design.md +187 -0
  206. marim_harness-0.1.0/docs/superpowers/specs/2026-07-11-providers-settings-design.md +158 -0
  207. marim_harness-0.1.0/docs/superpowers/specs/2026-07-11-scratchpad-design.md +133 -0
  208. marim_harness-0.1.0/docs/superpowers/specs/2026-07-11-workflows-polish-design.md +184 -0
  209. marim_harness-0.1.0/docs/superpowers/specs/2026-07-12-deep-research-workflows-design.md +173 -0
  210. marim_harness-0.1.0/docs/superpowers/specs/2026-07-12-workflow-resumability-journal-design.md +199 -0
  211. marim_harness-0.1.0/docs/superpowers/specs/2026-07-13-subagent-model-tiers-design.md +152 -0
  212. marim_harness-0.1.0/docs/superpowers/specs/2026-07-21-advisor-tool-design.md +177 -0
  213. marim_harness-0.1.0/docs/superpowers/specs/2026-07-21-compaction-pipeline-design.md +208 -0
  214. marim_harness-0.1.0/docs/superpowers/specs/2026-07-21-lsp-plugins-design.md +221 -0
  215. marim_harness-0.1.0/docs/superpowers/specs/2026-07-22-memory-gaps-design.md +113 -0
  216. marim_harness-0.1.0/docs/superpowers/specs/2026-07-22-thinking-level-design.md +284 -0
  217. marim_harness-0.1.0/examples/README.md +49 -0
  218. marim_harness-0.1.0/examples/agentmemory/.marim-plugin/plugin.json +46 -0
  219. marim_harness-0.1.0/examples/agentmemory/README.md +79 -0
  220. marim_harness-0.1.0/examples/embedding/README.md +58 -0
  221. marim_harness-0.1.0/examples/embedding/assistant.py +132 -0
  222. marim_harness-0.1.0/examples/playwright/.marim-plugin/plugin.json +8 -0
  223. marim_harness-0.1.0/examples/playwright/AGENTS.md +30 -0
  224. marim_harness-0.1.0/examples/playwright/README.md +48 -0
  225. marim_harness-0.1.0/examples/playwright/agents/generator.md +67 -0
  226. marim_harness-0.1.0/examples/playwright/agents/healer.md +50 -0
  227. marim_harness-0.1.0/examples/playwright/agents/planner.md +55 -0
  228. marim_harness-0.1.0/examples/playwright/mcp.json +8 -0
  229. marim_harness-0.1.0/examples/playwright/skills/e2e-tests/SKILL.md +69 -0
  230. marim_harness-0.1.0/examples/scraper-gen/.marim-plugin/plugin.json +8 -0
  231. marim_harness-0.1.0/examples/scraper-gen/README.md +36 -0
  232. marim_harness-0.1.0/examples/scraper-gen/agents/generator.md +130 -0
  233. marim_harness-0.1.0/examples/scraper-gen/agents/healer.md +43 -0
  234. marim_harness-0.1.0/examples/scraper-gen/agents/planner.md +80 -0
  235. marim_harness-0.1.0/examples/scraper-gen/skills/web-scrapers/SKILL.md +131 -0
  236. marim_harness-0.1.0/examples/superpowers/.marim-plugin/plugin.json +34 -0
  237. marim_harness-0.1.0/examples/superpowers/LICENSE +21 -0
  238. marim_harness-0.1.0/examples/superpowers/README.md +52 -0
  239. marim_harness-0.1.0/examples/superpowers/hooks/marim-session-start.sh +32 -0
  240. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/SKILL.md +159 -0
  241. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/scripts/frame-template.html +213 -0
  242. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/scripts/helper.js +167 -0
  243. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/scripts/server.cjs +723 -0
  244. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/scripts/start-server.sh +209 -0
  245. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/scripts/stop-server.sh +120 -0
  246. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  247. marim_harness-0.1.0/examples/superpowers/skills/brainstorming/visual-companion.md +291 -0
  248. marim_harness-0.1.0/examples/superpowers/skills/dispatching-parallel-agents/SKILL.md +185 -0
  249. marim_harness-0.1.0/examples/superpowers/skills/executing-plans/SKILL.md +70 -0
  250. marim_harness-0.1.0/examples/superpowers/skills/finishing-a-development-branch/SKILL.md +241 -0
  251. marim_harness-0.1.0/examples/superpowers/skills/receiving-code-review/SKILL.md +213 -0
  252. marim_harness-0.1.0/examples/superpowers/skills/requesting-code-review/SKILL.md +103 -0
  253. marim_harness-0.1.0/examples/superpowers/skills/requesting-code-review/code-reviewer.md +172 -0
  254. marim_harness-0.1.0/examples/superpowers/skills/subagent-driven-development/SKILL.md +418 -0
  255. marim_harness-0.1.0/examples/superpowers/skills/subagent-driven-development/implementer-prompt.md +139 -0
  256. marim_harness-0.1.0/examples/superpowers/skills/subagent-driven-development/scripts/review-package +44 -0
  257. marim_harness-0.1.0/examples/superpowers/skills/subagent-driven-development/scripts/sdd-workspace +22 -0
  258. marim_harness-0.1.0/examples/superpowers/skills/subagent-driven-development/scripts/task-brief +40 -0
  259. marim_harness-0.1.0/examples/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +188 -0
  260. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
  261. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/SKILL.md +296 -0
  262. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  263. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
  264. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
  265. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/find-polluter.sh +63 -0
  266. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
  267. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/test-academic.md +14 -0
  268. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
  269. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
  270. marim_harness-0.1.0/examples/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
  271. marim_harness-0.1.0/examples/superpowers/skills/test-driven-development/SKILL.md +371 -0
  272. marim_harness-0.1.0/examples/superpowers/skills/test-driven-development/testing-anti-patterns.md +299 -0
  273. marim_harness-0.1.0/examples/superpowers/skills/using-git-worktrees/SKILL.md +202 -0
  274. marim_harness-0.1.0/examples/superpowers/skills/using-superpowers/SKILL.md +62 -0
  275. marim_harness-0.1.0/examples/superpowers/skills/using-superpowers/references/antigravity-tools.md +23 -0
  276. marim_harness-0.1.0/examples/superpowers/skills/using-superpowers/references/codex-tools.md +39 -0
  277. marim_harness-0.1.0/examples/superpowers/skills/using-superpowers/references/pi-tools.md +16 -0
  278. marim_harness-0.1.0/examples/superpowers/skills/verification-before-completion/SKILL.md +139 -0
  279. marim_harness-0.1.0/examples/superpowers/skills/writing-plans/SKILL.md +174 -0
  280. marim_harness-0.1.0/examples/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
  281. marim_harness-0.1.0/examples/superpowers/skills/writing-skills/SKILL.md +689 -0
  282. marim_harness-0.1.0/examples/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
  283. marim_harness-0.1.0/examples/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  284. marim_harness-0.1.0/examples/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
  285. marim_harness-0.1.0/examples/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
  286. marim_harness-0.1.0/examples/superpowers/skills/writing-skills/render-graphs.js +168 -0
  287. marim_harness-0.1.0/examples/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -0
  288. marim_harness-0.1.0/examples/superpowers/update-from-upstream.sh +79 -0
  289. marim_harness-0.1.0/install.sh +115 -0
  290. marim_harness-0.1.0/pyproject.toml +124 -0
  291. marim_harness-0.1.0/src/marim_harness/__init__.py +36 -0
  292. marim_harness-0.1.0/src/marim_harness/__main__.py +4 -0
  293. marim_harness-0.1.0/src/marim_harness/advisor.py +150 -0
  294. marim_harness-0.1.0/src/marim_harness/ask_user.py +81 -0
  295. marim_harness-0.1.0/src/marim_harness/atomic_io.py +176 -0
  296. marim_harness-0.1.0/src/marim_harness/builtin/agents/researcher.md +40 -0
  297. marim_harness-0.1.0/src/marim_harness/builtin/skills/deep-research/SKILL.md +153 -0
  298. marim_harness-0.1.0/src/marim_harness/command_policy.py +84 -0
  299. marim_harness-0.1.0/src/marim_harness/compaction.py +699 -0
  300. marim_harness-0.1.0/src/marim_harness/config/__init__.py +26 -0
  301. marim_harness-0.1.0/src/marim_harness/config/claude_cli_model.py +901 -0
  302. marim_harness-0.1.0/src/marim_harness/config/context_limits.py +322 -0
  303. marim_harness-0.1.0/src/marim_harness/config/env.py +154 -0
  304. marim_harness-0.1.0/src/marim_harness/config/model.py +599 -0
  305. marim_harness-0.1.0/src/marim_harness/config/openrouter_cost.py +213 -0
  306. marim_harness-0.1.0/src/marim_harness/config/persist.py +99 -0
  307. marim_harness-0.1.0/src/marim_harness/forge/__init__.py +0 -0
  308. marim_harness-0.1.0/src/marim_harness/forge/backend.py +25 -0
  309. marim_harness-0.1.0/src/marim_harness/forge/gitref.py +50 -0
  310. marim_harness-0.1.0/src/marim_harness/forge/models.py +73 -0
  311. marim_harness-0.1.0/src/marim_harness/forge/select.py +21 -0
  312. marim_harness-0.1.0/src/marim_harness/forge/tea_backend.py +245 -0
  313. marim_harness-0.1.0/src/marim_harness/hooks/__init__.py +7 -0
  314. marim_harness-0.1.0/src/marim_harness/hooks/config.py +55 -0
  315. marim_harness-0.1.0/src/marim_harness/hooks/dispatch.py +164 -0
  316. marim_harness-0.1.0/src/marim_harness/hooks/events.py +20 -0
  317. marim_harness-0.1.0/src/marim_harness/hooks/runner.py +260 -0
  318. marim_harness-0.1.0/src/marim_harness/images.py +247 -0
  319. marim_harness-0.1.0/src/marim_harness/interfaces/__init__.py +0 -0
  320. marim_harness-0.1.0/src/marim_harness/interfaces/cli/__init__.py +0 -0
  321. marim_harness-0.1.0/src/marim_harness/interfaces/cli/config.py +153 -0
  322. marim_harness-0.1.0/src/marim_harness/interfaces/cli/default_cmd.py +178 -0
  323. marim_harness-0.1.0/src/marim_harness/interfaces/cli/headless.py +141 -0
  324. marim_harness-0.1.0/src/marim_harness/interfaces/cli/mcp.py +217 -0
  325. marim_harness-0.1.0/src/marim_harness/interfaces/cli/models.py +50 -0
  326. marim_harness-0.1.0/src/marim_harness/interfaces/cli/plugin.py +269 -0
  327. marim_harness-0.1.0/src/marim_harness/interfaces/cli/router.py +73 -0
  328. marim_harness-0.1.0/src/marim_harness/interfaces/cli/serve.py +64 -0
  329. marim_harness-0.1.0/src/marim_harness/interfaces/cli/sessions.py +102 -0
  330. marim_harness-0.1.0/src/marim_harness/interfaces/durations.py +20 -0
  331. marim_harness-0.1.0/src/marim_harness/interfaces/history.py +71 -0
  332. marim_harness-0.1.0/src/marim_harness/interfaces/prefs.py +49 -0
  333. marim_harness-0.1.0/src/marim_harness/interfaces/tui/__init__.py +0 -0
  334. marim_harness-0.1.0/src/marim_harness/interfaces/tui/app.py +1213 -0
  335. marim_harness-0.1.0/src/marim_harness/interfaces/tui/commands.py +635 -0
  336. marim_harness-0.1.0/src/marim_harness/interfaces/tui/interactions/__init__.py +15 -0
  337. marim_harness-0.1.0/src/marim_harness/interfaces/tui/interactions/approval.py +130 -0
  338. marim_harness-0.1.0/src/marim_harness/interfaces/tui/interactions/ask_user.py +222 -0
  339. marim_harness-0.1.0/src/marim_harness/interfaces/tui/interactions/ask_user_render.py +131 -0
  340. marim_harness-0.1.0/src/marim_harness/interfaces/tui/interactions/base.py +114 -0
  341. marim_harness-0.1.0/src/marim_harness/interfaces/tui/interactions/plan_card.py +100 -0
  342. marim_harness-0.1.0/src/marim_harness/interfaces/tui/model_picker.py +147 -0
  343. marim_harness-0.1.0/src/marim_harness/interfaces/tui/notify.py +36 -0
  344. marim_harness-0.1.0/src/marim_harness/interfaces/tui/plan_screen.py +63 -0
  345. marim_harness-0.1.0/src/marim_harness/interfaces/tui/providers.py +429 -0
  346. marim_harness-0.1.0/src/marim_harness/interfaces/tui/queue.py +88 -0
  347. marim_harness-0.1.0/src/marim_harness/interfaces/tui/session_view.py +537 -0
  348. marim_harness-0.1.0/src/marim_harness/interfaces/tui/settings.py +925 -0
  349. marim_harness-0.1.0/src/marim_harness/interfaces/tui/shell_passthrough.py +154 -0
  350. marim_harness-0.1.0/src/marim_harness/interfaces/tui/status.py +171 -0
  351. marim_harness-0.1.0/src/marim_harness/interfaces/tui/stream_render.py +1126 -0
  352. marim_harness-0.1.0/src/marim_harness/interfaces/tui/styles.tcss +147 -0
  353. marim_harness-0.1.0/src/marim_harness/interfaces/tui/subagents/__init__.py +18 -0
  354. marim_harness-0.1.0/src/marim_harness/interfaces/tui/subagents/card.py +427 -0
  355. marim_harness-0.1.0/src/marim_harness/interfaces/tui/subagents/list.py +52 -0
  356. marim_harness-0.1.0/src/marim_harness/interfaces/tui/subagents/pane.py +208 -0
  357. marim_harness-0.1.0/src/marim_harness/interfaces/tui/subagents/screen.py +255 -0
  358. marim_harness-0.1.0/src/marim_harness/interfaces/tui/subagents/stats.py +126 -0
  359. marim_harness-0.1.0/src/marim_harness/interfaces/tui/subagents/view.py +111 -0
  360. marim_harness-0.1.0/src/marim_harness/interfaces/tui/themes.py +55 -0
  361. marim_harness-0.1.0/src/marim_harness/interfaces/tui/thinking_picker.py +70 -0
  362. marim_harness-0.1.0/src/marim_harness/interfaces/tui/wake.py +57 -0
  363. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/__init__.py +64 -0
  364. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/autocomplete.py +106 -0
  365. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/diff.py +212 -0
  366. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/format.py +42 -0
  367. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/highlight.py +96 -0
  368. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/messages.py +347 -0
  369. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/panels.py +198 -0
  370. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/prompt.py +509 -0
  371. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/tool_summary.py +190 -0
  372. marim_harness-0.1.0/src/marim_harness/interfaces/tui/widgets/tools.py +506 -0
  373. marim_harness-0.1.0/src/marim_harness/jobs.py +517 -0
  374. marim_harness-0.1.0/src/marim_harness/lsp/__init__.py +1 -0
  375. marim_harness-0.1.0/src/marim_harness/lsp/basedpyright.py +155 -0
  376. marim_harness-0.1.0/src/marim_harness/lsp/bundled/cpp/.marim-plugin/plugin.json +12 -0
  377. marim_harness-0.1.0/src/marim_harness/lsp/bundled/java/.marim-plugin/plugin.json +12 -0
  378. marim_harness-0.1.0/src/marim_harness/lsp/bundled/python/.marim-plugin/plugin.json +12 -0
  379. marim_harness-0.1.0/src/marim_harness/lsp/bundled/typescript/.marim-plugin/plugin.json +12 -0
  380. marim_harness-0.1.0/src/marim_harness/lsp/bundled.py +52 -0
  381. marim_harness-0.1.0/src/marim_harness/lsp/checks.py +195 -0
  382. marim_harness-0.1.0/src/marim_harness/lsp/diagnostics.py +75 -0
  383. marim_harness-0.1.0/src/marim_harness/lsp/generic.py +163 -0
  384. marim_harness-0.1.0/src/marim_harness/lsp/manager.py +591 -0
  385. marim_harness-0.1.0/src/marim_harness/lsp/provider.py +220 -0
  386. marim_harness-0.1.0/src/marim_harness/lsp/registry.py +110 -0
  387. marim_harness-0.1.0/src/marim_harness/mcp/__init__.py +21 -0
  388. marim_harness-0.1.0/src/marim_harness/mcp/catalog.py +62 -0
  389. marim_harness-0.1.0/src/marim_harness/mcp/config.py +474 -0
  390. marim_harness-0.1.0/src/marim_harness/mcp/discovered_instructions_capability.py +84 -0
  391. marim_harness-0.1.0/src/marim_harness/mcp/manager.py +356 -0
  392. marim_harness-0.1.0/src/marim_harness/notifications.py +244 -0
  393. marim_harness-0.1.0/src/marim_harness/plugins/__init__.py +85 -0
  394. marim_harness-0.1.0/src/marim_harness/plugins/discovery.py +485 -0
  395. marim_harness-0.1.0/src/marim_harness/plugins/install.py +342 -0
  396. marim_harness-0.1.0/src/marim_harness/plugins/manifest.py +165 -0
  397. marim_harness-0.1.0/src/marim_harness/plugins/state.py +105 -0
  398. marim_harness-0.1.0/src/marim_harness/py.typed +0 -0
  399. marim_harness-0.1.0/src/marim_harness/read_only_commands.py +255 -0
  400. marim_harness-0.1.0/src/marim_harness/runtime/__init__.py +19 -0
  401. marim_harness-0.1.0/src/marim_harness/runtime/bootstrap.py +221 -0
  402. marim_harness-0.1.0/src/marim_harness/runtime/builder.py +458 -0
  403. marim_harness-0.1.0/src/marim_harness/runtime/context.py +169 -0
  404. marim_harness-0.1.0/src/marim_harness/runtime/controller.py +1092 -0
  405. marim_harness-0.1.0/src/marim_harness/runtime/deps.py +312 -0
  406. marim_harness-0.1.0/src/marim_harness/runtime/errors.py +389 -0
  407. marim_harness-0.1.0/src/marim_harness/runtime/harness.py +912 -0
  408. marim_harness-0.1.0/src/marim_harness/runtime/instructions.py +395 -0
  409. marim_harness-0.1.0/src/marim_harness/runtime/permissions.py +134 -0
  410. marim_harness-0.1.0/src/marim_harness/runtime/toolsets.py +74 -0
  411. marim_harness-0.1.0/src/marim_harness/runtime/ttft.py +63 -0
  412. marim_harness-0.1.0/src/marim_harness/server/__init__.py +5 -0
  413. marim_harness-0.1.0/src/marim_harness/server/auth.py +29 -0
  414. marim_harness-0.1.0/src/marim_harness/server/bus.py +124 -0
  415. marim_harness-0.1.0/src/marim_harness/server/host.py +309 -0
  416. marim_harness-0.1.0/src/marim_harness/server/http.py +480 -0
  417. marim_harness-0.1.0/src/marim_harness/server/schema.py +79 -0
  418. marim_harness-0.1.0/src/marim_harness/server/supervisor.py +219 -0
  419. marim_harness-0.1.0/src/marim_harness/server/workspaces.py +130 -0
  420. marim_harness-0.1.0/src/marim_harness/session/__init__.py +11 -0
  421. marim_harness-0.1.0/src/marim_harness/session/checkpoints.py +487 -0
  422. marim_harness-0.1.0/src/marim_harness/session/ctrl.py +860 -0
  423. marim_harness-0.1.0/src/marim_harness/session/store.py +508 -0
  424. marim_harness-0.1.0/src/marim_harness/session/transcripts.py +139 -0
  425. marim_harness-0.1.0/src/marim_harness/stream_events.py +44 -0
  426. marim_harness-0.1.0/src/marim_harness/subagents/__init__.py +14 -0
  427. marim_harness-0.1.0/src/marim_harness/subagents/backend.py +69 -0
  428. marim_harness-0.1.0/src/marim_harness/subagents/cli_backend.py +728 -0
  429. marim_harness-0.1.0/src/marim_harness/subagents/cli_demux.py +279 -0
  430. marim_harness-0.1.0/src/marim_harness/subagents/cli_spawn.py +269 -0
  431. marim_harness-0.1.0/src/marim_harness/subagents/isolation.py +117 -0
  432. marim_harness-0.1.0/src/marim_harness/subagents/masking.py +113 -0
  433. marim_harness-0.1.0/src/marim_harness/subagents/output_schema.py +42 -0
  434. marim_harness-0.1.0/src/marim_harness/subagents/persistence.py +99 -0
  435. marim_harness-0.1.0/src/marim_harness/subagents/policies.py +78 -0
  436. marim_harness-0.1.0/src/marim_harness/subagents/run_driver.py +274 -0
  437. marim_harness-0.1.0/src/marim_harness/subagents/runner.py +1165 -0
  438. marim_harness-0.1.0/src/marim_harness/subagents/tiers.py +25 -0
  439. marim_harness-0.1.0/src/marim_harness/tasks.py +99 -0
  440. marim_harness-0.1.0/src/marim_harness/thinking.py +79 -0
  441. marim_harness-0.1.0/src/marim_harness/tools/__init__.py +0 -0
  442. marim_harness-0.1.0/src/marim_harness/tools/advisor_tools.py +56 -0
  443. marim_harness-0.1.0/src/marim_harness/tools/edit_tools.py +141 -0
  444. marim_harness-0.1.0/src/marim_harness/tools/forge_tools.py +193 -0
  445. marim_harness-0.1.0/src/marim_harness/tools/fs_tools.py +127 -0
  446. marim_harness-0.1.0/src/marim_harness/tools/impl/__init__.py +10 -0
  447. marim_harness-0.1.0/src/marim_harness/tools/impl/coerce.py +150 -0
  448. marim_harness-0.1.0/src/marim_harness/tools/impl/fetch.py +405 -0
  449. marim_harness-0.1.0/src/marim_harness/tools/impl/fs.py +793 -0
  450. marim_harness-0.1.0/src/marim_harness/tools/impl/offload.py +96 -0
  451. marim_harness-0.1.0/src/marim_harness/tools/impl/shell.py +387 -0
  452. marim_harness-0.1.0/src/marim_harness/tools/impl/suggest.py +114 -0
  453. marim_harness-0.1.0/src/marim_harness/tools/impl/web.py +132 -0
  454. marim_harness-0.1.0/src/marim_harness/tools/job_tools.py +158 -0
  455. marim_harness-0.1.0/src/marim_harness/tools/lenient.py +35 -0
  456. marim_harness-0.1.0/src/marim_harness/tools/lsp_tools.py +78 -0
  457. marim_harness-0.1.0/src/marim_harness/tools/memory_tools.py +95 -0
  458. marim_harness-0.1.0/src/marim_harness/tools/names.py +56 -0
  459. marim_harness-0.1.0/src/marim_harness/tools/net_tools.py +37 -0
  460. marim_harness-0.1.0/src/marim_harness/tools/planning_tools.py +182 -0
  461. marim_harness-0.1.0/src/marim_harness/tools/provider.py +244 -0
  462. marim_harness-0.1.0/src/marim_harness/tools/skill_tools.py +49 -0
  463. marim_harness-0.1.0/src/marim_harness/tools/spawn_tools.py +378 -0
  464. marim_harness-0.1.0/src/marim_harness/tools/workflow_tools.py +140 -0
  465. marim_harness-0.1.0/src/marim_harness/trust.py +41 -0
  466. marim_harness-0.1.0/src/marim_harness/usage.py +137 -0
  467. marim_harness-0.1.0/src/marim_harness/workflows/__init__.py +6 -0
  468. marim_harness-0.1.0/src/marim_harness/workflows/engine.py +420 -0
  469. marim_harness-0.1.0/src/marim_harness/workflows/errors.py +13 -0
  470. marim_harness-0.1.0/src/marim_harness/workflows/schema.py +83 -0
  471. marim_harness-0.1.0/src/marim_harness/workspace/__init__.py +88 -0
  472. marim_harness-0.1.0/src/marim_harness/workspace/_discovery.py +46 -0
  473. marim_harness-0.1.0/src/marim_harness/workspace/_frontmatter.py +11 -0
  474. marim_harness-0.1.0/src/marim_harness/workspace/agents.py +499 -0
  475. marim_harness-0.1.0/src/marim_harness/workspace/catalog.py +281 -0
  476. marim_harness-0.1.0/src/marim_harness/workspace/fs.py +63 -0
  477. marim_harness-0.1.0/src/marim_harness/workspace/identifiers.py +16 -0
  478. marim_harness-0.1.0/src/marim_harness/workspace/memory.py +269 -0
  479. marim_harness-0.1.0/src/marim_harness/workspace/plans.py +72 -0
  480. marim_harness-0.1.0/src/marim_harness/workspace/scratchpad.py +115 -0
  481. marim_harness-0.1.0/src/marim_harness/workspace/skills.py +273 -0
  482. marim_harness-0.1.0/src/marim_harness/workspace/snapshot.py +357 -0
  483. marim_harness-0.1.0/src/marim_harness/workspace/worktree.py +208 -0
  484. marim_harness-0.1.0/tests/__init__.py +0 -0
  485. marim_harness-0.1.0/tests/conftest.py +228 -0
  486. marim_harness-0.1.0/tests/fake_lsp_server.py +62 -0
  487. marim_harness-0.1.0/tests/fixtures/plugins/demo-plugin/.marim-plugin/plugin.json +7 -0
  488. marim_harness-0.1.0/tests/fixtures/plugins/demo-plugin/AGENTS.md +1 -0
  489. marim_harness-0.1.0/tests/fixtures/plugins/demo-plugin/agents/reviewer.md +6 -0
  490. marim_harness-0.1.0/tests/fixtures/plugins/demo-plugin/hooks/hooks.json +7 -0
  491. marim_harness-0.1.0/tests/fixtures/plugins/demo-plugin/mcp.json +5 -0
  492. marim_harness-0.1.0/tests/fixtures/plugins/demo-plugin/skills/greet/SKILL.md +6 -0
  493. marim_harness-0.1.0/tests/fixtures/session_v1_pydantic_ai_1107.json +1 -0
  494. marim_harness-0.1.0/tests/test_advisor.py +94 -0
  495. marim_harness-0.1.0/tests/test_advisor_command.py +51 -0
  496. marim_harness-0.1.0/tests/test_advisor_instructions.py +26 -0
  497. marim_harness-0.1.0/tests/test_advisor_render.py +12 -0
  498. marim_harness-0.1.0/tests/test_advisor_session.py +54 -0
  499. marim_harness-0.1.0/tests/test_advisor_tool.py +106 -0
  500. marim_harness-0.1.0/tests/test_advisor_wiring.py +96 -0
  501. marim_harness-0.1.0/tests/test_agent.py +506 -0
  502. marim_harness-0.1.0/tests/test_agent_autoname.py +226 -0
  503. marim_harness-0.1.0/tests/test_agent_backend_field.py +44 -0
  504. marim_harness-0.1.0/tests/test_agent_checkpoints.py +53 -0
  505. marim_harness-0.1.0/tests/test_agent_consumables.py +156 -0
  506. marim_harness-0.1.0/tests/test_agent_hooks.py +526 -0
  507. marim_harness-0.1.0/tests/test_agent_instructions.py +247 -0
  508. marim_harness-0.1.0/tests/test_agent_mcp.py +465 -0
  509. marim_harness-0.1.0/tests/test_agent_sessions.py +598 -0
  510. marim_harness-0.1.0/tests/test_agent_subagents.py +593 -0
  511. marim_harness-0.1.0/tests/test_agents.py +462 -0
  512. marim_harness-0.1.0/tests/test_app.py +4167 -0
  513. marim_harness-0.1.0/tests/test_app_decomposition.py +104 -0
  514. marim_harness-0.1.0/tests/test_app_present_plan.py +73 -0
  515. marim_harness-0.1.0/tests/test_app_turn_race.py +224 -0
  516. marim_harness-0.1.0/tests/test_approval.py +173 -0
  517. marim_harness-0.1.0/tests/test_ask_user.py +41 -0
  518. marim_harness-0.1.0/tests/test_ask_user_panel.py +313 -0
  519. marim_harness-0.1.0/tests/test_ask_user_render.py +86 -0
  520. marim_harness-0.1.0/tests/test_ask_user_tool.py +132 -0
  521. marim_harness-0.1.0/tests/test_atomic_io.py +171 -0
  522. marim_harness-0.1.0/tests/test_autocomplete.py +305 -0
  523. marim_harness-0.1.0/tests/test_autocomplete_integration.py +278 -0
  524. marim_harness-0.1.0/tests/test_aux_model_clone.py +105 -0
  525. marim_harness-0.1.0/tests/test_bootstrap.py +460 -0
  526. marim_harness-0.1.0/tests/test_builder.py +278 -0
  527. marim_harness-0.1.0/tests/test_builder_turns.py +71 -0
  528. marim_harness-0.1.0/tests/test_catalog.py +392 -0
  529. marim_harness-0.1.0/tests/test_checkpoints.py +663 -0
  530. marim_harness-0.1.0/tests/test_claude_cli_model.py +804 -0
  531. marim_harness-0.1.0/tests/test_cli.py +286 -0
  532. marim_harness-0.1.0/tests/test_cli_backend.py +177 -0
  533. marim_harness-0.1.0/tests/test_cli_demux.py +211 -0
  534. marim_harness-0.1.0/tests/test_cli_serve.py +45 -0
  535. marim_harness-0.1.0/tests/test_cli_startup.py +49 -0
  536. marim_harness-0.1.0/tests/test_coerce.py +148 -0
  537. marim_harness-0.1.0/tests/test_command_policy.py +70 -0
  538. marim_harness-0.1.0/tests/test_commands.py +696 -0
  539. marim_harness-0.1.0/tests/test_compaction.py +666 -0
  540. marim_harness-0.1.0/tests/test_config.py +1027 -0
  541. marim_harness-0.1.0/tests/test_config_cli.py +265 -0
  542. marim_harness-0.1.0/tests/test_config_seams.py +170 -0
  543. marim_harness-0.1.0/tests/test_context.py +28 -0
  544. marim_harness-0.1.0/tests/test_context_limits.py +270 -0
  545. marim_harness-0.1.0/tests/test_deep_research_skill.py +37 -0
  546. marim_harness-0.1.0/tests/test_default_cmd.py +16 -0
  547. marim_harness-0.1.0/tests/test_deps.py +116 -0
  548. marim_harness-0.1.0/tests/test_deps_plan.py +25 -0
  549. marim_harness-0.1.0/tests/test_detach_fanout.py +236 -0
  550. marim_harness-0.1.0/tests/test_discovered_instructions_capability.py +109 -0
  551. marim_harness-0.1.0/tests/test_docs_reference.py +67 -0
  552. marim_harness-0.1.0/tests/test_env_blocklist.py +198 -0
  553. marim_harness-0.1.0/tests/test_errors_transient_precision.py +55 -0
  554. marim_harness-0.1.0/tests/test_examples_agentmemory_plugin.py +47 -0
  555. marim_harness-0.1.0/tests/test_examples_embedding.py +82 -0
  556. marim_harness-0.1.0/tests/test_examples_playwright_plugin.py +58 -0
  557. marim_harness-0.1.0/tests/test_examples_scraper_gen_plugin.py +54 -0
  558. marim_harness-0.1.0/tests/test_examples_superpowers_plugin.py +58 -0
  559. marim_harness-0.1.0/tests/test_fetch.py +682 -0
  560. marim_harness-0.1.0/tests/test_finished_job_notifier.py +44 -0
  561. marim_harness-0.1.0/tests/test_forge_gitref.py +41 -0
  562. marim_harness-0.1.0/tests/test_forge_models.py +28 -0
  563. marim_harness-0.1.0/tests/test_forge_select.py +20 -0
  564. marim_harness-0.1.0/tests/test_forge_tea_backend.py +335 -0
  565. marim_harness-0.1.0/tests/test_forge_tools.py +188 -0
  566. marim_harness-0.1.0/tests/test_forge_wiring.py +29 -0
  567. marim_harness-0.1.0/tests/test_fs.py +822 -0
  568. marim_harness-0.1.0/tests/test_headless.py +311 -0
  569. marim_harness-0.1.0/tests/test_history.py +71 -0
  570. marim_harness-0.1.0/tests/test_hooks_config.py +54 -0
  571. marim_harness-0.1.0/tests/test_hooks_events.py +35 -0
  572. marim_harness-0.1.0/tests/test_hooks_runner.py +352 -0
  573. marim_harness-0.1.0/tests/test_image_attachments.py +41 -0
  574. marim_harness-0.1.0/tests/test_image_paste.py +270 -0
  575. marim_harness-0.1.0/tests/test_images.py +155 -0
  576. marim_harness-0.1.0/tests/test_imports.py +26 -0
  577. marim_harness-0.1.0/tests/test_instructions.py +279 -0
  578. marim_harness-0.1.0/tests/test_interaction_panel.py +147 -0
  579. marim_harness-0.1.0/tests/test_jobs.py +681 -0
  580. marim_harness-0.1.0/tests/test_jobs_tools.py +205 -0
  581. marim_harness-0.1.0/tests/test_live_smoke.py +46 -0
  582. marim_harness-0.1.0/tests/test_logging.py +275 -0
  583. marim_harness-0.1.0/tests/test_lsp_basedpyright.py +147 -0
  584. marim_harness-0.1.0/tests/test_lsp_bootstrap_gate.py +39 -0
  585. marim_harness-0.1.0/tests/test_lsp_bundled.py +28 -0
  586. marim_harness-0.1.0/tests/test_lsp_checks.py +181 -0
  587. marim_harness-0.1.0/tests/test_lsp_diagnostics.py +91 -0
  588. marim_harness-0.1.0/tests/test_lsp_generic.py +50 -0
  589. marim_harness-0.1.0/tests/test_lsp_integration.py +34 -0
  590. marim_harness-0.1.0/tests/test_lsp_manager.py +545 -0
  591. marim_harness-0.1.0/tests/test_lsp_manager_registry.py +61 -0
  592. marim_harness-0.1.0/tests/test_lsp_plugin_discovery.py +68 -0
  593. marim_harness-0.1.0/tests/test_lsp_provider.py +196 -0
  594. marim_harness-0.1.0/tests/test_lsp_registry.py +165 -0
  595. marim_harness-0.1.0/tests/test_lsp_tools.py +180 -0
  596. marim_harness-0.1.0/tests/test_lsp_toolset.py +17 -0
  597. marim_harness-0.1.0/tests/test_lsp_wiring.py +29 -0
  598. marim_harness-0.1.0/tests/test_mcp.py +751 -0
  599. marim_harness-0.1.0/tests/test_mcp_cli.py +240 -0
  600. marim_harness-0.1.0/tests/test_mcp_enable_status.py +77 -0
  601. marim_harness-0.1.0/tests/test_mcp_tool_search.py +208 -0
  602. marim_harness-0.1.0/tests/test_memory.py +455 -0
  603. marim_harness-0.1.0/tests/test_memory_tool.py +210 -0
  604. marim_harness-0.1.0/tests/test_model_picker.py +179 -0
  605. marim_harness-0.1.0/tests/test_models_cli.py +94 -0
  606. marim_harness-0.1.0/tests/test_notifications.py +324 -0
  607. marim_harness-0.1.0/tests/test_notifications_async.py +137 -0
  608. marim_harness-0.1.0/tests/test_offload.py +97 -0
  609. marim_harness-0.1.0/tests/test_openrouter_cost.py +98 -0
  610. marim_harness-0.1.0/tests/test_openrouter_cost_live.py +49 -0
  611. marim_harness-0.1.0/tests/test_paste_collapse.py +214 -0
  612. marim_harness-0.1.0/tests/test_permissions.py +302 -0
  613. marim_harness-0.1.0/tests/test_persist.py +151 -0
  614. marim_harness-0.1.0/tests/test_plan_card.py +161 -0
  615. marim_harness-0.1.0/tests/test_plan_mode_e2e.py +145 -0
  616. marim_harness-0.1.0/tests/test_plan_screen.py +59 -0
  617. marim_harness-0.1.0/tests/test_plans.py +47 -0
  618. marim_harness-0.1.0/tests/test_plugin_agents.py +123 -0
  619. marim_harness-0.1.0/tests/test_plugin_cli.py +186 -0
  620. marim_harness-0.1.0/tests/test_plugin_command.py +82 -0
  621. marim_harness-0.1.0/tests/test_plugin_discovery.py +370 -0
  622. marim_harness-0.1.0/tests/test_plugin_hooks.py +106 -0
  623. marim_harness-0.1.0/tests/test_plugin_install.py +532 -0
  624. marim_harness-0.1.0/tests/test_plugin_instructions.py +158 -0
  625. marim_harness-0.1.0/tests/test_plugin_integration.py +44 -0
  626. marim_harness-0.1.0/tests/test_plugin_linked_elevation.py +129 -0
  627. marim_harness-0.1.0/tests/test_plugin_manifest.py +116 -0
  628. marim_harness-0.1.0/tests/test_plugin_mcp.py +82 -0
  629. marim_harness-0.1.0/tests/test_plugin_security.py +194 -0
  630. marim_harness-0.1.0/tests/test_plugin_skills.py +68 -0
  631. marim_harness-0.1.0/tests/test_plugin_state.py +68 -0
  632. marim_harness-0.1.0/tests/test_prefs.py +36 -0
  633. marim_harness-0.1.0/tests/test_present_plan_tool.py +100 -0
  634. marim_harness-0.1.0/tests/test_provider.py +1106 -0
  635. marim_harness-0.1.0/tests/test_provider_errors.py +694 -0
  636. marim_harness-0.1.0/tests/test_providers_section.py +663 -0
  637. marim_harness-0.1.0/tests/test_queue.py +300 -0
  638. marim_harness-0.1.0/tests/test_read_ledger.py +198 -0
  639. marim_harness-0.1.0/tests/test_read_only_commands.py +153 -0
  640. marim_harness-0.1.0/tests/test_recovery.py +693 -0
  641. marim_harness-0.1.0/tests/test_resume_transcript.py +51 -0
  642. marim_harness-0.1.0/tests/test_run_failure_recovery.py +187 -0
  643. marim_harness-0.1.0/tests/test_runtime_toolsets.py +123 -0
  644. marim_harness-0.1.0/tests/test_scratchpad.py +186 -0
  645. marim_harness-0.1.0/tests/test_server_auth.py +19 -0
  646. marim_harness-0.1.0/tests/test_server_bus.py +82 -0
  647. marim_harness-0.1.0/tests/test_server_host.py +212 -0
  648. marim_harness-0.1.0/tests/test_server_http.py +463 -0
  649. marim_harness-0.1.0/tests/test_server_schema.py +30 -0
  650. marim_harness-0.1.0/tests/test_server_supervisor.py +297 -0
  651. marim_harness-0.1.0/tests/test_server_workspaces.py +140 -0
  652. marim_harness-0.1.0/tests/test_server_ws.py +200 -0
  653. marim_harness-0.1.0/tests/test_session.py +1474 -0
  654. marim_harness-0.1.0/tests/test_session_duration.py +55 -0
  655. marim_harness-0.1.0/tests/test_session_persist_cache.py +280 -0
  656. marim_harness-0.1.0/tests/test_session_sanitize.py +100 -0
  657. marim_harness-0.1.0/tests/test_session_store_isolation.py +21 -0
  658. marim_harness-0.1.0/tests/test_session_store_lock.py +123 -0
  659. marim_harness-0.1.0/tests/test_session_tool_search_roundtrip.py +65 -0
  660. marim_harness-0.1.0/tests/test_session_v1_compat.py +56 -0
  661. marim_harness-0.1.0/tests/test_session_view_replay.py +754 -0
  662. marim_harness-0.1.0/tests/test_sessions_cli.py +128 -0
  663. marim_harness-0.1.0/tests/test_settings_screen.py +858 -0
  664. marim_harness-0.1.0/tests/test_shell.py +421 -0
  665. marim_harness-0.1.0/tests/test_shell_passthrough.py +125 -0
  666. marim_harness-0.1.0/tests/test_skills.py +339 -0
  667. marim_harness-0.1.0/tests/test_skills_tool.py +188 -0
  668. marim_harness-0.1.0/tests/test_snapshot.py +373 -0
  669. marim_harness-0.1.0/tests/test_spawn_transcripts.py +104 -0
  670. marim_harness-0.1.0/tests/test_spawn_worktree.py +100 -0
  671. marim_harness-0.1.0/tests/test_steering.py +448 -0
  672. marim_harness-0.1.0/tests/test_stream_events.py +61 -0
  673. marim_harness-0.1.0/tests/test_subagent_after.py +249 -0
  674. marim_harness-0.1.0/tests/test_subagent_card.py +163 -0
  675. marim_harness-0.1.0/tests/test_subagent_cli_spawn.py +234 -0
  676. marim_harness-0.1.0/tests/test_subagent_concurrency.py +83 -0
  677. marim_harness-0.1.0/tests/test_subagent_depth.py +307 -0
  678. marim_harness-0.1.0/tests/test_subagent_detail.py +310 -0
  679. marim_harness-0.1.0/tests/test_subagent_extra_agents.py +51 -0
  680. marim_harness-0.1.0/tests/test_subagent_isolation.py +406 -0
  681. marim_harness-0.1.0/tests/test_subagent_masking.py +194 -0
  682. marim_harness-0.1.0/tests/test_subagent_model.py +241 -0
  683. marim_harness-0.1.0/tests/test_subagent_output_schema.py +88 -0
  684. marim_harness-0.1.0/tests/test_subagent_plan_egress.py +446 -0
  685. marim_harness-0.1.0/tests/test_subagent_resume.py +466 -0
  686. marim_harness-0.1.0/tests/test_subagent_retry.py +594 -0
  687. marim_harness-0.1.0/tests/test_subagent_safety.py +128 -0
  688. marim_harness-0.1.0/tests/test_subagent_stats.py +213 -0
  689. marim_harness-0.1.0/tests/test_subagent_tiers.py +202 -0
  690. marim_harness-0.1.0/tests/test_subagent_timing.py +63 -0
  691. marim_harness-0.1.0/tests/test_subagent_tool.py +175 -0
  692. marim_harness-0.1.0/tests/test_subagent_transcript_capture.py +142 -0
  693. marim_harness-0.1.0/tests/test_subagents_cli.py +740 -0
  694. marim_harness-0.1.0/tests/test_subagents_screen.py +902 -0
  695. marim_harness-0.1.0/tests/test_switch_jobs_history.py +57 -0
  696. marim_harness-0.1.0/tests/test_task_panel_plan_title.py +87 -0
  697. marim_harness-0.1.0/tests/test_tasks.py +94 -0
  698. marim_harness-0.1.0/tests/test_tasks_tool.py +133 -0
  699. marim_harness-0.1.0/tests/test_themes.py +45 -0
  700. marim_harness-0.1.0/tests/test_thinking.py +72 -0
  701. marim_harness-0.1.0/tests/test_thinking_command.py +60 -0
  702. marim_harness-0.1.0/tests/test_thinking_controller.py +79 -0
  703. marim_harness-0.1.0/tests/test_thinking_session.py +53 -0
  704. marim_harness-0.1.0/tests/test_thinking_spawn_tool.py +45 -0
  705. marim_harness-0.1.0/tests/test_thinking_subagent.py +96 -0
  706. marim_harness-0.1.0/tests/test_thinking_subagent_ui.py +99 -0
  707. marim_harness-0.1.0/tests/test_thinking_wiring.py +25 -0
  708. marim_harness-0.1.0/tests/test_tool_catalog.py +74 -0
  709. marim_harness-0.1.0/tests/test_tool_suggest.py +118 -0
  710. marim_harness-0.1.0/tests/test_tool_summary.py +216 -0
  711. marim_harness-0.1.0/tests/test_transcript_cap.py +42 -0
  712. marim_harness-0.1.0/tests/test_transcript_store.py +110 -0
  713. marim_harness-0.1.0/tests/test_trust.py +37 -0
  714. marim_harness-0.1.0/tests/test_ttft_model.py +111 -0
  715. marim_harness-0.1.0/tests/test_turn_context.py +39 -0
  716. marim_harness-0.1.0/tests/test_turn_controller.py +520 -0
  717. marim_harness-0.1.0/tests/test_turn_queue.py +66 -0
  718. marim_harness-0.1.0/tests/test_usage.py +185 -0
  719. marim_harness-0.1.0/tests/test_wake.py +66 -0
  720. marim_harness-0.1.0/tests/test_web_search.py +367 -0
  721. marim_harness-0.1.0/tests/test_widgets.py +1803 -0
  722. marim_harness-0.1.0/tests/test_workflow_acceptance.py +59 -0
  723. marim_harness-0.1.0/tests/test_workflow_engine.py +728 -0
  724. marim_harness-0.1.0/tests/test_workflow_schema.py +87 -0
  725. marim_harness-0.1.0/tests/test_workflow_tool.py +123 -0
  726. marim_harness-0.1.0/tests/test_workflow_wiring.py +84 -0
  727. marim_harness-0.1.0/tests/test_workspace.py +20 -0
  728. marim_harness-0.1.0/tests/test_workspace_knobs.py +45 -0
  729. marim_harness-0.1.0/tests/test_worktree.py +186 -0
  730. marim_harness-0.1.0/uv.lock +2735 -0
@@ -0,0 +1,178 @@
1
+ # Copy this file to .env and fill in your values. .env is gitignored.
2
+ # Real shell environment variables take priority over .env.
3
+
4
+ # --- OpenRouter (default provider) ---
5
+ OPENROUTER_API_KEY=
6
+
7
+ # Optional: override the default model (anthropic/claude-sonnet-4-6)
8
+ # MARIM_MODEL=anthropic/claude-sonnet-4-6
9
+
10
+ # --- Local provider (any OpenAI-compatible server) instead of OpenRouter ---
11
+ # The model picker (and `marim models list`) discovers models from the server's
12
+ # /v1/models endpoint, so MARIM_MODEL is optional once the server is reachable.
13
+ # Ollama:
14
+ # MARIM_PROVIDER=local
15
+ # MARIM_MODEL=qwen2.5-coder
16
+ # MARIM_BASE_URL=http://localhost:11434/v1
17
+ # MARIM_API_KEY=local
18
+ # LM Studio (note the 1234 port; start the server from the Developer tab):
19
+ # MARIM_PROVIDER=local
20
+ # MARIM_BASE_URL=http://localhost:1234/v1
21
+ # MARIM_API_KEY=lmstudio
22
+
23
+ # --- Multiple providers at once ---
24
+ # Any provider whose credentials are present is auto-detected and its models are
25
+ # merged into one tagged picker list (filter by id, name, or provider). Set
26
+ # several at once; MARIM_PROVIDER selects the default (startup model + the target
27
+ # for a typed model id with no provider prefix). Pick another provider's model in
28
+ # the picker, or type a qualified id like: local:qwen2.5-coder
29
+
30
+ # --- Claude subscription via the claude CLI (Claude Code) ---
31
+ # Use a Claude Pro/Max subscription via the `claude` CLI (Claude Code must be
32
+ # installed and logged in). In this provider marim delegates the whole turn to
33
+ # `claude -p`: Claude runs its own tools/loop, so marim's own tools, approval
34
+ # gating, LSP, and MCP do not apply. `auto`/`ask` map to acceptEdits, `plan` to
35
+ # read-only plan. MARIM_MODEL is optional (sonnet/opus/haiku; default: CLI's own).
36
+ # MARIM_PROVIDER=claude-cli
37
+ # MARIM_MODEL=sonnet
38
+ # MARIM_CLAUDE_CLI_BIN=claude # override the binary if not on PATH
39
+
40
+ # --- Context window & budget ---
41
+ # Compaction/masking trigger at min(budget, 0.8 × the model's context window).
42
+ # The window is discovered from the provider (catalog / LM Studio probe); the
43
+ # budget is your spend ceiling in tokens. 0 = unbudgeted (window-only).
44
+ # Replaces the deprecated MARIM_MAX_CONTEXT_TOKENS (same meaning).
45
+ # MARIM_CONTEXT_BUDGET=100000
46
+ # Manual window override (tokens) for servers discovery can't read, e.g. a
47
+ # non-LM-Studio local server; always wins over discovery.
48
+ # MARIM_CONTEXT_WINDOW=131072
49
+ # Per-model budgets: comma-separated fnmatch pattern=tokens pairs matched
50
+ # against the model id, first match wins; =0 means unbudgeted for that model.
51
+ # MARIM_CONTEXT_BUDGETS=anthropic/claude-opus*=60000,openrouter/*free*=0
52
+
53
+ # --- Web search (SearXNG) ---
54
+ # The web_search tool queries this SearXNG instance. Override to point at your
55
+ # own/self-hosted instance; defaults to https://searxng.marim.dev. The instance
56
+ # must have the JSON output format enabled (SearXNG disables it by default).
57
+ # MARIM_SEARXNG_URL=https://searxng.marim.dev
58
+
59
+ # --- Google (Gemini) ---
60
+ # MARIM_PROVIDER=google
61
+ # MARIM_MODEL=gemini-2.5-flash
62
+ # GOOGLE_API_KEY= # or GEMINI_API_KEY / MARIM_API_KEY
63
+
64
+ # --- Session & UI ---
65
+ # Initial approval mode for interactive sessions: ask (default), auto, or plan.
66
+ # Ignored when set from a project .env — a cloned repo must not self-elevate.
67
+ # MARIM_DEFAULT_MODE=ask
68
+ # DEBUG logging to the log file (also enables spawn timing lines).
69
+ # MARIM_DEBUG=1
70
+ # Detached fan-out: spawn_agent with `background` unset auto-detaches in the
71
+ # TUI (live cards + job handles) instead of running inline. On by default.
72
+ # MARIM_DETACH_FANOUT=1
73
+ # Desktop notifications: on by default; pick events from turn_complete,
74
+ # error, approval_needed, ask_user, job_done (default: all but job_done).
75
+ # MARIM_NOTIFICATIONS=0
76
+ # MARIM_NOTIFICATION_EVENTS=approval_needed,ask_user
77
+ # Autonomous wake: finished background jobs start a new turn to deliver their
78
+ # reports while you're away; the depth cap bounds chained wakes.
79
+ # MARIM_AUTONOMOUS_WAKE=1
80
+ # MARIM_WAKE_DEPTH_CAP=8
81
+
82
+ # --- Command policy (bash tool) ---
83
+ # Comma-separated command prefixes to always allow / always block, checked
84
+ # before the built-in policy.
85
+ # MARIM_COMMAND_ALLOWLIST=git status,ls
86
+ # MARIM_COMMAND_DENYLIST=rm -rf
87
+
88
+ # --- Trust (project-local executable config) ---
89
+ # Project-local hooks (.marim/hooks.json), MCP servers (.marim/mcp.json), and
90
+ # project-scope plugins launch code from the repo on startup. They load only
91
+ # when this is set — leave it unset for repos you don't fully trust.
92
+ # MARIM_TRUST_PROJECT_HOOKS=1
93
+
94
+ # --- LSP ---
95
+ # Language-server integration: MARIM_LSP gates the manager + diagnostics on
96
+ # write/edit; MARIM_LSP_TOOLS gates the six navigation tools. Both on by
97
+ # default; 0 disables.
98
+ # The four bundled language plugins (python, typescript, cpp, java; see
99
+ # docs/lsp-plugins.md) always load regardless of trust. Third-party plugins
100
+ # that add a language via an `lsp` manifest block follow the same
101
+ # MARIM_TRUST_PROJECT_HOOKS gate as project-local hooks/MCP servers above.
102
+ # MARIM_LSP=1
103
+ # MARIM_LSP_TOOLS=1
104
+
105
+ # --- Forge (Gitea/GitHub) ---
106
+ # Forge (Gitea/GitHub) tools via the tea CLI; on by default. Set to 0 to disable.
107
+ # MARIM_FORGE=1
108
+
109
+ # --- Scratchpad ---
110
+ # Session scratchpad: a per-session /tmp directory the agent uses for
111
+ # intermediate files (advertised in the prompt; writes there skip approval
112
+ # in ask mode). 1 (default) or 0.
113
+ # MARIM_SCRATCHPAD=1
114
+
115
+ # --- Dynamic workflows ---
116
+ # Dynamic workflows (the run_workflow tool; needs the [workflows] extra). Default on.
117
+ # MARIM_WORKFLOWS=1
118
+ # Ceiling (seconds) on the wall-clock budget one run_workflow call may request
119
+ # via its timeout_secs parameter. Default 1800 (30 min).
120
+ # MARIM_WORKFLOW_TIMEOUT=1800
121
+
122
+ # --- Compaction / observation masking ---
123
+ # Elide bulky, stale tool observations at compaction time (keep the newest N
124
+ # payloads; only bodies over the char floor are masked). On by default.
125
+ # MARIM_MASK_OBSERVATIONS=0
126
+ # MARIM_MASK_KEEP_RECENT=4
127
+ # MARIM_MASK_MIN_CHARS=200
128
+
129
+ # --- Sub-agents ---
130
+ # Cap concurrent spawn model-runs (default 8; 0 = unbounded) / per-spawn request
131
+ # budget (default 50) / persisted transcript size in messages (default 2000).
132
+ # MARIM_SUBAGENT_CONCURRENCY=8
133
+ # MARIM_SUBAGENT_REQUEST_LIMIT=50
134
+ # MARIM_SUBAGENT_TRANSCRIPT_CAP=2000
135
+ # Sub-agent model tiers: the model each tier routes to (qualified provider:model_id).
136
+ # A read-only spawn defaults to cheap, a mutating one to high; a spec's `tier:` or
137
+ # the spawner's tier= override picks explicitly. Unset ⇒ inherit the main model.
138
+ # MARIM_SUBAGENT_TIER_CHEAP=local:ornith-1.0-9b
139
+ # MARIM_SUBAGENT_TIER_MED=openrouter:anthropic/claude-sonnet-4-6
140
+ # MARIM_SUBAGENT_TIER_HIGH=openrouter:anthropic/claude-opus-4
141
+ # Master switch for tier routing. 0 ⇒ every spawn inherits the main model while
142
+ # the tier slugs above stay configured (toggle back on to restore routing). The
143
+ # TUI settings checkbox applies this live. Default on.
144
+ # MARIM_SUBAGENT_TIERING=1
145
+
146
+ # --- Advisor ---
147
+ # A model the agent can consult mid-task for strategic guidance (the advisor
148
+ # tool): qualified provider:model_id, or a bare slug for the default provider.
149
+ # Unset = no advisor (the tool is not offered to the model).
150
+ # MARIM_ADVISOR_MODEL=openrouter:anthropic/claude-opus-4.8
151
+ # Output cap per consultation (default 2048).
152
+ # MARIM_ADVISOR_MAX_TOKENS=2048
153
+ # Per-turn call cap. Unset or 0 = unlimited.
154
+ # MARIM_ADVISOR_MAX_USES=3
155
+
156
+ # --- Thinking level (reasoning effort) ---
157
+ # Reasoning effort applied to the model via ModelSettings.thinking. One of:
158
+ # off, minimal, low, medium, high, xhigh. Unset or 'off' = no reasoning effort
159
+ # (marim's default). /think overrides it per session, live.
160
+ # MARIM_THINKING=medium
161
+
162
+ # Claude Code model for `backend: claude-cli` sub-agents (alias or full id).
163
+ # MARIM_CLAUDE_CLI_MODEL=sonnet
164
+ # Proactive memory: the agent saves/recalls notes unprompted (off by default).
165
+ # MARIM_PROACTIVE_MEMORY=1
166
+
167
+ # --- MCP tool search ---
168
+ # Defer a large MCP/plugin tool surface behind a searchable index instead of
169
+ # advertising every tool: on, off, or auto (defer above the threshold).
170
+ # MARIM_TOOL_SEARCH=auto
171
+ # MARIM_TOOL_SEARCH_THRESHOLD=15
172
+
173
+ # --- Misc ---
174
+ # Combined `job(action, …)` tool instead of the four jobs/job_output/
175
+ # wait_for_job/cancel_job tools (for models that handle fewer tools better).
176
+ # MARIM_JOB_TOOL_COMBINED=1
177
+ # Where pasted-image bytes are cached (content-addressed, per session).
178
+ # MARIM_IMAGE_CACHE_DIR=~/.marim/image-cache
@@ -0,0 +1,71 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+
8
+ concurrency:
9
+ group: ci-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ python-version: ["3.10", "3.12", "3.14"]
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ # Install uv via the official script rather than a marketplace action, so
23
+ # the job doesn't depend on the Gitea runner mirroring third-party actions.
24
+ - name: Install uv
25
+ run: |
26
+ curl -LsSf https://astral.sh/uv/install.sh | sh
27
+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
28
+
29
+ # Cache uv's download/build cache (compiled wheels for grpcio, cryptography,
30
+ # pydantic-core, …) so a cold matrix leg doesn't rebuild them every run. Keyed
31
+ # on uv.lock; first-party actions/* already resolve here (see checkout above).
32
+ - name: Cache uv
33
+ uses: actions/cache@v4
34
+ with:
35
+ path: ~/.cache/uv
36
+ key: uv-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('uv.lock') }}
37
+ restore-keys: |
38
+ uv-${{ runner.os }}-py${{ matrix.python-version }}-
39
+
40
+ - name: Sync dependencies
41
+ run: uv sync --python ${{ matrix.python-version }}
42
+
43
+ - name: Lint (ruff)
44
+ run: uv run ruff check src tests
45
+
46
+ - name: Type-check (pyright)
47
+ run: uv run pyright
48
+
49
+ - name: Test (pytest)
50
+ run: uv run pytest
51
+
52
+ # Catch packaging regressions (missing metadata, broken includes) before a
53
+ # release does. One leg is enough — the artifacts are version-independent.
54
+ - name: Build sdist + wheel
55
+ if: matrix.python-version == '3.12'
56
+ run: uv build
57
+
58
+ # Pinned to v3: upload-artifact@v4 uses the @actions/artifact v2 API, which
59
+ # the Gitea act_runner (GHES-like) does not support — it fails the step with
60
+ # "GHESNotSupportedError". v3 uses the older artifact protocol Gitea implements.
61
+ - name: Upload coverage
62
+ if: always()
63
+ uses: actions/upload-artifact@v3
64
+ with:
65
+ name: coverage-py${{ matrix.python-version }}
66
+ path: coverage.xml
67
+
68
+ # Trim cache to only what this run actually used, keeping the saved cache lean.
69
+ - name: Prune uv cache
70
+ if: always()
71
+ run: uv cache prune --ci
@@ -0,0 +1,55 @@
1
+ name: Release
2
+
3
+ # Publish to PyPI when a version tag is pushed. Cut a release with:
4
+ # git tag v0.1.0 && git push origin v0.1.0
5
+ # Requires a repository secret PYPI_API_TOKEN (a PyPI API token scoped to the
6
+ # marim-harness project). Trusted publishing (OIDC) isn't available from a
7
+ # self-hosted Gitea, so a token it is.
8
+
9
+ on:
10
+ push:
11
+ tags: ["v*"]
12
+
13
+ jobs:
14
+ publish:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ # Install uv via the official script rather than a marketplace action, so
20
+ # the job doesn't depend on the Gitea runner mirroring third-party actions.
21
+ - name: Install uv
22
+ run: |
23
+ curl -LsSf https://astral.sh/uv/install.sh | sh
24
+ echo "$HOME/.local/bin" >> "$GITHUB_PATH"
25
+
26
+ - name: Sync dependencies
27
+ run: uv sync --python 3.12
28
+
29
+ # Re-run the full check sequence on the tagged commit — a tag can point
30
+ # anywhere, so don't assume a green CI run already covered it.
31
+ - name: Lint (ruff)
32
+ run: uv run ruff check src tests
33
+
34
+ - name: Type-check (pyright)
35
+ run: uv run pyright
36
+
37
+ - name: Test (pytest)
38
+ run: uv run pytest
39
+
40
+ # Refuse to publish a version that doesn't match the tag — catches the
41
+ # classic "tagged v0.2.0 but pyproject still says 0.1.0" mistake.
42
+ - name: Check tag matches project version
43
+ run: |
44
+ version=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
45
+ tag="${GITHUB_REF_NAME#v}"
46
+ if [ "$version" != "$tag" ]; then
47
+ echo "pyproject version ($version) != tag ($tag)" >&2
48
+ exit 1
49
+ fi
50
+
51
+ - name: Build sdist + wheel
52
+ run: uv build
53
+
54
+ - name: Publish to PyPI
55
+ run: uv publish --token "${{ secrets.PYPI_API_TOKEN }}"
@@ -0,0 +1,56 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .env
5
+
6
+ # Tool caches / generated reports
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .mypy_cache/
10
+ .VSCodeCounter/
11
+
12
+ # Coverage artifacts from the test runner
13
+ .coverage
14
+ coverage.xml
15
+ htmlcov/
16
+
17
+ # Python build / packaging artifacts (uv build, pip wheel, etc.)
18
+ build/
19
+ dist/
20
+ *.egg-info/
21
+
22
+ # Node / Playwright — the e2e-tests workflow runs @playwright/test via npx.
23
+ node_modules/
24
+ /test-results/
25
+ /playwright-report/
26
+ /blob-report/
27
+ .last-run.json
28
+
29
+ # OS / editor cruft.
30
+ .DS_Store
31
+ *.swp
32
+
33
+ # marim's per-project working dir: offloaded fetch bodies, sub-agent/output
34
+ # spill, the last-provider-error payload, and generated test reports — all local
35
+ # scratch. Ignored wholesale; commit a specific file with a negation (e.g.
36
+ # `!.marim/mcp.json`) if a project ever needs to track project-local config.
37
+ .marim/
38
+
39
+ # Git worktrees created by --worktree / the /worktree command.
40
+ .worktrees/
41
+
42
+ # Claude Code host config — per-machine and duplicated by marim's own plugins.
43
+ # marim never reads .claude/ (see test_ignores_claude_agents_dir) nor the root
44
+ # .mcp.json (it uses .marim/mcp.json; see mcp/config.py). The playwright agents
45
+ # + MCP server ship as the examples/playwright plugin, the source of truth.
46
+ .claude/
47
+ .mcp.json
48
+ # Stray Playwright seed scaffolded at the repo root by `playwright init-agents`.
49
+ # The e2e workflow's real seed lives at tests/seed.spec.ts (still trackable);
50
+ # only the misplaced root copy is ignored.
51
+ /seed.spec.ts
52
+
53
+ # Playwright e2e workspace scaffolded by `playwright init-agents` (the planner's
54
+ # specs/plan.md output dir). Scaffold, not marim source — the workflow itself
55
+ # lives in the examples/playwright plugin. Ignored wholesale.
56
+ /specs/
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+
3
+ All notable changes to marim-harness are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and the project adheres to [Semantic Versioning](https://semver.org/) —
7
+ pre-1.0, minor versions may contain breaking changes.
8
+
9
+ ## [Unreleased]
10
+
11
+ Everything so far — `0.1.0` will be the first tagged release. Highlights of
12
+ what exists today:
13
+
14
+ - **Interactive TUI** (Textual): streaming responses, tool-call cards, live
15
+ token counter, inline approval / ask-user / plan panels, sub-agents screen,
16
+ settings, model picker, themes.
17
+ - **Headless mode**: one-shot prompts with `text`, `json`, or `stream-json`
18
+ output; `marim serve` HTTP daemon (REST + WebSocket) in the `[serve]` extra.
19
+ - **Providers**: OpenRouter (default), any local OpenAI-compatible server
20
+ (Ollama, LM Studio), Google Gemini, and a `claude-cli` provider that
21
+ delegates turns to Claude Code on a Claude subscription.
22
+ - **Permission modes** (`auto` / `ask` / `plan`), a configurable shell command
23
+ policy, and workspace-confined file tools.
24
+ - **Sessions**: per-workspace persistence, resume, compaction with observation
25
+ masking, checkpoints and `/rewind` backed by git snapshots.
26
+ - **Sub-agents**: parallel spawns with granted tool reach, model tiers
27
+ (`cheap`/`med`/`high`), nesting with a depth ceiling, detached fan-out with
28
+ live cards, and an optional `claude -p` backend.
29
+ - **Dynamic workflows**: a gated `run_workflow` tool executing model-authored
30
+ scripts in a pydantic-monty sandbox (`[workflows]` extra).
31
+ - **Integrations**: MCP servers (global / project / plugin scope), LSP
32
+ navigation + diagnostics via pluggable providers (Python, TypeScript, C++,
33
+ Java bundled), Gitea/GitHub forge tools via the `tea` CLI, lifecycle hooks
34
+ (Claude-Code-compatible), plugins, skills, and persistent memory.
35
+ - **Embeddable**: `HarnessBuilder` composes the same agent loop as a library
36
+ with explicit config and no env reads (see `docs/embedding.md` and
37
+ `docs/sdk/`).
38
+ - **Extras**: advisor model, thinking levels, desktop notifications, image
39
+ input, background jobs with autonomous wake, session scratchpad.
@@ -0,0 +1,234 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What this is
6
+
7
+ `marim-harness` is a terminal coding agent built on [Pydantic AI](https://ai.pydantic.dev/)
8
+ and [Textual](https://textual.textualize.io/). It reads/searches/edits files and runs
9
+ commands in a workspace, with an interactive TUI and a headless one-shot mode. The
10
+ console scripts are `marim` and `marim-harness` (both → `marim_harness.__main__:main`).
11
+
12
+ ## Commands
13
+
14
+ ```bash
15
+ uv sync # install deps (creates .venv)
16
+ uv run pytest # full test suite (coverage is on by default via pyproject)
17
+ uv run pytest tests/test_agent.py # one file
18
+ uv run pytest tests/test_agent.py::test_name # one test
19
+ uv run pytest --no-cov tests/test_x.py # skip coverage for a fast single run
20
+ uv run ruff check src tests # lint
21
+ uv run ruff check --fix src tests
22
+ uv run pyright # type-check (standard mode, src only)
23
+ uv run marim serve --port 8642 # HTTP daemon (REST + WebSocket); needs the [serve] extra
24
+ ```
25
+
26
+ CI (`.gitea/workflows/ci.yml`) runs ruff → pyright → pytest on Python 3.10, 3.12,
27
+ and 3.14 (plus a `uv build` packaging check on the 3.12 leg). Match that order
28
+ locally before claiming work is done. `requires-python` is `>=3.10`, so avoid
29
+ 3.11+ only syntax.
30
+
31
+ Set `MARIM_DEBUG=1` for DEBUG logging. Provider config lives in env vars / `.env`
32
+ (see `.env.example`): `MARIM_PROVIDER` (`openrouter`|`local`|`google`|`claude-cli`), `MARIM_MODEL`,
33
+ `OPENROUTER_API_KEY`, etc. Default provider is OpenRouter, default model
34
+ `anthropic/claude-sonnet-4-6`. `claude-cli` delegates each turn to the `claude` CLI on a
35
+ Claude subscription — marim acts as a launcher (Claude runs its own tools/loop), so marim's
36
+ own tools/approval/LSP/MCP do not apply in that provider. Claude's own Agent/Task
37
+ sub-agents, however, are demuxed out of the stream (`subagents/cli_demux.py`) and
38
+ rendered as first-class cards in the sub-agents screen, for both the main-loop
39
+ provider and `backend: claude-cli` spawns. Interrupted `claude-cli` spawns
40
+ resume via the CLI's own `--resume` (the session id is checkpointed in the
41
+ spawn's sidecar meta).
42
+
43
+ ## Architecture
44
+
45
+ The dependency flow is **`__main__` → `interfaces/cli/router` → `default_cmd` →
46
+ `runtime/bootstrap.py`'s `build_harness` → `Harness`**. The two front-ends (TUI and
47
+ headless) both go through `build_harness`, so they wire up models, sessions, MCP,
48
+ hooks, and LSP identically — keep new wiring there, not duplicated per interface.
49
+
50
+ The turn-execution engine lives in the **`runtime/`** package: `harness.py`
51
+ (`Harness`, `build_collaborators`, `build_services`), `controller.py`
52
+ (`TurnController`, the approval/persist loop), `context.py` (per-turn context
53
+ helpers), `deps.py`, `permissions.py` (`Mode`), `errors.py`, `instructions.py`,
54
+ `builder.py`, and `bootstrap.py`. Imports target submodules directly (`from
55
+ .deps import Deps`); the package root deliberately re-exports nothing, keeping
56
+ the deps/services cycle below from leaking through `__init__` at import time.
57
+
58
+ `HarnessBuilder` (`builder.py`) is the embedding front door — explicit model,
59
+ explicit tool/session/sub-agent composition, no `MARIM_*` env reads; see
60
+ `docs/embedding.md`. `bootstrap.build_harness` is the CLI preset built on top
61
+ of that same builder (env config, workspace scanning, TUI/headless wiring).
62
+ New construction wiring (a tool group, a config knob) goes in the builder;
63
+ env/discovery reading stays in bootstrap, so the two paths cannot drift.
64
+
65
+ ### The core turn loop (`runtime/harness.py`)
66
+
67
+ `Harness` owns the Pydantic AI `Agent` and drives one user turn to completion.
68
+ `Harness.run_turn` → `_run_with_approval` is the heart of the system. Key invariants
69
+ encoded there (read the docstrings before touching):
70
+
71
+ - **Approval rounds.** The agent's `output_type` is `[str, DeferredToolRequests]`.
72
+ Gated tools (`write_file`, `edit_file`, `bash`) defer; `_run_with_approval` loops,
73
+ resolving each deferred batch via `resolve_approvals` against the current `Mode`
74
+ (`auto`/`ask`/`plan`), then continues the run with the results.
75
+ - **Resumability.** A persisted history must never end with a `ToolCallPart` lacking
76
+ its `ToolReturnPart` — every provider rejects that on the next request.
77
+ `_repair_unanswered_tool_calls` self-heals such histories; an aborted turn is
78
+ flushed via `_flush_resumable` (with a tight deadline so Ctrl-C stays snappy).
79
+ The dirty history held during an approval round is deliberately **not** persisted —
80
+ `resumable` is the rollback baseline and is refreshed only after a clean persist.
81
+ - **Prompt assembly.** `_assemble_prompt` prepends per-turn context (task checklist,
82
+ finished-job digests, the prior turn's actionable error note, SessionStart /
83
+ UserPromptSubmit hook output) and wraps the injected prefix in a `<turn-context>`
84
+ envelope so a resumed session can recover just what the user typed
85
+ (`strip_turn_context`). The system prompt is kept stable to preserve prompt caching.
86
+ - **Error notes.** `_actionable_error_note` surfaces only failures the *model* can act
87
+ on (4xx client errors, usage limits, malformed responses) and stays silent on infra
88
+ (429/5xx), cancels, and render bugs. Full provider payloads spill to
89
+ `.marim/last-provider-error.json`.
90
+
91
+ ### Construction & the deps/services cycle
92
+
93
+ `build_collaborators` (in `runtime/harness.py`) builds the whole collaborator graph
94
+ (agent, MCP, LSP, session, checkpoints, hooks, subagents) in dependency order. There
95
+ is one unavoidable late binding: `Deps` and `HarnessServices` form a reference cycle — `TurnHooks` and the
96
+ sub-agent runners hold `deps`, while tools reach back through `ctx.deps.services`.
97
+ `build_services` performs that single binding. `HarnessConfig` bundles all optional
98
+ knobs; `Harness.__init__` still accepts legacy `**kwargs` as a shorthand for
99
+ building one (pass `config=` *or* kwargs, not both — mixing raises `TypeError`).
100
+
101
+ `Deps` (`runtime/deps.py`) is the `RunContext` payload threaded through every tool. All
102
+ UI-facing collaboration is **optional callbacks** that headless leaves as `None`
103
+ (each reader guards with `is None`). The TUI wires them in one place via
104
+ `Harness.bind_ui` — don't poke `harness.deps`/`harness.session` field-by-field from
105
+ the interface layer.
106
+
107
+ ### Tools (`tools/`)
108
+
109
+ Tool implementations are module-level functions in `tools/provider.py` so they can be
110
+ registered two ways from one source of truth: onto the main agent (gated tools behind
111
+ `requires_approval=True`) and onto sub-agents (registered *plain* — reach is decided
112
+ up front by which names are granted, never by mid-run prompting). `spawn_agent`
113
+ is granted to a sub-agent only when it could still nest within the depth ceiling
114
+ (`depth + 1 < SUBAGENT_MAX_DEPTH`, default 3) — see `SubagentRunner.build`; at
115
+ the leaf depth the tool is absent, so nesting is bounded, not forbidden. Nested
116
+ spawns render in the sub-agents screen as an indented tree (a child card streams
117
+ into its parent's transcript pane). Tool docstrings are the model-facing tool
118
+ descriptions — they are part of the product; write them with that in mind.
119
+ `names.py` is the leaf module holding tool-name sets (`GATED_TOOLS`, `LSP_TOOLS`, etc.)
120
+ to avoid import cycles.
121
+
122
+ ### Supporting subsystems (one concern each)
123
+
124
+ - `session/` — `SessionStore` (persists to `$XDG_DATA_HOME/marim-harness/sessions`),
125
+ `SessionManager`, `SessionController` (compaction/autoname), `CheckpointManager`
126
+ (rewind via `GitSnapshotter`, honoring `.gitignore`).
127
+ - `mcp/` — Model Context Protocol server config + lifecycle; servers can be granted
128
+ selectively to sub-agents. Project-local `.marim/mcp.json` servers launch code on
129
+ connect, so they load only when the project is trusted (the same
130
+ `MARIM_TRUST_PROJECT_HOOKS` gate as project hooks); global/plugin servers always load.
131
+ - `lsp/` — multilspy-backed language servers, now assembled from **LSP providers**
132
+ (`provider.py`: `LspProvider` + `LspRegistry`) rather than a hard-coded set. Four
133
+ bundled language plugins (`lsp/bundled/{python,typescript,cpp,java}`) ship in-tree
134
+ and always load; third-party plugins add languages via an `lsp` manifest block
135
+ (declarative `command`/`args` only) under the same `MARIM_TRUST_PROJECT_HOOKS` gate
136
+ as MCP. `backend:`/named-`diagnostics:` keys are a bundled-only seam to in-tree tuned
137
+ code (`basedpyright.py`, ruff/pyright via `checks.py`). Declarative servers launch
138
+ through `GenericStdioServer` (`generic.py`). Two switches still gate the whole thing:
139
+ `lsp_enabled` (manager + diagnostics-on-edit) and `lsp_tools_enabled` (the six nav
140
+ tools). marim never downloads server binaries — it probes PATH and surfaces the
141
+ provider's install hint.
142
+ - `forge/` — Gitea/GitHub integration via a `ForgeBackend` seam. `TeaBackend`
143
+ shells out to the `tea` CLI (`--output json`); five forge-agnostic tools
144
+ (`tools/forge_tools.py`) list/view PRs, check CI, and open/check out PRs, with
145
+ create/checkout gated for approval. Attached at build time only when
146
+ `MARIM_FORGE` is on (default) and a backend is available (`tea` on PATH + a
147
+ configured login). A `gh` backend is a future drop-in behind the same protocol.
148
+ - `hooks/` — Claude-Code-compatible lifecycle hook engine (session/prompt/tool/
149
+ compaction events). Observe-only except SessionStart/UserPromptSubmit (inject
150
+ context) and PreCompact (may block a *manual* /compact via exit 2 or
151
+ `{"decision":"block"}`; block verdicts on auto compaction are logged and
152
+ ignored). Project-local hooks run only when trusted
153
+ (`MARIM_TRUST_PROJECT_HOOKS`).
154
+ - `plugins/` — bundles skills + sub-agents + hooks + MCP + `AGENTS.md`; hooks/MCP load
155
+ only for *trusted* plugins. Namespaced `plugin:item`. See `docs/plugins.md`.
156
+ - `workspace/` — fs primitives, memory (`remember`/`recall`), skills, sub-agent specs,
157
+ git worktrees, snapshots, and the session scratchpad (a per-session /tmp dir for
158
+ intermediate files: advertised in the prompt, reachable by the file tools as an
159
+ extra guard root, auto-approved in ask mode, gated by `MARIM_SCRATCHPAD`). (The
160
+ root-level `compaction.py` builds the summarizer/titler aux agents and the
161
+ token-budget compaction helpers.)
162
+ - `subagents/` — `runner.py` (`SubagentRunner`: spawn-lifecycle coordinator),
163
+ `run_driver.py` (model-loop retry/overflow/contention recovery),
164
+ `cli_spawn.py` (`claude -p` execute/resume orchestration), `masking.py`
165
+ (per-spawn context masking of stale tool observations), and `cli_backend.py`
166
+ (the optional `claude -p` CLI backend it delegates to). Re-exported as
167
+ `marim_harness.subagents.SubagentRunner`. Native spawns pick a model by **tier** (`cheap`/`med`/`high`, in `subagents/tiers.py`): resolved from the spawner's `tier=` override → the spec's `tier:` frontmatter → tool reach (read-only→cheap, mutating→high), mapped to `MARIM_SUBAGENT_TIER_*`; unset tiers inherit the main model and a `model=` slug stays a bounded escape hatch.
168
+ - `workflows/` — dynamic workflows: the gated `run_workflow` tool executes a
169
+ model-authored Python script in a pydantic-monty sandbox (`engine.py`);
170
+ `agent()`/`log()` host functions delegate to `SubagentRunner.run` through
171
+ the `services.run_workflow` seam. Schema validation of agent() reports is
172
+ engine-level (`schema.py`, jsonschema). Never cancel the Monty VM task —
173
+ aborts flow through host functions (see engine.py's module docstring).
174
+ Optional extra `[workflows]`; `MARIM_WORKFLOWS` gates it.
175
+ - `advisor.py` (root) — the advisor: an `advisor()` tool on the main agent
176
+ forwards the full transcript to a separately-configured model
177
+ (`MARIM_ADVISOR_MODEL`, any provider) and returns strategic guidance.
178
+ Live seam is `services.advise` (a pydantic-ai `prepare` hook omits the tool
179
+ when it's `None`, so `/advisor <model>`/`/advisor off` toggle without a
180
+ rebuild — at the cost of one prompt-cache break per toggle). Session
181
+ persistence mirrors `store.model` (`"off"` sentinel = explicitly disabled);
182
+ per-turn call cap `MARIM_ADVISOR_MAX_USES` rides on `Deps`. Main loop only
183
+ (sub-agents have tiering); the tool doesn't exist under the claude-cli
184
+ main-loop provider (marim's tools don't apply there), but a claude-cli
185
+ *advisor* model works via the `aux_model_for` clone.
186
+ - `thinking.py` (root) — thinking level (reasoning effort): one ordered
187
+ vocabulary (`off/minimal/low/medium/high/xhigh`) and three pure helpers —
188
+ `parse_thinking_level` (env/CLI/`/think` coercion), `settings_for` (fold a
189
+ level into `ModelSettings.thinking`; `off`/unset OMITS the key, byte-identical
190
+ to pre-thinking behavior), and `resolve_thinking` (sub-agent precedence:
191
+ spawn override → spec `thinking:`/`effort:` → inherited session level). The
192
+ main loop applies it per turn in `TurnController._turn_model_settings`; the
193
+ level persists on `SessionStore.thinking` and lives on `Harness.thinking_level_id`
194
+ (read lazily by the controller closure and the sub-agent runner, so `/think`
195
+ switches without a rebuild). Seeded by `MARIM_THINKING` / `--think`; TUI
196
+ `/think` command + Settings row. Under the `claude-cli` main provider it's a
197
+ documented no-op (marim's `ModelSettings` don't reach Claude Code). Detection
198
+ (`catalog.supports_thinking`) is best-effort UI annotation only — it never
199
+ blocks a level.
200
+ - `interfaces/tui/` — Textual app, widgets, `styles.tcss`, streaming render;
201
+ `interactions/` — inline approval/ask-user/plan-card panels (mounted above the
202
+ status bar, not modals, so the transcript stays scrollable) sharing an
203
+ `InteractionPanel` base; `subagents/` — the sub-agents screen: master list,
204
+ full-bleed view, inline card, persistent transcript pane, pure stats.
205
+ `interfaces/cli/` — router + per-command modules (lazily imported so
206
+ `config`/`models` don't pay for `pydantic_ai`).
207
+
208
+ ## Conventions
209
+
210
+ - Use `uv` for everything (`uv run …`, `uv sync`). Don't invoke `pip` or a bare
211
+ `python`/`pytest`.
212
+ - Ruff line length is 100; lint set is `E,F,I,UP,B,SIM,C901` (import sorting
213
+ enforced; pyupgrade, bugbear, and flake8-simplify also on).
214
+ - Cyclomatic complexity is capped at 10 (`C901`, mccabe). CI rejects any function
215
+ above it. When a function trips the ceiling, extract cohesive branch-clusters into
216
+ named helpers (or a small state value-object where locals mutate across the region)
217
+ — do not add a blanket `# noqa: C901`. Note: this bounds *branch count*, not length;
218
+ a long, straight-line, well-commented function is fine.
219
+ - Keep pure decision/parse helpers (command policy, snapshot diffing, arg coercion,
220
+ path-guard resolution, and the extracted module-level helpers inside the effectful
221
+ modules) side-effect-free and unit-tested directly. The effectful I/O itself lives in
222
+ `tools/impl/` (`fs.py` writes, `shell.py` spawns, `fetch.py` opens sockets) — that is
223
+ the real I/O *core*, not a pure layer; it is exercised directly against a tmp
224
+ workspace. Above it, the tool layer (`fs_tools.py`, `edit_tools.py`, `net_tools.py`)
225
+ is thin `ctx.deps`-unwrapping wiring. Follow that three-way split when adding behavior.
226
+ - The codebase favors long, explanatory comments on *why* a non-obvious invariant
227
+ holds (especially around resumability and the deps/services cycle). Preserve them
228
+ when editing nearby code.
229
+ - Follow `coding-guidelines.md` for code design principles: control complexity,
230
+ prefer straight-line flow, model the domain when it pays off, encapsulate
231
+ collections with behavior, limit deep navigation, name for clarity, optimize for
232
+ cohesion, treat large state as a smell, and encapsulate behavior over data.
233
+ It's guidance, not dogma — break a rule when the tradeoff is clear and
234
+ document why.