agent-cli 0.85.0__tar.gz → 0.86.1__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 (377) hide show
  1. {agent_cli-0.85.0/agent_cli/dev/skill → agent_cli-0.86.1/.claude/skills/agent-cli-dev}/SKILL.md +3 -2
  2. {agent_cli-0.85.0 → agent_cli-0.86.1}/.claude/skills/agent-cli-dev/examples.md +1 -1
  3. {agent_cli-0.85.0/.claude → agent_cli-0.86.1/.claude-plugin}/skills/agent-cli-dev/SKILL.md +3 -2
  4. {agent_cli-0.85.0 → agent_cli-0.86.1}/.claude-plugin/skills/agent-cli-dev/examples.md +1 -1
  5. {agent_cli-0.85.0 → agent_cli-0.86.1}/.pre-commit-config.yaml +1 -1
  6. {agent_cli-0.85.0 → agent_cli-0.86.1}/PKG-INFO +1 -1
  7. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/cli.py +28 -7
  8. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/launch.py +15 -7
  9. {agent_cli-0.85.0/.claude-plugin/skills/agent-cli-dev → agent_cli-0.86.1/agent_cli/dev/skill}/SKILL.md +3 -2
  10. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/skill/examples.md +1 -1
  11. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/tmux.py +9 -1
  12. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/worktree.py +28 -1
  13. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/dev.md +4 -3
  14. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_cli.py +135 -0
  15. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_launch.py +83 -1
  16. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_terminals.py +29 -0
  17. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_worktree.py +117 -0
  18. {agent_cli-0.85.0 → agent_cli-0.86.1}/.claude-plugin/README.md +0 -0
  19. {agent_cli-0.85.0 → agent_cli-0.86.1}/.claude-plugin/marketplace.json +0 -0
  20. {agent_cli-0.85.0 → agent_cli-0.86.1}/.claude-plugin/plugin.json +0 -0
  21. {agent_cli-0.85.0 → agent_cli-0.86.1}/.cursorrules +0 -0
  22. {agent_cli-0.85.0 → agent_cli-0.86.1}/.dockerignore +0 -0
  23. {agent_cli-0.85.0 → agent_cli-0.86.1}/.env.example +0 -0
  24. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/logo.svg +0 -0
  25. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/release-drafter.yml +0 -0
  26. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/renovate.json +0 -0
  27. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/scripts/check_extras_sync.py +0 -0
  28. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/scripts/check_plugin_skill_sync.py +0 -0
  29. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/scripts/sync_extras.py +0 -0
  30. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/scripts/sync_requirements.py +0 -0
  31. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/automerge.yml +0 -0
  32. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/docker.yml +0 -0
  33. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/docs.yml +0 -0
  34. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/markdown-code-runner.yml +0 -0
  35. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/pytest.yml +0 -0
  36. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/release-drafter.yml +0 -0
  37. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/release.yml +0 -0
  38. {agent_cli-0.85.0 → agent_cli-0.86.1}/.github/workflows/toc.yaml +0 -0
  39. {agent_cli-0.85.0 → agent_cli-0.86.1}/.gitignore +0 -0
  40. {agent_cli-0.85.0 → agent_cli-0.86.1}/.jscpd.json +0 -0
  41. {agent_cli-0.85.0 → agent_cli-0.86.1}/.prompts/docs-review.md +0 -0
  42. {agent_cli-0.85.0 → agent_cli-0.86.1}/.prompts/pr-review.md +0 -0
  43. {agent_cli-0.85.0 → agent_cli-0.86.1}/CLAUDE.md +0 -0
  44. {agent_cli-0.85.0 → agent_cli-0.86.1}/LICENSE +0 -0
  45. {agent_cli-0.85.0 → agent_cli-0.86.1}/README.md +0 -0
  46. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/__init__.py +0 -0
  47. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/__main__.py +0 -0
  48. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_extras.json +0 -0
  49. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/.gitkeep +0 -0
  50. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/audio.txt +0 -0
  51. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/faster-whisper.txt +0 -0
  52. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/kokoro.txt +0 -0
  53. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/llm.txt +0 -0
  54. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/memory.txt +0 -0
  55. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/mlx-whisper.txt +0 -0
  56. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/piper.txt +0 -0
  57. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/rag.txt +0 -0
  58. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/server.txt +0 -0
  59. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/speed.txt +0 -0
  60. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/vad.txt +0 -0
  61. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/vectordb.txt +0 -0
  62. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/whisper-transformers.txt +0 -0
  63. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_requirements/wyoming.txt +0 -0
  64. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/_tools.py +0 -0
  65. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/__init__.py +0 -0
  66. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/_voice_agent_common.py +0 -0
  67. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/assistant.py +0 -0
  68. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/autocorrect.py +0 -0
  69. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/chat.py +0 -0
  70. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/memory/__init__.py +0 -0
  71. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/memory/add.py +0 -0
  72. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/memory/proxy.py +0 -0
  73. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/rag_proxy.py +0 -0
  74. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/speak.py +0 -0
  75. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/transcribe.py +0 -0
  76. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/transcribe_live.py +0 -0
  77. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/agents/voice_edit.py +0 -0
  78. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/api.py +0 -0
  79. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/cli.py +0 -0
  80. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/config.py +0 -0
  81. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/config_cmd.py +0 -0
  82. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/constants.py +0 -0
  83. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/__init__.py +0 -0
  84. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/audio.py +0 -0
  85. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/audio_format.py +0 -0
  86. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/chroma.py +0 -0
  87. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/deps.py +0 -0
  88. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/openai_proxy.py +0 -0
  89. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/process.py +0 -0
  90. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/reranker.py +0 -0
  91. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/sse.py +0 -0
  92. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/transcription_logger.py +0 -0
  93. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/utils.py +0 -0
  94. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/vad.py +0 -0
  95. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/core/watch.py +0 -0
  96. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/daemon/__init__.py +0 -0
  97. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/daemon/cli.py +0 -0
  98. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/__init__.py +0 -0
  99. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/_branch_name.py +0 -0
  100. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/_config.py +0 -0
  101. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/_output.py +0 -0
  102. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/cleanup.py +0 -0
  103. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/__init__.py +0 -0
  104. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/aider.py +0 -0
  105. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/base.py +0 -0
  106. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/claude.py +0 -0
  107. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/codex.py +0 -0
  108. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
  109. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/copilot.py +0 -0
  110. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
  111. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/gemini.py +0 -0
  112. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/opencode.py +0 -0
  113. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/coding_agents/registry.py +0 -0
  114. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/__init__.py +0 -0
  115. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/base.py +0 -0
  116. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/cursor.py +0 -0
  117. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/emacs.py +0 -0
  118. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/jetbrains.py +0 -0
  119. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/nano.py +0 -0
  120. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/neovim.py +0 -0
  121. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/registry.py +0 -0
  122. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/sublime.py +0 -0
  123. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/vim.py +0 -0
  124. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/vscode.py +0 -0
  125. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/editors/zed.py +0 -0
  126. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/hooks.py +0 -0
  127. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/project.py +0 -0
  128. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/registry.py +0 -0
  129. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/__init__.py +0 -0
  130. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/apple_terminal.py +0 -0
  131. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/base.py +0 -0
  132. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/gnome.py +0 -0
  133. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/iterm2.py +0 -0
  134. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/kitty.py +0 -0
  135. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/registry.py +0 -0
  136. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/warp.py +0 -0
  137. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/dev/terminals/zellij.py +0 -0
  138. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/docs_gen.py +0 -0
  139. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/example-config.toml +0 -0
  140. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/__init__.py +0 -0
  141. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/common.py +0 -0
  142. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/extras.py +0 -0
  143. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/hotkeys.py +0 -0
  144. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/launchd.py +0 -0
  145. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/service_config.py +0 -0
  146. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/services.py +0 -0
  147. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/install/systemd.py +0 -0
  148. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/__init__.py +0 -0
  149. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_files.py +0 -0
  150. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_filters.py +0 -0
  151. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_git.py +0 -0
  152. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_indexer.py +0 -0
  153. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_ingest.py +0 -0
  154. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_persistence.py +0 -0
  155. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_prompt.py +0 -0
  156. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_retrieval.py +0 -0
  157. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_store.py +0 -0
  158. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_streaming.py +0 -0
  159. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/_tasks.py +0 -0
  160. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/api.py +0 -0
  161. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/client.py +0 -0
  162. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/engine.py +0 -0
  163. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/entities.py +0 -0
  164. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/memory/models.py +0 -0
  165. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/opts.py +0 -0
  166. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/py.typed +0 -0
  167. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/__init__.py +0 -0
  168. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/_indexer.py +0 -0
  169. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/_indexing.py +0 -0
  170. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/_prompt.py +0 -0
  171. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/_retriever.py +0 -0
  172. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/_store.py +0 -0
  173. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/_utils.py +0 -0
  174. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/api.py +0 -0
  175. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/client.py +0 -0
  176. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/engine.py +0 -0
  177. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/rag/models.py +0 -0
  178. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/.runtime/.gitkeep +0 -0
  179. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/__init__.py +0 -0
  180. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
  181. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
  182. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
  183. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
  184. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
  185. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
  186. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
  187. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
  188. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
  189. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
  190. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
  191. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
  192. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
  193. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
  194. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/run-openwakeword.sh +0 -0
  195. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
  196. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/setup-linux.sh +0 -0
  197. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
  198. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/setup-macos.sh +0 -0
  199. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/setup-windows.ps1 +0 -0
  200. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
  201. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/scripts/start-all-services.sh +0 -0
  202. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/__init__.py +0 -0
  203. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/cli.py +0 -0
  204. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/common.py +0 -0
  205. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/model_manager.py +0 -0
  206. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/model_registry.py +0 -0
  207. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/proxy/__init__.py +0 -0
  208. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/proxy/api.py +0 -0
  209. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/streaming.py +0 -0
  210. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/__init__.py +0 -0
  211. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/api.py +0 -0
  212. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/backends/__init__.py +0 -0
  213. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/backends/base.py +0 -0
  214. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/backends/kokoro.py +0 -0
  215. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/backends/piper.py +0 -0
  216. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/model_manager.py +0 -0
  217. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/model_registry.py +0 -0
  218. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/tts/wyoming_handler.py +0 -0
  219. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/__init__.py +0 -0
  220. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/api.py +0 -0
  221. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/backends/__init__.py +0 -0
  222. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/backends/base.py +0 -0
  223. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
  224. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/backends/mlx.py +0 -0
  225. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/backends/transformers.py +0 -0
  226. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/languages.py +0 -0
  227. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/model_manager.py +0 -0
  228. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/model_registry.py +0 -0
  229. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/server/whisper/wyoming_handler.py +0 -0
  230. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/services/__init__.py +0 -0
  231. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/services/_wyoming_utils.py +0 -0
  232. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/services/asr.py +0 -0
  233. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/services/llm.py +0 -0
  234. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/services/tts.py +0 -0
  235. {agent_cli-0.85.0 → agent_cli-0.86.1}/agent_cli/services/wake_word.py +0 -0
  236. {agent_cli-0.85.0 → agent_cli-0.86.1}/docker/docker-compose.yml +0 -0
  237. {agent_cli-0.85.0 → agent_cli-0.86.1}/docker/memory-proxy.Dockerfile +0 -0
  238. {agent_cli-0.85.0 → agent_cli-0.86.1}/docker/rag-proxy.Dockerfile +0 -0
  239. {agent_cli-0.85.0 → agent_cli-0.86.1}/docker/transcribe-proxy.Dockerfile +0 -0
  240. {agent_cli-0.85.0 → agent_cli-0.86.1}/docker/tts.Dockerfile +0 -0
  241. {agent_cli-0.85.0 → agent_cli-0.86.1}/docker/whisper.Dockerfile +0 -0
  242. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/CNAME +0 -0
  243. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/architecture/index.md +0 -0
  244. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/architecture/memory.md +0 -0
  245. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/architecture/rag.md +0 -0
  246. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/assistant.md +0 -0
  247. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/autocorrect.md +0 -0
  248. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/chat.md +0 -0
  249. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/config.md +0 -0
  250. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/daemon.md +0 -0
  251. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/index.md +0 -0
  252. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/install-extras.md +0 -0
  253. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/install-hotkeys.md +0 -0
  254. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/install-services.md +0 -0
  255. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/memory.md +0 -0
  256. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/rag-proxy.md +0 -0
  257. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/server/index.md +0 -0
  258. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/server/transcribe-proxy.md +0 -0
  259. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/server/tts.md +0 -0
  260. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/server/whisper.md +0 -0
  261. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/speak.md +0 -0
  262. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/start-services.md +0 -0
  263. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/transcribe-live.md +0 -0
  264. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/transcribe.md +0 -0
  265. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/commands/voice-edit.md +0 -0
  266. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/configuration.md +0 -0
  267. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/getting-started.md +0 -0
  268. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/iOS_Shortcut_Guide.md +0 -0
  269. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/index.md +0 -0
  270. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/installation/docker.md +0 -0
  271. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/installation/index.md +0 -0
  272. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/installation/linux.md +0 -0
  273. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/installation/macos.md +0 -0
  274. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/installation/nixos.md +0 -0
  275. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/installation/windows.md +0 -0
  276. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/logo-clean.svg +0 -0
  277. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
  278. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/run_markdown_code_runner.py +0 -0
  279. {agent_cli-0.85.0 → agent_cli-0.86.1}/docs/system-integration.md +0 -0
  280. {agent_cli-0.85.0 → agent_cli-0.86.1}/example.agent-cli-config.toml +0 -0
  281. {agent_cli-0.85.0 → agent_cli-0.86.1}/justfile +0 -0
  282. {agent_cli-0.85.0 → agent_cli-0.86.1}/pyproject.toml +0 -0
  283. {agent_cli-0.85.0 → agent_cli-0.86.1}/shell.nix +0 -0
  284. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/__init__.py +0 -0
  285. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/__init__.py +0 -0
  286. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_fix_my_text.py +0 -0
  287. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_interactive.py +0 -0
  288. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_interactive_extra.py +0 -0
  289. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_memory_add.py +0 -0
  290. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_speak.py +0 -0
  291. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_speak_e2e.py +0 -0
  292. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_transcribe.py +0 -0
  293. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_transcribe_agent.py +0 -0
  294. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_transcribe_e2e.py +0 -0
  295. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_transcribe_live.py +0 -0
  296. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_transcribe_recovery.py +0 -0
  297. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_tts_common.py +0 -0
  298. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_tts_common_extra.py +0 -0
  299. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_voice_agent_common.py +0 -0
  300. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_voice_edit.py +0 -0
  301. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_voice_edit_e2e.py +0 -0
  302. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/agents/test_wake_word_assistant.py +0 -0
  303. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/conftest.py +0 -0
  304. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/core/__init__.py +0 -0
  305. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/core/test_audio.py +0 -0
  306. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/core/test_audio_format.py +0 -0
  307. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/core/test_chroma.py +0 -0
  308. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/core/test_sse.py +0 -0
  309. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/core/test_vad.py +0 -0
  310. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/core/test_watch.py +0 -0
  311. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/__init__.py +0 -0
  312. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_coding_agents.py +0 -0
  313. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_editors.py +0 -0
  314. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_hooks.py +0 -0
  315. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_project.py +0 -0
  316. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/dev/test_verification.py +0 -0
  317. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/install/__init__.py +0 -0
  318. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/install/test_extras.py +0 -0
  319. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/__init__.py +0 -0
  320. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_api_health.py +0 -0
  321. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_api_integration_liveish.py +0 -0
  322. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_client.py +0 -0
  323. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_engine.py +0 -0
  324. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_files.py +0 -0
  325. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_filters.py +0 -0
  326. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_git_integration.py +0 -0
  327. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_indexer.py +0 -0
  328. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_memory_integration.py +0 -0
  329. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_proxy_passthrough.py +0 -0
  330. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_store.py +0 -0
  331. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/memory/test_utils.py +0 -0
  332. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/mocks/__init__.py +0 -0
  333. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/mocks/audio.py +0 -0
  334. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/mocks/llm.py +0 -0
  335. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/mocks/wyoming.py +0 -0
  336. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/__init__.py +0 -0
  337. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_api.py +0 -0
  338. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_engine.py +0 -0
  339. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_history.py +0 -0
  340. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_indexer.py +0 -0
  341. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_indexing.py +0 -0
  342. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_rag_client.py +0 -0
  343. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_rag_integration_liveish.py +0 -0
  344. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_rag_proxy_passthrough.py +0 -0
  345. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_retriever.py +0 -0
  346. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_store.py +0 -0
  347. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/rag/test_utils.py +0 -0
  348. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_api.py +0 -0
  349. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_api_integration.py +0 -0
  350. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_asr.py +0 -0
  351. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_asr_recovery.py +0 -0
  352. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_audio_e2e.py +0 -0
  353. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_cli.py +0 -0
  354. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_config.py +0 -0
  355. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_config_cmd.py +0 -0
  356. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_daemon.py +0 -0
  357. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_docs_gen.py +0 -0
  358. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_env_vars.py +0 -0
  359. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_json_output.py +0 -0
  360. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_llm.py +0 -0
  361. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_llm_gemini.py +0 -0
  362. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_memory_tools.py +0 -0
  363. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_mlx_backend.py +0 -0
  364. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_process_manager.py +0 -0
  365. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_requires_extras.py +0 -0
  366. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_server_streaming.py +0 -0
  367. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_server_tts.py +0 -0
  368. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_server_whisper.py +0 -0
  369. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_services.py +0 -0
  370. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_tools.py +0 -0
  371. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_transformers_backend.py +0 -0
  372. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_tts.py +0 -0
  373. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_utils.py +0 -0
  374. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_wake_word.py +0 -0
  375. {agent_cli-0.85.0 → agent_cli-0.86.1}/tests/test_wyoming_utils.py +0 -0
  376. {agent_cli-0.85.0 → agent_cli-0.86.1}/uv.lock +0 -0
  377. {agent_cli-0.85.0 → agent_cli-0.86.1}/zensical.toml +0 -0
