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.
- {pcode-0.1.8 → pcode-0.1.10}/PKG-INFO +12 -6
- {pcode-0.1.8 → pcode-0.1.10}/README.md +4 -1
- {pcode-0.1.8 → pcode-0.1.10}/pyproject.toml +14 -5
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/agent.py +22 -28
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/app.py +597 -130
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/aside.py +46 -9
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/aside_guard.py +7 -3
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/aside_ui.py +154 -64
- pcode-0.1.10/src/pcode/auth.py +34 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/background_delegation.py +137 -36
- pcode-0.1.10/src/pcode/browser.py +786 -0
- pcode-0.1.10/src/pcode/btw_view.py +220 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cache_settings.py +1 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cache_warnings.py +2 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/__init__.py +2 -3
- pcode-0.1.10/src/pcode/claude_sdk/login.py +114 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/model.py +35 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/session.py +4 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/clipboard.py +48 -1
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/commands.py +21 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/compaction.py +41 -23
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/config.py +10 -12
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/controller.py +513 -195
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/conversation_ids.py +6 -5
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/conversation_tree.py +50 -7
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/copy_ui.py +36 -169
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/delegation.py +34 -3
- pcode-0.1.10/src/pcode/drafts.py +202 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edit_preview.py +2 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/ext.py +5 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/browser.py +112 -6
- pcode-0.1.10/src/pcode/extensions/manager.py +406 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/plan_mode.py +52 -77
- pcode-0.1.10/src/pcode/extensions/reflect.py +364 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/sandbox.py +12 -5
- pcode-0.1.10/src/pcode/extensions/session_history.py +162 -0
- pcode-0.1.10/src/pcode/extensions/workflows.py +189 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/file_refs.py +3 -2
- pcode-0.1.10/src/pcode/filesystem.py +277 -0
- pcode-0.1.10/src/pcode/glyphs.py +202 -0
- pcode-0.1.10/src/pcode/history.py +705 -0
- pcode-0.1.10/src/pcode/history_index.py +331 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/host.py +45 -14
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/host_protocol.py +6 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/host_ui.py +44 -12
- pcode-0.1.10/src/pcode/images.py +257 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/inspection.py +18 -6
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/isolated_delegation.py +218 -50
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/keymap.py +9 -3
- pcode-0.1.10/src/pcode/library_log.py +57 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/live.py +308 -58
- pcode-0.1.10/src/pcode/logins.py +146 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/mcp_notice.py +1 -1
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/mcp_oauth.py +84 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/model_metadata.py +51 -38
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/models.py +9 -32
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/native_results.py +62 -3
- pcode-0.1.10/src/pcode/obsidian_plans.py +213 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/output_limits.py +1 -1
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/planning.py +59 -23
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/popup_ui.py +53 -4
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/preferences.py +93 -46
- pcode-0.1.10/src/pcode/prompt_images.py +179 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/prompt_keys.py +168 -20
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/remote.py +9 -9
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/remote_print.py +2 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/remote_profile.py +0 -5
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/replay_benchmark.py +13 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/repo_context.py +7 -2
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/retries.py +5 -1
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/runtime.py +20 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/session_naming.py +18 -3
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/session_ui.py +29 -3
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/sessions.py +203 -170
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/shell_tools.py +10 -3
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/startup_input.py +40 -7
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/steering.py +38 -6
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/stream_display.py +12 -3
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/stream_events.py +19 -2
- pcode-0.1.10/src/pcode/terminal_color.py +122 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/theme.py +67 -13
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tool_display.py +49 -4
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tool_output_limits.py +36 -5
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tree_ui.py +67 -24
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/turn.py +3 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/ui.py +713 -203
- pcode-0.1.10/src/pcode/usage.py +213 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/word_wrap.py +76 -4
- pcode-0.1.10/src/pcode/worker_channel.py +433 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/worker_ui.py +138 -18
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/workers.py +91 -3
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/workspace_filesystem.py +2 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/worktree.py +43 -4
- pcode-0.1.8/src/pcode/anthropic_oauth.py +0 -469
- pcode-0.1.8/src/pcode/auth.py +0 -113
- pcode-0.1.8/src/pcode/browser.py +0 -393
- pcode-0.1.8/src/pcode/extensions/basic_memory/Brief format.md +0 -91
- pcode-0.1.8/src/pcode/extensions/basic_memory/Briefs.base +0 -50
- pcode-0.1.8/src/pcode/extensions/basic_memory/Home.md +0 -11
- pcode-0.1.8/src/pcode/extensions/basic_memory/__init__.py +0 -731
- pcode-0.1.8/src/pcode/extensions/basic_memory/memory-states.css +0 -58
- pcode-0.1.8/src/pcode/extensions/session_history.py +0 -170
- pcode-0.1.8/src/pcode/filesystem.py +0 -131
- pcode-0.1.8/src/pcode/history.py +0 -589
- pcode-0.1.8/src/pcode/history_cursor.py +0 -147
- pcode-0.1.8/src/pcode/logins.py +0 -236
- pcode-0.1.8/src/pcode/meridian.py +0 -233
- pcode-0.1.8/src/pcode/meridian_process.py +0 -337
- pcode-0.1.8/src/pcode/meridian_setup.py +0 -356
- pcode-0.1.8/src/pcode/oauth_pages.py +0 -66
- pcode-0.1.8/src/pcode/usage.py +0 -293
- {pcode-0.1.8 → pcode-0.1.10}/.gitignore +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/LICENSE +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/__init__.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/_job_supervisor.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/appearance.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/block.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cache_diagnostics.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/cli.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/errors.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/messages.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/resume.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/session_pool.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/web.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/claude_sdk/workspace.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/cli.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/code_mode.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/codex_login.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/command_transcript.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/completion.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/config_ui.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/context_breakdown.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/context_usage.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/delta.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/diagnostics.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edit_transcript.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edit_ui.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/edits.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/__init__.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/cli.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/listener.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/mailbox.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/outbound.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/parsing.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/render.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/email_remote/state.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/error_report.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extension_guide.md +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/ponytail.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/extensions/web_research.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/frame.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/gateway.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/git_diff.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/history_embeddings.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/input_keys.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/inspector_ui.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/job_notices.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/jobs.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/jobs_ui.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/keyboard_protocol.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/layout_speed.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/links.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/links_ui.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/llm_proxy.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/mcp.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/model_ui.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/path_completion.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/plan_preview.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/plan_sizes.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/prefix_keys.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/proctitle.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/profile_benchmark.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/profiling.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/project_trust.py +0 -0
- /pcode-0.1.8/src/pcode/meridian_reminders.py → /pcode-0.1.10/src/pcode/reminders.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/rpc.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/sandbox.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/shell.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/shell_mode.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/skills.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/stall_log.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/strict_tools.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/syntax.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/syntax_colors.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/task_prompt.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/task_worktrees.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/terminal_notify.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/terminal_text.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/text_selection.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/theme_gallery.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/thinking_markdown.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/token_accounting.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/tool_panel.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/transcript_log.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/transcript_notice.py +0 -0
- {pcode-0.1.8 → pcode-0.1.10}/src/pcode/update_check.py +0 -0
- {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.
|
|
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.
|
|
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.
|
|
29
|
-
Requires-Dist: pydantic-ai-slim[anthropic,bedrock,duckduckgo,google,groq,mcp,openai,web-fetch,xai]<3,>=2.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
504
|
-
if
|
|
505
|
-
|
|
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
|
-
|
|
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)
|