claude-code-log 1.4.0__tar.gz → 1.6.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 (311) hide show
  1. claude_code_log-1.6.0/.claude/skills/foldyard/SKILL.md +84 -0
  2. claude_code_log-1.6.0/.claude/skills/foldyard/references/egress-and-capture.md +50 -0
  3. claude_code_log-1.6.0/.claude/skills/foldyard/references/posture-and-credentials.md +54 -0
  4. claude_code_log-1.6.0/.claude/skills/foldyard/references/when-a-change-doesnt-take.md +32 -0
  5. claude_code_log-1.6.0/.claude/skills/update-tools-coverage/SKILL.md +114 -0
  6. claude_code_log-1.6.0/.claude/skills/update-tools-coverage/check_codex_coverage.py +89 -0
  7. claude_code_log-1.6.0/.claude/skills/update-tools-coverage/check_coverage.py +119 -0
  8. claude_code_log-1.6.0/.editorconfig +25 -0
  9. claude_code_log-1.6.0/.github/workflows/ci.yml +117 -0
  10. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.gitignore +16 -1
  11. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/CHANGELOG.md +101 -0
  12. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/CLAUDE.md +4 -1
  13. claude_code_log-1.6.0/CONTRIBUTING.md +505 -0
  14. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/PKG-INFO +11 -3
  15. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/README.md +7 -0
  16. claude_code_log-1.6.0/claude_code_log/api.py +198 -0
  17. claude_code_log-1.6.0/claude_code_log/builtin_plugins/__init__.py +1 -0
  18. claude_code_log-1.6.0/claude_code_log/builtin_plugins/codex_docs.py +373 -0
  19. claude_code_log-1.6.0/claude_code_log/cache.py +2956 -0
  20. claude_code_log-1.6.0/claude_code_log/cli.py +2528 -0
  21. claude_code_log-1.6.0/claude_code_log/converter.py +6983 -0
  22. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/dag.py +178 -16
  23. claude_code_log-1.6.0/claude_code_log/discovery.py +72 -0
  24. claude_code_log-1.6.0/claude_code_log/entry_store.py +335 -0
  25. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/__init__.py +2 -0
  26. claude_code_log-1.6.0/claude_code_log/factories/attachment_factory.py +322 -0
  27. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/meta_factory.py +8 -1
  28. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/system_factory.py +3 -0
  29. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/tool_factory.py +166 -9
  30. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/user_factory.py +265 -18
  31. claude_code_log-1.6.0/claude_code_log/fragment_store.py +311 -0
  32. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/git_remote.py +27 -3
  33. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/__init__.py +4 -0
  34. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/async_formatter.py +2 -2
  35. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/renderer.py +444 -53
  36. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/renderer_code.py +13 -1
  37. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/system_formatters.py +18 -15
  38. claude_code_log-1.6.0/claude_code_log/html/templates/archive_search.html +735 -0
  39. claude_code_log-1.6.0/claude_code_log/html/templates/components/archive_search_link.html +18 -0
  40. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/global_styles.css +78 -9
  41. claude_code_log-1.6.0/claude_code_log/html/templates/components/live_update.js +566 -0
  42. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/message_styles.css +637 -11
  43. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/pygments_styles.css +17 -0
  44. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/search.html +439 -136
  45. claude_code_log-1.6.0/claude_code_log/html/templates/components/search_inline.html +36 -0
  46. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/search_styles.css +43 -0
  47. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/session_nav.html +8 -0
  48. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/session_nav_styles.css +8 -3
  49. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/timeline.html +109 -8
  50. claude_code_log-1.6.0/claude_code_log/html/templates/components/timezone_converter.js +148 -0
  51. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/index.html +8 -1
  52. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/transcript.html +536 -321
  53. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/tool_formatters.py +764 -52
  54. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/user_formatters.py +172 -1
  55. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/utils.py +305 -35
  56. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/image_export.py +32 -8
  57. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/json/renderer.py +13 -4
  58. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/markdown/renderer.py +469 -44
  59. claude_code_log-1.6.0/claude_code_log/migrations/007_subagents_fingerprint.sql +16 -0
  60. claude_code_log-1.6.0/claude_code_log/migrations/008_session_sidecar.sql +53 -0
  61. claude_code_log-1.6.0/claude_code_log/migrations/009_sessions_hidden.sql +17 -0
  62. claude_code_log-1.6.0/claude_code_log/migrations/010_sessions_residual_count.sql +29 -0
  63. claude_code_log-1.6.0/claude_code_log/migrations/011_cached_file_size.sql +24 -0
  64. claude_code_log-1.6.0/claude_code_log/migrations/012_message_lookup_indexes.sql +81 -0
  65. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/models.py +347 -81
  66. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/plugins.py +53 -10
  67. claude_code_log-1.6.0/claude_code_log/providers/__init__.py +11 -0
  68. claude_code_log-1.6.0/claude_code_log/providers/agy.py +381 -0
  69. claude_code_log-1.6.0/claude_code_log/providers/base.py +368 -0
  70. claude_code_log-1.6.0/claude_code_log/providers/claude.py +71 -0
  71. claude_code_log-1.6.0/claude_code_log/providers/codex.py +2869 -0
  72. claude_code_log-1.6.0/claude_code_log/providers/codex_messages.py +155 -0
  73. claude_code_log-1.6.0/claude_code_log/providers/codex_quickjs.py +780 -0
  74. claude_code_log-1.6.0/claude_code_log/providers/codex_tools.py +879 -0
  75. claude_code_log-1.6.0/claude_code_log/providers/codex_web.py +75 -0
  76. claude_code_log-1.6.0/claude_code_log/providers/registry.py +133 -0
  77. claude_code_log-1.6.0/claude_code_log/render_cache.py +203 -0
  78. claude_code_log-1.6.0/claude_code_log/render_dispatch.py +258 -0
  79. claude_code_log-1.6.0/claude_code_log/render_pool.py +720 -0
  80. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/renderer.py +1384 -339
  81. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/renderer_timings.py +42 -5
  82. claude_code_log-1.6.0/claude_code_log/search.py +1081 -0
  83. claude_code_log-1.6.0/claude_code_log/server.py +304 -0
  84. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/tui.py +7 -7
  85. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/utils.py +358 -43
  86. claude_code_log-1.6.0/claude_code_log/watch.py +239 -0
  87. claude_code_log-1.6.0/claude_code_log/workflow.py +661 -0
  88. claude_code_log-1.6.0/dev-docs/agents.md +369 -0
  89. claude_code_log-1.6.0/dev-docs/application_model.md +1495 -0
  90. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/css-classes.md +20 -1
  91. claude_code_log-1.6.0/dev-docs/dag.md +721 -0
  92. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/implementing-a-tool-renderer.md +24 -0
  93. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/message-hierarchy.md +40 -36
  94. claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_result.json +24 -0
  95. claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_result.jsonl +1 -0
  96. claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_use.json +27 -0
  97. claude_code_log-1.6.0/dev-docs/messages/claude-code/tools/Artifact-tool_use.jsonl +1 -0
  98. claude_code_log-1.6.0/dev-docs/messages/codex/README.md +82 -0
  99. claude_code_log-1.6.0/dev-docs/messages/codex/collaboration/agent-tools.json +19 -0
  100. claude_code_log-1.6.0/dev-docs/messages/codex/collaboration/thread-spawn.json +15 -0
  101. claude_code_log-1.6.0/dev-docs/messages/codex/legacy/flat-rollout.md +6 -0
  102. claude_code_log-1.6.0/dev-docs/messages/codex/lifecycle/turn-context.json +9 -0
  103. claude_code_log-1.6.0/dev-docs/messages/codex/manifest.json +16 -0
  104. claude_code_log-1.6.0/dev-docs/messages/codex/messages/environment-context.json +7 -0
  105. claude_code_log-1.6.0/dev-docs/messages/codex/messages/user-shell-command.json +7 -0
  106. claude_code_log-1.6.0/dev-docs/messages/codex/messages/visible-pair.json +17 -0
  107. claude_code_log-1.6.0/dev-docs/messages/codex/reasoning/summary.json +9 -0
  108. claude_code_log-1.6.0/dev-docs/messages/codex/session/session_meta.json +10 -0
  109. claude_code_log-1.6.0/dev-docs/messages/codex/tools/async-command.json +41 -0
  110. claude_code_log-1.6.0/dev-docs/messages/codex/tools/exec-wrapper.json +19 -0
  111. claude_code_log-1.6.0/dev-docs/messages/codex/tools/function-call.json +19 -0
  112. claude_code_log-1.6.0/dev-docs/messages/codex/tools/web-run.json +19 -0
  113. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/messages.md +269 -55
  114. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/plugins.md +131 -49
  115. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/rendering-architecture.md +17 -8
  116. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/dev-docs/teammates.md +13 -12
  117. claude_code_log-1.6.0/dev-docs/tools-coverage.md +344 -0
  118. claude_code_log-1.6.0/dev-docs/workflows.md +341 -0
  119. claude_code_log-1.6.0/foldyard.local.toml.example +86 -0
  120. claude_code_log-1.6.0/foldyard.toml +248 -0
  121. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/justfile +28 -22
  122. claude_code_log-1.6.0/mise.toml +8 -0
  123. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/mkdocs.yml +11 -1
  124. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/pyproject.toml +49 -3
  125. claude_code_log-1.6.0/stubs/quickjs.pyi +13 -0
  126. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/uv.lock +67 -24
  127. claude_code_log-1.6.0/work/agent-hierarchies-design.md +229 -0
  128. claude_code_log-1.6.0/work/archive-search-server.md +1088 -0
  129. claude_code_log-1.6.0/work/codex-backlog.md +373 -0
  130. claude_code_log-1.6.0/work/identifier-consolidation.md +162 -0
  131. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/obsidian-friendly-output.md +25 -2
  132. claude_code_log-1.6.0/work/parse-memory-spike.md +140 -0
  133. claude_code_log-1.6.0/work/render-format-once.md +1472 -0
  134. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/rendering-next.md +43 -0
  135. claude_code_log-1.6.0/work/tui-output-fixes.md +75 -0
  136. claude_code_log-1.6.0/work/watch-mode.md +1695 -0
  137. claude_code_log-1.6.0/work/win-io.md +79 -0
  138. claude_code_log-1.6.0/work/xdist-import-cost.md +133 -0
  139. claude_code_log-1.4.0/.github/workflows/ci.yml +0 -87
  140. claude_code_log-1.4.0/CONTRIBUTING.md +0 -329
  141. claude_code_log-1.4.0/claude_code_log/cache.py +0 -1712
  142. claude_code_log-1.4.0/claude_code_log/cli.py +0 -1162
  143. claude_code_log-1.4.0/claude_code_log/converter.py +0 -2934
  144. claude_code_log-1.4.0/claude_code_log/factories/attachment_factory.py +0 -126
  145. claude_code_log-1.4.0/claude_code_log/html/templates/components/search_inline.html +0 -29
  146. claude_code_log-1.4.0/claude_code_log/html/templates/components/search_inline_script.html +0 -3
  147. claude_code_log-1.4.0/claude_code_log/html/templates/components/search_results_panel.html +0 -10
  148. claude_code_log-1.4.0/claude_code_log/html/templates/components/timezone_converter.js +0 -115
  149. claude_code_log-1.4.0/dev-docs/agents.md +0 -191
  150. claude_code_log-1.4.0/dev-docs/application_model.md +0 -458
  151. claude_code_log-1.4.0/dev-docs/dag.md +0 -701
  152. claude_code_log-1.4.0/mise.toml +0 -2
  153. claude_code_log-1.4.0/work/refactor-reindex-with-ghosting.md +0 -197
  154. claude_code_log-1.4.0/work/simplify-converter-renderer.md +0 -312
  155. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.claude/settings.json +0 -0
  156. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.claude/skills/tool-renderer/SKILL.md +0 -0
  157. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.github/workflows/docs.yml +0 -0
  158. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/.vscode/settings.json +0 -0
  159. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/LICENSE +0 -0
  160. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/__init__.py +0 -0
  161. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/agent_metadata_factory.py +0 -0
  162. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/assistant_factory.py +0 -0
  163. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/priorities.py +0 -0
  164. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/task_notification_factory.py +0 -0
  165. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/teammate_factory.py +0 -0
  166. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/factories/transcript_factory.py +0 -0
  167. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/ansi_colors.py +0 -0
  168. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/assistant_formatters.py +0 -0
  169. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/teammate_formatter.py +0 -0
  170. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/edit_diff_styles.css +0 -0
  171. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/filter_styles.css +0 -0
  172. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/page_nav_styles.css +0 -0
  173. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/project_card_styles.css +0 -0
  174. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/teammate_styles.css +0 -0
  175. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/timeline_styles.css +0 -0
  176. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/html/templates/components/todo_styles.css +0 -0
  177. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/json/__init__.py +0 -0
  178. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/markdown/__init__.py +0 -0
  179. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/markdown_plugins.py +0 -0
  180. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/001_initial_schema.sql +0 -0
  181. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/002_html_cache.sql +0 -0
  182. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/003_html_pagination.sql +0 -0
  183. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/004_html_pagination_variant.sql +0 -0
  184. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/005_session_team_name.sql +0 -0
  185. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/006_session_ai_title.sql +0 -0
  186. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/__init__.py +0 -0
  187. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/migrations/runner.py +0 -0
  188. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/parser.py +0 -0
  189. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/claude_code_log/py.typed +0 -0
  190. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant.json +0 -0
  191. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant.jsonl +0 -0
  192. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant_sidechain.json +0 -0
  193. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/assistant_sidechain.jsonl +0 -0
  194. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/thinking.json +0 -0
  195. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/assistant/thinking.jsonl +0 -0
  196. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/file_history_snapshot.json +0 -0
  197. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/file_history_snapshot.jsonl +0 -0
  198. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/queue_operation.json +0 -0
  199. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/queue_operation.jsonl +0 -0
  200. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/summary.json +0 -0
  201. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/summary.jsonl +0 -0
  202. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/system_info.json +0 -0
  203. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/system/system_info.jsonl +0 -0
  204. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result.json +0 -0
  205. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result.jsonl +0 -0
  206. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result_error.json +0 -0
  207. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_result_error.jsonl +0 -0
  208. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_use.json +0 -0
  209. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/AskUserQuestion-tool_use.jsonl +0 -0
  210. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result.json +0 -0
  211. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result.jsonl +0 -0
  212. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result_error.json +0 -0
  213. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_result_error.jsonl +0 -0
  214. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_use.json +0 -0
  215. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Bash-tool_use.jsonl +0 -0
  216. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_result.json +0 -0
  217. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_result.jsonl +0 -0
  218. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_use.json +0 -0
  219. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/BashOutput-tool_use.jsonl +0 -0
  220. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result.json +0 -0
  221. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result.jsonl +0 -0
  222. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result_error.json +0 -0
  223. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_result_error.jsonl +0 -0
  224. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_use.json +0 -0
  225. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Edit-tool_use.jsonl +0 -0
  226. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result.json +0 -0
  227. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result.jsonl +0 -0
  228. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result_error.json +0 -0
  229. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_result_error.jsonl +0 -0
  230. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_use.json +0 -0
  231. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/ExitPlanMode-tool_use.jsonl +0 -0
  232. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_result.json +0 -0
  233. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_result.jsonl +0 -0
  234. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_use.json +0 -0
  235. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Glob-tool_use.jsonl +0 -0
  236. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_result.json +0 -0
  237. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_result.jsonl +0 -0
  238. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_use.json +0 -0
  239. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Grep-tool_use.jsonl +0 -0
  240. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result.json +0 -0
  241. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result.jsonl +0 -0
  242. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result_error.json +0 -0
  243. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_result_error.jsonl +0 -0
  244. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_use.json +0 -0
  245. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/KillShell-tool_use.jsonl +0 -0
  246. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_result.json +0 -0
  247. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_result.jsonl +0 -0
  248. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_use.json +0 -0
  249. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/LS-tool_use.jsonl +0 -0
  250. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result.json +0 -0
  251. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result.jsonl +0 -0
  252. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result_error.json +0 -0
  253. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_result_error.jsonl +0 -0
  254. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_use.json +0 -0
  255. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/MultiEdit-tool_use.jsonl +0 -0
  256. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result.json +0 -0
  257. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result.jsonl +0 -0
  258. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result_error.json +0 -0
  259. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_result_error.jsonl +0 -0
  260. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_use.json +0 -0
  261. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Read-tool_use.jsonl +0 -0
  262. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_result.json +0 -0
  263. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_result.jsonl +0 -0
  264. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_use.json +0 -0
  265. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Task-tool_use.jsonl +0 -0
  266. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_result.json +0 -0
  267. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_result.jsonl +0 -0
  268. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_use.json +0 -0
  269. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/TodoWrite-tool_use.jsonl +0 -0
  270. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_result.json +0 -0
  271. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_result.jsonl +0 -0
  272. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_use.json +0 -0
  273. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebFetch-tool_use.jsonl +0 -0
  274. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_result.json +0 -0
  275. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_result.jsonl +0 -0
  276. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_use.json +0 -0
  277. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/WebSearch-tool_use.jsonl +0 -0
  278. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result.json +0 -0
  279. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result.jsonl +0 -0
  280. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result_error.json +0 -0
  281. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_result_error.jsonl +0 -0
  282. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_use.json +0 -0
  283. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/Write-tool_use.jsonl +0 -0
  284. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_result.json +0 -0
  285. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_result.jsonl +0 -0
  286. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_use.json +0 -0
  287. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/tools/exit_plan_mode-tool_use.jsonl +0 -0
  288. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_input.json +0 -0
  289. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_input.jsonl +0 -0
  290. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_output.json +0 -0
  291. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/bash_output.jsonl +0 -0
  292. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/command_output.json +0 -0
  293. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/command_output.jsonl +0 -0
  294. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/image.json +0 -0
  295. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/image.jsonl +0 -0
  296. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user.json +0 -0
  297. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user.jsonl +0 -0
  298. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_command.json +0 -0
  299. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_command.jsonl +0 -0
  300. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_sidechain.json +0 -0
  301. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_sidechain.jsonl +0 -0
  302. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_slash_command.json +0 -0
  303. {claude_code_log-1.4.0/dev-docs/messages → claude_code_log-1.6.0/dev-docs/messages/claude-code}/user/user_slash_command.jsonl +0 -0
  304. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/__init__.pyi +0 -0
  305. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/formatter.pyi +0 -0
  306. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/formatters/__init__.pyi +0 -0
  307. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/lexer.pyi +0 -0
  308. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/lexers/__init__.pyi +0 -0
  309. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/stubs/pygments/util.pyi +0 -0
  310. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/session-state-propagation.md +0 -0
  311. {claude_code_log-1.4.0 → claude_code_log-1.6.0}/work/tool-renderer-plugins.md +0 -0
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: foldyard
3
+ description: Orient yourself in a foldyard dev box and drive it — the host/box split, what the box structurally cannot do, posture modes for credentials, egress and the proxy, worktrees, and why a config or compose change might not have taken effect. Use whenever `fy`/`foldyard` commands appear, when something needs a credential or network access it doesn't have, when a change "doesn't take", or when asked to work on the dev environment itself.
4
+ ---
5
+
6
+ # Working in (and on) a foldyard dev box
7
+
8
+ Foldyard runs this project inside a **rootless VM that mounts only this repo**. You are almost
9
+ certainly *in the box* — a container in that VM — and the person you're working with is on the
10
+ **host** (their Mac). That split explains nearly everything below.
11
+
12
+ Check where you are: `fy mode` prints the posture and says which side it's reading from.
13
+ `fy verify` proves the boundary (it exits non-zero if any of it is false).
14
+
15
+ ## The four facts that will save you the most time
16
+
17
+ 1. **You cannot push.** No credential to the git remote reaches the box, by design. Read and
18
+ commit locally; the human pushes. Don't try to work around it — there is nothing to find.
19
+ 2. **You hold no real secrets, and can't grant yourself any.** Posture state lives in the host's
20
+ home, outside the mount. `fy mode` *shows* posture anywhere; *setting* it is host-only.
21
+ 3. **Your egress goes through the host's proxy** and may be allow-listed or walled. A blocked
22
+ host is a decision, not a bug — ask; don't route around it.
23
+ 4. **The engine socket you have is real** and bounded to this VM. `docker`/`podman` commands
24
+ work and act on the live dev stack — including anything a test suite's mocks let slip.
25
+
26
+ ## Ask the tool, don't guess
27
+
28
+ Foldyard is introspectable, and its own output is always current — prefer it over any summary
29
+ (including this one):
30
+
31
+ | question | command |
32
+ | --- | --- |
33
+ | what can this environment do right now? | `fy mode` (posture), `fy state` (desired vs observed) |
34
+ | what's broken / missing? | `fy doctor` — one line per check, each with its fix |
35
+ | is the isolation intact? | `fy verify` |
36
+ | what does this verb do? | `fy --help`, `fy <verb> --help` |
37
+ | the manual, offline, by topic | `fy docs` — then `fy docs <topic>` |
38
+ | what does the config let the host do? | `fy config widenings` |
39
+
40
+ `fy docs` serves **this install's** documentation, so it can't drift from the code you're running.
41
+ Start with `fy docs quickstart`, `fy docs modes`, `fy docs networking`, `fy docs security`; the
42
+ ADRs (`fy docs adr-0001` …) carry the reasoning behind each design decision.
43
+
44
+ ## Daily verbs
45
+
46
+ `fy up | ps | logs [svc] | shell | down` drive the compose stack; `fy box shell | ps` the dev box
47
+ itself; `fy verify` proves the cage. A consumer repo usually wraps these in its own `just`
48
+ recipes — check the repo's justfile and CLAUDE.md before reaching for `fy` directly.
49
+
50
+ ## When you need something you don't have
51
+
52
+ **A credential** (a cloud token, an API key): you can't grant it. Name the exact command the human
53
+ should run on their Mac and why. Postures are per-axis — `fy mode` lists the axes this project
54
+ declares and their rungs, and high-privilege rungs expire on a timer by design. Detail:
55
+ [posture-and-credentials.md](references/posture-and-credentials.md).
56
+
57
+ **A host through the network wall**: `fy allow add <host> --level session` — **on the host**. Tell
58
+ them the hostname and what needs it. Detail:
59
+ [egress-and-capture.md](references/egress-and-capture.md).
60
+
61
+ **A tool in the box**: it belongs in the project's `foldyard.toml` (`[[box.tools]]`) so it survives
62
+ a box rebuild, not in an ad-hoc `apt install` that the next `fy box down` throws away. The
63
+ `bootstrap-devbox` skill covers growing that config from inside the box.
64
+
65
+ ## "I changed it and nothing happened"
66
+
67
+ The most common class of confusion here. Full table:
68
+ [when-a-change-doesnt-take.md](references/when-a-change-doesnt-take.md). The three big ones:
69
+
70
+ - **`foldyard.toml`** — the host runs the copy it **adopted**, not your working tree. Your edit is
71
+ inert until the human answers the prompt at the next `fy up`/`fy host` (or runs `fy config
72
+ adopt`). Check with `fy config status`; see what changed with `fy config diff`.
73
+ - **Compose files** — read from the **primary checkout**, so an edit inside a worktree changes
74
+ nothing until it reaches that checkout.
75
+ - **A running container** — keeps the command and env it was created with. A config change needs a
76
+ recreate (`fy up`), not a restart.
77
+
78
+ ## Working on foldyard itself
79
+
80
+ Read `fy docs` first — it's the installed version's own manual. The source lives at
81
+ <https://github.com/twistco/foldyard>. Don't clone it into the box to "check how it works": you'd
82
+ get a different version than the one running here, which is the exact confusion this design goes
83
+ out of its way to prevent. The supported way to develop against it is the **co-dev mount**
84
+ (`fy docs adr-0020`), which mounts the real checkout and installs it editable.
@@ -0,0 +1,50 @@
1
+ # Egress, capture and the wall — why a request failed, and who can unblock it
2
+
3
+ All of the box's internet traffic routes through a proxy **on the host**. That's how credential
4
+ injection works, and it's the observation point for everything leaving the yard. Three separate
5
+ controls sit on that path; they get conflated constantly, so name the right one when you ask.
6
+
7
+ | control | question it answers | who changes it |
8
+ | --- | --- | --- |
9
+ | **routing** | does traffic go through the proxy at all? | baked in at box creation (always on) |
10
+ | **the wall** | can traffic *ignore* the proxy and go direct? | project config, at VM provisioning |
11
+ | **the allowlist** | which hosts may the proxy reach? | `fy allow …` on the host, live |
12
+ | **capture** | is traffic decrypted and logged? | `fy mode capture=on` / `fy mode capture=off`, on the host, live |
13
+
14
+ ## Diagnosing a failed request
15
+
16
+ - **`403` from the proxy / "blocked by the egress wall"** — the allowlist refused the host. It's a
17
+ decision. Ask the human for `fy allow add <host> --level session` (or `--level permanent` if it's
18
+ a permanent dependency of the project). Grants live in the host's home, outside the mount, so
19
+ there is deliberately no way to grant one from here. If the host is a real dependency of the
20
+ PROJECT (not just this task), also add it to `[proxy] recommend` in `foldyard.toml` with a
21
+ one-line `why`: that commits the recommendation for the whole team — each operator is OFFERED
22
+ it per host (after reviewing your edit at the adoption gate) instead of rediscovering the
23
+ block, and nothing is granted without their yes.
24
+ - **Connection refused / hangs on everything** — the host proxy probably isn't running. `fy doctor`
25
+ names it; the fix is `fy up` or `fy host` on the Mac.
26
+ - **TLS/certificate errors** — the proxy re-signs decrypted traffic with a CA the box trusts, so a
27
+ tool with its own hardcoded trust store (or one that pins) can fail here. Point it at the box's
28
+ combined CA bundle rather than disabling verification.
29
+ - **Works for a while, then dies ~60s in** — that's an idle-connection reset from the upstream,
30
+ not the proxy. Streaming or keepalives fix it; the proxy doesn't.
31
+
32
+ ## Capture is not filtering
33
+
34
+ `capture=on` decrypts and logs requests so the human can *see* what the yard talks to. It doesn't
35
+ block anything, and hosts on the project's `passthrough` list are tunnelled without decryption —
36
+ often a couple of hundred of them, since one `@bundle` reference expands to a whole toolchain.
37
+ `fy config widenings` prints the real count.
38
+
39
+ Conversely the wall (`[machine] wall = true`) is the enforcing control: traffic that ignores the
40
+ proxy environment is *rejected*, not silently allowed. Without it, routing is cooperative — it
41
+ bounds what is **logged**, not what can leave. `fy verify` probes this directly.
42
+
43
+ ## Don't route around it
44
+
45
+ Unsetting `HTTPS_PROXY`, adding `--insecure`, or hunting for a direct path defeats the observation
46
+ the human relies on — and under the wall it simply fails. If a task genuinely needs a host, say
47
+ which host and why; that's a one-command grant for them.
48
+
49
+ Depth: `fy docs networking`, `fy docs security`, `fy docs adr-0009` (why monitoring is called
50
+ monitoring and not filtering).
@@ -0,0 +1,54 @@
1
+ # Posture and credentials — how the box gets access, and why you can't grant it
2
+
3
+ The yard's resting state is **zero secrets**: no key files, no token env vars, no credential
4
+ helpers. Nothing to lift, so nothing to leak. Access is a *posture* the human declares on the host,
5
+ and it reaches you as capability, never as a secret you hold.
6
+
7
+ ## Axes and rungs
8
+
9
+ Posture is a set of independent **axes**, each at a **rung**. Which axes exist is per project —
10
+ `fy mode` prints them with a one-line blurb per rung; there is no fixed list to memorise. Typical
11
+ shapes: an off/on injector for one API, or a ladder like `off → logs → sa → user` where each rung
12
+ grants more.
13
+
14
+ - **Rung 0 is always the secretless one.** An axis at rest costs nothing and grants nothing.
15
+ - **High-privilege rungs are TTL-bound.** "Act as me" rungs expire (default an hour) and revert to
16
+ the default rung on their own. If something worked earlier and now 401s, check `fy mode` first —
17
+ a lapse looks exactly like a broken credential.
18
+ - `fy mode` also renders **DEGRADED**: the rung is set, but the host's capability probe says the
19
+ chain behind it isn't working right now (an expired grant, revoked access). That's the difference
20
+ between "not asked for" and "asked for, not currently working".
21
+
22
+ ## How a credential reaches you (and doesn't)
23
+
24
+ The real token is minted **on the host** and injected into your request in flight by the egress
25
+ proxy. The box holds a dummy value at most. So:
26
+
27
+ - reading the env var gives you a placeholder — that's expected, not a misconfiguration;
28
+ - the access only exists while the axis is on, and only against the host it's scoped to;
29
+ - a fully compromised box can *use* the access during that window but can never *hold* it.
30
+
31
+ Some services in the stack instead get an identity from a local metadata emulator — same idea:
32
+ the container is handed short-lived capability, not a key.
33
+
34
+ ## What to do when you need access
35
+
36
+ You cannot set posture from the box (`fy mode <axis>=<rung>` refuses here — the authoritative state
37
+ is in the host's home, outside the mount). So:
38
+
39
+ 1. Run `fy mode` and read the axis blurbs; work out the exact rung you need.
40
+ 2. Ask for it explicitly, with the reason and the command:
41
+ *"To read staging logs I need `fy mode gcp=logs` on your Mac (expires in an hour)."*
42
+ 3. If a **secret** is missing rather than a posture — the host may need to capture it once
43
+ (`fy box up` prompts on a TTY, storing it host-side at 0600). `fy doctor` on the host names
44
+ which one.
45
+
46
+ ## Reading the current grant surface
47
+
48
+ `fy config widenings` inventories what this project's config asks the host to allow: which hosts
49
+ are exempt from traffic capture, where each mechanism delivers a credential (armed *and* declared
50
+ but not yet armed), which agent prompts are shared with the team vs personal, and any config key
51
+ that reads as a control but is no longer honoured.
52
+
53
+ Depth: `fy docs modes`, `fy docs security`, `fy docs adr-0005` (why axes are data), `fy docs
54
+ adr-0007` (injection at the proxy), `fy docs adr-0008` (keyless agent auth).
@@ -0,0 +1,32 @@
1
+ # "I changed it and nothing happened"
2
+
3
+ Every entry below is a place where the thing you edited is **not** the thing that's running. They
4
+ share one root cause: state that the box can write is never authoritative for what the host does,
5
+ and containers freeze parts of their config at creation. Work down the table before assuming a bug.
6
+
7
+ | you edited | why it didn't take | what makes it take |
8
+ | --- | --- | --- |
9
+ | `foldyard.toml` / `foldyard.local.toml` | the host reconciles from the copy it **adopted**, outside the mount — your edit is inert by design | the human answers the adopt/revert/ignore prompt at the next `fy up`/`fy host`, or runs `fy config adopt`. `fy config status` / `fy config diff` show where you are |
10
+ | a block you deleted from `foldyard.toml` | `foldyard.local.toml` wins the merge and may still declare it (that file is gitignored, so it's invisible in `git status`) | `fy config widenings` names the file behind each one; a local `disabled = true` is how one person opts out of a block the team keeps |
11
+ | a compose file, inside a worktree | compose runs from the **primary checkout**, not your worktree | the edit has to reach the primary checkout |
12
+ | a compose file, anywhere | a running container keeps the command + env it was CREATED with | `fy up` (recreates on a config change) — a `restart` is not enough |
13
+ | an env var in the stack's env file | same: baked at container creation | recreate the service |
14
+ | posture (`fy mode …`) | setting is host-only; from the box it refuses | ask the human, then re-check `fy mode` |
15
+ | an egress allow / the wall | grants live in the host's home | `fy allow add <host>` on the host |
16
+ | a code file, expecting hot reload | the watcher may not see host-side writes across the VM's shared filesystem — but **edits made in the box do** propagate | make the edit in the box (you're already there); if a host-side edit was the trigger, touch the file from here |
17
+ | foldyard's own source (vendored consumers only) | a running supervisor holds the code it started with | the next host-side `fy up` bounces it and adopts the new code |
18
+ | a bundled skill / docs | they ship inside the installed package | reinstall foldyard, or run from the source checkout |
19
+
20
+ ## Diagnosing, in order
21
+
22
+ 1. `fy config status` — is the config the host runs the one you edited?
23
+ 2. `fy state` — desired vs observed, per tier (files, daemons, capability, stack, box). It exits
24
+ non-zero on drift, so it's the fastest "is anything out of sync" check.
25
+ 3. `fy doctor` — one line per check with its fix; the row that's warning usually is the answer.
26
+ 4. `fy ps` / `fy logs <svc>` — is the container even the one you think? Check when it was created.
27
+
28
+ ## The general rule
29
+
30
+ If a change would let the **box** widen what the **host** does — its credentials, its egress, its
31
+ capture — assume it needs a host-side act, and say which one. That's not an obstacle to route
32
+ around; it's the property that makes it safe to run an agent here with permissions skipped.
@@ -0,0 +1,114 @@
1
+ ---
2
+ name: update-tools-coverage
3
+ description: Refresh dev-docs/tools-coverage.md against the upstream Claude Code tools reference and the Codex app-server item schema. Use when checkpointing tool-renderer/provider coverage, after adding/removing a renderer or Codex adapter, or when either upstream taxonomy may have changed.
4
+ ---
5
+
6
+ # Update Tool Coverage
7
+
8
+ Keeps [`dev-docs/tools-coverage.md`](../../../dev-docs/tools-coverage.md) in
9
+ sync with the upstream contracts and our implementation:
10
+
11
+ 1. **Upstream** — the documented tool list at
12
+ <https://code.claude.com/docs/en/tools-reference>.
13
+ 2. **Us** — `TOOL_INPUT_MODELS` / `TOOL_OUTPUT_PARSERS` in
14
+ [`claude_code_log/factories/tool_factory.py`](../../../claude_code_log/factories/tool_factory.py).
15
+ 3. **Codex** — the installed version's generated app-server `ThreadItem`
16
+ schema, plus the rollout adapters in `providers/codex.py`,
17
+ `providers/codex_tools.py`, and `providers/codex_javascript.py`.
18
+
19
+ The doc grades each documented tool **Full** (typed input + typed output),
20
+ **Input only** (typed input, generic output), or **Generic** (no registry
21
+ entry → params-table + raw-`<pre>` fallback), and separately lists tools we
22
+ support that upstream no longer documents (renames like `Task`→`Agent`,
23
+ supersessions like `MultiEdit`, legacy aliases, undocumented features).
24
+
25
+ ## Claude Code procedure
26
+
27
+ 1. **Fetch the upstream tool names.** WebFetch the reference and ask only
28
+ for the tool-table names (the page is ~80 KB; a targeted prompt keeps it
29
+ manageable):
30
+
31
+ > WebFetch `https://code.claude.com/docs/en/tools-reference` —
32
+ > "List the exact tool names in the main tools table, one per line.
33
+ > Names only, no descriptions."
34
+
35
+ Note any tool the page marks deprecated/renamed — that's a candidate for
36
+ the second table.
37
+
38
+ 2. **Compute the truth mechanically.** Feed those names to the bundled
39
+ helper (run from the repo root; `uv run` is required so `pydantic`
40
+ resolves — bare `python3` fails with `ModuleNotFoundError: pydantic`):
41
+
42
+ ```bash
43
+ printf 'Agent Artifact AskUserQuestion ... Write' \
44
+ | uv run python .claude/skills/update-tools-coverage/check_coverage.py
45
+ ```
46
+
47
+ It prints each tool's support level, the totals, the "we register but
48
+ upstream doesn't document" set, and — if the doc exists — a **drift
49
+ report** (missing / mismatched / stale rows). If it says `in sync [OK]` and
50
+ the upstream name set is unchanged, there is nothing to do.
51
+
52
+ 3. **Reconcile the doc.** Apply the helper's output to
53
+ `dev-docs/tools-coverage.md`:
54
+ - Move rows between the two tables as tools enter/leave the upstream list —
55
+ **never delete** a row for a tool we still register. A tool leaving the
56
+ reference moves to the "no longer documented" table (it's history a
57
+ transcript viewer must still render); it does not lose support.
58
+ - Fix any support-level the drift report flags.
59
+ - Update the **totals line** and the **snapshot date** in the intro
60
+ (`snapshot YYYY-MM-DD`).
61
+ - The **Notes column is hand-maintained** — carry notes forward; only the
62
+ support level is machine-derived.
63
+
64
+ 4. **Re-run the helper** to confirm `in sync [OK]`.
65
+
66
+ ## Codex procedure
67
+
68
+ Codex function/MCP/plugin names are open-ended, so do not try to create a
69
+ closed upstream function-name list. Check two separate tables instead:
70
+
71
+ 1. Generate the public semantic item schema for the installed Codex version:
72
+
73
+ ```bash
74
+ codex --version
75
+ codex app-server generate-json-schema --out /tmp/codex-app-server-schema
76
+ ```
77
+
78
+ 2. Read `definitions.ThreadItem.oneOf` in
79
+ `/tmp/codex-app-server-schema/codex_app_server_protocol.v2.schemas.json`.
80
+ Reconcile added/removed variants with "Codex provider coverage / Public
81
+ item families" and update its version, date, and totals.
82
+ Run the local drift checker after editing:
83
+
84
+ ```bash
85
+ uv run python .claude/skills/update-tools-coverage/check_codex_coverage.py \
86
+ /tmp/codex-app-server-schema/codex_app_server_protocol.v2.schemas.json
87
+ ```
88
+
89
+ 3. Reconcile concrete call mappings with `_canonicalize()` in
90
+ `providers/codex_tools.py`, result/batch reconstruction in
91
+ `providers/codex.py`, and the `test/test_codex_*` contracts.
92
+ 4. Reconcile the static-JavaScript list with the whitelisted transfer
93
+ functions in `providers/codex_javascript.py`. Never describe legacy-regex
94
+ support as production fallback: it is retained only as an explicit test
95
+ comparison baseline.
96
+
97
+ The generated schema is version-specific and the rollout format is not a
98
+ public wire contract. State both facts in the documentation snapshot.
99
+
100
+ ## Guardrails
101
+
102
+ - **Generic is a feature, not a gap.** Unknown / `mcp__*` / plugin tools
103
+ *should* fall back to generic rendering. Only type a tool when it's common
104
+ or carries structure worth surfacing — see
105
+ [`implementing-a-tool-renderer.md`](../../../dev-docs/implementing-a-tool-renderer.md)
106
+ (or the `tool-renderer` skill) to actually add one.
107
+ - **Undocumented ≠ obsolete.** The reference table isn't a full census of
108
+ what lands in a JSONL file (e.g. `TeamCreate`/`TeamDelete` are typed both
109
+ sides but never appeared upstream). Keep those under "no longer /never
110
+ documented" with a note, not removed.
111
+ - **Dead models.** `GlobOutput` / `GrepOutput` exist in `models.py` but no
112
+ parser constructs them, so `Glob`/`Grep` are **Input only**. If a future
113
+ change wires up a parser, they graduate to Full automatically — the helper
114
+ will show the flip.
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env python3
2
+ """Check the documented Codex ThreadItem census against a generated schema."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import json
7
+ import re
8
+ import sys
9
+ from collections import Counter
10
+ from pathlib import Path
11
+
12
+
13
+ DOC_PATH = Path(__file__).parents[3] / "dev-docs" / "tools-coverage.md"
14
+ SECTION_START = "### Public item families"
15
+ SECTION_END = "### Concrete Codex call adapters"
16
+ ROW_RE = re.compile(
17
+ r"^\| `(?P<name>[^`]+)` \| "
18
+ r"(?P<status>Direct|Adapted|Partial|Missing) \|",
19
+ re.MULTILINE,
20
+ )
21
+ TOTAL_RE = re.compile(
22
+ r"\*\*Totals:\*\* (?P<direct>\d+) direct · "
23
+ r"(?P<adapted>\d+) adapted · (?P<partial>\d+) partial · "
24
+ r"(?P<missing>\d+) missing\."
25
+ )
26
+
27
+
28
+ def schema_items(path: Path) -> set[str]:
29
+ schema = json.loads(path.read_text(encoding="utf-8"))
30
+ variants = schema["definitions"]["ThreadItem"]["oneOf"]
31
+ return {variant["properties"]["type"]["enum"][0] for variant in variants}
32
+
33
+
34
+ def documented_items() -> tuple[dict[str, str], Counter[str], Counter[str]]:
35
+ document = DOC_PATH.read_text(encoding="utf-8")
36
+ section = document.split(SECTION_START, 1)[1].split(SECTION_END, 1)[0]
37
+ rows = ROW_RE.findall(section)
38
+ names = Counter(name for name, _ in rows)
39
+ statuses = Counter(status.lower() for _, status in rows)
40
+ return dict(rows), names, statuses
41
+
42
+
43
+ def main() -> int:
44
+ if len(sys.argv) != 2:
45
+ print(f"Usage: {Path(sys.argv[0]).name} SCHEMA.json", file=sys.stderr)
46
+ return 2
47
+
48
+ expected = schema_items(Path(sys.argv[1]))
49
+ documented, name_counts, statuses = documented_items()
50
+ actual = set(documented)
51
+ errors: list[str] = []
52
+
53
+ if duplicates := sorted(name for name, count in name_counts.items() if count > 1):
54
+ errors.append(f"duplicate documented items: {', '.join(duplicates)}")
55
+ if missing := sorted(expected - actual):
56
+ errors.append(f"schema items missing from documentation: {', '.join(missing)}")
57
+ if stale := sorted(actual - expected):
58
+ errors.append(f"documented items absent from schema: {', '.join(stale)}")
59
+
60
+ document = DOC_PATH.read_text(encoding="utf-8")
61
+ total_match = TOTAL_RE.search(document)
62
+ if not total_match:
63
+ errors.append("Codex totals line is missing or malformed")
64
+ else:
65
+ totals = {name: int(value) for name, value in total_match.groupdict().items()}
66
+ if totals != statuses:
67
+ errors.append(
68
+ f"documented totals {totals} do not match table {dict(statuses)}"
69
+ )
70
+
71
+ if errors:
72
+ for error in errors:
73
+ print(f"[FAIL] {error}")
74
+ return 1
75
+
76
+ print(f"Codex ThreadItem census: {len(actual)} variants")
77
+ print(
78
+ "Coverage: "
79
+ + " / ".join(
80
+ f"{status.title()} {statuses[status]}"
81
+ for status in ("direct", "adapted", "partial", "missing")
82
+ )
83
+ )
84
+ print("Generated schema and documentation are in sync [OK]")
85
+ return 0
86
+
87
+
88
+ if __name__ == "__main__":
89
+ raise SystemExit(main())
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python3
2
+ """Compute tool-coverage status from the live factory registries.
3
+
4
+ Run from the repo root via ``uv run`` (needs pydantic on the path):
5
+
6
+ # Feed the upstream documented tool names (whitespace/newline separated)
7
+ printf 'Agent Artifact ... Write' | uv run python .claude/skills/update-tools-coverage/check_coverage.py
8
+
9
+ Emits, for the given upstream tool set:
10
+ * per-tool support level (Full / Input only / Generic),
11
+ * totals,
12
+ * tools we register that upstream does NOT list (obsolete / undocumented),
13
+ * drift vs. the committed dev-docs/tools-coverage.md table, if present.
14
+
15
+ The classification here is the *source of truth*; the doc's Notes column is
16
+ hand-maintained, so reconcile prose by hand after reading this output.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import re
22
+ import sys
23
+ from collections import Counter
24
+ from pathlib import Path
25
+
26
+ from claude_code_log.factories.tool_factory import (
27
+ TOOL_INPUT_MODELS,
28
+ TOOL_OUTPUT_PARSERS,
29
+ )
30
+
31
+ DOC = Path("dev-docs/tools-coverage.md")
32
+
33
+
34
+ def support(tool: str) -> str:
35
+ has_in = tool in TOOL_INPUT_MODELS
36
+ has_out = tool in TOOL_OUTPUT_PARSERS
37
+ if has_in and has_out:
38
+ return "Full"
39
+ if has_in:
40
+ return "Input only"
41
+ return "Generic"
42
+
43
+
44
+ def read_upstream() -> list[str]:
45
+ raw = " ".join(sys.argv[1:]) if len(sys.argv) > 1 else sys.stdin.read()
46
+ tools = raw.split()
47
+ if not tools:
48
+ sys.exit(
49
+ "No upstream tool names given.\n"
50
+ "Pass them as args or on stdin (whitespace/newline separated).\n"
51
+ "Get them by fetching https://code.claude.com/docs/en/tools-reference"
52
+ )
53
+ # de-dupe, preserve order
54
+ seen: dict[str, None] = {}
55
+ for t in tools:
56
+ seen.setdefault(t, None)
57
+ return list(seen)
58
+
59
+
60
+ def main() -> None:
61
+ upstream = read_upstream()
62
+ print(f"UPSTREAM documented tools: {len(upstream)}\n")
63
+
64
+ print("=== Support level (source of truth) ===")
65
+ width = max(len(t) for t in upstream)
66
+ for t in sorted(upstream):
67
+ print(f" {t:<{width}} {support(t)}")
68
+
69
+ counts = Counter(support(t) for t in upstream)
70
+ print(
71
+ f"\n=== Totals === "
72
+ f"Full: {counts['Full']} "
73
+ f"Input only: {counts['Input only']} "
74
+ f"Generic: {counts['Generic']}"
75
+ )
76
+
77
+ registered = set(TOOL_INPUT_MODELS) | set(TOOL_OUTPUT_PARSERS)
78
+ extra = sorted(registered - set(upstream))
79
+ print("\n=== We register but upstream does NOT document ===")
80
+ print("(obsolete renames/supersessions, legacy aliases, or undocumented features)")
81
+ for t in extra:
82
+ sides = []
83
+ if t in TOOL_INPUT_MODELS:
84
+ sides.append("input")
85
+ if t in TOOL_OUTPUT_PARSERS:
86
+ sides.append("output")
87
+ print(f" {t:<20} typed: {', '.join(sides)}")
88
+
89
+ # --- Drift check against the committed doc, if present ------------------
90
+ if not DOC.exists():
91
+ print(f"\n(no {DOC} yet — nothing to diff)")
92
+ return
93
+
94
+ doc_rows = dict(
95
+ re.findall(
96
+ r"^\| `(\w+)` \| (Full|Input only|Generic) \|",
97
+ DOC.read_text(encoding="utf-8"),
98
+ re.M,
99
+ )
100
+ )
101
+ print(f"\n=== Drift vs {DOC} ===")
102
+ problems = False
103
+ for t in upstream:
104
+ want, have = support(t), doc_rows.get(t)
105
+ if have is None:
106
+ print(f" MISSING from doc: {t} (should be {want})")
107
+ problems = True
108
+ elif have != want:
109
+ print(f" MISMATCH: {t} — doc says {have!r}, code says {want!r}")
110
+ problems = True
111
+ for t in doc_rows.keys() - set(upstream):
112
+ print(f" STALE in doc (not in upstream list): {t}")
113
+ problems = True
114
+ if not problems:
115
+ print(" in sync [OK]")
116
+
117
+
118
+ if __name__ == "__main__":
119
+ main()
@@ -0,0 +1,25 @@
1
+ # EditorConfig — https://editorconfig.org
2
+ # Baseline whitespace hygiene, observed by most editors/IDEs. See the
3
+ # "Code Quality" section of CONTRIBUTING.md.
4
+ root = true
5
+
6
+ [*]
7
+ charset = utf-8
8
+ end_of_line = lf
9
+ insert_final_newline = true
10
+ trim_trailing_whitespace = true
11
+
12
+ # Markdown: a line ending in two spaces is a hard line break — trimming it
13
+ # would silently rewrite content, so leave trailing whitespace alone here.
14
+ [*.md]
15
+ trim_trailing_whitespace = false
16
+
17
+ # Syrupy snapshots: the serializer indents *every* line of the embedded block,
18
+ # including blank ones, so blank lines legitimately carry trailing whitespace.
19
+ # Never trim — regenerate with `pytest --snapshot-update -n0` instead.
20
+ [*.ambr]
21
+ trim_trailing_whitespace = false
22
+
23
+ [*.py]
24
+ indent_style = space
25
+ indent_size = 4