pcode 0.1.8__tar.gz → 0.1.10__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 (197) hide show
  1. {pcode-0.1.8 → pcode-0.1.10}/PKG-INFO +12 -6
  2. {pcode-0.1.8 → pcode-0.1.10}/README.md +4 -1
  3. {pcode-0.1.8 → pcode-0.1.10}/pyproject.toml +14 -5
  4. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/agent.py +22 -28
  5. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/app.py +597 -130
  6. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/aside.py +46 -9
  7. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/aside_guard.py +7 -3
  8. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/aside_ui.py +154 -64
  9. pcode-0.1.10/src/pcode/auth.py +34 -0
  10. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/background_delegation.py +137 -36
  11. pcode-0.1.10/src/pcode/browser.py +786 -0
  12. pcode-0.1.10/src/pcode/btw_view.py +220 -0
  13. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cache_settings.py +1 -2
  14. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cache_warnings.py +2 -2
  15. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/__init__.py +2 -3
  16. pcode-0.1.10/src/pcode/claude_sdk/login.py +114 -0
  17. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/model.py +35 -2
  18. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/session.py +4 -0
  19. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/clipboard.py +48 -1
  20. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/commands.py +21 -2
  21. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/compaction.py +41 -23
  22. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/config.py +10 -12
  23. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/controller.py +513 -195
  24. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/conversation_ids.py +6 -5
  25. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/conversation_tree.py +50 -7
  26. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/copy_ui.py +36 -169
  27. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/delegation.py +34 -3
  28. pcode-0.1.10/src/pcode/drafts.py +202 -0
  29. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edit_preview.py +2 -2
  30. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/ext.py +5 -0
  31. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/browser.py +112 -6
  32. pcode-0.1.10/src/pcode/extensions/manager.py +406 -0
  33. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/plan_mode.py +52 -77
  34. pcode-0.1.10/src/pcode/extensions/reflect.py +364 -0
  35. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/sandbox.py +12 -5
  36. pcode-0.1.10/src/pcode/extensions/session_history.py +162 -0
  37. pcode-0.1.10/src/pcode/extensions/workflows.py +189 -0
  38. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/file_refs.py +3 -2
  39. pcode-0.1.10/src/pcode/filesystem.py +277 -0
  40. pcode-0.1.10/src/pcode/glyphs.py +202 -0
  41. pcode-0.1.10/src/pcode/history.py +705 -0
  42. pcode-0.1.10/src/pcode/history_index.py +331 -0
  43. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/host.py +45 -14
  44. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/host_protocol.py +6 -2
  45. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/host_ui.py +44 -12
  46. pcode-0.1.10/src/pcode/images.py +257 -0
  47. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/inspection.py +18 -6
  48. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/isolated_delegation.py +218 -50
  49. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/keymap.py +9 -3
  50. pcode-0.1.10/src/pcode/library_log.py +57 -0
  51. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/live.py +308 -58
  52. pcode-0.1.10/src/pcode/logins.py +146 -0
  53. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/mcp_notice.py +1 -1
  54. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/mcp_oauth.py +84 -2
  55. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/model_metadata.py +51 -38
  56. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/models.py +9 -32
  57. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/native_results.py +62 -3
  58. pcode-0.1.10/src/pcode/obsidian_plans.py +213 -0
  59. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/output_limits.py +1 -1
  60. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/planning.py +59 -23
  61. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/popup_ui.py +53 -4
  62. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/preferences.py +93 -46
  63. pcode-0.1.10/src/pcode/prompt_images.py +179 -0
  64. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/prompt_keys.py +168 -20
  65. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/remote.py +9 -9
  66. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/remote_print.py +2 -2
  67. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/remote_profile.py +0 -5
  68. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/replay_benchmark.py +13 -0
  69. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/repo_context.py +7 -2
  70. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/retries.py +5 -1
  71. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/runtime.py +20 -0
  72. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/session_naming.py +18 -3
  73. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/session_ui.py +29 -3
  74. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/sessions.py +203 -170
  75. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/shell_tools.py +10 -3
  76. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/startup_input.py +40 -7
  77. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/steering.py +38 -6
  78. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/stream_display.py +12 -3
  79. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/stream_events.py +19 -2
  80. pcode-0.1.10/src/pcode/terminal_color.py +122 -0
  81. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/theme.py +67 -13
  82. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tool_display.py +49 -4
  83. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tool_output_limits.py +36 -5
  84. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tree_ui.py +67 -24
  85. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/turn.py +3 -0
  86. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/ui.py +713 -203
  87. pcode-0.1.10/src/pcode/usage.py +213 -0
  88. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/word_wrap.py +76 -4
  89. pcode-0.1.10/src/pcode/worker_channel.py +433 -0
  90. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/worker_ui.py +138 -18
  91. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/workers.py +91 -3
  92. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/workspace_filesystem.py +2 -0
  93. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/worktree.py +43 -4
  94. pcode-0.1.8/src/pcode/anthropic_oauth.py +0 -469
  95. pcode-0.1.8/src/pcode/auth.py +0 -113
  96. pcode-0.1.8/src/pcode/browser.py +0 -393
  97. pcode-0.1.8/src/pcode/extensions/basic_memory/Brief format.md +0 -91
  98. pcode-0.1.8/src/pcode/extensions/basic_memory/Briefs.base +0 -50
  99. pcode-0.1.8/src/pcode/extensions/basic_memory/Home.md +0 -11
  100. pcode-0.1.8/src/pcode/extensions/basic_memory/__init__.py +0 -731
  101. pcode-0.1.8/src/pcode/extensions/basic_memory/memory-states.css +0 -58
  102. pcode-0.1.8/src/pcode/extensions/session_history.py +0 -170
  103. pcode-0.1.8/src/pcode/filesystem.py +0 -131
  104. pcode-0.1.8/src/pcode/history.py +0 -589
  105. pcode-0.1.8/src/pcode/history_cursor.py +0 -147
  106. pcode-0.1.8/src/pcode/logins.py +0 -236
  107. pcode-0.1.8/src/pcode/meridian.py +0 -233
  108. pcode-0.1.8/src/pcode/meridian_process.py +0 -337
  109. pcode-0.1.8/src/pcode/meridian_setup.py +0 -356
  110. pcode-0.1.8/src/pcode/oauth_pages.py +0 -66
  111. pcode-0.1.8/src/pcode/usage.py +0 -293
  112. {pcode-0.1.8 → pcode-0.1.10}/.gitignore +0 -0
  113. {pcode-0.1.8 → pcode-0.1.10}/LICENSE +0 -0
  114. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/__init__.py +0 -0
  115. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/_job_supervisor.py +0 -0
  116. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/appearance.py +0 -0
  117. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/block.py +0 -0
  118. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cache_diagnostics.py +0 -0
  119. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/cli.py +0 -0
  120. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/errors.py +0 -0
  121. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/messages.py +0 -0
  122. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/resume.py +0 -0
  123. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/session_pool.py +0 -0
  124. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/web.py +0 -0
  125. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/workspace.py +0 -0
  126. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cli.py +0 -0
  127. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/code_mode.py +0 -0
  128. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/codex_login.py +0 -0
  129. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/command_transcript.py +0 -0
  130. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/completion.py +0 -0
  131. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/config_ui.py +0 -0
  132. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/context_breakdown.py +0 -0
  133. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/context_usage.py +0 -0
  134. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/delta.py +0 -0
  135. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/diagnostics.py +0 -0
  136. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edit_transcript.py +0 -0
  137. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edit_ui.py +0 -0
  138. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edits.py +0 -0
  139. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/__init__.py +0 -0
  140. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/cli.py +0 -0
  141. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/listener.py +0 -0
  142. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/mailbox.py +0 -0
  143. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/outbound.py +0 -0
  144. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/parsing.py +0 -0
  145. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/render.py +0 -0
  146. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/state.py +0 -0
  147. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/error_report.py +0 -0
  148. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extension_guide.md +0 -0
  149. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/ponytail.py +0 -0
  150. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/web_research.py +0 -0
  151. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/frame.py +0 -0
  152. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/gateway.py +0 -0
  153. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/git_diff.py +0 -0
  154. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/history_embeddings.py +0 -0
  155. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/input_keys.py +0 -0
  156. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/inspector_ui.py +0 -0
  157. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/job_notices.py +0 -0
  158. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/jobs.py +0 -0
  159. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/jobs_ui.py +0 -0
  160. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/keyboard_protocol.py +0 -0
  161. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/layout_speed.py +0 -0
  162. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/links.py +0 -0
  163. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/links_ui.py +0 -0
  164. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/llm_proxy.py +0 -0
  165. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/mcp.py +0 -0
  166. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/model_ui.py +0 -0
  167. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/path_completion.py +0 -0
  168. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/plan_preview.py +0 -0
  169. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/plan_sizes.py +0 -0
  170. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/prefix_keys.py +0 -0
  171. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/proctitle.py +0 -0
  172. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/profile_benchmark.py +0 -0
  173. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/profiling.py +0 -0
  174. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/project_trust.py +0 -0
  175. /pcode-0.1.8/src/pcode/meridian_reminders.py → /pcode-0.1.10/src/pcode/reminders.py +0 -0
  176. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/rpc.py +0 -0
  177. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/sandbox.py +0 -0
  178. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/shell.py +0 -0
  179. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/shell_mode.py +0 -0
  180. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/skills.py +0 -0
  181. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/stall_log.py +0 -0
  182. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/strict_tools.py +0 -0
  183. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/syntax.py +0 -0
  184. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/syntax_colors.py +0 -0
  185. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/task_prompt.py +0 -0
  186. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/task_worktrees.py +0 -0
  187. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/terminal_notify.py +0 -0
  188. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/terminal_text.py +0 -0
  189. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/text_selection.py +0 -0
  190. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/theme_gallery.py +0 -0
  191. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/thinking_markdown.py +0 -0
  192. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/token_accounting.py +0 -0
  193. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tool_panel.py +0 -0
  194. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/transcript_log.py +0 -0
  195. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/transcript_notice.py +0 -0
  196. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/update_check.py +0 -0
  197. {pcode-0.1.8 → pcode-0.1.10}/src/pcode/workspace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pcode
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: Terminal-native AI coding agent with background jobs, parallel worktrees, forkable sessions, and multi-model support
5
5
  Project-URL: Homepage, https://github.com/cruxwell/pcode