@@ -56,7 +56,7 @@ agent-cli dev new <branch-name> --from HEAD --agent --prompt-file path/to/prompt
56
56
  This creates:
57
57
  1. A new git worktree with its own branch
58
58
  2. Runs project setup (installs dependencies)
59
- 3. Saves your prompt to `.claude/TASK.md` in the worktree (for reference)
59
+ 3. Saves your prompt to a unique task file in `.claude/` in the worktree (for reference)
60
60
  4. Opens a new terminal tab with an AI coding agent
61
61
  5. Passes your prompt to the agent
62
62
 
@@ -144,11 +144,12 @@ agent-cli dev agent review-auth -m tmux --prompt-file .claude/review-tests.md
144
144
 
145
145
  Key rules for same-worktree launches:
146
146
  - Use `dev agent`, not `dev new`, after the worktree already exists
147
+ - Use `dev agent -a <agent>` to select a specific agent for an existing worktree; `--with-agent` remains a deprecated alias on this subcommand
147
148
  - Use `-m tmux` for headless or scripted launching; it works even when not already inside tmux
148
149
  - Each launch joins the same deterministic repo-scoped tmux session, so related agents stay grouped together
149
150
  - Ask each agent to write to a unique report path such as `.claude/REPORT-security-<run-id>.md` or `.claude/REPORT-tests-<run-id>.md`
