agent-cli 0.85.0__tar.gz → 0.86.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.
- {agent_cli-0.85.0/agent_cli/dev/skill → agent_cli-0.86.0/.claude/skills/agent-cli-dev}/SKILL.md +3 -2
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.claude/skills/agent-cli-dev/examples.md +1 -1
- {agent_cli-0.85.0/.claude → agent_cli-0.86.0/.claude-plugin}/skills/agent-cli-dev/SKILL.md +3 -2
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.claude-plugin/skills/agent-cli-dev/examples.md +1 -1
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.pre-commit-config.yaml +1 -1
- {agent_cli-0.85.0 → agent_cli-0.86.0}/PKG-INFO +1 -1
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/cli.py +28 -7
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/launch.py +15 -7
- {agent_cli-0.85.0/.claude-plugin/skills/agent-cli-dev → agent_cli-0.86.0/agent_cli/dev/skill}/SKILL.md +3 -2
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/skill/examples.md +1 -1
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/worktree.py +28 -1
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/dev.md +4 -3
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_cli.py +135 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_launch.py +83 -1
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_worktree.py +117 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.claude-plugin/README.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.claude-plugin/marketplace.json +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.claude-plugin/plugin.json +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.cursorrules +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.dockerignore +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.env.example +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/logo.svg +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/release-drafter.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/renovate.json +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/scripts/check_extras_sync.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/scripts/check_plugin_skill_sync.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/scripts/sync_extras.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/scripts/sync_requirements.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/automerge.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/docker.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/docs.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/markdown-code-runner.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/pytest.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/release-drafter.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/release.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.github/workflows/toc.yaml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.gitignore +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.jscpd.json +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.prompts/docs-review.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/.prompts/pr-review.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/CLAUDE.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/LICENSE +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/README.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/__main__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_extras.json +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/.gitkeep +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/audio.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/faster-whisper.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/kokoro.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/llm.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/memory.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/mlx-whisper.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/piper.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/rag.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/server.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/speed.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/vad.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/vectordb.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/whisper-transformers.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_requirements/wyoming.txt +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/_tools.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/_voice_agent_common.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/assistant.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/autocorrect.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/chat.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/memory/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/memory/add.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/memory/proxy.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/rag_proxy.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/speak.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/transcribe.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/transcribe_live.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/agents/voice_edit.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/cli.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/config.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/config_cmd.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/constants.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/audio.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/audio_format.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/chroma.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/deps.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/openai_proxy.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/process.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/reranker.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/sse.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/transcription_logger.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/utils.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/vad.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/core/watch.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/daemon/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/daemon/cli.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/_branch_name.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/_config.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/_output.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/cleanup.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/aider.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/base.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/claude.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/codex.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/continue_dev.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/copilot.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/cursor_agent.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/gemini.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/opencode.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/coding_agents/registry.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/base.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/cursor.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/emacs.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/jetbrains.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/nano.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/neovim.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/registry.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/sublime.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/vim.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/vscode.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/editors/zed.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/hooks.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/project.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/registry.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/apple_terminal.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/base.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/gnome.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/iterm2.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/kitty.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/registry.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/tmux.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/warp.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/dev/terminals/zellij.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/docs_gen.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/example-config.toml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/common.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/extras.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/hotkeys.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/launchd.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/service_config.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/services.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/install/systemd.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_files.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_filters.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_git.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_indexer.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_ingest.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_persistence.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_prompt.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_retrieval.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_store.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_streaming.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/_tasks.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/client.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/engine.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/entities.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/memory/models.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/opts.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/py.typed +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/_indexer.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/_indexing.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/_prompt.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/_retriever.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/_store.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/_utils.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/client.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/engine.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/rag/models.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/.runtime/.gitkeep +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/linux-hotkeys/README.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/linux-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/linux-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/linux-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/macos-hotkeys/README.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/macos-hotkeys/skhd-config-example +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/macos-hotkeys/toggle-autocorrect.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/macos-hotkeys/toggle-transcription.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/macos-hotkeys/toggle-voice-edit.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/nvidia-asr-server/README.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/nvidia-asr-server/pyproject.toml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/nvidia-asr-server/server.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/nvidia-asr-server/shell.nix +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/nvidia-asr-server/uv.lock +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/run-openwakeword.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/setup-linux-hotkeys.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/setup-linux.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/setup-macos-hotkeys.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/setup-macos.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/setup-windows.ps1 +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/start-all-services-windows.ps1 +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/scripts/start-all-services.sh +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/cli.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/common.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/model_manager.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/model_registry.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/proxy/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/proxy/api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/streaming.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/backends/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/backends/base.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/backends/kokoro.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/backends/piper.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/model_manager.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/model_registry.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/tts/wyoming_handler.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/backends/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/backends/base.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/backends/faster_whisper.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/backends/mlx.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/backends/transformers.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/languages.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/model_manager.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/model_registry.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/server/whisper/wyoming_handler.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/services/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/services/_wyoming_utils.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/services/asr.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/services/llm.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/services/tts.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/agent_cli/services/wake_word.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docker/docker-compose.yml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docker/memory-proxy.Dockerfile +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docker/rag-proxy.Dockerfile +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docker/transcribe-proxy.Dockerfile +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docker/tts.Dockerfile +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docker/whisper.Dockerfile +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/CNAME +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/architecture/index.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/architecture/memory.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/architecture/rag.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/assistant.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/autocorrect.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/chat.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/config.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/daemon.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/index.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/install-extras.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/install-hotkeys.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/install-services.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/memory.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/rag-proxy.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/server/index.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/server/transcribe-proxy.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/server/tts.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/server/whisper.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/speak.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/start-services.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/transcribe-live.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/transcribe.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/commands/voice-edit.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/configuration.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/getting-started.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/iOS_Shortcut_Guide.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/index.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/installation/docker.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/installation/index.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/installation/linux.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/installation/macos.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/installation/nixos.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/installation/windows.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/logo-clean.svg +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/overrides/partials/integrations/analytics/custom.html +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/run_markdown_code_runner.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/docs/system-integration.md +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/example.agent-cli-config.toml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/justfile +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/pyproject.toml +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/shell.nix +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_fix_my_text.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_interactive.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_interactive_extra.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_memory_add.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_speak.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_speak_e2e.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_transcribe.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_transcribe_agent.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_transcribe_e2e.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_transcribe_live.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_transcribe_recovery.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_tts_common.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_tts_common_extra.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_voice_agent_common.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_voice_edit.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_voice_edit_e2e.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/agents/test_wake_word_assistant.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/conftest.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/core/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/core/test_audio.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/core/test_audio_format.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/core/test_chroma.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/core/test_sse.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/core/test_vad.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/core/test_watch.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_coding_agents.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_editors.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_hooks.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_project.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_terminals.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/dev/test_verification.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/install/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/install/test_extras.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_api_health.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_api_integration_liveish.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_client.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_engine.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_files.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_filters.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_git_integration.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_indexer.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_memory_integration.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_proxy_passthrough.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_store.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/memory/test_utils.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/mocks/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/mocks/audio.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/mocks/llm.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/mocks/wyoming.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/__init__.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_engine.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_history.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_indexer.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_indexing.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_rag_client.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_rag_integration_liveish.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_rag_proxy_passthrough.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_retriever.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_store.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/rag/test_utils.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_api.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_api_integration.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_asr.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_asr_recovery.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_audio_e2e.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_cli.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_config.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_config_cmd.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_daemon.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_docs_gen.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_env_vars.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_json_output.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_llm.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_llm_gemini.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_memory_tools.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_mlx_backend.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_process_manager.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_requires_extras.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_server_streaming.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_server_tts.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_server_whisper.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_services.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_tools.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_transformers_backend.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_tts.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_utils.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_wake_word.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/tests/test_wyoming_utils.py +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/uv.lock +0 -0
- {agent_cli-0.85.0 → agent_cli-0.86.0}/zensical.toml +0 -0
{agent_cli-0.85.0/agent_cli/dev/skill → agent_cli-0.86.0/.claude/skills/agent-cli-dev}/SKILL.md
RENAMED
|
@@ -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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.86.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>
|
|
@@ -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/
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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/
|
|
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(
|
|
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/
|
|
171
|
+
"""Write the prompt to a unique file in .claude/ in the worktree.
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
|
|
@@ -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/
|
|
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/
|
|
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.
|
|
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
|
|
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()
|