6
6
  Project-URL: Documentation, https://cruxwell.github.io/pcode/
@@ -20,18 +20,21 @@ Classifier: Programming Language :: Python :: 3.14
20
20
  Classifier: Programming Language :: Python :: 3.15
21
21
  Classifier: Topic :: Software Development
22
22
  Requires-Python: >=3.14
23
+ Requires-Dist: anthropic<3,>=2.7.0
23
24
  Requires-Dist: filelock<5,>=4
24
- Requires-Dist: genai-prices<0.2,>=0.1.7
25
+ Requires-Dist: genai-prices<0.3,>=0.2.2
26
+ Requires-Dist: google-genai<3,>=2.34.0
25
27
  Requires-Dist: httpx2<3,>=2.13.1
28
+ Requires-Dist: openai<4,>=3.48.0
26
29
  Requires-Dist: prompt-toolkit==3.0.53
27
30
  Requires-Dist: psutil<8,>=6
28
- Requires-Dist: pydantic-ai-harness[codemode,coder,exa,playwright]<0.57,>=0.56.0
29
- Requires-Dist: pydantic-ai-slim[anthropic,bedrock,duckduckgo,google,groq,mcp,openai,web-fetch,xai]<3,>=2.56.0
31
+ Requires-Dist: pydantic-ai-harness[codemode,coder,exa,playwright]<0.67,>=0.66.0
32
+ Requires-Dist: pydantic-ai-slim[anthropic,bedrock,duckduckgo,google,groq,mcp,openai,web-fetch,xai]<3,>=2.66.0
30
33
  Requires-Dist: rich<16,>=15