150
151
  - If you rerun the same prompt repeatedly, include a timestamp or other run id in the report filename so later runs do not overwrite earlier ones
151
- - Do not rely on `.claude/TASK.md` as per-agent state in shared worktrees; later launches overwrite it
152
+ - Each agent launch gets its own unique task file in `.claude/` (e.g., `TASK-{timestamp}-{hex}.md`), so parallel launches do not overwrite each other
152
153
 
153
154
  ### Prompt guidance for shared worktrees
154
155
 
@@ -585,7 +585,7 @@ Write findings to .claude/REPORT-tests-$run_id.md:
585
585
  - If you rerun the same prompt often, include a timestamp or run id in the filename so reports do not get replaced
586
586
  - `-m tmux` works even when the caller is not already inside tmux
587
587
  - All three agents land in the same deterministic tmux session for that repo
588
- - `.claude/TASK.md` is shared state and may be overwritten by later launches, so keep prompt files outside that convention
588
+ - Each agent launch gets its own unique task file in `.claude/`, so parallel launches do not conflict
589
589
 
590
590
  ## Scenario 7: Parallel test validation
591
591
 
@@ -56,7 +56,7 @@ agent-cli dev new <branch-name> --from HEAD --agent --prompt-file path/to/prompt
56
56
  This creates:
