agent-cli 0.100.0__tar.gz → 0.101.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (452) hide show
  1. {agent_cli-0.100.0 → agent_cli-0.101.0}/PKG-INFO +1 -1
  2. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/cleanup.py +6 -4
  3. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/cli.py +76 -33
  4. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/launch.py +31 -39
  5. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/__init__.py +2 -1
  6. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/base.py +43 -0
  7. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/tmux.py +8 -18
  8. agent_cli-0.101.0/agent_cli/dev/terminals/zellij.py +369 -0
  9. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/dev.md +4 -2
  10. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/appcast.xml +19 -16
  11. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_cleanup.py +27 -9
  12. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_cli.py +83 -2
  13. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_launch.py +128 -2
  14. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_terminals.py +354 -1
  15. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_verification.py +95 -7
  16. agent_cli-0.100.0/agent_cli/dev/terminals/zellij.py +0 -78
  17. {agent_cli-0.100.0 → agent_cli-0.101.0}/.claude/skills/agent-cli-dev/SKILL.md +0 -0
  18. {agent_cli-0.100.0 → agent_cli-0.101.0}/.claude/skills/agent-cli-dev/examples.md +0 -0
  19. {agent_cli-0.100.0 → agent_cli-0.101.0}/.claude-plugin/README.md +0 -0
  20. {agent_cli-0.100.0 → agent_cli-0.101.0}/.claude-plugin/marketplace.json +0 -0
  21. {agent_cli-0.100.0 → agent_cli-0.101.0}/.claude-plugin/plugin.json +0 -0
  22. {agent_cli-0.100.0 → agent_cli-0.101.0}/.claude-plugin/skills/agent-cli-dev/SKILL.md +0 -0
  23. {agent_cli-0.100.0 → agent_cli-0.101.0}/.claude-plugin/skills/agent-cli-dev/examples.md +0 -0
  24. {agent_cli-0.100.0 → agent_cli-0.101.0}/.cursorrules +0 -0
  25. {agent_cli-0.100.0 → agent_cli-0.101.0}/.dockerignore +0 -0
  26. {agent_cli-0.100.0 → agent_cli-0.101.0}/.env.example +0 -0
  27. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/logo.svg +0 -0
  28. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/release-drafter.yml +0 -0
  29. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/renovate.json +0 -0
  30. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/scripts/check_extras_sync.py +0 -0
  31. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/scripts/check_plugin_skill_sync.py +0 -0
  32. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/scripts/normalize_appcast.py +0 -0
  33. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/scripts/sync_extras.py +0 -0
  34. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/scripts/sync_requirements.py +0 -0
  35. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/automerge.yml +0 -0
  36. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/docker.yml +0 -0
  37. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/docs.yml +0 -0
  38. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/markdown-code-runner.yml +0 -0
  39. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/pytest.yml +0 -0
  40. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/release-drafter.yml +0 -0
  41. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/release.yml +0 -0
  42. {agent_cli-0.100.0 → agent_cli-0.101.0}/.github/workflows/toc.yaml +0 -0
  43. {agent_cli-0.100.0 → agent_cli-0.101.0}/.gitignore +0 -0
  44. {agent_cli-0.100.0 → agent_cli-0.101.0}/.jscpd.json +0 -0
  45. {agent_cli-0.100.0 → agent_cli-0.101.0}/.pre-commit-config.yaml +0 -0
  46. {agent_cli-0.100.0 → agent_cli-0.101.0}/.prompts/docs-review.md +0 -0
  47. {agent_cli-0.100.0 → agent_cli-0.101.0}/.prompts/pr-review.md +0 -0
  48. {agent_cli-0.100.0 → agent_cli-0.101.0}/CLAUDE.md +0 -0
  49. {agent_cli-0.100.0 → agent_cli-0.101.0}/LICENSE +0 -0
  50. {agent_cli-0.100.0 → agent_cli-0.101.0}/LLAMA_SERVER_USAGE.md +0 -0
  51. {agent_cli-0.100.0 → agent_cli-0.101.0}/README.md +0 -0
  52. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/__init__.py +0 -0
  53. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/__main__.py +0 -0
  54. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_extras.json +0 -0
  55. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_overrides/nemo-whisper.txt +0 -0
  56. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/.gitkeep +0 -0
  57. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/audio.txt +0 -0
  58. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/diarization.txt +0 -0
  59. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/faster-whisper.txt +0 -0
  60. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/kokoro.txt +0 -0
  61. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/llm.txt +0 -0
  62. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/memory.txt +0 -0
  63. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/mlx-whisper.txt +0 -0
  64. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/nemo-whisper.txt +0 -0
  65. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/piper.txt +0 -0
  66. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/rag.txt +0 -0
  67. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/server.txt +0 -0
  68. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/speed.txt +0 -0
  69. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/vad.txt +0 -0
  70. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/vectordb.txt +0 -0
  71. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/whisper-transformers.txt +0 -0
  72. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_requirements/wyoming.txt +0 -0
  73. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/_tools.py +0 -0
  74. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/__init__.py +0 -0
  75. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/_voice_agent_common.py +0 -0
  76. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/assistant.py +0 -0
  77. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/autocorrect.py +0 -0
  78. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/chat.py +0 -0
  79. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/diarize_live_session.py +0 -0
  80. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/memory/__init__.py +0 -0
  81. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/memory/add.py +0 -0
  82. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/memory/proxy.py +0 -0
  83. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/rag_proxy.py +0 -0
  84. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/speak.py +0 -0
  85. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/speakers.py +0 -0
  86. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/transcribe.py +0 -0
  87. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/transcribe_live.py +0 -0
  88. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/agents/voice_edit.py +0 -0
  89. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/api.py +0 -0
  90. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/cli.py +0 -0
  91. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/config.py +0 -0
  92. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/config_cmd.py +0 -0
  93. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/constants.py +0 -0
  94. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/__init__.py +0 -0
  95. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/alignment.py +0 -0
  96. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/audio.py +0 -0
  97. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/audio_format.py +0 -0
  98. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/chroma.py +0 -0
  99. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/deps.py +0 -0
  100. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/diarization.py +0 -0
  101. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/openai_proxy.py +0 -0
  102. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/process.py +0 -0
  103. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/reranker.py +0 -0
  104. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/speaker_identity.py +0 -0
  105. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/sse.py +0 -0
  106. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/transcription_logger.py +0 -0
  107. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/utils.py +0 -0
  108. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/vad.py +0 -0
  109. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/core/watch.py +0 -0
  110. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/daemon/__init__.py +0 -0
  111. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/daemon/cli.py +0 -0
  112. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/__init__.py +0 -0
  113. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/_branch_name.py +0 -0
  114. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/_config.py +0 -0
  115. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/_output.py +0 -0
  116. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/__init__.py +0 -0
  117. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/aider.py +0 -0
  118. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/base.py +0 -0
  119. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/claude.py +0 -0
  120. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/codex.py +0 -0
  121. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
  122. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/copilot.py +0 -0
  123. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
  124. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/gemini.py +0 -0
  125. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/opencode.py +0 -0
  126. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/coding_agents/registry.py +0 -0
  127. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/__init__.py +0 -0
  128. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/base.py +0 -0
  129. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/cursor.py +0 -0
  130. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/emacs.py +0 -0
  131. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/jetbrains.py +0 -0
  132. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/nano.py +0 -0
  133. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/neovim.py +0 -0
  134. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/registry.py +0 -0
  135. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/sublime.py +0 -0
  136. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/vim.py +0 -0
  137. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/vscode.py +0 -0
  138. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/editors/zed.py +0 -0
  139. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/hooks.py +0 -0
  140. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/project.py +0 -0
  141. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/registry.py +0 -0
  142. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/skill/SKILL.md +0 -0
  143. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/skill/examples.md +0 -0
  144. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/apple_terminal.py +0 -0
  145. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/cmux.py +0 -0
  146. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/gnome.py +0 -0
  147. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/iterm2.py +0 -0
  148. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/kitty.py +0 -0
  149. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/registry.py +0 -0
  150. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/terminals/warp.py +0 -0
  151. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/dev/worktree.py +0 -0
  152. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/docs_gen.py +0 -0
  153. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/example-config.toml +0 -0
  154. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/__init__.py +0 -0
  155. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/common.py +0 -0
  156. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/extras.py +0 -0
  157. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/hotkeys.py +0 -0
  158. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/launchd.py +0 -0
  159. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/service_config.py +0 -0
  160. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/services.py +0 -0
  161. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/install/systemd.py +0 -0
  162. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/__init__.py +0 -0
  163. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_files.py +0 -0
  164. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_filters.py +0 -0
  165. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_git.py +0 -0
  166. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_indexer.py +0 -0
  167. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_ingest.py +0 -0
  168. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_persistence.py +0 -0
  169. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_prompt.py +0 -0
  170. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_retrieval.py +0 -0
  171. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_store.py +0 -0
  172. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_streaming.py +0 -0
  173. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/_tasks.py +0 -0
  174. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/api.py +0 -0
  175. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/client.py +0 -0
  176. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/engine.py +0 -0
  177. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/entities.py +0 -0
  178. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/memory/models.py +0 -0
  179. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/opts.py +0 -0
  180. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/py.typed +0 -0
  181. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/__init__.py +0 -0
  182. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/_indexer.py +0 -0
  183. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/_indexing.py +0 -0
  184. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/_prompt.py +0 -0
  185. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/_retriever.py +0 -0
  186. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/_store.py +0 -0
  187. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/_utils.py +0 -0
  188. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/api.py +0 -0
  189. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/client.py +0 -0
  190. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/engine.py +0 -0
  191. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/rag/models.py +0 -0
  192. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/.runtime/.gitkeep +0 -0
  193. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/__init__.py +0 -0
  194. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
  195. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
  196. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
  197. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
  198. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
  199. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
  200. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
  201. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
  202. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
  203. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
  204. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
  205. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
  206. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
  207. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
  208. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/run-openwakeword.sh +0 -0
  209. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
  210. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/setup-linux.sh +0 -0
  211. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
  212. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/setup-macos.sh +0 -0
  213. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/setup-windows.ps1 +0 -0
  214. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
  215. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/scripts/start-all-services.sh +0 -0
  216. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/__init__.py +0 -0
  217. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/cli.py +0 -0
  218. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/common.py +0 -0
  219. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/model_manager.py +0 -0
  220. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/model_registry.py +0 -0
  221. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/proxy/__init__.py +0 -0
  222. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/proxy/api.py +0 -0
  223. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/streaming.py +0 -0
  224. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/__init__.py +0 -0
  225. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/api.py +0 -0
  226. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/backends/__init__.py +0 -0
  227. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/backends/base.py +0 -0
  228. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/backends/kokoro.py +0 -0
  229. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/backends/piper.py +0 -0
  230. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/model_manager.py +0 -0
  231. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/model_registry.py +0 -0
  232. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/tts/wyoming_handler.py +0 -0
  233. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/__init__.py +0 -0
  234. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/api.py +0 -0
  235. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/backends/__init__.py +0 -0
  236. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/backends/base.py +0 -0
  237. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
  238. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/backends/mlx.py +0 -0
  239. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/backends/nemo.py +0 -0
  240. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/backends/transformers.py +0 -0
  241. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/languages.py +0 -0
  242. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/model_manager.py +0 -0
  243. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/model_registry.py +0 -0
  244. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/server/whisper/wyoming_handler.py +0 -0
  245. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/services/__init__.py +0 -0
  246. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/services/_wyoming_utils.py +0 -0
  247. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/services/asr.py +0 -0
  248. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/services/llm.py +0 -0
  249. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/services/tts.py +0 -0
  250. {agent_cli-0.100.0 → agent_cli-0.101.0}/agent_cli/services/wake_word.py +0 -0
  251. {agent_cli-0.100.0 → agent_cli-0.101.0}/docker/docker-compose.yml +0 -0
  252. {agent_cli-0.100.0 → agent_cli-0.101.0}/docker/memory-proxy.Dockerfile +0 -0
  253. {agent_cli-0.100.0 → agent_cli-0.101.0}/docker/rag-proxy.Dockerfile +0 -0
  254. {agent_cli-0.100.0 → agent_cli-0.101.0}/docker/transcribe-proxy.Dockerfile +0 -0
  255. {agent_cli-0.100.0 → agent_cli-0.101.0}/docker/tts.Dockerfile +0 -0
  256. {agent_cli-0.100.0 → agent_cli-0.101.0}/docker/whisper.Dockerfile +0 -0
  257. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/CNAME +0 -0
  258. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/architecture/index.md +0 -0
  259. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/architecture/memory.md +0 -0
  260. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/architecture/rag.md +0 -0
  261. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/assistant.md +0 -0
  262. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/autocorrect.md +0 -0
  263. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/chat.md +0 -0
  264. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/config.md +0 -0
  265. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/daemon.md +0 -0
  266. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/diarize-live-session.md +0 -0
  267. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/index.md +0 -0
  268. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/install-extras.md +0 -0
  269. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/install-hotkeys.md +0 -0
  270. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/install-services.md +0 -0
  271. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/memory.md +0 -0
  272. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/rag-proxy.md +0 -0
  273. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/server/index.md +0 -0
  274. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/server/transcribe-proxy.md +0 -0
  275. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/server/tts.md +0 -0
  276. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/server/whisper.md +0 -0
  277. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/speak.md +0 -0
  278. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/speakers.md +0 -0
  279. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/start-services.md +0 -0
  280. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/transcribe-live.md +0 -0
  281. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/transcribe.md +0 -0
  282. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/commands/voice-edit.md +0 -0
  283. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/configuration.md +0 -0
  284. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/getting-started.md +0 -0
  285. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/iOS_Shortcut_Guide.md +0 -0
  286. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/index.md +0 -0
  287. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/installation/docker.md +0 -0
  288. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/installation/index.md +0 -0
  289. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/installation/linux.md +0 -0
  290. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/installation/macos-app.md +0 -0
  291. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/installation/macos.md +0 -0
  292. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/installation/nixos.md +0 -0
  293. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/installation/windows.md +0 -0
  294. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/logo-avatar.svg +0 -0
  295. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/logo-clean.svg +0 -0
  296. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
  297. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/run_markdown_code_runner.py +0 -0
  298. {agent_cli-0.100.0 → agent_cli-0.101.0}/docs/system-integration.md +0 -0
  299. {agent_cli-0.100.0 → agent_cli-0.101.0}/example.agent-cli-config.toml +0 -0
  300. {agent_cli-0.100.0 → agent_cli-0.101.0}/justfile +0 -0
  301. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Package.resolved +0 -0
  302. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Package.swift +0 -0
  303. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/README.md +0 -0
  304. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Resources/AgentCLI.entitlements +0 -0
  305. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Resources/Info.plist +0 -0
  306. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Resources/dmg-background.svg +0 -0
  307. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/AgentCLIApp.swift +0 -0
  308. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommand.swift +0 -0
  309. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/AgentCommandRunner.swift +0 -0
  310. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/AgentRuntime.swift +0 -0
  311. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/AppDelegate.swift +0 -0
  312. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/AppMetadata.swift +0 -0
  313. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/AppUpdater.swift +0 -0
  314. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/BootstrapState.swift +0 -0
  315. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/CommandResult.swift +0 -0
  316. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/ConfigurableHotkeyController.swift +0 -0
  317. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/FocusedTextTarget.swift +0 -0
  318. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/LiveTranscriptionPreview.swift +0 -0
  319. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/LoginItemController.swift +0 -0
  320. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatus.swift +0 -0
  321. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityStatusRow.swift +0 -0
  322. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/MenuActivityTracker.swift +0 -0
  323. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/MenuBarIcon.swift +0 -0
  324. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/RecentTranscriptionReader.swift +0 -0
  325. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/RecordingIndicatorController.swift +0 -0
  326. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/RecordingSoundSettings.swift +0 -0
  327. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/RuntimeSettings.swift +0 -0
  328. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/SettingsWindowController.swift +0 -0
  329. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/Shortcuts.swift +0 -0
  330. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/StatusMenuController.swift +0 -0
  331. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/TranscriptPasteController.swift +0 -0
  332. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/TranscriptionSettings.swift +0 -0
  333. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Sources/AgentCLI/VoiceLevelOverlay.swift +0 -0
  334. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/AgentCommandTests.swift +0 -0
  335. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/ConfigurableHotkeyControllerTests.swift +0 -0
  336. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/LivePreviewSwiftTestingTests.swift +0 -0
  337. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/LiveTranscriptionPreviewTests.swift +0 -0
  338. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/LoginItemControllerTests.swift +0 -0
  339. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/RecentTranscriptionReaderTests.swift +0 -0
  340. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/RecordingIndicatorControllerTests.swift +0 -0
  341. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/ShortcutDefaultsTests.swift +0 -0
  342. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/AgentCLI/Tests/AgentCLITests/VoiceLevelMeterTests.swift +0 -0
  343. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/build-macos-app.sh +0 -0
  344. {agent_cli-0.100.0 → agent_cli-0.101.0}/macos/test-macos-app-e2e.sh +0 -0
  345. {agent_cli-0.100.0 → agent_cli-0.101.0}/pyproject.toml +0 -0
  346. {agent_cli-0.100.0 → agent_cli-0.101.0}/reddit.md +0 -0
  347. {agent_cli-0.100.0 → agent_cli-0.101.0}/shell.nix +0 -0
  348. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/__init__.py +0 -0
  349. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/__init__.py +0 -0
  350. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_fix_my_text.py +0 -0
  351. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_interactive.py +0 -0
  352. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_interactive_extra.py +0 -0
  353. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_memory_add.py +0 -0
  354. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_speak.py +0 -0
  355. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_speak_e2e.py +0 -0
  356. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_speakers.py +0 -0
  357. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_transcribe.py +0 -0
  358. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_transcribe_agent.py +0 -0
  359. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_transcribe_e2e.py +0 -0
  360. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_transcribe_live.py +0 -0
  361. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_transcribe_recovery.py +0 -0
  362. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_tts_common.py +0 -0
  363. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_tts_common_extra.py +0 -0
  364. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_voice_agent_common.py +0 -0
  365. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_voice_edit.py +0 -0
  366. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_voice_edit_e2e.py +0 -0
  367. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/agents/test_wake_word_assistant.py +0 -0
  368. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/conftest.py +0 -0
  369. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/__init__.py +0 -0
  370. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/test_audio.py +0 -0
  371. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/test_audio_format.py +0 -0
  372. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/test_audio_levels.py +0 -0
  373. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/test_chroma.py +0 -0
  374. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/test_sse.py +0 -0
  375. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/test_vad.py +0 -0
  376. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/core/test_watch.py +0 -0
  377. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/__init__.py +0 -0
  378. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_coding_agents.py +0 -0
  379. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_editors.py +0 -0
  380. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_hooks.py +0 -0
  381. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_project.py +0 -0
  382. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/dev/test_worktree.py +0 -0
  383. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/install/__init__.py +0 -0
  384. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/install/test_extras.py +0 -0
  385. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/install/test_launchd.py +0 -0
  386. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/__init__.py +0 -0
  387. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_api_health.py +0 -0
  388. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_api_integration_liveish.py +0 -0
  389. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_client.py +0 -0
  390. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_engine.py +0 -0
  391. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_files.py +0 -0
  392. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_filters.py +0 -0
  393. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_git_integration.py +0 -0
  394. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_indexer.py +0 -0
  395. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_memory_integration.py +0 -0
  396. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_proxy_passthrough.py +0 -0
  397. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_store.py +0 -0
  398. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/memory/test_utils.py +0 -0
  399. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/mocks/__init__.py +0 -0
  400. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/mocks/audio.py +0 -0
  401. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/mocks/llm.py +0 -0
  402. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/mocks/wyoming.py +0 -0
  403. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/__init__.py +0 -0
  404. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_api.py +0 -0
  405. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_engine.py +0 -0
  406. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_history.py +0 -0
  407. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_indexer.py +0 -0
  408. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_indexing.py +0 -0
  409. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_rag_client.py +0 -0
  410. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_rag_integration_liveish.py +0 -0
  411. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_rag_proxy_passthrough.py +0 -0
  412. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_retriever.py +0 -0
  413. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_store.py +0 -0
  414. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/rag/test_utils.py +0 -0
  415. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_alignment.py +0 -0
  416. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_api.py +0 -0
  417. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_api_integration.py +0 -0
  418. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_asr.py +0 -0
  419. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_asr_recovery.py +0 -0
  420. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_audio_e2e.py +0 -0
  421. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_cli.py +0 -0
  422. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_config.py +0 -0
  423. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_config_cmd.py +0 -0
  424. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_daemon.py +0 -0
  425. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_diarization.py +0 -0
  426. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_diarize_live_session.py +0 -0
  427. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_docs_gen.py +0 -0
  428. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_env_vars.py +0 -0
  429. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_faster_whisper_backend.py +0 -0
  430. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_json_output.py +0 -0
  431. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_llm.py +0 -0
  432. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_llm_gemini.py +0 -0
  433. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_macos_app.py +0 -0
  434. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_memory_tools.py +0 -0
  435. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_mlx_backend.py +0 -0
  436. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_nemo_backend.py +0 -0
  437. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_normalize_appcast.py +0 -0
  438. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_process_manager.py +0 -0
  439. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_requires_extras.py +0 -0
  440. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_server_streaming.py +0 -0
  441. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_server_tts.py +0 -0
  442. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_server_whisper.py +0 -0
  443. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_services.py +0 -0
  444. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_speaker_identity.py +0 -0
  445. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_tools.py +0 -0
  446. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_transformers_backend.py +0 -0
  447. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_tts.py +0 -0
  448. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_utils.py +0 -0
  449. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_wake_word.py +0 -0
  450. {agent_cli-0.100.0 → agent_cli-0.101.0}/tests/test_wyoming_utils.py +0 -0
  451. {agent_cli-0.100.0 → agent_cli-0.101.0}/uv.lock +0 -0
  452. {agent_cli-0.100.0 → agent_cli-0.101.0}/zensical.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-cli