31
34
  Requires-Dist: websockets<17,>=15.0.1
32
35
  Requires-Dist: yappi<2,>=1.7.6
33
36
  Provides-Extra: claude
34
- Requires-Dist: claude-agent-sdk<0.3,>=0.2.167; extra == 'claude'
37
+ Requires-Dist: claude-agent-sdk<0.3,>=0.2.180; extra == 'claude'
35
38
  Description-Content-Type: text/markdown
36
39
 
37
40
  <img width="1392" height="1522" alt="pcode in a dark terminal" src="docs/assets/screenshots/tabs-dark.png" />
@@ -64,6 +67,8 @@ your Claude or ChatGPT subscription.
64
67
 
65
68
  **Documentation: [cruxwell.github.io/pcode](https://cruxwell.github.io/pcode/)**
66
69
 
70
+ **Tried it? [Share feedback](https://github.com/cruxwell/pcode/discussions/4)**: what worked, what didn't, and where you got stuck.
71
+
67
72
  ## Install
68
73
 
69
74
  With [Homebrew](https://brew.sh/):
@@ -131,7 +136,7 @@ See [PLAN.md](https://github.com/cruxwell/pcode/blob/master/PLAN.md) for the lon
131
136
  | [Configuration](https://cruxwell.github.io/pcode/configuration/) | `pcode config`, per-repository overrides, trusting repository code, the settings table, syntax styles |
132
137
  | [Commands and keys](https://cruxwell.github.io/pcode/commands/) | Slash commands, key bindings, vi mode, tmux newlines, status line, `!command`, the diff and tool inspectors |
133
138
  | [Keybindings](https://cruxwell.github.io/pcode/keybindings/) | Custom command mappings with `/bind`, Ctrl shortcuts, vi editing, a normal-mode leader, and custom escape sequences such as `jj` |
134
- | [Terminal setup](https://cruxwell.github.io/pcode/terminal/) | Tab titles, the progress bar, iTerm2 and tmux settings |
139
+ | [Terminal setup](https://cruxwell.github.io/pcode/terminal/) | Tab titles, the progress bar, symbols and colors, iTerm2 and tmux settings |
135
140
  | [Tools](https://cruxwell.github.io/pcode/tools/) | Tool permissions, web search, the browser, code mode |
136
141
  | [MCP servers](https://cruxwell.github.io/pcode/mcp/) | Opt-in MCP configuration, OAuth sign-in, deferred tool search |
137
142
  | [Working in a repository](https://cruxwell.github.io/pcode/workspace/) | `AGENTS.md`/`CLAUDE.md`, skills as slash commands, one worktree per session |
@@ -148,6 +153,7 @@ checks every page and anchor link.
148
153
  ## Contributing
149
154
 
150
155
  Bugs: [open an issue](https://github.com/cruxwell/pcode/issues/new/choose).
156
+ Feedback and ideas: [the feedback discussion](https://github.com/cruxwell/pcode/discussions/4).
151
157
  Security problems: see [SECURITY.md](https://github.com/cruxwell/pcode/blob/master/SECURITY.md). Setup and checks are in
152
158
  [CONTRIBUTING.md](https://github.com/cruxwell/pcode/blob/master/CONTRIBUTING.md).
153
159
 
@@ -28,6 +28,8 @@ your Claude or ChatGPT subscription.
28
28
 
29
29
  **Documentation: [cruxwell.github.io/pcode](https://cruxwell.github.io/pcode/)**
30
30
 
31
+ **Tried it? [Share feedback](https://github.com/cruxwell/pcode/discussions/4)**: what worked, what didn't, and where you got stuck.
32
+
31
33
  ## Install
32
34
 
33
35
  With [Homebrew](https://brew.sh/):
@@ -95,7 +97,7 @@ See [PLAN.md](https://github.com/cruxwell/pcode/blob/master/PLAN.md) for the lon
95
97
  | [Configuration](https://cruxwell.github.io/pcode/configuration/) | `pcode config`, per-repository overrides, trusting repository code, the settings table, syntax styles |
96
98
  | [Commands and keys](https://cruxwell.github.io/pcode/commands/) | Slash commands, key bindings, vi mode, tmux newlines, status line, `!command`, the diff and tool inspectors |
97
99
  | [Keybindings](https://cruxwell.github.io/pcode/keybindings/) | Custom command mappings with `/bind`, Ctrl shortcuts, vi editing, a normal-mode leader, and custom escape sequences such as `jj` |
98
- | [Terminal setup](https://cruxwell.github.io/pcode/terminal/) | Tab titles, the progress bar, iTerm2 and tmux settings |
100
+ | [Terminal setup](https://cruxwell.github.io/pcode/terminal/) | Tab titles, the progress bar, symbols and colors, iTerm2 and tmux settings |
99
101
  | [Tools](https://cruxwell.github.io/pcode/tools/) | Tool permissions, web search, the browser, code mode |
100
102
  | [MCP servers](https://cruxwell.github.io/pcode/mcp/) | Opt-in MCP configuration, OAuth sign-in, deferred tool search |
101
103
  | [Working in a repository](https://cruxwell.github.io/pcode/workspace/) | `AGENTS.md`/`CLAUDE.md`, skills as slash commands, one worktree per session |
@@ -112,6 +114,7 @@ checks every page and anchor link.
112
114
  ## Contributing
113
115
 
114
116
  Bugs: [open an issue](https://github.com/cruxwell/pcode/issues/new/choose).
117
+ Feedback and ideas: [the feedback discussion](https://github.com/cruxwell/pcode/discussions/4).
115
118
  Security problems: see [SECURITY.md](https://github.com/cruxwell/pcode/blob/master/SECURITY.md). Setup and checks are in
116
119
  [CONTRIBUTING.md](https://github.com/cruxwell/pcode/blob/master/CONTRIBUTING.md).
117
120
 
@@ -21,7 +21,8 @@ classifiers = [
21
21
  requires-python = ">=3.14"
22
22
  dependencies = [
23
23
  "filelock>=4,<5",
24
- "genai-prices>=0.1.7,<0.2",
24
+ # 0.2.2 is the first to price claude-fable-5-2.
25
+ "genai-prices>=0.2.2,<0.3",
25
26
  "httpx2>=2.13.1,<3",
26
27
  # Exact: pcode relies on prompt_toolkit internals, and point releases
27
28
  # change them. Bump on purpose after tests/test_prompt_toolkit_internals.py
@@ -33,14 +34,21 @@ dependencies = [
33
34
  # itself is downloaded on first use, not at install.
34
35
  # Harness ships from the pydantic-ai repo with every Pydantic AI release and
35
36
  # pins pydantic-ai-slim to the same minor; bump both together.
36
- "pydantic-ai-harness[exa,coder,codemode,playwright]>=0.56.0,<0.57",
37
+ "pydantic-ai-harness[exa,coder,codemode,playwright]>=0.66.0,<0.67",
37
38
  # duckduckgo and web-fetch back the bundled web_research extension when no
38
39
  # provider-native search or Exa key is available.
39
40
  # google covers both google and google-cloud providers; bedrock pulls boto3.
40
- "pydantic-ai-slim[anthropic,bedrock,duckduckgo,google,groq,mcp,openai,web-fetch,xai]>=2.56.0,<3",
41
+ "pydantic-ai-slim[anthropic,bedrock,duckduckgo,google,groq,mcp,openai,web-fetch,xai]>=2.66.0,<3",
42
+ # Floors for provider SDKs pydantic-ai-slim leaves loose. anthropic 2.7 is
43
+ # the first to list claude-fable-5-2. Pydantic AI's main branch caps
44
+ # google-genai below 3; follow it until a release says 3.x works.
45
+ "anthropic>=2.7.0,<3",
46
+ "openai>=3.48.0,<4",
47
+ "google-genai>=2.34.0,<3",
41
48
  "rich>=15,<16",
42
49
  # FastMCP 4.x OAuth callback server selects Uvicorn's websockets-sansio protocol.
43
- # Capped below 17 by google-genai (still <17 as of 2.29), not by pcode.
50
+ # The <17 cap came from google-genai, which allows <18 since 2.34; raise it
51
+ # once the OAuth callback flow is checked on websockets 17.
44
52
  "websockets>=15.0.1,<17",
45
53
  ]
46
54
 
@@ -49,7 +57,8 @@ dependencies = [
49
57
  # (about 95 MB to download, 215 MB installed); the sdist would run whatever
50
58
  # `claude` is on PATH instead of the CLI version pcode was verified against.
51
59
  claude = [
52
- "claude-agent-sdk>=0.2.167,<0.3",
60
+ # 0.2.180 bundles Claude Code 2.1.321, the first to serve claude-fable-5-2.
61
+ "claude-agent-sdk>=0.2.180,<0.3",
53
62
  ]
54
63
 
55
64
  [project.urls]
@@ -39,12 +39,12 @@ from pcode.code_mode import create_code_mode
39
39
  from pcode.delegation import DelegationReporting, stream_child_activity
40
40
  from pcode.ext import EXTENSION_GUIDE, ExtensionCapabilities
41
41
  from pcode.filesystem import DisplayFileSystem
42
+ from pcode.images import ImageGate
42
43
  from pcode.isolated_delegation import WorkspaceSubAgents
43
44
  from pcode.job_notices import JobNotices
44
45
  from pcode.jobs import isolated_registry
45
46
  from pcode.mcp import configured_servers
46
47
  from pcode.mcp_notice import MCPServers
47
- from pcode.meridian import MeridianSessionIdentity
48
48
  from pcode.output_limits import ModelOutputLimits
49
49
  from pcode.planning import IdentifiedPlanning
50
50
  from pcode.preferences import SETTINGS, load_preferences, subagent_models
@@ -52,6 +52,7 @@ from pcode.repo_context import create_repo_context
52
52
  from pcode.shell_tools import JobShell
53
53
  from pcode.strict_tools import create_strict_tools
54
54
  from pcode.tool_output_limits import create_tool_output_limits
55
+ from pcode.worker_channel import ChildChannel
55
56
  from pcode.workspace import WorkspaceGuard
56
57
 
57
58
  if TYPE_CHECKING:
@@ -214,13 +215,11 @@ def _job_shell(shell: Shell, workspace: Path) -> JobShell:
214
215
  `__init__`.
215
216
  """
216
217
  values = _init_fields(shell)
217
- # direnv writes its status banner to stderr on every cd into a managed
218
- # directory, which pollutes command output the agent parses (e.g.
219
- # `... | jq`). An empty log format silences it.
220
- values["env"] = {**(shell.env or os.environ), "DIRENV_LOG_FORMAT": ""}
221
218
  # Commands inherit the whole host environment (see `JobShell`), so keep
222
219
  # provider credentials out of it, as Coder did before it left the
223
- # environment to the workspace.
220
+ # environment to the workspace. The env must be explicit: Harness applies
221
+ # `denied_env_patterns` only to an explicit env, never to `None`.
222
+ values["env"] = dict(shell.env or os.environ)
224
223
  values["denied_env_patterns"] = [*values["denied_env_patterns"], *LLM_API_KEY_ENV_PATTERNS]
225
224
  return JobShell(**values, workdir=workspace)
226
225
 
@@ -279,8 +278,8 @@ def _worker_capabilities(capabilities: Sequence) -> list:
279
278
  """
280
279
  shared_types = (
281
280
  ToolOutputLimits,
282
- MeridianSessionIdentity,
283
281
  ModelOutputLimits,
282
+ ImageGate,
284
283
  CacheBustReporting,
285
284
  TurnLimits,
286
285
  )
@@ -337,13 +336,15 @@ def _delegation(
337
336
  shared_capabilities=[
338
337
  # Extension sub-agents have no coder of their own to set it.
339
338
  ClaudeWorkspace(workspace, fallback=True),
340
- MeridianSessionIdentity(),
341
339
  ModelOutputLimits(),
340
+ ImageGate(),
342
341
  *([replace(cache_notices)] if cache_notices else []),
343
342
  ProviderCacheSettings(),
344
343
  replace(output_limits),
345
344
  # A remote host's turn budget counts its sub-agents' work too.
346
345
  *turn_limits(),
346
+ # ask_parent, parent messages and the report format, for every delegate.
347
+ ChildChannel(),
347
348
  ],
348
349
  )
349
350
 
@@ -360,7 +361,7 @@ def create_coder(
360
361
  _ensure_bundled_rg()
361
362
  # Delegation is pcode's own `WorkspaceSubAgents`, added below. Caching is
362
363
  # `ProviderCacheSettings`' per-provider choice: Coder's default `cache=True`
363
- # would also reach Meridian and OpenAI's explicit-breakpoint models.
364
+ # would also reach OpenAI's explicit-breakpoint models.
364
365
  coder = Coder(sub_agents=False, caching=False)
365
366
  output_limits = create_tool_output_limits()
366
367
  # Keep Coder's tool selection, including its persistent shell (as a
@@ -379,8 +380,8 @@ def create_coder(
379
380
  ClaudeWorkspace(workspace),
380
381
  IdentifiedPlanning(),
381
382
  DelegationReporting(),
382
- MeridianSessionIdentity(),
383
383
  ModelOutputLimits(),
384
+ ImageGate(),
384
385
  *turn_limits(),
385
386
  ]
386
387
  # Ahead of the worker copy below, so a delegate edits under the same schema.
@@ -482,33 +483,26 @@ def resolve_model(model: str) -> Model | str:
482
483
  """
483
484
  if model.startswith("openai-codex:"):
484
485
  return codex_model(model)
485
- if model.startswith("meridian:"):
486
- from pcode.models import LEGACY_ANTHROPIC_AUTH
487
-
488
- if not LEGACY_ANTHROPIC_AUTH:
489
- name = model.removeprefix("meridian:")
490
- raise ValueError(f"Meridian is turned off; switch to claude:{name} with /model.")
491
- from pcode.meridian import meridian_model
492
-
493
- return meridian_model(model)
494
486
  if model.startswith("claude:"):
495
487
  from pcode.claude_sdk import claude_model
496
488
 
497
489
  return claude_model(model)
498
490
  if not model.startswith("anthropic:"):
499
491
  return model
500
- from pcode.anthropic_oauth import anthropic_auth_source
501
492
  from pcode.auth import anthropic_model
502
493
 
503
- auth_source = anthropic_auth_source()
504
- if auth_source == "oauth":
505
- from pcode.anthropic_oauth import AnthropicOAuthModel
494
+ key = os.environ.get("ANTHROPIC_API_KEY", "").strip()
495
+ return anthropic_model(model, key) if key else model
496
+
497
+
498
+ def is_unknown_model(error: BaseException) -> bool:
499
+ """Whether Pydantic AI refused a model name it has no provider for.
500
+
501
+ Its message names only the model, so it is safe to show as is.
502
+ """
503
+ from pydantic_ai.exceptions import UserError
506
504
 
507
- return AnthropicOAuthModel(model)
508
- if auth_source == "api-key":
509
- key = os.environ.get("ANTHROPIC_API_KEY", "").strip()
510
- return anthropic_model(model, key) if key else model
511
- raise ValueError("PCODE_ANTHROPIC_AUTH must be api-key or oauth.")
505
+ return isinstance(error, UserError) and str(error).startswith("Unknown model:")
512
506
 
513
507
 
514
508
  @dataclass(frozen=True)