57
57
  1. A new git worktree with its own branch
58
58
  2. Runs project setup (installs dependencies)
59
- 3. Saves your prompt to `.claude/TASK.md` in the worktree (for reference)
59
+ 3. Saves your prompt to a unique task file in `.claude/` in the worktree (for reference)
60
60
  4. Opens a new terminal tab with an AI coding agent
61
61
  5. Passes your prompt to the agent
62
62
 
@@ -144,11 +144,12 @@ agent-cli dev agent review-auth -m tmux --prompt-file .claude/review-tests.md
144
144
 
145
145
  Key rules for same-worktree launches:
146
146
  - Use `dev agent`, not `dev new`, after the worktree already exists
147
+ - Use `dev agent -a <agent>` to select a specific agent for an existing worktree; `--with-agent` remains a deprecated alias on this subcommand
147
148
  - Use `-m tmux` for headless or scripted launching; it works even when not already inside tmux
148
149
  - Each launch joins the same deterministic repo-scoped tmux session, so related agents stay grouped together
149
150
  - Ask each agent to write to a unique report path such as `.claude/REPORT-security-<run-id>.md` or `.claude/REPORT-tests-<run-id>.md`
150
151
  - If you rerun the same prompt repeatedly, include a timestamp or other run id in the report filename so later runs do not overwrite earlier ones
151
- - Do not rely on `.claude/TASK.md` as per-agent state in shared worktrees; later launches overwrite it
152
+ - Each agent launch gets its own unique task file in `.claude/` (e.g., `TASK-{timestamp}-{hex}.md`), so parallel launches do not overwrite each other
152
153
 
153
154
  ### Prompt guidance for shared worktrees
154
155
 
@@ -585,7 +585,7 @@ Write findings to .claude/REPORT-tests-$run_id.md:
585
585
  - If you rerun the same prompt often, include a timestamp or run id in the filename so reports do not get replaced
586
586
  - `-m tmux` works even when the caller is not already inside tmux
587
587
  - All three agents land in the same deterministic tmux session for that repo
588
- - `.claude/TASK.md` is shared state and may be overwritten by later launches, so keep prompt files outside that convention
588
+ - Each agent launch gets its own unique task file in `.claude/`, so parallel launches do not conflict
589
589
 
590
590
  ## Scenario 7: Parallel test validation
591
591
 
@@ -11,7 +11,7 @@ repos:
11
11
  - id: end-of-file-fixer
12
12
  - id: mixed-line-ending
13
13
  - repo: https://github.com/astral-sh/ruff-pre-commit
14
- rev: "v0.15.6"
14
+ rev: "v0.15.7"
15
15
  hooks:
16
16
  - id: ruff