3
- Version: 0.100.0
3
+ Version: 0.101.0
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>
@@ -9,6 +9,7 @@ from typing import TYPE_CHECKING
9
9
 
10
10
  from . import worktree
11
11
  from .terminals.tmux import Tmux
12
+ from .terminals.zellij import Zellij
12
13
 
13
14
  if TYPE_CHECKING:
14
15
  from pathlib import Path
@@ -16,7 +17,7 @@ if TYPE_CHECKING:
16
17
 
17
18
  @dataclass
18
19
  class RemoveWorktreeResult:
19
- """Outcome of removing a worktree and any tagged tmux windows."""
20
+ """Outcome of removing a worktree and any multiplexer tabs/windows it owned."""
20
21
 
21
22
  name: str
22
23
  success: bool
@@ -130,7 +131,7 @@ def remove_worktree(
130
131
  force: bool = False,
131
132
  delete_branch: bool = False,
132
133
  ) -> RemoveWorktreeResult:
133
- """Remove one worktree and then clean up any tagged tmux windows."""
134
+ """Remove one worktree and then clean up any tmux windows and zellij tabs it owned."""
134
135
  removed, error = worktree.remove_worktree(
135
136
  wt.path,
136
137
  force=force,
@@ -145,7 +146,8 @@ def remove_worktree(
145
146
  if not removed:
146
147
  return result
147
148
 
148
- tmux = Tmux()
149
- tmux_cleanup = tmux.kill_windows_for_worktree(wt.path)
149
+ tmux_cleanup = Tmux().kill_windows_for_worktree(wt.path)
150
150
  result.warnings.extend(tmux_cleanup.errors)
151
+ zellij_cleanup = Zellij().close_tabs_for_worktree(wt.path)
152
+ result.warnings.extend(zellij_cleanup.errors)
151
153
  return result
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import os
7
- import shlex
8
7
  import shutil
9
8
  import subprocess
10
9
  from pathlib import Path
@@ -164,21 +163,44 @@ def _resolve_prompt_text(
164
163
  return prompt
165
164
 
166
165
 
167
- def _normalize_tmux_session(
166
+ def _normalize_multiplexer_session(
168
167
  tmux_session: str | None,
169
- multiplexer: Literal["tmux"] | None,
170
- ) -> tuple[str | None, Literal["tmux"] | None]:
171
- """Normalize `--tmux-session` and make it imply tmux launches."""
172
- if tmux_session is None:
173
- return None, multiplexer
174
-
175
- normalized_session = tmux_session.strip()
176
- if not normalized_session:
177
- error("--tmux-session cannot be empty")
178
- if "." in normalized_session or ":" in normalized_session:
179
- error("tmux session names cannot contain '.' or ':'")
180
-
181
- return normalized_session, "tmux"
168
+ zellij_session: str | None,
169
+ multiplexer: Literal["tmux", "zellij"] | None,
170
+ ) -> tuple[str | None, Literal["tmux", "zellij"] | None]:
171
+ """Normalize `--tmux-session`/`--zellij-session` and make them imply a multiplexer."""
172
+ if tmux_session is not None and zellij_session is not None:
173
+ error("Cannot use --tmux-session and --zellij-session together")
174
+
175
+ if tmux_session is not None:
176
+ if multiplexer == "zellij":
177
+ error("--tmux-session cannot be combined with --multiplexer zellij")
178
+ normalized_session = tmux_session.strip()
179
+ if not normalized_session:
180
+ error("--tmux-session cannot be empty")
181
+ if "." in normalized_session or ":" in normalized_session:
182
+ error("tmux session names cannot contain '.' or ':'")
183
+ return normalized_session, "tmux"
184
+
185
+ if zellij_session is not None:
186
+ if multiplexer == "tmux":
187
+ error("--zellij-session cannot be combined with --multiplexer tmux")
188
+ normalized_session = zellij_session.strip()
189
+ if not normalized_session:
190
+ error("--zellij-session cannot be empty")
191
+ return normalized_session, "zellij"
192
+
193
+ return None, multiplexer
194
+
195
+
196
+ def _attach_hint(handle: terminals.TerminalHandle) -> str | None:
197
+ """Shell command to attach to the session holding a launched agent, if any."""
198
+ if handle.session_name is None:
199
+ return None
200
+ terminal = terminals.get_terminal(handle.terminal_name)
201
+ if isinstance(terminal, terminals.Multiplexer):
202
+ return terminal.attach_command(handle.session_name)
203
+ return None
182
204
 
183
205
 
184
206
  def _resolve_dev_new_agent_request(
@@ -457,12 +479,12 @@ def new(
457
479
  ),
458
480
  ] = None,
459
481
  multiplexer: Annotated[
460
- Literal["tmux"] | None,
482
+ Literal["tmux", "zellij"] | None,
461
483
  typer.Option(
462
484
  "--multiplexer",
463
485
  "-m",
464
486
  case_sensitive=False,
465
- help="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",
487
+ help="Launch the agent in a specific multiplexer. Currently supported: tmux, zellij (zellij requires >= 0.44.0). When started outside the multiplexer, creates or reuses a detached session and reports the tab/pane handle",
466
488
  ),
467
489
  ] = None,
468
490
  tmux_session: Annotated[
@@ -472,6 +494,13 @@ def new(
472
494
  help="Reuse or create a specific tmux session for the agent. Implies --multiplexer tmux",
473
495
  ),
474
496
  ] = None,
497
+ zellij_session: Annotated[
498
+ str | None,
499
+ typer.Option(
500
+ "--zellij-session",
501
+ help="Reuse or create a specific zellij session for the agent. Implies --multiplexer zellij",
502
+ ),
503
+ ] = None,
475
504
  hooks: Annotated[
476
505
  bool,
477
506
  typer.Option(
@@ -521,7 +550,11 @@ def new(
521
550
  agent_name_deprecated=agent_name_deprecated,
522
551
  prompt=prompt,
523
552
  )
524
- tmux_session, multiplexer = _normalize_tmux_session(tmux_session, multiplexer)
553
+ multiplexer_session, multiplexer = _normalize_multiplexer_session(
554
+ tmux_session,
555
+ zellij_session,
556
+ multiplexer,
557
+ )
525
558
 
526
559
  repo_root = _ensure_git_repo()
527
560
  runtime_config = _runtime_config_from_ctx(ctx)
@@ -606,7 +639,7 @@ def new(
606
639
  task_file,
607
640
  agent_env,
608
641
  multiplexer_name=multiplexer,
609
- tmux_session=tmux_session,
642
+ multiplexer_session=multiplexer_session,
610
643
  )
611
644
 
612
645
  # Print summary
@@ -618,13 +651,15 @@ def new(
618
651
  summary_lines.append(
619
652
  f"[bold]Agent Handle:[/bold] {agent_handle.handle} ({agent_handle.terminal_name})",
620
653
  )
621
- if agent_handle.session_name and agent_handle.terminal_name == "tmux":
622
- summary_lines.append(f"[bold]tmux Session:[/bold] {agent_handle.session_name}")
654
+ if agent_handle.session_name and agent_handle.terminal_name == "cmux":
655
+ summary_lines.append(f"[bold]cmux Workspace:[/bold] {agent_handle.session_name}")
656
+ elif agent_handle.session_name:
623
657
  summary_lines.append(
624
- f"[bold]Attach:[/bold] tmux attach -t {shlex.quote(agent_handle.session_name)}",
658
+ f"[bold]{agent_handle.terminal_name} Session:[/bold] {agent_handle.session_name}",
625
659
  )
626
- elif agent_handle.session_name and agent_handle.terminal_name == "cmux":
627
- summary_lines.append(f"[bold]cmux Workspace:[/bold] {agent_handle.session_name}")
660
+ attach = _attach_hint(agent_handle)
661
+ if attach:
662
+ summary_lines.append(f"[bold]Attach:[/bold] {attach}")
628
663
 
629
664
  console.print()
630
665
  console.print(
@@ -1051,12 +1086,12 @@ def start_agent(
1051
1086
  ),
1052
1087
  ] = None,
1053
1088
  multiplexer: Annotated[
1054
- Literal["tmux"] | None,
1089
+ Literal["tmux", "zellij"] | None,
1055
1090
  typer.Option(
1056
1091
  "--multiplexer",
1057
1092
  "-m",
1058
1093
  case_sensitive=False,
1059
- help="Launch the agent in a specific multiplexer instead of the current terminal. Currently supported: tmux",
1094
+ help="Launch the agent in a specific multiplexer instead of the current terminal. Currently supported: tmux, zellij (zellij requires >= 0.44.0)",
1060
1095
  ),
1061
1096
  ] = None,
1062
1097
  tmux_session: Annotated[
@@ -1066,6 +1101,13 @@ def start_agent(
1066
1101
  help="Reuse or create a specific tmux session for the agent. Implies --multiplexer tmux",
1067
1102
  ),
1068
1103
  ] = None,
1104
+ zellij_session: Annotated[
1105
+ str | None,
1106
+ typer.Option(
1107
+ "--zellij-session",
1108
+ help="Reuse or create a specific zellij session for the agent. Implies --multiplexer zellij",
1109
+ ),
1110
+ ] = None,
1069
1111
  hooks: Annotated[
1070
1112
  bool,
1071
1113
  typer.Option(
@@ -1091,7 +1133,11 @@ def start_agent(
1091
1133
  agent_name = agent_name or agent_name_deprecated
1092
1134
 
1093
1135
  prompt = _resolve_prompt_text(prompt, prompt_file=prompt_file)
1094
- tmux_session, multiplexer = _normalize_tmux_session(tmux_session, multiplexer)
1136
+ multiplexer_session, multiplexer = _normalize_multiplexer_session(
1137
+ tmux_session,
1138
+ zellij_session,
1139
+ multiplexer,
1140
+ )
1095
1141
 
1096
1142
  repo_root = _ensure_git_repo()
1097
1143
  runtime_config = _runtime_config_from_ctx(ctx)
@@ -1141,16 +1187,13 @@ def start_agent(
1141
1187
  task_file,
1142
1188
  agent_env,
1143
1189
  multiplexer_name=multiplexer,
1144
- tmux_session=tmux_session,
1190
+ multiplexer_session=multiplexer_session,
1145
1191
  )
1146
1192
  if handle:
1193
+ attach = _attach_hint(handle)
1147
1194
  info(
1148
1195
  f"{handle.terminal_name} handle: {handle.handle}"
1149
- + (
1150
- f" (attach with: tmux attach -t {shlex.quote(handle.session_name)})"
1151
- if handle.session_name and handle.terminal_name == "tmux"
1152
- else ""
1153
- ),
1196
+ + (f" (attach with: {attach})" if attach else ""),
1154
1197
  )
1155
1198
  return
1156
1199
 
@@ -280,45 +280,27 @@ def _tab_name_for_path(path: Path) -> tuple[Path | None, str]:
280
280
  return repo_root, tab_name
281
281
 
282
282
 
283
- def _launch_in_tmux(
283
+ def _launch_in_multiplexer(
284
284
  path: Path,
285
- agent: CodingAgent,
286
- terminal: terminals.Terminal,
285
+ terminal: terminals.Multiplexer,
287
286
  full_cmd: str,
288
287
  tab_name: str,
289
288
  repo_root: Path | None,
290
- multiplexer_name: str | None,
291
- tmux_session: str | None,
289
+ *,
290
+ requested: bool,
291
+ session_override: str | None,
292
292
  ) -> TerminalHandle | None:
293
- """Launch an agent via tmux and return its pane handle."""
294
- from .terminals.tmux import Tmux # noqa: PLC0415
295
-
296
- if not isinstance(terminal, Tmux):
297
- warn("Could not open new tab in tmux")
298
- return None
299
-
300
- requested_tmux = multiplexer_name == "tmux"
301
- session_name = tmux_session
302
- if session_name is None and requested_tmux and not terminal.detect():
293
+ """Launch an agent in a multiplexer and return its tab/pane handle."""
294
+ session_name = session_override
295
+ if session_name is None and requested and not terminal.detect():
303
296
  session_name = terminal.session_name_for_repo(repo_root or path)
304
297
 
305
- handle = terminal.open_in_session(
298
+ return terminal.open_in_session(
306
299
  path,
307
300
  full_cmd,
308
301
  tab_name=tab_name,
309
302
  session_name=session_name,
310
303
  )
311
- if handle is None:
312
- warn("Could not open new tab in tmux")
313
- return None
314
-
315
- session_label = (
316
- f" in tmux session {handle.session_name}"
317
- if (requested_tmux or tmux_session is not None) and handle.session_name
318
- else " in new tmux tab"
319
- )
320
- success(f"Started {agent.name}{session_label}")
321
- return handle
322
304
 
323
305
 
324
306
  def _launch_in_cmux(
@@ -359,25 +341,36 @@ def _launch_in_terminal(
359
341
  tab_name: str,
360
342
  repo_root: Path | None,
361
343
  multiplexer_name: str | None,
362
- tmux_session: str | None,
344
+ multiplexer_session: str | None,
363
345
  ) -> tuple[bool, TerminalHandle | None]:
364
346
  """Launch an agent in the resolved terminal."""
365
347
  if terminal.name == "cmux":
366
348
  handle = _launch_in_cmux(path, agent, terminal, full_cmd, tab_name, repo_root)
367
349
  return handle is not None, handle
368
350
 
369
- if terminal.name == "tmux":
370
- handle = _launch_in_tmux(
351
+ if isinstance(terminal, terminals.Multiplexer):
352
+ requested = multiplexer_name == terminal.name or multiplexer_session is not None
353
+ handle = _launch_in_multiplexer(
371
354
  path,
372
- agent,
373
355
  terminal,
374
356
  full_cmd,
375
357
  tab_name,
376
358
  repo_root,
377
- multiplexer_name,
378
- tmux_session,
359
+ requested=requested,
360
+ session_override=multiplexer_session,
379
361
  )
380
- return handle is not None, handle
362
+ if handle is not None:
363
+ session_label = (
364
+ f" in {terminal.name} session {handle.session_name}"
365
+ if requested and handle.session_name
366
+ else f" in new {terminal.name} tab"
367
+ )
368
+ success(f"Started {agent.name}{session_label}")
369
+ return True, handle
370
+ if requested:
371
+ warn(f"Could not open new tab in {terminal.name}")
372
+ return False, None
373
+ # Fall through to plain tab opening (e.g. zellij < 0.44 inside a session)
381
374
 
382
375
  if terminal.open_new_tab(path, full_cmd, tab_name=tab_name):
383
376
  success(f"Started {agent.name} in new {terminal.name} tab")
@@ -395,15 +388,14 @@ def launch_agent(
395
388
  task_file: Path | None = None,
396
389
  env: dict[str, str] | None = None,
397
390
  multiplexer_name: str | None = None,
398
- tmux_session: str | None = None,
391
+ multiplexer_session: str | None = None,
399
392
  ) -> TerminalHandle | None:
400
393
  """Launch agent in a new terminal tab.
401
394
 
402
395
  Agents are interactive TUIs that need a proper terminal.
403
396
  Priority: tmux/zellij tab > terminal tab > print instructions.
404
397
  """
405
- effective_multiplexer_name = "tmux" if tmux_session is not None else multiplexer_name
406
- terminal = _resolve_launch_terminal(effective_multiplexer_name)
398
+ terminal = _resolve_launch_terminal(multiplexer_name)
407
399
  full_cmd = _build_agent_launch_command(
408
400
  path, agent, extra_args, prompt, task_file, env, terminal
409
401
  )
@@ -417,8 +409,8 @@ def launch_agent(
417
409
  full_cmd,
418
410
  tab_name,
419
411
  repo_root,
420
- effective_multiplexer_name,
421
- tmux_session,
412
+ multiplexer_name,
413
+ multiplexer_session,
422
414
  )
423
415
  if launched:
424
416
  return handle
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from .base import Terminal, TerminalHandle
5
+ from .base import Multiplexer, Terminal, TerminalHandle
6
6
  from .registry import (
7
7
  detect_current_terminal,
8
8
  get_all_terminals,
@@ -11,6 +11,7 @@ from .registry import (
11
11
  )
12
12
 
13
13
  __all__ = [
14
+ "Multiplexer",
14
15
  "Terminal",
15
16
  "TerminalHandle",
16
17
  "detect_current_terminal",
@@ -2,12 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import hashlib
5
6
  import os
7
+ import re
6
8
  from abc import ABC, abstractmethod
7
9
  from dataclasses import dataclass
8
10
  from typing import TYPE_CHECKING
9
11
 
10
12
  if TYPE_CHECKING:
13
+ import subprocess
11
14
  from pathlib import Path
12
15
 
13
16
 
@@ -61,6 +64,46 @@ class Terminal(ABC):
61
64
  return f"<{self.__class__.__name__} {self.name!r} ({status})>"
62
65
 
63
66
 
67
+ class Multiplexer(Terminal):
68
+ """Terminal multiplexer that can host named sessions with addressable tabs/windows."""
69
+
70
+ def session_name_for_repo(self, repo_root: Path) -> str:
71
+ """Build a deterministic session name for a repo (safe for tmux and zellij)."""
72
+ repo_slug = re.sub(r"[^A-Za-z0-9_-]+", "-", repo_root.name).strip("-") or "repo"
73
+ repo_hash = hashlib.sha256(str(repo_root).encode()).hexdigest()[:8]
74
+ return f"agent-cli-{repo_slug[:24]}-{repo_hash}"
75
+
76
+ @abstractmethod
77
+ def current_session_name(self) -> str | None:
78
+ """Get the session name this process is running inside, when available."""
79
+
80
+ @abstractmethod
81
+ def attach_command(self, session_name: str) -> str:
82
+ """Shell command a user can run to attach to a session."""
83
+
84
+ @abstractmethod
85
+ def open_in_session(
86
+ self,
87
+ path: Path,
88
+ command: str | None = None,
89
+ tab_name: str | None = None,
90
+ *,
91
+ session_name: str | None = None,
92
+ ) -> TerminalHandle | None:
93
+ """Open a tab/window and return its handle.
94
+
95
+ If ``session_name`` is omitted, the current session is used.
96
+ When a named session does not exist yet, it is created in detached mode.
97
+ """
98
+
99
+
100
+ def subprocess_error_text(exc: subprocess.CalledProcessError) -> str:
101
+ """Extract a useful stderr/stdout payload from a subprocess error."""
102
+ stderr = exc.stderr.strip() if exc.stderr else ""
103
+ stdout = exc.stdout.strip() if exc.stdout else ""
104
+ return stderr or stdout or str(exc)
105
+
106
+
64
107
  def _get_term_program() -> str | None:
65
108
  """Get the TERM_PROGRAM environment variable."""
66
109
  return os.environ.get("TERM_PROGRAM")
@@ -2,15 +2,14 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import hashlib
6
5
  import os
7
- import re
6
+ import shlex
8
7
  import shutil
9
8
  import subprocess
10
9
  from dataclasses import dataclass
11
10
  from typing import TYPE_CHECKING
12
11
 
13
- from .base import Terminal, TerminalHandle
12
+ from .base import Multiplexer, TerminalHandle, subprocess_error_text
14
13
 
15
14
  if TYPE_CHECKING:
16
15
  from pathlib import Path
@@ -44,7 +43,7 @@ class TmuxCleanupResult:
44
43
  errors: tuple[str, ...] = ()
45
44
 
46
45
 
47
- class Tmux(Terminal):
46
+ class Tmux(Multiplexer):
48
47
  """tmux - Terminal multiplexer."""
49
48
 
50
49
  name = "tmux"
@@ -58,11 +57,9 @@ class Tmux(Terminal):
58
57
  """Check if tmux is available."""
59
58
  return shutil.which("tmux") is not None
60
59
 
61
- def session_name_for_repo(self, repo_root: Path) -> str:
62
- """Build a deterministic tmux-safe session name for a repo."""
63
- repo_slug = re.sub(r"[^A-Za-z0-9_-]+", "-", repo_root.name).strip("-") or "repo"
64
- repo_hash = hashlib.sha256(str(repo_root).encode()).hexdigest()[:8]
65
- return f"agent-cli-{repo_slug[:24]}-{repo_hash}"
60
+ def attach_command(self, session_name: str) -> str:
61
+ """Shell command a user can run to attach to a tmux session."""
62
+ return f"tmux attach -t {shlex.quote(session_name)}"
66
63
 
67
64
  def current_session_name(self) -> str | None:
68
65
  """Get the current tmux session name."""
@@ -156,7 +153,7 @@ class Tmux(Terminal):
156
153
  if self._is_server_unavailable_error(e):
157
154
  return TmuxInventory()
158
155
  return TmuxInventory(
159
- error=f"Failed to inspect tmux windows for {normalized_path}: {self._error_text(e)}",
156
+ error=f"Failed to inspect tmux windows for {normalized_path}: {subprocess_error_text(e)}",
160
157
  )
161
158
 
162
159
  windows: list[TmuxWindow] = []
@@ -208,7 +205,7 @@ class Tmux(Terminal):
208
205
  except subprocess.CalledProcessError as e:
209
206
  errors.append(
210
207
  "Failed to kill tmux window "
211
- f"{window.window_id} in session {window.session_name}: {self._error_text(e)}",
208
+ f"{window.window_id} in session {window.session_name}: {subprocess_error_text(e)}",
212
209
  )
213
210
  continue
214
211
  killed_windows.append(window)
@@ -306,13 +303,6 @@ class Tmux(Terminal):
306
303
  """Normalize a worktree path for tmux window tagging and lookup."""
307
304
  return str(path.resolve(strict=False))
308
305
 
309
- @staticmethod
310
- def _error_text(exc: subprocess.CalledProcessError) -> str:
311
- """Extract a useful stderr/stdout payload from a tmux subprocess error."""
312
- stderr = exc.stderr.strip() if exc.stderr else ""
313
- stdout = exc.stdout.strip() if exc.stdout else ""
314
- return stderr or stdout or str(exc)
315
-
316
306
  @staticmethod
317
307
  def _is_server_unavailable_error(exc: subprocess.CalledProcessError) -> bool:
318
308
  """Detect tmux errors that mean there is no server/client to inspect."""