claude-code-tools 1.17.0__tar.gz → 1.19.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.
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/PKG-INFO +42 -79
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/README.md +25 -78
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/__init__.py +1 -1
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/aichat.py +111 -4
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server.py +32 -31
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_fingerprint.py +205 -15
- claude_code_tools-1.19.0/claude_code_tools/codex_server_legacy.py +278 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_models.py +10 -32
- claude_code_tools-1.19.0/claude_code_tools/codex_server_reservation.py +70 -0
- claude_code_tools-1.19.0/claude_code_tools/codex_server_retry.py +45 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_reuse.py +21 -0
- claude_code_tools-1.19.0/claude_code_tools/codex_server_state.py +65 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/export_session.py +249 -140
- claude_code_tools-1.19.0/claude_code_tools/port_claude_noise.py +405 -0
- claude_code_tools-1.19.0/claude_code_tools/port_claude_to_codex.py +760 -0
- claude_code_tools-1.19.0/claude_code_tools/port_codex_flatten.py +518 -0
- claude_code_tools-1.19.0/claude_code_tools/port_codex_to_claude.py +714 -0
- claude_code_tools-1.19.0/claude_code_tools/port_service.py +384 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/resolve_session.py +380 -217
- claude_code_tools-1.19.0/claude_code_tools/resolve_session_names.py +60 -0
- claude_code_tools-1.19.0/claude_code_tools/resolve_session_render.py +177 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/session_utils.py +281 -105
- claude_code_tools-1.19.0/claude_code_tools/voice_type/__init__.py +6 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/app.py +625 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/cli.py +231 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/config.py +400 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/engine_parakeet.py +999 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/engine_parakeet_mlx.py +196 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/engines.py +183 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/hotkey.py +361 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/inject.py +69 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/logic.py +119 -0
- claude_code_tools-1.19.0/claude_code_tools/voice_type/overlay.py +235 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/pyproject.toml +27 -2
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/.gitignore +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/LICENSE +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/action_rpc.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/__init__.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/backends.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/cli.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/config.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/convert.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/discord_bot.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/locking.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/paths.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/registry.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/store.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/tmux.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/agent_tunnel/trust.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/claude_continue.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_continue.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_cli.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_generation.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_process.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_supervisor.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/codex_server_worker.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/config.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/csv2gsheet.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/delete_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/dotenv_vault.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/env_safe.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/export_all.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/export_claude_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/export_codex_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/find_claude_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/find_codex_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/find_original_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/find_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/find_trimmed_sessions.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/fix_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/gdoc2docx.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/gdoc2md.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/gsheet2csv.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/md2gdoc.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/msg/__init__.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/msg/cli.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/msg/hooks.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/msg/models.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/msg/prompt_detect.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/msg/store.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/msg/watcher.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/node_menu_ui.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/search_index.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/session_lineage.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/session_menu.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/session_menu_cli.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/smart_trim.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/smart_trim_core.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/tmux_cli_controller.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/tmux_execution_helpers.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/tmux_remote_controller.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/trim_in_place.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/trim_session.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/trim_session_claude.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/trim_session_codex.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_contract.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_formatting.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_identity_policy.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_manifest.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_projection.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_rendering.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_snapshots.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_cli_store_backends.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_processes.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_runs.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_store_io.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/claude_code_tools/workflow_validation.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/agent-tunnel-spec.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/ai-agent-writing-skills.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/cc-codex-instructions.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/claude-code-chutes.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/claude-code-tmux-tutorials.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/dot-zshrc.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/ensemble-ideas.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/example-with-images.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/find-claude-session.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/intercom-spec.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/linked-in-20260102.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/lmsh.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/local-llm-setup.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/msg-phase-a-plan.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/msg-plan-v2.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/paper-writing-style-transfer-tools.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/reddit-aichat-resume-v2.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/reddit-aichat-resume.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/reddit-aichat.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/reddit-post.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/rollover-details.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/tmux-cli-instructions.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/docs/vault-documentation.md +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/hatch_build.py +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/node_ui/action_config.js +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/node_ui/menu.js +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/node_ui/package-lock.json +0 -0
- {claude_code_tools-1.17.0 → claude_code_tools-1.19.0}/node_ui/package.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-tools
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.19.0
|
|
4
4
|
Summary: Collection of tools for working with Claude Code
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -22,6 +22,22 @@ Provides-Extra: gdocs
|
|
|
22
22
|
Requires-Dist: google-api-python-client>=2.0.0; extra == 'gdocs'
|
|
23
23
|
Requires-Dist: google-auth-oauthlib>=1.0.0; extra == 'gdocs'
|
|
24
24
|
Requires-Dist: pillow>=10.0.0; extra == 'gdocs'
|
|
25
|
+
Provides-Extra: voice
|
|
26
|
+
Requires-Dist: moonshine-voice>=0.0.69; extra == 'voice'
|
|
27
|
+
Requires-Dist: pynput>=1.7.7; extra == 'voice'
|
|
28
|
+
Provides-Extra: voice-mlx
|
|
29
|
+
Requires-Dist: numpy>=1.26.0; extra == 'voice-mlx'
|
|
30
|
+
Requires-Dist: parakeet-mlx>=0.5.0; extra == 'voice-mlx'
|
|
31
|
+
Requires-Dist: pynput>=1.7.7; extra == 'voice-mlx'
|
|
32
|
+
Requires-Dist: sherpa-onnx-core<1.13,>=1.12.0; extra == 'voice-mlx'
|
|
33
|
+
Requires-Dist: sherpa-onnx<1.13,>=1.12.0; extra == 'voice-mlx'
|
|
34
|
+
Requires-Dist: sounddevice>=0.5.0; extra == 'voice-mlx'
|
|
35
|
+
Provides-Extra: voice-parakeet
|
|
36
|
+
Requires-Dist: numpy>=1.26.0; extra == 'voice-parakeet'
|
|
37
|
+
Requires-Dist: pynput>=1.7.7; extra == 'voice-parakeet'
|
|
38
|
+
Requires-Dist: sherpa-onnx-core<1.13,>=1.12.0; extra == 'voice-parakeet'
|
|
39
|
+
Requires-Dist: sherpa-onnx<1.13,>=1.12.0; extra == 'voice-parakeet'
|
|
40
|
+
Requires-Dist: sounddevice>=0.5.0; extra == 'voice-parakeet'
|
|
25
41
|
Description-Content-Type: text/markdown
|
|
26
42
|
|
|
27
43
|
<div align="center">
|
|
@@ -66,81 +82,14 @@ separate Rust binary:
|
|
|
66
82
|
[Releases](https://github.com/pchalasani/claude-code-tools/releases)
|
|
67
83
|
(look for `rust-v*`)
|
|
68
84
|
|
|
69
|
-
Install the Claude Code
|
|
85
|
+
Install the Claude Code
|
|
86
|
+
[plugins](https://pchalasani.github.io/claude-code-tools/getting-started/plugins/)
|
|
87
|
+
for hooks, skills, and agents:
|
|
70
88
|
|
|
71
89
|
```bash
|
|
72
90
|
claude plugin marketplace add pchalasani/claude-code-tools
|
|
73
|
-
claude plugin install workflow@cctools-plugins
|
|
74
91
|
```
|
|
75
92
|
|
|
76
|
-
Install the equivalent dynamic workflow plugin for Codex:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
codex plugin marketplace add pchalasani/claude-code-tools
|
|
80
|
-
codex plugin add dynamic-workflow@cctools-codex-plugins
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
The Codex plugin installs independently: it does not require the Python
|
|
84
|
-
`claude-code-tools` package or an npm install. Node.js 20 or newer and Codex
|
|
85
|
-
CLI 0.136.0 or newer are required for callbacks. Version 0.136.0 is the first
|
|
86
|
-
compatible CLI release for this callback protocol. Codex still marks the app
|
|
87
|
-
server and remote TUI interfaces as experimental, so those surfaces may evolve.
|
|
88
|
-
The plugin can notify the originating Codex thread through Codex's shared app
|
|
89
|
-
server after a detached workflow finishes. Callback preflight also rejects a
|
|
90
|
-
stale connected server.
|
|
91
|
-
|
|
92
|
-
The optional Python package makes that callback setup a single command:
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
codex-dynamic
|
|
96
|
-
# Or continue the latest conversation:
|
|
97
|
-
codex-dynamic resume --last
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
`codex-dynamic` starts or reuses the local app server and then hands the
|
|
101
|
-
terminal directly to Codex. After a plugin or Codex upgrade, the next launch
|
|
102
|
-
automatically starts a fresh server generation; existing sessions and workflow
|
|
103
|
-
callbacks stay connected to their old generation. No manual restart is needed.
|
|
104
|
-
Use `codex-server status` or `logs` for nondisruptive inspection. A forced stop
|
|
105
|
-
or restart cleans up every retained generation and disconnects its attached
|
|
106
|
-
TUIs, so use those commands only after exiting the sessions normally.
|
|
107
|
-
|
|
108
|
-
The Python package also installs `codex-workflows`, an observational dashboard
|
|
109
|
-
for durable workflow runs:
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
codex-workflows
|
|
113
|
-
codex-workflows watch --limit 20
|
|
114
|
-
codex-workflows show RUN_ID
|
|
115
|
-
codex-workflows --all
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
The default list contains only active workflows and identifies the project
|
|
119
|
-
folder from which each workflow was launched. Use `show RUN_ID` for its full
|
|
120
|
-
working directory, or `--all` to include completed and diagnostic history. The
|
|
121
|
-
command reads durable workflow state and process metadata. It never changes a
|
|
122
|
-
run, sends a signal, repairs state, or launches an agent. See the
|
|
123
|
-
[codex-workflows reference][codex-workflows-reference] for filters, JSON output,
|
|
124
|
-
and the complete versioned schema.
|
|
125
|
-
|
|
126
|
-
[codex-workflows-reference]:
|
|
127
|
-
//pchalasani.github.io/claude-code-tools/tools/codex-dynamic/#observe-workflow-runs
|
|
128
|
-
|
|
129
|
-
Server management and passive supervision add no model calls. Completion
|
|
130
|
-
reporting starts a new turn only while the thread is idle; otherwise it steers
|
|
131
|
-
and extends the active turn. Either reporting path consumes model tokens.
|
|
132
|
-
|
|
133
|
-
Each workflow `run` or `resume` uses narrow host execution for that exact
|
|
134
|
-
reviewed supervisor command. The workflow JavaScript remains restricted, and
|
|
135
|
-
every headless Codex worker keeps its declared sandbox.
|
|
136
|
-
|
|
137
|
-
See the
|
|
138
|
-
[Claude → Codex migration guide][claude-to-codex-guide]
|
|
139
|
-
for usage and workflow-porting instructions.
|
|
140
|
-
|
|
141
|
-
[claude-to-codex-guide]:
|
|
142
|
-
https://pchalasani.github.io/claude-code-tools/guides/claude-to-codex/
|
|
143
|
-
|
|
144
93
|
---
|
|
145
94
|
|
|
146
95
|
Click a card to jump to that feature, or
|
|
@@ -171,17 +120,22 @@ Click a card to jump to that feature, or
|
|
|
171
120
|
</a>
|
|
172
121
|
</td>
|
|
173
122
|
<td align="center">
|
|
123
|
+
<a href="https://pchalasani.github.io/claude-code-tools/tools/voice-type/">
|
|
124
|
+
<img src="assets/card-voice-type.svg" alt="voice-type" width="200"/>
|
|
125
|
+
</a>
|
|
126
|
+
</td>
|
|
127
|
+
<td align="center">
|
|
174
128
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/tmux-cli/">
|
|
175
129
|
<img src="assets/card-tmux.svg" alt="tmux-cli" width="200"/>
|
|
176
130
|
</a>
|
|
177
131
|
</td>
|
|
132
|
+
</tr>
|
|
133
|
+
<tr>
|
|
178
134
|
<td align="center">
|
|
179
135
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/agent-tunnel/">
|
|
180
136
|
<img src="assets/card-agent-tunnel.svg" alt="agent-tunnel" width="200"/>
|
|
181
137
|
</a>
|
|
182
138
|
</td>
|
|
183
|
-
</tr>
|
|
184
|
-
<tr>
|
|
185
139
|
<td align="center">
|
|
186
140
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/lmsh/">
|
|
187
141
|
<img src="assets/card-lmsh.svg" alt="lmsh" width="200"/>
|
|
@@ -192,13 +146,13 @@ Click a card to jump to that feature, or
|
|
|
192
146
|
<img src="assets/card-vault.svg" alt="vault" width="200"/>
|
|
193
147
|
</a>
|
|
194
148
|
</td>
|
|
149
|
+
</tr>
|
|
150
|
+
<tr>
|
|
195
151
|
<td align="center">
|
|
196
152
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/env-safe/">
|
|
197
153
|
<img src="assets/card-env-safe.svg" alt="env-safe" width="200"/>
|
|
198
154
|
</a>
|
|
199
155
|
</td>
|
|
200
|
-
</tr>
|
|
201
|
-
<tr>
|
|
202
156
|
<td align="center">
|
|
203
157
|
<a href="https://pchalasani.github.io/claude-code-tools/plugins-detail/safety-hooks/">
|
|
204
158
|
<img src="assets/card-safety.svg" alt="safety" width="200"/>
|
|
@@ -209,13 +163,13 @@ Click a card to jump to that feature, or
|
|
|
209
163
|
<img src="assets/card-statusline.svg" alt="statusline" width="200"/>
|
|
210
164
|
</a>
|
|
211
165
|
</td>
|
|
166
|
+
</tr>
|
|
167
|
+
<tr>
|
|
212
168
|
<td align="center">
|
|
213
169
|
<a href="https://pchalasani.github.io/claude-code-tools/integrations/google-docs/">
|
|
214
170
|
<img src="assets/card-gdocs.svg" alt="gdocs" width="200"/>
|
|
215
171
|
</a>
|
|
216
172
|
</td>
|
|
217
|
-
</tr>
|
|
218
|
-
<tr>
|
|
219
173
|
<td align="center">
|
|
220
174
|
<a href="https://pchalasani.github.io/claude-code-tools/integrations/google-sheets/">
|
|
221
175
|
<img src="assets/card-gsheets.svg" alt="gsheets" width="200"/>
|
|
@@ -226,13 +180,13 @@ Click a card to jump to that feature, or
|
|
|
226
180
|
<img src="assets/card-alt.svg" alt="alt" width="200"/>
|
|
227
181
|
</a>
|
|
228
182
|
</td>
|
|
183
|
+
</tr>
|
|
184
|
+
<tr>
|
|
229
185
|
<td align="center">
|
|
230
186
|
<a href="https://pchalasani.github.io/claude-code-tools/plugins-detail/voice/">
|
|
231
187
|
<img src="assets/card-voice.svg" alt="voice" width="200"/>
|
|
232
188
|
</a>
|
|
233
189
|
</td>
|
|
234
|
-
</tr>
|
|
235
|
-
<tr>
|
|
236
190
|
<td align="center">
|
|
237
191
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/fix-session/">
|
|
238
192
|
<img src="assets/card-session-repair.svg" alt="session repair" width="200"/>
|
|
@@ -243,6 +197,8 @@ Click a card to jump to that feature, or
|
|
|
243
197
|
<img src="assets/card-sasy-guard.svg" alt="sasy-guard" width="200"/>
|
|
244
198
|
</a>
|
|
245
199
|
</td>
|
|
200
|
+
</tr>
|
|
201
|
+
<tr>
|
|
246
202
|
<td align="center">
|
|
247
203
|
<a href="https://pchalasani.github.io/claude-code-tools/guides/claude-to-codex/">
|
|
248
204
|
<img src="assets/card-claude-to-codex.svg" alt="Claude to Codex" width="200"/>
|
|
@@ -287,6 +243,13 @@ See [tmux-cli](https://pchalasani.github.io/claude-code-tools/tools/tmux-cli/) i
|
|
|
287
243
|
## Voice Plugin
|
|
288
244
|
See [Voice](https://pchalasani.github.io/claude-code-tools/plugins-detail/voice/) in the full documentation.
|
|
289
245
|
|
|
246
|
+
<a id="voice-type"></a>
|
|
247
|
+
## voice-type — Local Voice Dictation
|
|
248
|
+
Fully on-device speech-to-text (Moonshine + VAD) that types wherever your
|
|
249
|
+
cursor is, with a configurable toggle hotkey and optional wake word.
|
|
250
|
+
Install with `uv tool install "claude-code-tools[voice]"`.
|
|
251
|
+
See [voice-type](https://pchalasani.github.io/claude-code-tools/tools/voice-type/) in the full documentation.
|
|
252
|
+
|
|
290
253
|
<a id="license"></a>
|
|
291
254
|
## License
|
|
292
255
|
|
|
@@ -40,81 +40,14 @@ separate Rust binary:
|
|
|
40
40
|
[Releases](https://github.com/pchalasani/claude-code-tools/releases)
|
|
41
41
|
(look for `rust-v*`)
|
|
42
42
|
|
|
43
|
-
Install the Claude Code
|
|
43
|
+
Install the Claude Code
|
|
44
|
+
[plugins](https://pchalasani.github.io/claude-code-tools/getting-started/plugins/)
|
|
45
|
+
for hooks, skills, and agents:
|
|
44
46
|
|
|
45
47
|
```bash
|
|
46
48
|
claude plugin marketplace add pchalasani/claude-code-tools
|
|
47
|
-
claude plugin install workflow@cctools-plugins
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
Install the equivalent dynamic workflow plugin for Codex:
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
codex plugin marketplace add pchalasani/claude-code-tools
|
|
54
|
-
codex plugin add dynamic-workflow@cctools-codex-plugins
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
The Codex plugin installs independently: it does not require the Python
|
|
58
|
-
`claude-code-tools` package or an npm install. Node.js 20 or newer and Codex
|
|
59
|
-
CLI 0.136.0 or newer are required for callbacks. Version 0.136.0 is the first
|
|
60
|
-
compatible CLI release for this callback protocol. Codex still marks the app
|
|
61
|
-
server and remote TUI interfaces as experimental, so those surfaces may evolve.
|
|
62
|
-
The plugin can notify the originating Codex thread through Codex's shared app
|
|
63
|
-
server after a detached workflow finishes. Callback preflight also rejects a
|
|
64
|
-
stale connected server.
|
|
65
|
-
|
|
66
|
-
The optional Python package makes that callback setup a single command:
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
codex-dynamic
|
|
70
|
-
# Or continue the latest conversation:
|
|
71
|
-
codex-dynamic resume --last
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
`codex-dynamic` starts or reuses the local app server and then hands the
|
|
75
|
-
terminal directly to Codex. After a plugin or Codex upgrade, the next launch
|
|
76
|
-
automatically starts a fresh server generation; existing sessions and workflow
|
|
77
|
-
callbacks stay connected to their old generation. No manual restart is needed.
|
|
78
|
-
Use `codex-server status` or `logs` for nondisruptive inspection. A forced stop
|
|
79
|
-
or restart cleans up every retained generation and disconnects its attached
|
|
80
|
-
TUIs, so use those commands only after exiting the sessions normally.
|
|
81
|
-
|
|
82
|
-
The Python package also installs `codex-workflows`, an observational dashboard
|
|
83
|
-
for durable workflow runs:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
codex-workflows
|
|
87
|
-
codex-workflows watch --limit 20
|
|
88
|
-
codex-workflows show RUN_ID
|
|
89
|
-
codex-workflows --all
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
The default list contains only active workflows and identifies the project
|
|
93
|
-
folder from which each workflow was launched. Use `show RUN_ID` for its full
|
|
94
|
-
working directory, or `--all` to include completed and diagnostic history. The
|
|
95
|
-
command reads durable workflow state and process metadata. It never changes a
|
|
96
|
-
run, sends a signal, repairs state, or launches an agent. See the
|
|
97
|
-
[codex-workflows reference][codex-workflows-reference] for filters, JSON output,
|
|
98
|
-
and the complete versioned schema.
|
|
99
|
-
|
|
100
|
-
[codex-workflows-reference]:
|
|
101
|
-
//pchalasani.github.io/claude-code-tools/tools/codex-dynamic/#observe-workflow-runs
|
|
102
|
-
|
|
103
|
-
Server management and passive supervision add no model calls. Completion
|
|
104
|
-
reporting starts a new turn only while the thread is idle; otherwise it steers
|
|
105
|
-
and extends the active turn. Either reporting path consumes model tokens.
|
|
106
|
-
|
|
107
|
-
Each workflow `run` or `resume` uses narrow host execution for that exact
|
|
108
|
-
reviewed supervisor command. The workflow JavaScript remains restricted, and
|
|
109
|
-
every headless Codex worker keeps its declared sandbox.
|
|
110
|
-
|
|
111
|
-
See the
|
|
112
|
-
[Claude → Codex migration guide][claude-to-codex-guide]
|
|
113
|
-
for usage and workflow-porting instructions.
|
|
114
|
-
|
|
115
|
-
[claude-to-codex-guide]:
|
|
116
|
-
https://pchalasani.github.io/claude-code-tools/guides/claude-to-codex/
|
|
117
|
-
|
|
118
51
|
---
|
|
119
52
|
|
|
120
53
|
Click a card to jump to that feature, or
|
|
@@ -145,17 +78,22 @@ Click a card to jump to that feature, or
|
|
|
145
78
|
</a>
|
|
146
79
|
</td>
|
|
147
80
|
<td align="center">
|
|
81
|
+
<a href="https://pchalasani.github.io/claude-code-tools/tools/voice-type/">
|
|
82
|
+
<img src="assets/card-voice-type.svg" alt="voice-type" width="200"/>
|
|
83
|
+
</a>
|
|
84
|
+
</td>
|
|
85
|
+
<td align="center">
|
|
148
86
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/tmux-cli/">
|
|
149
87
|
<img src="assets/card-tmux.svg" alt="tmux-cli" width="200"/>
|
|
150
88
|
</a>
|
|
151
89
|
</td>
|
|
90
|
+
</tr>
|
|
91
|
+
<tr>
|
|
152
92
|
<td align="center">
|
|
153
93
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/agent-tunnel/">
|
|
154
94
|
<img src="assets/card-agent-tunnel.svg" alt="agent-tunnel" width="200"/>
|
|
155
95
|
</a>
|
|
156
96
|
</td>
|
|
157
|
-
</tr>
|
|
158
|
-
<tr>
|
|
159
97
|
<td align="center">
|
|
160
98
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/lmsh/">
|
|
161
99
|
<img src="assets/card-lmsh.svg" alt="lmsh" width="200"/>
|
|
@@ -166,13 +104,13 @@ Click a card to jump to that feature, or
|
|
|
166
104
|
<img src="assets/card-vault.svg" alt="vault" width="200"/>
|
|
167
105
|
</a>
|
|
168
106
|
</td>
|
|
107
|
+
</tr>
|
|
108
|
+
<tr>
|
|
169
109
|
<td align="center">
|
|
170
110
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/env-safe/">
|
|
171
111
|
<img src="assets/card-env-safe.svg" alt="env-safe" width="200"/>
|
|
172
112
|
</a>
|
|
173
113
|
</td>
|
|
174
|
-
</tr>
|
|
175
|
-
<tr>
|
|
176
114
|
<td align="center">
|
|
177
115
|
<a href="https://pchalasani.github.io/claude-code-tools/plugins-detail/safety-hooks/">
|
|
178
116
|
<img src="assets/card-safety.svg" alt="safety" width="200"/>
|
|
@@ -183,13 +121,13 @@ Click a card to jump to that feature, or
|
|
|
183
121
|
<img src="assets/card-statusline.svg" alt="statusline" width="200"/>
|
|
184
122
|
</a>
|
|
185
123
|
</td>
|
|
124
|
+
</tr>
|
|
125
|
+
<tr>
|
|
186
126
|
<td align="center">
|
|
187
127
|
<a href="https://pchalasani.github.io/claude-code-tools/integrations/google-docs/">
|
|
188
128
|
<img src="assets/card-gdocs.svg" alt="gdocs" width="200"/>
|
|
189
129
|
</a>
|
|
190
130
|
</td>
|
|
191
|
-
</tr>
|
|
192
|
-
<tr>
|
|
193
131
|
<td align="center">
|
|
194
132
|
<a href="https://pchalasani.github.io/claude-code-tools/integrations/google-sheets/">
|
|
195
133
|
<img src="assets/card-gsheets.svg" alt="gsheets" width="200"/>
|
|
@@ -200,13 +138,13 @@ Click a card to jump to that feature, or
|
|
|
200
138
|
<img src="assets/card-alt.svg" alt="alt" width="200"/>
|
|
201
139
|
</a>
|
|
202
140
|
</td>
|
|
141
|
+
</tr>
|
|
142
|
+
<tr>
|
|
203
143
|
<td align="center">
|
|
204
144
|
<a href="https://pchalasani.github.io/claude-code-tools/plugins-detail/voice/">
|
|
205
145
|
<img src="assets/card-voice.svg" alt="voice" width="200"/>
|
|
206
146
|
</a>
|
|
207
147
|
</td>
|
|
208
|
-
</tr>
|
|
209
|
-
<tr>
|
|
210
148
|
<td align="center">
|
|
211
149
|
<a href="https://pchalasani.github.io/claude-code-tools/tools/fix-session/">
|
|
212
150
|
<img src="assets/card-session-repair.svg" alt="session repair" width="200"/>
|
|
@@ -217,6 +155,8 @@ Click a card to jump to that feature, or
|
|
|
217
155
|
<img src="assets/card-sasy-guard.svg" alt="sasy-guard" width="200"/>
|
|
218
156
|
</a>
|
|
219
157
|
</td>
|
|
158
|
+
</tr>
|
|
159
|
+
<tr>
|
|
220
160
|
<td align="center">
|
|
221
161
|
<a href="https://pchalasani.github.io/claude-code-tools/guides/claude-to-codex/">
|
|
222
162
|
<img src="assets/card-claude-to-codex.svg" alt="Claude to Codex" width="200"/>
|
|
@@ -261,6 +201,13 @@ See [tmux-cli](https://pchalasani.github.io/claude-code-tools/tools/tmux-cli/) i
|
|
|
261
201
|
## Voice Plugin
|
|
262
202
|
See [Voice](https://pchalasani.github.io/claude-code-tools/plugins-detail/voice/) in the full documentation.
|
|
263
203
|
|
|
204
|
+
<a id="voice-type"></a>
|
|
205
|
+
## voice-type — Local Voice Dictation
|
|
206
|
+
Fully on-device speech-to-text (Moonshine + VAD) that types wherever your
|
|
207
|
+
cursor is, with a configurable toggle hotkey and optional wake word.
|
|
208
|
+
Install with `uv tool install "claude-code-tools[voice]"`.
|
|
209
|
+
See [voice-type](https://pchalasani.github.io/claude-code-tools/tools/voice-type/) in the full documentation.
|
|
210
|
+
|
|
264
211
|
<a id="license"></a>
|
|
265
212
|
## License
|
|
266
213
|
|
|
@@ -37,7 +37,7 @@ class ResolveCommand(click.Command):
|
|
|
37
37
|
"""Parse arguments, converting Click usage failures to resolver errors."""
|
|
38
38
|
import sys
|
|
39
39
|
|
|
40
|
-
from claude_code_tools.
|
|
40
|
+
from claude_code_tools.resolve_session_render import _render_error
|
|
41
41
|
|
|
42
42
|
raw_args = tuple(args)
|
|
43
43
|
try:
|
|
@@ -115,9 +115,12 @@ def main(ctx, claude_home, codex_home):
|
|
|
115
115
|
# Auto-index sessions on every aichat command (incremental, fast if up-to-date)
|
|
116
116
|
# Skip for build-index/clear-index to avoid double-indexing or state conflicts
|
|
117
117
|
# In JSON mode (-j/--json), suppress all output for clean parsing
|
|
118
|
+
# 'port' is also skipped: its contract requires the detected
|
|
119
|
+
# direction line to be the FIRST output, so the indexer's progress
|
|
120
|
+
# bar must never print before it.
|
|
118
121
|
skip_auto_index_cmds = ['build-index', 'clear-index', 'index-stats']
|
|
119
122
|
should_skip = (
|
|
120
|
-
ctx.invoked_subcommand
|
|
123
|
+
ctx.invoked_subcommand in ('port', 'resolve')
|
|
121
124
|
or ctx.invoked_subcommand in skip_auto_index_cmds
|
|
122
125
|
or any(cmd in sys.argv for cmd in skip_auto_index_cmds)
|
|
123
126
|
)
|
|
@@ -182,10 +185,16 @@ def resolve_session_cmd(
|
|
|
182
185
|
json_output: bool,
|
|
183
186
|
pretty_output: bool,
|
|
184
187
|
) -> None:
|
|
185
|
-
"""Resolve a name, full
|
|
188
|
+
"""Resolve a session name, full ID, ID fragment, or filename fragment.
|
|
189
|
+
|
|
190
|
+
Ordered tiers (first non-empty wins): exact ID, exact name, ID
|
|
191
|
+
prefix, ID substring, name substring, session-file name
|
|
192
|
+
substring (e.g. a codex rollout timestamp like
|
|
193
|
+
2026-03-25T14-50).
|
|
194
|
+
"""
|
|
186
195
|
import sys
|
|
187
196
|
|
|
188
|
-
from claude_code_tools.
|
|
197
|
+
from claude_code_tools.resolve_session_render import run
|
|
189
198
|
|
|
190
199
|
if json_output and pretty_output:
|
|
191
200
|
click.echo(
|
|
@@ -1442,6 +1451,104 @@ def move_session(session, new_project, agent):
|
|
|
1442
1451
|
console.print(f" [cyan]{resume_cmd}[/cyan]")
|
|
1443
1452
|
|
|
1444
1453
|
|
|
1454
|
+
@main.command("port")
|
|
1455
|
+
@click.argument("session", required=True)
|
|
1456
|
+
@click.option("--claude-home", help="Path to Claude home directory")
|
|
1457
|
+
@click.option("--codex-home", help="Path to Codex home directory")
|
|
1458
|
+
@click.pass_context
|
|
1459
|
+
def port_session(
|
|
1460
|
+
ctx: click.Context,
|
|
1461
|
+
session: str,
|
|
1462
|
+
claude_home: "str | None",
|
|
1463
|
+
codex_home: "str | None",
|
|
1464
|
+
) -> None:
|
|
1465
|
+
"""Port a session to the OTHER agent (codex <-> claude).
|
|
1466
|
+
|
|
1467
|
+
Auto-detects which agent the session belongs to. Codex sessions
|
|
1468
|
+
are converted into a flattened, resumable Claude Code session;
|
|
1469
|
+
Claude sessions are converted into a flattened, resumable Codex
|
|
1470
|
+
rollout.
|
|
1471
|
+
|
|
1472
|
+
SESSION may be a full session id, a partial id (prefix, middle,
|
|
1473
|
+
or suffix fragment), a session name (set with /rename), a
|
|
1474
|
+
rollout filename fragment (e.g. 2026-03-25T14-50), or a session
|
|
1475
|
+
file path. Lookup is global across all projects in both homes.
|
|
1476
|
+
|
|
1477
|
+
\b
|
|
1478
|
+
Examples:
|
|
1479
|
+
aichat port 019f6d85-df3c-7c83-84f6-b97e73305fcf
|
|
1480
|
+
aichat port abc123 --claude-home ~/.claude-alt
|
|
1481
|
+
aichat port my-session-name
|
|
1482
|
+
aichat port 2026-03-25T14-50
|
|
1483
|
+
"""
|
|
1484
|
+
import sys
|
|
1485
|
+
|
|
1486
|
+
from claude_code_tools.port_service import (
|
|
1487
|
+
PortSessionError,
|
|
1488
|
+
port_claude_session,
|
|
1489
|
+
port_codex_session,
|
|
1490
|
+
resolve_port_session,
|
|
1491
|
+
)
|
|
1492
|
+
|
|
1493
|
+
# Group-level --claude-home/--codex-home (given BEFORE the
|
|
1494
|
+
# subcommand) are stored on the root context; command-level
|
|
1495
|
+
# options take precedence.
|
|
1496
|
+
root_obj = ctx.find_root().obj or {}
|
|
1497
|
+
claude_home = claude_home or root_obj.get("claude_home")
|
|
1498
|
+
codex_home = codex_home or root_obj.get("codex_home")
|
|
1499
|
+
|
|
1500
|
+
try:
|
|
1501
|
+
resolved = resolve_port_session(
|
|
1502
|
+
session, claude_home=claude_home, codex_home=codex_home
|
|
1503
|
+
)
|
|
1504
|
+
except PortSessionError as e:
|
|
1505
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
1506
|
+
sys.exit(1)
|
|
1507
|
+
|
|
1508
|
+
if resolved.agent == "claude":
|
|
1509
|
+
print("Detected source agent: claude — porting to Codex")
|
|
1510
|
+
try:
|
|
1511
|
+
result = port_claude_session(
|
|
1512
|
+
resolved.session_file, codex_home=codex_home
|
|
1513
|
+
)
|
|
1514
|
+
except PortSessionError as e:
|
|
1515
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
1516
|
+
sys.exit(1)
|
|
1517
|
+
|
|
1518
|
+
print()
|
|
1519
|
+
print(f"New Codex session id: {result.new_session_id}")
|
|
1520
|
+
print(f"Output file: {result.output_file}")
|
|
1521
|
+
print(f"Session cwd: {result.cwd}")
|
|
1522
|
+
print()
|
|
1523
|
+
print("To resume:")
|
|
1524
|
+
print(f" {result.resume_hint}")
|
|
1525
|
+
print()
|
|
1526
|
+
print(
|
|
1527
|
+
"Tip: codex's /import can also import Claude sessions "
|
|
1528
|
+
"natively (interactive alternative)."
|
|
1529
|
+
)
|
|
1530
|
+
return
|
|
1531
|
+
|
|
1532
|
+
print("Detected source agent: codex — porting to Claude Code")
|
|
1533
|
+
try:
|
|
1534
|
+
result = port_codex_session(
|
|
1535
|
+
resolved.session_file, claude_home=claude_home
|
|
1536
|
+
)
|
|
1537
|
+
except PortSessionError as e:
|
|
1538
|
+
# Expected failure modes (missing/empty session, filesystem
|
|
1539
|
+
# or encoding errors) become a clean error, not a traceback.
|
|
1540
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
1541
|
+
sys.exit(1)
|
|
1542
|
+
|
|
1543
|
+
print()
|
|
1544
|
+
print(f"New Claude session id: {result.new_session_id}")
|
|
1545
|
+
print(f"Output file: {result.output_file}")
|
|
1546
|
+
print(f"Session cwd: {result.cwd}")
|
|
1547
|
+
print()
|
|
1548
|
+
print("To resume:")
|
|
1549
|
+
print(f" {result.resume_hint}")
|
|
1550
|
+
|
|
1551
|
+
|
|
1445
1552
|
@main.command("query")
|
|
1446
1553
|
@click.argument("session", required=False)
|
|
1447
1554
|
@click.argument("question", required=False)
|
|
@@ -14,11 +14,13 @@ import struct
|
|
|
14
14
|
import subprocess
|
|
15
15
|
import sys
|
|
16
16
|
import time
|
|
17
|
-
from contextlib import contextmanager
|
|
17
|
+
from contextlib import ExitStack, contextmanager
|
|
18
18
|
from dataclasses import replace
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
from typing import Iterator, Mapping, Sequence
|
|
21
21
|
|
|
22
|
+
from claude_code_tools import codex_server_retry
|
|
23
|
+
from claude_code_tools.codex_server_legacy import reauthenticate_legacy_state
|
|
22
24
|
from claude_code_tools.codex_server_fingerprint import (
|
|
23
25
|
PluginSnapshot as _PluginSnapshot,
|
|
24
26
|
hash_plugin_tree as _hash_plugin_tree, # noqa: F401
|
|
@@ -78,6 +80,7 @@ from claude_code_tools.codex_server_reuse import (
|
|
|
78
80
|
disconnect_refusal as _disconnect_refusal,
|
|
79
81
|
helper_restart_reason as _reuse_restart_reason,
|
|
80
82
|
require_external_compatible as _external_compatible,
|
|
83
|
+
same_server_launch as _same_server_launch,
|
|
81
84
|
)
|
|
82
85
|
|
|
83
86
|
|
|
@@ -150,6 +153,22 @@ def _lifecycle_lock(paths: ServerPaths) -> Iterator[None]:
|
|
|
150
153
|
os.close(fd)
|
|
151
154
|
|
|
152
155
|
|
|
156
|
+
@contextmanager
|
|
157
|
+
def _reserved_generation_lifecycle(
|
|
158
|
+
base: ServerPaths,
|
|
159
|
+
paths: ServerPaths,
|
|
160
|
+
generation: str,
|
|
161
|
+
) -> Iterator[None]:
|
|
162
|
+
"""Reserve capacity before releasing the base lifecycle lock."""
|
|
163
|
+
generation_lock = ExitStack()
|
|
164
|
+
with _lifecycle_lock(base):
|
|
165
|
+
require_generation_capacity(base, generation)
|
|
166
|
+
prepare_runtime(paths)
|
|
167
|
+
generation_lock.enter_context(_lifecycle_lock(paths))
|
|
168
|
+
with generation_lock:
|
|
169
|
+
yield
|
|
170
|
+
|
|
171
|
+
|
|
153
172
|
def _resolve_codex(env: Mapping[str, str]) -> str:
|
|
154
173
|
"""Resolve a canonical executable used by both server and TUI."""
|
|
155
174
|
configured = env.get("CCTOOLS_CODEX_BIN")
|
|
@@ -519,6 +538,7 @@ def get_status(env: Mapping[str, str] | None = None) -> ServerStatus:
|
|
|
519
538
|
except StateFileError as exc:
|
|
520
539
|
state = None
|
|
521
540
|
state_error = str(exc)
|
|
541
|
+
state = reauthenticate_legacy_state(paths, state, _socket_peer_pid)
|
|
522
542
|
probe = _probe_server(codex_path, child_env, paths)
|
|
523
543
|
return _status_from(paths, state, probe, state_error)
|
|
524
544
|
|
|
@@ -557,33 +577,12 @@ def _require_unchanged_plugin_snapshot(
|
|
|
557
577
|
) -> None:
|
|
558
578
|
"""Reject a lifecycle decision made across a plugin input change."""
|
|
559
579
|
if _plugin_configuration_snapshot(paths, codex_options) != expected:
|
|
560
|
-
raise
|
|
580
|
+
raise codex_server_retry.PluginSnapshotChangedError(
|
|
561
581
|
"the Codex plugin or marketplace snapshot changed during "
|
|
562
582
|
f"{operation}; retry after plugin updates finish"
|
|
563
583
|
)
|
|
564
584
|
|
|
565
585
|
|
|
566
|
-
def _same_server_launch(expected: OwnedServer, current: OwnedServer) -> bool:
|
|
567
|
-
"""Return whether two states name the same exact supervised launch."""
|
|
568
|
-
return (
|
|
569
|
-
current.pid,
|
|
570
|
-
current.pgid,
|
|
571
|
-
current.process_started_at,
|
|
572
|
-
current.launch_token,
|
|
573
|
-
current.worker_pid,
|
|
574
|
-
current.worker_pgid,
|
|
575
|
-
current.worker_started_at,
|
|
576
|
-
) == (
|
|
577
|
-
expected.pid,
|
|
578
|
-
expected.pgid,
|
|
579
|
-
expected.process_started_at,
|
|
580
|
-
expected.launch_token,
|
|
581
|
-
expected.worker_pid,
|
|
582
|
-
expected.worker_pgid,
|
|
583
|
-
expected.worker_started_at,
|
|
584
|
-
)
|
|
585
|
-
|
|
586
|
-
|
|
587
586
|
def _certify_helper_boundary(
|
|
588
587
|
expected: OwnedServer,
|
|
589
588
|
active_env: Mapping[str, str],
|
|
@@ -724,6 +723,7 @@ def _wait_for_process_group_exit(
|
|
|
724
723
|
)
|
|
725
724
|
|
|
726
725
|
|
|
726
|
+
@codex_server_retry.retry_plugin_snapshot_changes
|
|
727
727
|
def ensure_server(
|
|
728
728
|
env: Mapping[str, str] | None = None,
|
|
729
729
|
*,
|
|
@@ -745,16 +745,15 @@ def ensure_server(
|
|
|
745
745
|
codex_options,
|
|
746
746
|
)
|
|
747
747
|
paths = paths_for_generation(base_paths, generation)
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
with _lifecycle_lock(paths):
|
|
748
|
+
with _reserved_generation_lifecycle(base_paths, paths, generation):
|
|
749
|
+
child_env = _command_env(active_env, paths)
|
|
750
|
+
child_env[CODEX_SERVER_OPTIONS_ENV] = json.dumps(
|
|
751
|
+
list(codex_options),
|
|
752
|
+
separators=(",", ":"),
|
|
753
|
+
)
|
|
755
754
|
locked_snapshot = _plugin_configuration_snapshot(paths, codex_options)
|
|
756
755
|
if locked_snapshot.fingerprint != plugin_snapshot.fingerprint:
|
|
757
|
-
raise
|
|
756
|
+
raise codex_server_retry.PluginSnapshotChangedError(
|
|
758
757
|
"the Codex plugin or marketplace snapshot changed during "
|
|
759
758
|
"app-server generation selection; retry after updates finish"
|
|
760
759
|
)
|
|
@@ -766,6 +765,7 @@ def ensure_server(
|
|
|
766
765
|
except StateFileError as exc:
|
|
767
766
|
state = None
|
|
768
767
|
state_error = str(exc)
|
|
768
|
+
state = reauthenticate_legacy_state(paths, state, _socket_peer_pid)
|
|
769
769
|
|
|
770
770
|
probe = _probe_server(codex_path, child_env, paths)
|
|
771
771
|
status = _status_from(paths, state, probe, state_error)
|
|
@@ -938,6 +938,7 @@ def _stop_server_at(
|
|
|
938
938
|
) from exc
|
|
939
939
|
_quarantine_invalid_state(paths)
|
|
940
940
|
state = None
|
|
941
|
+
state = reauthenticate_legacy_state(paths, state, _socket_peer_pid)
|
|
941
942
|
|
|
942
943
|
if state is not None and _state_is_owned(state):
|
|
943
944
|
if not allow_disconnect:
|