17
17
  args: ["--fix"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-cli
3
- Version: 0.85.0
3
+ Version: 0.86.1
4
4
  Summary: A suite of AI-powered command-line tools for text correction, audio transcription, and voice assistance.
5
5
  Project-URL: Homepage, https://github.com/basnijholt/agent-cli
6
6
  Author-email: Bas Nijholt <bas@nijho.lt>
@@ -373,7 +373,7 @@ def new(
373
373
  typer.Option(
374
374
  "--prompt",
375
375
  "-p",
376
- help="Initial task for the AI agent. Saved to .claude/TASK.md. Implies --agent. Example: --prompt='Fix the login bug'",
376
+ help="Initial task for the AI agent. Saved to a unique file in .claude/ to avoid conflicts. Implies --agent. Example: --prompt='Fix the login bug'",
377
377
  ),
378
378
  ] = None,
379
379
  prompt_file: Annotated[
@@ -776,7 +776,9 @@ def status_cmd( # noqa: PLR0915
776
776
  def remove(
777
777
  name: Annotated[
778
778
  str,
779
- typer.Argument(help="Worktree to remove. Can be branch name or directory name"),
779
+ typer.Argument(
780
+ help="Worktree to remove. Can be branch name, directory name, or '.' for current"
781
+ ),
780
782
  ],
781
783
  force: Annotated[
782
784
  bool,
@@ -840,7 +842,9 @@ def remove(
840
842
  def path_cmd(
841
843
  name: Annotated[
842
844
  str,
843
- typer.Argument(help="Worktree to get path for. Can be branch name or directory name"),
845
+ typer.Argument(
846
+ help="Worktree to get path for. Can be branch name, directory name, or '.' for current"
847
+ ),
844
848
  ],
845
849
  ) -> None:
846
850
  """Print the absolute path to a dev environment.
@@ -862,7 +866,9 @@ def path_cmd(
862
866
  def open_editor(
863
867
  name: Annotated[
864
868
  str,
865
- typer.Argument(help="Worktree to open. Can be branch name or directory name"),
869
+ typer.Argument(
870
+ help="Worktree to open. Can be branch name, directory name, or '.' for current"
871
+ ),
866
872
  ],
867
873
  editor_name: Annotated[
868
874
  str | None,
@@ -911,7 +917,7 @@ def start_agent(
911
917
  name: Annotated[
912
918
  str,
913
919
  typer.Argument(
914
- help="Worktree to start the agent in. Can be branch name or directory name",
920
+ help="Worktree to start the agent in. Can be branch name, directory name, or '.' for current",
915
921
  ),
916
922
  ],
917
923
  agent_name: Annotated[
@@ -922,6 +928,14 @@ def start_agent(
922
928
  help="Which agent: claude, codex, gemini, aider, copilot, cn, opencode, cursor-agent. Auto-detects if omitted",
923
929
  ),
924
930
  ] = None,
931
+ agent_name_deprecated: Annotated[
932
+ str | None,
933
+ typer.Option(
934
+ "--with-agent",
935
+ hidden=True,
936
+ help="[Deprecated: use --agent/-a] Which agent to start",
937
+ ),
938
+ ] = None,
925
939
  agent_args: Annotated[
926
940
  list[str] | None,
927
941
  typer.Option(
@@ -934,7 +948,7 @@ def start_agent(
934
948
  typer.Option(
935
949
  "--prompt",
936
950
  "-p",
937
- help="Initial task for the agent. Saved to .claude/TASK.md. Example: --prompt='Add unit tests for auth'",
951
+ help="Initial task for the agent. Saved to a unique file in .claude/ to avoid conflicts. Example: --prompt='Add unit tests for auth'",
938
952
  ),
939
953
  ] = None,
940
954
  prompt_file: Annotated[
@@ -975,6 +989,11 @@ def start_agent(
975
989
  - `dev agent my-feature -a claude` — Start Claude specifically
976
990
  - `dev agent my-feature -p "Continue the auth refactor"` — Start with a task
977
991
  """
992
+ # Handle deprecated --with-agent alias
993
+ if agent_name_deprecated is not None:
994
+ warn("--with-agent is deprecated for 'dev agent', use --agent/-a instead")
995
+ agent_name = agent_name or agent_name_deprecated
996
+
978
997
  prompt = _resolve_prompt_text(prompt, prompt_file=prompt_file)
979
998
 
980
999
  repo_root = _ensure_git_repo()
@@ -1233,7 +1252,9 @@ def _doctor_check_git() -> None:
1233
1252
  def run_cmd(
1234
1253
  name: Annotated[
1235
1254
  str,
1236
- typer.Argument(help="Worktree to run command in. Can be branch name or directory name"),
1255
+ typer.Argument(
1256
+ help="Worktree to run command in. Can be branch name, directory name, or '.' for current"
1257
+ ),
1237
1258
  ],
1238
1259
  command: Annotated[
1239
1260
  list[str],
@@ -168,14 +168,18 @@ def launch_editor(path: Path, editor: Editor) -> None:
168
168
 
169
169
 
170
170
  def write_prompt_to_worktree(worktree_path: Path, prompt: str) -> Path:
171
- """Write the prompt to .claude/TASK.md in the worktree.
171
+ """Write the prompt to a unique file in .claude/ in the worktree.
172
172
 
173
- This makes the task description available to the spawned agent
174
- and provides a record of what was requested.
173
+ Uses a timestamp and random suffix to avoid overwrites when multiple
174
+ agents are launched in parallel on the same worktree.
175
175
  """
176
+ import time # noqa: PLC0415
177
+
176
178
  claude_dir = worktree_path / ".claude"
177
179
  claude_dir.mkdir(parents=True, exist_ok=True)
178
- task_file = claude_dir / "TASK.md"
180
+ timestamp = int(time.time())
181
+ suffix = os.urandom(2).hex()
182
+ task_file = claude_dir / f"TASK-{timestamp}-{suffix}.md"
179
183
  task_file.write_text(prompt + "\n")
180
184
  return task_file
181
185
 
@@ -201,8 +205,6 @@ def _create_prompt_wrapper_script(
201
205
  env: dict[str, str] | None = None,
202
206
  ) -> Path:
203
207
  """Create a wrapper script that reads prompt from file to avoid shell quoting issues."""
204
- script_path = Path(tempfile.gettempdir()) / f"agent-cli-{worktree_path.name}.sh"
205
-
206
208
  # Build the agent command without the prompt
207
209
  exe = agent.get_executable()
208
210
  if exe is None:
@@ -222,7 +224,13 @@ def _create_prompt_wrapper_script(
222
224
  # Reads prompt from file to avoid shell parsing issues with special characters
223
225
  {env_prefix}exec {agent_cmd} "$(cat {shlex.quote(str(task_file_rel))})"
224
226
  """
225
- script_path.write_text(script_content)
227
+ fd, script_path_str = tempfile.mkstemp(
228
+ prefix=f"agent-cli-{worktree_path.name}-",
229
+ suffix=".sh",
230
+ )
231
+ os.write(fd, script_content.encode())
232
+ os.close(fd)
233
+ script_path = Path(script_path_str)
226
234
  script_path.chmod(0o755)
227
235
  return script_path
228
236
 
@@ -56,7 +56,7 @@ agent-cli dev new <branch-name> --from HEAD --agent --prompt-file path/to/prompt
56
56
  This creates:
57
57
  1. A new git worktree with its own branch
58
58
  2. Runs project setup (installs dependencies)
59
- 3. Saves your prompt to `.claude/TASK.md` in the worktree (for reference)
59
+ 3. Saves your prompt to a unique task file in `.claude/` in the worktree (for reference)
60
60
  4. Opens a new terminal tab with an AI coding agent
61
61
  5. Passes your prompt to the agent
62
62
 
@@ -144,11 +144,12 @@ agent-cli dev agent review-auth -m tmux --prompt-file .claude/review-tests.md
144
144
 
145
145
  Key rules for same-worktree launches:
146
146
  - Use `dev agent`, not `dev new`, after the worktree already exists
147
+ - Use `dev agent -a <agent>` to select a specific agent for an existing worktree; `--with-agent` remains a deprecated alias on this subcommand
147
148
  - Use `-m tmux` for headless or scripted launching; it works even when not already inside tmux
148
149
  - Each launch joins the same deterministic repo-scoped tmux session, so related agents stay grouped together
149
150
  - Ask each agent to write to a unique report path such as `.claude/REPORT-security-<run-id>.md` or `.claude/REPORT-tests-<run-id>.md`
150
151
  - If you rerun the same prompt repeatedly, include a timestamp or other run id in the report filename so later runs do not overwrite earlier ones
151
- - Do not rely on `.claude/TASK.md` as per-agent state in shared worktrees; later launches overwrite it
152
+ - Each agent launch gets its own unique task file in `.claude/` (e.g., `TASK-{timestamp}-{hex}.md`), so parallel launches do not overwrite each other
152
153
 
153
154
  ### Prompt guidance for shared worktrees
154
155
 
@@ -585,7 +585,7 @@ Write findings to .claude/REPORT-tests-$run_id.md:
585
585
  - If you rerun the same prompt often, include a timestamp or run id in the filename so reports do not get replaced
586
586
  - `-m tmux` works even when the caller is not already inside tmux
587
587
  - All three agents land in the same deterministic tmux session for that repo
588
- - `.claude/TASK.md` is shared state and may be overwritten by later launches, so keep prompt files outside that convention
588
+ - Each agent launch gets its own unique task file in `.claude/`, so parallel launches do not conflict
589
589
 
590
590
  ## Scenario 7: Parallel test validation
591
591
 
@@ -122,13 +122,21 @@ class Tmux(Terminal):
122
122
  session_name: str,
123
123
  ) -> TerminalHandle | None:
124
124
  """Create a detached tmux session and return its initial pane handle."""
125
- return self._spawn_target(
125
+ handle = self._spawn_target(
126
126
  ["tmux", "new-session", "-d", "-s", session_name],
127
127
  path=path,
128
128
  command=command,
129
129
  tab_name=tab_name,
130
130
  session_name=session_name,
131
131
  )
132
+ if handle is None:
133
+ return None
134
+ subprocess.run(
135
+ ["tmux", "set-option", "-t", session_name, "renumber-windows", "off"], # noqa: S607
136
+ capture_output=True,
137
+ check=False,
138
+ )
139
+ return handle
132
140
 
133
141
  def _spawn_target(
134
142
  self,
@@ -285,12 +285,39 @@ def resolve_worktree_base_dir(repo_root: Path) -> Path:
285
285
  return repo_root.parent / f"{repo_root.name}-worktrees"
286
286
 
287
287
 
288
+ def _find_worktree_for_cwd(worktrees: list[WorktreeInfo]) -> WorktreeInfo | None:
289
+ """Find the worktree containing the current working directory."""
290
+ cwd = Path.cwd().resolve()
291
+ # Prefer the deepest matching path so nested layouts like .worktrees/<name>
292
+ # resolve to the actual worktree instead of the main repo.
293
+ for wt in sorted(
294
+ worktrees,
295
+ key=lambda worktree: len(worktree.path.resolve().parts),
296
+ reverse=True,
297
+ ):
298
+ try:
299
+ cwd.relative_to(wt.path.resolve())
300
+ return wt
301
+ except ValueError:
302
+ continue
303
+ # Fallback: return main worktree
304
+ return next((wt for wt in worktrees if wt.is_main), None)
305
+
306
+
288
307
  def find_worktree_by_name(
289
308
  name: str,
290
309
  repo_path: Path | None = None,
291
310
  ) -> WorktreeInfo | None:
292
- """Find a worktree by branch name or directory name."""
311
+ """Find a worktree by branch name or directory name.
312
+
313
+ Use '.' to match the worktree containing the current working directory,
314
+ or the main worktree if the CWD is not inside any worktree.
315
+ """
293
316
  worktrees = list_worktrees(repo_path)
317
+
318
+ if name == ".":
319
+ return _find_worktree_for_cwd(worktrees)
320
+
294
321
  sanitized = sanitize_branch_name(name)
295
322
 
296
323
  for wt in worktrees:
@@ -84,7 +84,7 @@ agent-cli dev new [BRANCH] [OPTIONS]
84
84
  | `--branch-name-timeout` | `20.0` | Timeout in seconds for AI branch naming command |
85
85
  | `--direnv/--no-direnv` | - | Generate .envrc based on project type and run 'direnv allow'. Auto-enabled if direnv is installed |
86
86
  | `--agent-args` | - | Extra CLI args for the agent. Can be repeated. Example: --agent-args='--dangerously-skip-permissions' |
87
- | `--prompt, -p` | - | Initial task for the AI agent. Saved to .claude/TASK.md. Implies --agent. Example: --prompt='Fix the login bug' |
87
+ | `--prompt, -p` | - | Initial task for the AI agent. Saved to a unique file in .claude/ to avoid conflicts. Implies --agent. Example: --prompt='Fix the login bug' |
88
88
  | `--prompt-file, -P` | - | Read the agent prompt from a file. Useful for long prompts to avoid shell quoting. Implies --agent |
89
89
  | `--multiplexer, -m` | - | Launch the agent in a specific multiplexer. Currently supported: tmux. When started outside tmux, creates or reuses a detached session and reports the pane handle |
90
90
  | `--hooks/--no-hooks` | `true` | Run built-in agent preparation (like Codex auto-trust) and configured pre-launch hooks before starting the agent |
@@ -292,8 +292,9 @@ agent-cli dev agent NAME [--agent/-a AGENT] [--agent-args ARGS] [--prompt/-p PRO
292
292
  | Option | Default | Description |
293
293
  |--------|---------|-------------|
294
294
  | `--agent, -a` | - | Which agent: claude, codex, gemini, aider, copilot, cn, opencode, cursor-agent. Auto-detects if omitted |
295
+ | `--with-agent` | - | [Deprecated: use --agent/-a] Which agent to start |
295
296
  | `--agent-args` | - | Extra CLI args for the agent. Example: --agent-args='--dangerously-skip-permissions' |
296
- | `--prompt, -p` | - | Initial task for the agent. Saved to .claude/TASK.md. Example: --prompt='Add unit tests for auth' |
297
+ | `--prompt, -p` | - | Initial task for the agent. Saved to a unique file in .claude/ to avoid conflicts. Example: --prompt='Add unit tests for auth' |
297
298
  | `--prompt-file, -P` | - | Read the agent prompt from a file instead of command line |
298
299
  | `--multiplexer, -m` | - | Launch the agent in a specific multiplexer instead of the current terminal. Currently supported: tmux |
299
300
  | `--hooks/--no-hooks` | `true` | Run built-in agent preparation (like Codex auto-trust) and configured pre-launch hooks before starting the agent |
@@ -775,7 +776,7 @@ for section in 1 2 3 4; do
775
776
  done
776
777
  ```
777
778
 
778
- If multiple agents share one worktree, do not have them all write to `.claude/REPORT.md` because they will overwrite each other. Instead, assign unique report paths such as `.claude/REPORT-security-<run-id>.md` and `.claude/REPORT-tests-<run-id>.md`. If you rerun the same prompt repeatedly, use a timestamp or other run id so later runs do not replace earlier results. The same applies to `.claude/TASK.md`: it reflects the most recent launch, not stable per-agent state.
779
+ If multiple agents share one worktree, do not have them all write to `.claude/REPORT.md` because they will overwrite each other. Instead, assign unique report paths such as `.claude/REPORT-security-<run-id>.md` and `.claude/REPORT-tests-<run-id>.md`. If you rerun the same prompt repeatedly, use a timestamp or other run id so later runs do not replace earlier results. Each agent launch also gets its own `.claude/TASK-{timestamp}-{hex}.md` file, so prompt files no longer overwrite each other.
779
780
 
780
781
  ## Shell Integration
781
782
 
@@ -854,6 +854,141 @@ class TestDevAgent:
854
854
  assert f"Prompt file is empty: {prompt_file}" in result.output
855
855
  mock_ensure_repo.assert_not_called()
856
856
 
857
+ def test_agent_with_agent_flag(self) -> None:
858
+ """`dev agent foo -a claude` selects the named agent."""
859
+ wt = WorktreeInfo(
860
+ path=Path("/repo-worktrees/feature"),
861
+ branch="feature",
862
+ commit="abc",
863
+ is_main=False,
864
+ is_detached=False,
865
+ is_locked=False,
866
+ is_prunable=False,
867
+ )
868
+
869
+ with (
870
+ patch("agent_cli.dev.cli._ensure_git_repo", return_value=Path("/repo")),
871
+ patch("agent_cli.dev.worktree.find_worktree_by_name", return_value=wt),
872
+ patch("agent_cli.dev.cli.coding_agents.get_agent") as mock_get_agent,
873
+ patch("agent_cli.dev.cli.prepare_agent_launch"),
874
+ patch("agent_cli.dev.cli.merge_agent_args", return_value=None),
875
+ patch("agent_cli.dev.cli.get_agent_env", return_value={}),
876
+ patch("agent_cli.dev.cli.os.chdir"),
877
+ patch("agent_cli.dev.cli.subprocess.run"),
878
+ ):
879
+ mock_agent = mock_get_agent.return_value
880
+ mock_agent.name = "claude"
881
+ mock_agent.is_available.return_value = True
882
+ mock_agent.launch_command.return_value = ["claude"]
883
+ result = runner.invoke(
884
+ app,
885
+ ["dev", "agent", "feature", "-a", "claude"],
886
+ )
887
+
888
+ assert result.exit_code == 0
889
+ mock_get_agent.assert_called_once_with("claude")
890
+
891
+ def test_agent_deprecated_flag_warns(self) -> None:
892
+ """`dev agent foo --with-agent claude` works but prints a deprecation warning."""
893
+ wt = WorktreeInfo(
894
+ path=Path("/repo-worktrees/feature"),
895
+ branch="feature",
896
+ commit="abc",
897
+ is_main=False,
898
+ is_detached=False,
899
+ is_locked=False,
900
+ is_prunable=False,
901
+ )
902
+
903
+ with (
904
+ patch("agent_cli.dev.cli._ensure_git_repo", return_value=Path("/repo")),
905
+ patch("agent_cli.dev.worktree.find_worktree_by_name", return_value=wt),
906
+ patch("agent_cli.dev.cli.coding_agents.get_agent") as mock_get_agent,
907
+ patch("agent_cli.dev.cli.prepare_agent_launch"),
908
+ patch("agent_cli.dev.cli.merge_agent_args", return_value=None),
909
+ patch("agent_cli.dev.cli.get_agent_env", return_value={}),
910
+ patch("agent_cli.dev.cli.os.chdir"),
911
+ patch("agent_cli.dev.cli.subprocess.run"),
912
+ ):
913
+ mock_agent = mock_get_agent.return_value
914
+ mock_agent.name = "claude"
915
+ mock_agent.is_available.return_value = True
916
+ mock_agent.launch_command.return_value = ["claude"]
917
+ result = runner.invoke(
918
+ app,
919
+ ["dev", "agent", "feature", "--with-agent", "claude"],
920
+ )
921
+
922
+ assert result.exit_code == 0
923
+ assert "deprecated" in result.output.lower()
924
+ mock_get_agent.assert_called_once_with("claude")
925
+
926
+ def test_agent_dot_resolves_current_worktree(self) -> None:
927
+ """`dev agent .` resolves '.' to the current worktree via find_worktree_by_name."""
928
+ wt = WorktreeInfo(
929
+ path=Path("/repo-worktrees/feature"),
930
+ branch="feature",
931
+ commit="abc",
932
+ is_main=False,
933
+ is_detached=False,
934
+ is_locked=False,
935
+ is_prunable=False,
936
+ )
937
+
938
+ with (
939
+ patch("agent_cli.dev.cli._ensure_git_repo", return_value=Path("/repo")),
940
+ patch("agent_cli.dev.worktree.find_worktree_by_name", return_value=wt) as mock_find,
941
+ patch("agent_cli.dev.cli.coding_agents.detect_current_agent") as mock_detect_current,
942
+ patch("agent_cli.dev.cli.prepare_agent_launch"),
943
+ patch("agent_cli.dev.cli.merge_agent_args", return_value=None),
944
+ patch("agent_cli.dev.cli.get_agent_env", return_value={}),
945
+ patch("agent_cli.dev.cli.os.chdir"),
946
+ patch("agent_cli.dev.cli.subprocess.run"),
947
+ ):
948
+ current_agent = mock_detect_current.return_value
949
+ current_agent.name = "claude"
950
+ current_agent.is_available.return_value = True
951
+ current_agent.launch_command.return_value = ["claude"]
952
+ result = runner.invoke(app, ["dev", "agent", "."])
953
+
954
+ assert result.exit_code == 0
955
+ mock_find.assert_called_once_with(".", Path("/repo"))
956
+
957
+ def test_agent_primary_flag_overrides_deprecated_alias(self) -> None:
958
+ """Primary -a/--agent takes precedence over deprecated --with-agent."""
959
+ wt = WorktreeInfo(
960
+ path=Path("/repo-worktrees/feature"),
961
+ branch="feature",
962
+ commit="abc",
963
+ is_main=False,
964
+ is_detached=False,
965
+ is_locked=False,
966
+ is_prunable=False,
967
+ )
968
+
969
+ with (
970
+ patch("agent_cli.dev.cli._ensure_git_repo", return_value=Path("/repo")),
971
+ patch("agent_cli.dev.worktree.find_worktree_by_name", return_value=wt),
972
+ patch("agent_cli.dev.cli.coding_agents.get_agent") as mock_get_agent,
973
+ patch("agent_cli.dev.cli.prepare_agent_launch"),
974
+ patch("agent_cli.dev.cli.merge_agent_args", return_value=None),
975
+ patch("agent_cli.dev.cli.get_agent_env", return_value={}),
976
+ patch("agent_cli.dev.cli.os.chdir"),
977
+ patch("agent_cli.dev.cli.subprocess.run"),
978
+ ):
979
+ mock_agent = mock_get_agent.return_value
980
+ mock_agent.name = "claude"
981
+ mock_agent.is_available.return_value = True
982
+ mock_agent.launch_command.return_value = ["claude"]
983
+ result = runner.invoke(
984
+ app,
985
+ ["dev", "agent", "feature", "--with-agent", "claude", "-a", "codex"],
986
+ )
987
+
988
+ assert result.exit_code == 0
989
+ assert "deprecated" in result.output.lower()
990
+ mock_get_agent.assert_called_once_with("codex")
991
+
857
992
 
858
993
  class TestDevAgents:
859
994
  """Tests for dev agents command."""
@@ -6,7 +6,11 @@ import shlex
6
6
  from pathlib import Path
7
7
  from unittest.mock import MagicMock, patch
8
8
 
9
- from agent_cli.dev.launch import launch_agent
9
+ from agent_cli.dev.launch import (
10
+ _create_prompt_wrapper_script,
11
+ launch_agent,
12
+ write_prompt_to_worktree,
13
+ )
10
14
  from agent_cli.dev.terminals import TerminalHandle
11
15
  from agent_cli.dev.terminals.tmux import Tmux
12
16
 
@@ -147,3 +151,81 @@ class TestLaunchAgent:
147
151
  printed = "\n".join(call.args[0] for call in mock_print.call_args_list if call.args)
148
152
  assert "To start codex:" in printed
149
153
  assert f"cd {tmp_path}" in printed
154
+
155
+
156
+ class TestCreatePromptWrapperScript:
157
+ """Tests for _create_prompt_wrapper_script unique path generation."""
158
+
159
+ def test_concurrent_launches_produce_unique_scripts(self, tmp_path: Path) -> None:
160
+ """Two calls for the same worktree produce different script paths.
161
+
162
+ This is a regression test for a race condition where concurrent launches
163
+ overwrote each other's wrapper script because the path was deterministic
164
+ (based only on worktree name).
165
+ """
166
+ task_file_a = tmp_path / ".claude" / "TASK-111-aaaa.md"
167
+ task_file_b = tmp_path / ".claude" / "TASK-222-bbbb.md"
168
+ task_file_a.parent.mkdir(parents=True)
169
+ task_file_a.write_text("task A\n")
170
+ task_file_b.write_text("task B\n")
171
+
172
+ agent = MagicMock()
173
+ agent.name = "claude"
174
+ agent.get_executable.return_value = "/usr/bin/claude"
175
+
176
+ path_a = _create_prompt_wrapper_script(tmp_path, agent, task_file_a)
177
+ path_b = _create_prompt_wrapper_script(tmp_path, agent, task_file_b)
178
+
179
+ assert path_a != path_b
180
+ assert "TASK-111-aaaa.md" in path_a.read_text()
181
+ assert "TASK-222-bbbb.md" in path_b.read_text()
182
+
183
+ def test_script_is_executable(self, tmp_path: Path) -> None:
184
+ """Generated wrapper script has execute permission."""
185
+ task_file = tmp_path / ".claude" / "TASK-111-aaaa.md"
186
+ task_file.parent.mkdir(parents=True)
187
+ task_file.write_text("task\n")
188
+
189
+ agent = MagicMock()
190
+ agent.name = "claude"
191
+ agent.get_executable.return_value = "/usr/bin/claude"
192
+
193
+ path = _create_prompt_wrapper_script(tmp_path, agent, task_file)
194
+ assert path.stat().st_mode & 0o755
195
+
196
+
197
+ class TestWritePromptToWorktree:
198
+ """Tests for write_prompt_to_worktree unique filename generation."""
199
+
200
+ def test_unique_task_filenames(self, tmp_path: Path) -> None:
201
+ """Two calls produce different filenames to avoid parallel overwrites."""
202
+ path1 = write_prompt_to_worktree(tmp_path, "task A")
203
+ path2 = write_prompt_to_worktree(tmp_path, "task B")
204
+ assert path1 != path2
205
+ assert path1.read_text() == "task A\n"
206
+ assert path2.read_text() == "task B\n"
207
+
208
+ def test_task_file_in_claude_dir(self, tmp_path: Path) -> None:
209
+ """File is created inside the .claude/ directory."""
210
+ path = write_prompt_to_worktree(tmp_path, "hello")
211
+ assert path.parent == tmp_path / ".claude"
212
+
213
+ def test_task_filename_pattern(self, tmp_path: Path) -> None:
214
+ """Filename matches TASK-{timestamp}-{hex}.md pattern."""
215
+ import re # noqa: PLC0415
216
+
217
+ path = write_prompt_to_worktree(tmp_path, "hello")
218
+ assert re.match(r"TASK-\d+-[0-9a-f]{4}\.md$", path.name)
219
+
220
+ def test_task_file_contains_prompt(self, tmp_path: Path) -> None:
221
+ """Written file contains the prompt text with trailing newline."""
222
+ path = write_prompt_to_worktree(tmp_path, "Fix the login bug")
223
+ assert path.read_text() == "Fix the login bug\n"
224
+
225
+ def test_creates_claude_dir_if_missing(self, tmp_path: Path) -> None:
226
+ """Creates .claude/ directory if it doesn't exist."""
227
+ worktree = tmp_path / "fresh-worktree"
228
+ worktree.mkdir()
229
+ path = write_prompt_to_worktree(worktree, "task")
230
+ assert path.exists()
231
+ assert (worktree / ".claude").is_dir()
@@ -97,6 +97,35 @@ class TestTmux:
97
97
  session_name="repo-session",
98
98
  )
99
99
 
100
+ def test_create_session_disables_renumber_windows(self) -> None:
101
+ """New tmux sessions disable window renumbering."""
102
+ terminal = Tmux()
103
+ mock_handle = MagicMock(handle="%42", session_name="repo-session")
104
+ with (
105
+ patch.object(terminal, "_spawn_target", return_value=mock_handle) as mock_spawn,
106
+ patch("subprocess.run") as mock_run,
107
+ ):
108
+ handle = terminal._create_session(
109
+ Path("/some/path"),
110
+ "echo hello",
111
+ "test",
112
+ session_name="repo-session",
113
+ )
114
+
115
+ assert handle is mock_handle
116
+ mock_spawn.assert_called_once_with(
117
+ ["tmux", "new-session", "-d", "-s", "repo-session"],
118
+ path=Path("/some/path"),
119
+ command="echo hello",
120
+ tab_name="test",
121
+ session_name="repo-session",
122
+ )
123
+ mock_run.assert_called_once_with(
124
+ ["tmux", "set-option", "-t", "repo-session", "renumber-windows", "off"],
125
+ capture_output=True,
126
+ check=False,
127
+ )
128
+
100
129
  def test_open_in_session_reuses_existing_session(self) -> None:
101
130
  """Outside tmux, a named session gets a new window when it already exists."""
102
131
  terminal = Tmux()