remo-cli 2.2.0rc10__tar.gz → 2.2.0rc12__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.
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/PKG-INFO +1 -1
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/web-session-interface.md +11 -3
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/package-lock.json +29 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/package.json +2 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/TerminalCard.tsx +59 -1
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/GhosttyRenderer.ts +15 -1
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/RendererAdapter.ts +6 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/XtermRenderer.ts +36 -1
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/keymap.test.ts +18 -1
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/keymap.ts +15 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/pyproject.toml +1 -1
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/uv.lock +1 -1
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-analyze/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-checklist/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-clarify/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-constitution/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-converge/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-git-commit/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-git-feature/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-git-initialize/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-git-remote/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-git-validate/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-implement/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-plan/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-specify/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-tasks/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.claude/skills/speckit-taskstoissues/SKILL.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.devcontainer/devcontainer.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.dockerignore +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.github/dependabot.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.github/workflows/ci.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.github/workflows/provision.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.github/workflows/release.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.github/workflows/smoke-test-cleanup.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.github/workflows/smoke-test.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.github/workflows/teardown.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.gitignore +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.maverick/checkpoints/feature/implementation_complete.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.maverick/checkpoints/feature/phase_${{ index }}_complete.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.maverick/checkpoints/feature/validation_complete.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/.registry +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/README.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.commit.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.feature.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.initialize.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.remote.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.validate.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/config-template.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/extension.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/git-config.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/create-new-feature.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/git-common.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/powershell/create-new-feature.ps1 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/feature.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/init-options.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/integration.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/integrations/claude.manifest.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/integrations/speckit.manifest.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/memory/constitution.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/scripts/bash/check-prerequisites.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/scripts/bash/common.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/scripts/bash/create-new-feature.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/scripts/bash/setup-plan.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/scripts/bash/setup-tasks.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/scripts/bash/update-agent-context.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/templates/agent-file-template.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/templates/checklist-template.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/templates/constitution-template.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/templates/plan-template.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/templates/spec-template.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/templates/tasks-template.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/workflows/speckit/workflow.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/workflows/workflow-registry.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/AGENTS.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/CLAUDE.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/CONTRIBUTING.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/Dockerfile +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/LICENSE +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/README.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/.ansible-lint +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/README.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/ansible.cfg +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/aws_configure.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/aws_resize.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/aws_site.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/aws_teardown.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/group_vars/all.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/group_vars/incus_containers.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/group_vars/proxmox_containers.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/hetzner_configure.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/hetzner_provision.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/hetzner_resize.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/hetzner_site.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/hetzner_teardown.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/incus_bootstrap.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/incus_configure.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/incus_provision.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/incus_resize.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/incus_site.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/incus_teardown.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/inventory/hosts.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/inventory/incus_containers.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/proxmox_bootstrap.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/proxmox_configure.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/proxmox_provision.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/proxmox_resize.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/proxmox_site.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/proxmox_teardown.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/requirements.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/aws_server/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/aws_server/tasks/ebs.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/aws_server/tasks/ec2.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/aws_server/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/aws_server/tasks/patch_manager.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/aws_server/tasks/preflight.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/aws_server/tasks/security_group.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/deacon/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/deacon/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/devcontainers/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/docker/handlers/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/docker/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/fzf/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/github_cli/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/hetzner_server/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/hetzner_server/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_bootstrap/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_bootstrap/handlers/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_bootstrap/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container/handlers/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container/meta/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container/tasks/preflight.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container_teardown/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container_teardown/meta/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/incus_container_teardown/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/nodejs/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/nodejs/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_bootstrap/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_bootstrap/meta/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_bootstrap/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container/handlers/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container/meta/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container/tasks/preflight.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container_teardown/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container_teardown/meta/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/proxmox_container_teardown/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/user_setup/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/user_setup/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/user_setup/templates/devshell.sh.j2 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/user_setup/templates/project-launch.sh.j2 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/user_setup/templates/project-menu.sh.j2 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/user_setup/templates/remo-host.sh.j2 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/zellij/defaults/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/zellij/tasks/main.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/zellij/templates/config.kdl.j2 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/roles/zellij/templates/layouts/minimal.kdl.j2 +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/ansible/tasks/configure_dev_tools.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docker/Dockerfile +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docker/compose.example.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docker/entrypoint.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/aws.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/hetzner.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/incus.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/install.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/proxmox.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/remo-web-speckit-input.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/docs/remo-web.html +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/index.html +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/public/README.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/public/dist__ghostty-vt.wasm +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/public/ghostty-vt.wasm +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/scripts/copy-ghostty-wasm.mjs +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/api/client.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/AppRoot.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/AppShell.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/AppShell.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/AwaitingAdoption.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/AwaitingAdoption.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/OfflineOverlay.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/OfflineOverlay.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/PairToSync.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/PairToSync.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/SessionRail.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/SessionRail.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/SettingsPage.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/SettingsPage.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/ShortcutsModal.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/ShortcutsModal.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/TerminalCard.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/TopBar.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/TopBar.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/WorkspacePane.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/WorkspacePane.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/providerMeta.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/components/railModel.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/lib/clipboard.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/lib/fullscreen.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/main.tsx +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/state/discovery.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/state/fonts.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/state/health.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/state/settings.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/state/useConsoleKeyboard.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/state/workspace.test.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/state/workspace.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/.gitkeep +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/TerminalConnection.test.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/TerminalConnection.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/terminal/defaultRenderer.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/test/setup.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/theme/fonts.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/src/theme/tokens.css +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/tsconfig.json +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/frontend/vite.config.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/install.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/maverick.yaml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/playwright.config.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/project-menu.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/remo +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/run.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/scripts/setup-aws-oidc.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/checklists/requirements.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/checklists/validation.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/contracts/playbook-interface.yaml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/contracts/role-interface.yaml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/data-model.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/plan.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/quickstart.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/research.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/001-bootstrap-incus-host/tasks.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/checklists/requirements.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/contracts/playbook-interface.yaml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/contracts/role-interface.yaml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/data-model.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/plan.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/quickstart.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/research.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/002-incus-container-support/tasks.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/003-python-cli-rewrite/checklists/requirements.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/003-python-cli-rewrite/data-model.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/003-python-cli-rewrite/plan.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/003-python-cli-rewrite/quickstart.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/003-python-cli-rewrite/research.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/003-python-cli-rewrite/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/003-python-cli-rewrite/tasks.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/004-proxmox-container-support/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/checklists/requirements.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/contracts/cli-surface.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/data-model.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/plan.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/quickstart.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/research.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/005-provider-snapshots/tasks.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/checklists/requirements.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/contracts/remo-host-protocol.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/contracts/rest-api.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/contracts/terminal-websocket.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/data-model.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/plan.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/quickstart.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/research.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/010-web-session-interface/tasks.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/checklists/requirements.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/contracts/cli-web-adopt.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/contracts/setup-api.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/data-model.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/plan.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/quickstart-results.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/quickstart.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/research.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/011-web-adopt/tasks.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/contracts/cli-web-adopt.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/contracts/pairing-api.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/contracts/setup-api.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/data-model.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/plan.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/quickstart.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/research.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/spec.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/specs/012-web-adopt-pairing/tasks.md +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/__main__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/cp.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/main.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/providers/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/providers/aws.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/providers/hetzner.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/providers/incus.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/providers/proxmox.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/shell.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/cli/web.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/ansible_runner.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/completion.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/config.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/known_hosts.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/output.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/picker.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/remo_host_client.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/rsync.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/ssh.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/validation.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/version.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/core/web_adopt.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/models/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/models/capability.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/models/discovery.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/models/host.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/models/session_target.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/models/snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/providers/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/providers/aws.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/providers/hetzner.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/providers/incus.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/providers/proxmox.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/api/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/api/hosts.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/api/pairing.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/api/setup.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/api/terminals.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/app.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/check.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/config.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/discovery.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/health.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/logging_config.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/models.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/operator_auth.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/pairing.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/ssh_master.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/state.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/terminal.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/terminal_registry.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/src/remo_cli/web/tokens.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/ansible/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/ansible/test_remo_host_idempotency.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/conftest.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/e2e/fixtures.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/e2e/ghostty-shell-io.spec.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/e2e/ghostty-tui-compatibility.spec.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/e2e/keyboard-routing.spec.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/e2e/mobile.spec.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/e2e/reconnect.spec.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/e2e/workspace-layout.spec.ts +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/image/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/image/test_docker_image.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/_nine_terminal_fixture.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/orbstack-cloud-init.yml +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/orbstack.sh +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/test_nine_terminals.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/test_nine_terminals_soak.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/test_remo_host_e2e.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/test_security_rejections.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/test_terminal_attach.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/test_web_adopt_e2e.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/integration/test_web_cli_parity.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/perf/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/perf/test_latency.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/providers/test_aws_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/providers/test_hetzner_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/providers/test_incus_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/providers/test_proxmox_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/test_cp.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/test_main.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/test_shell.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/cli/test_web_adopt_cmd.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_ansible_runner.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_config.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_known_hosts.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_output.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_picker.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_remo_host_client.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_rsync.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_ssh.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_ssh_controlpath.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_ssh_identity_opts.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_validation.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_version.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_web_adopt_authorize.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_web_adopt_code.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_web_adopt_payload.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_web_adopt_trust.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/core/test_web_push.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/models/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/models/test_capability.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/models/test_discovery.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/models/test_session_target.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/providers/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/providers/test_aws_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/providers/test_hetzner_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/providers/test_incus_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/providers/test_proxmox_devcontainer_runtime.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/providers/test_proxmox_snapshot.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/test_ansible_templates.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/test_host_model.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/__init__.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/_pairing_support.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/conftest.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_backpressure.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_check.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_csp.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_discovery.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_health_states.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_hosts_mapping.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_lazy_import.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_log_redaction.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_mint_gating.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_operator_auth.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_pairing.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_pairing_origin.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_setup_api.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_setup_auth.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_setup_dormancy.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_state.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_terminal_resize.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_terminals_api.py +0 -0
- {remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/tests/unit/web/test_tokens.py +0 -0
|
@@ -102,9 +102,10 @@ The SPA is a two-pane **web console**:
|
|
|
102
102
|
row (or its `+` button) **adds** it to a responsive grid (1/2/3 columns by count). In a grid, **drag
|
|
103
103
|
a tile's header onto another to swap their positions** — a window outline follows the cursor and the
|
|
104
104
|
swap target shows a dashed outline (mouse or touch press-and-hold; keyboard-accessible via the
|
|
105
|
-
handle); the arrangement persists until the grid is rebuilt. In a grid, **
|
|
106
|
-
(focus-follows-mouse
|
|
107
|
-
|
|
105
|
+
handle); the arrangement persists until the grid is rebuilt. In a grid, **resting the pointer on a
|
|
106
|
+
tile focuses it** (focus-follows-mouse, with a short dwell so passing through tiles doesn't steal
|
|
107
|
+
focus) — keystrokes go where the pointer is, no click needed. The **◻** control solos a tile; **Esc**
|
|
108
|
+
collapses the grid back to the focused terminal;
|
|
108
109
|
number keys **1–9** jump to the numbered sessions (⌘ 1–9 add to the grid). Hidden terminals stay
|
|
109
110
|
connected and keep their scrollback. Each terminal header shows `provider · instance · region`
|
|
110
111
|
(doubling as the drag handle), connection state, and a
|
|
@@ -115,6 +116,13 @@ The SPA is a two-pane **web console**:
|
|
|
115
116
|
toggle fullscreen on the focused terminal; **Esc** exits it. Fullscreen is a presentation overlay: it
|
|
116
117
|
never disturbs the single/grid layout underneath, so exiting returns to exactly where you were.
|
|
117
118
|
|
|
119
|
+
**Clipboard & links.** Select text and press **⌘C** (macOS) / **Ctrl+Shift+C** (Linux/Windows), or click
|
|
120
|
+
the **⧉ Copy** button that appears on selection, to copy to the system clipboard; bare **Ctrl+C** stays
|
|
121
|
+
SIGINT. **Paste** with ⌘V / Ctrl+V. **http(s) URLs are clickable** and open in a new tab. Remote apps that
|
|
122
|
+
emit **OSC 52** (e.g. Claude Code's copy-on-select) can write to the browser clipboard — best-effort: it
|
|
123
|
+
must traverse Zellij and the browser must permit a gesture-less clipboard write. OSC 52 *reads* are denied
|
|
124
|
+
(a remote app can never read your clipboard). Clipboard access needs a secure context (HTTPS or localhost).
|
|
125
|
+
|
|
118
126
|
**Session-row glyphs** (also shown in the rail legend):
|
|
119
127
|
|
|
120
128
|
| Glyph | Meaning |
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
"@fontsource/ibm-plex-mono": "^5.2.7",
|
|
14
14
|
"@fontsource/jetbrains-mono": "^5.2.8",
|
|
15
15
|
"@fontsource/source-code-pro": "^5.2.7",
|
|
16
|
+
"@xterm/addon-clipboard": "^0.1.0",
|
|
16
17
|
"@xterm/addon-fit": "^0.10.0",
|
|
17
18
|
"@xterm/addon-ligatures": "^0.9.0",
|
|
19
|
+
"@xterm/addon-web-links": "^0.11.0",
|
|
18
20
|
"@xterm/addon-webgl": "^0.18.0",
|
|
19
21
|
"@xterm/xterm": "^5.5.0",
|
|
20
22
|
"ghostty-web": "0.4.0",
|
|
@@ -1851,6 +1853,18 @@
|
|
|
1851
1853
|
"url": "https://opencollective.com/vitest"
|
|
1852
1854
|
}
|
|
1853
1855
|
},
|
|
1856
|
+
"node_modules/@xterm/addon-clipboard": {
|
|
1857
|
+
"version": "0.1.0",
|
|
1858
|
+
"resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.1.0.tgz",
|
|
1859
|
+
"integrity": "sha512-zdoM7p53T5sv/HbRTyp4hY0kKmEQ3MZvAvEtiXqNIHc/JdpqwByCtsTaQF5DX2n4hYdXRPO4P/eOS0QEhX1nPw==",
|
|
1860
|
+
"license": "MIT",
|
|
1861
|
+
"dependencies": {
|
|
1862
|
+
"js-base64": "^3.7.5"
|
|
1863
|
+
},
|
|
1864
|
+
"peerDependencies": {
|
|
1865
|
+
"@xterm/xterm": "^5.4.0"
|
|
1866
|
+
}
|
|
1867
|
+
},
|
|
1854
1868
|
"node_modules/@xterm/addon-fit": {
|
|
1855
1869
|
"version": "0.10.0",
|
|
1856
1870
|
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
|
|
@@ -1876,6 +1890,15 @@
|
|
|
1876
1890
|
"@xterm/xterm": "^5.0.0"
|
|
1877
1891
|
}
|
|
1878
1892
|
},
|
|
1893
|
+
"node_modules/@xterm/addon-web-links": {
|
|
1894
|
+
"version": "0.11.0",
|
|
1895
|
+
"resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.11.0.tgz",
|
|
1896
|
+
"integrity": "sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==",
|
|
1897
|
+
"license": "MIT",
|
|
1898
|
+
"peerDependencies": {
|
|
1899
|
+
"@xterm/xterm": "^5.0.0"
|
|
1900
|
+
}
|
|
1901
|
+
},
|
|
1879
1902
|
"node_modules/@xterm/addon-webgl": {
|
|
1880
1903
|
"version": "0.18.0",
|
|
1881
1904
|
"resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.18.0.tgz",
|
|
@@ -2611,6 +2634,12 @@
|
|
|
2611
2634
|
"@pkgjs/parseargs": "^0.11.0"
|
|
2612
2635
|
}
|
|
2613
2636
|
},
|
|
2637
|
+
"node_modules/js-base64": {
|
|
2638
|
+
"version": "3.9.1",
|
|
2639
|
+
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.9.1.tgz",
|
|
2640
|
+
"integrity": "sha512-U73qptcvf/HIOauFOmqT3a0mDUp0MYlfd15oqoe9kqZt5XhiXVb+HG09sLvI9PQ9tZIBFS4nlErai8zbWazP0g==",
|
|
2641
|
+
"license": "BSD-3-Clause"
|
|
2642
|
+
},
|
|
2614
2643
|
"node_modules/js-tokens": {
|
|
2615
2644
|
"version": "4.0.0",
|
|
2616
2645
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
"@fontsource/ibm-plex-mono": "^5.2.7",
|
|
21
21
|
"@fontsource/jetbrains-mono": "^5.2.8",
|
|
22
22
|
"@fontsource/source-code-pro": "^5.2.7",
|
|
23
|
+
"@xterm/addon-clipboard": "^0.1.0",
|
|
23
24
|
"@xterm/addon-fit": "^0.10.0",
|
|
24
25
|
"@xterm/addon-ligatures": "^0.9.0",
|
|
26
|
+
"@xterm/addon-web-links": "^0.11.0",
|
|
25
27
|
"@xterm/addon-webgl": "^0.18.0",
|
|
26
28
|
"@xterm/xterm": "^5.5.0",
|
|
27
29
|
"ghostty-web": "0.4.0",
|
|
@@ -28,6 +28,9 @@ const DEFAULT_COLS = 80;
|
|
|
28
28
|
const DEFAULT_ROWS = 24;
|
|
29
29
|
/** How much to shrink the terminal font in a grid tile when "scale to fit". */
|
|
30
30
|
const GRID_FIT_SCALE = 0.8;
|
|
31
|
+
/** Focus-follows-mouse dwell: the pointer must REST on a tile this long before
|
|
32
|
+
* it takes focus, so passing through tiles (or a small drift) doesn't steal it. */
|
|
33
|
+
const HOVER_FOCUS_DELAY_MS = 220;
|
|
31
34
|
|
|
32
35
|
const STATE_LABELS: Record<TerminalConnectionState, string> = {
|
|
33
36
|
connecting: "Connecting…",
|
|
@@ -119,10 +122,14 @@ export function TerminalCard({
|
|
|
119
122
|
// (to skip redundant resize frames).
|
|
120
123
|
const fitRafRef = useRef<number | null>(null);
|
|
121
124
|
const lastSentDimsRef = useRef<{ cols: number; rows: number } | null>(null);
|
|
125
|
+
// Pending focus-follows-mouse dwell timer (cleared if the pointer leaves first).
|
|
126
|
+
const hoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
122
127
|
|
|
123
128
|
const [connectionState, setConnectionState] = useState<TerminalConnectionState>("connecting");
|
|
124
129
|
const [needsManualReconnect, setNeedsManualReconnect] = useState(false);
|
|
125
130
|
const [error, setError] = useState<TypedError | null>(null);
|
|
131
|
+
const [hasSelection, setHasSelection] = useState(false);
|
|
132
|
+
const [copied, setCopied] = useState(false);
|
|
126
133
|
|
|
127
134
|
// dnd-kit reorder: the tile is both a draggable (handle = header grip, below)
|
|
128
135
|
// and a droppable (swap target). Disabled outside a reorderable grid. We use
|
|
@@ -247,6 +254,9 @@ export function TerminalCard({
|
|
|
247
254
|
}
|
|
248
255
|
});
|
|
249
256
|
|
|
257
|
+
// Show/hide the Copy affordance as the terminal selection changes.
|
|
258
|
+
const unsubscribeSelection = adapter.onSelectionChange((has) => setHasSelection(has));
|
|
259
|
+
|
|
250
260
|
// Reflow on every container size change (window resize, rail drag, grid
|
|
251
261
|
// <-> single, tile show/hide). scheduleFit coalesces bursts to one fit per
|
|
252
262
|
// frame and skips the hidden-0x0 case.
|
|
@@ -263,6 +273,7 @@ export function TerminalCard({
|
|
|
263
273
|
}
|
|
264
274
|
lastSentDimsRef.current = null;
|
|
265
275
|
unsubscribeInput();
|
|
276
|
+
unsubscribeSelection();
|
|
266
277
|
resizeObserver.disconnect();
|
|
267
278
|
void connection.close();
|
|
268
279
|
adapter.dispose();
|
|
@@ -306,6 +317,38 @@ export function TerminalCard({
|
|
|
306
317
|
onFocusRequest?.();
|
|
307
318
|
}, [onFocusRequest]);
|
|
308
319
|
|
|
320
|
+
const handleCopy = useCallback(() => {
|
|
321
|
+
void adapterRef.current?.copySelection().then((ok) => {
|
|
322
|
+
if (ok) {
|
|
323
|
+
setCopied(true);
|
|
324
|
+
setTimeout(() => setCopied(false), 1200);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}, []);
|
|
328
|
+
|
|
329
|
+
const clearHoverTimer = useCallback(() => {
|
|
330
|
+
if (hoverTimerRef.current !== null) {
|
|
331
|
+
clearTimeout(hoverTimerRef.current);
|
|
332
|
+
hoverTimerRef.current = null;
|
|
333
|
+
}
|
|
334
|
+
}, []);
|
|
335
|
+
|
|
336
|
+
// Focus-follows-mouse with a dwell delay: arm a timer on enter, fire only if
|
|
337
|
+
// the pointer is still resting here after HOVER_FOCUS_DELAY_MS.
|
|
338
|
+
const handleMouseEnter = useCallback(() => {
|
|
339
|
+
if (!onHoverFocus) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
clearHoverTimer();
|
|
343
|
+
hoverTimerRef.current = setTimeout(() => {
|
|
344
|
+
hoverTimerRef.current = null;
|
|
345
|
+
onHoverFocus();
|
|
346
|
+
}, HOVER_FOCUS_DELAY_MS);
|
|
347
|
+
}, [onHoverFocus, clearHoverTimer]);
|
|
348
|
+
|
|
349
|
+
// Cancel a pending dwell when the pointer leaves or the card unmounts.
|
|
350
|
+
useEffect(() => clearHoverTimer, [clearHoverTimer]);
|
|
351
|
+
|
|
309
352
|
const prov = providerMeta(target.instance_type);
|
|
310
353
|
const badge = [prov.label, target.instance_name, region].filter(Boolean).join(" · ");
|
|
311
354
|
|
|
@@ -322,7 +365,8 @@ export function TerminalCard({
|
|
|
322
365
|
data-focused={isFocused}
|
|
323
366
|
data-connection-state={connectionState}
|
|
324
367
|
style={{ display: isVisible ? undefined : "none" }}
|
|
325
|
-
onMouseEnter={
|
|
368
|
+
onMouseEnter={handleMouseEnter}
|
|
369
|
+
onMouseLeave={clearHoverTimer}
|
|
326
370
|
>
|
|
327
371
|
<header className="terminal-card-header">
|
|
328
372
|
{/* The header (left of the controls) is the drag handle for reordering
|
|
@@ -350,6 +394,20 @@ export function TerminalCard({
|
|
|
350
394
|
{STATE_LABELS[connectionState]}
|
|
351
395
|
</span>
|
|
352
396
|
<div className="terminal-card-controls">
|
|
397
|
+
{hasSelection && (
|
|
398
|
+
<button
|
|
399
|
+
type="button"
|
|
400
|
+
className="tc-btn"
|
|
401
|
+
data-testid={`terminal-copy-${target.id}`}
|
|
402
|
+
title="Copy selection (⌘C / Ctrl+Shift+C)"
|
|
403
|
+
onClick={(e) => {
|
|
404
|
+
e.stopPropagation();
|
|
405
|
+
handleCopy();
|
|
406
|
+
}}
|
|
407
|
+
>
|
|
408
|
+
{copied ? "✓ Copied" : "⧉ Copy"}
|
|
409
|
+
</button>
|
|
410
|
+
)}
|
|
353
411
|
{needsManualReconnect && (
|
|
354
412
|
<button
|
|
355
413
|
type="button"
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
// configured font/size so the cell grid stays correct after a font change.
|
|
11
11
|
|
|
12
12
|
import { Terminal } from "ghostty-web";
|
|
13
|
-
import {
|
|
13
|
+
import { copyText } from "../lib/clipboard";
|
|
14
|
+
import { inputForKeyEvent, isCopyChord } from "./keymap";
|
|
14
15
|
import type {
|
|
15
16
|
RendererAdapter,
|
|
16
17
|
TerminalDimensions,
|
|
@@ -63,6 +64,11 @@ export class GhosttyRenderer implements RendererAdapter {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
private handleKeyEvent(e: KeyboardEvent): boolean {
|
|
67
|
+
if (isCopyChord(e) && this.getSelection()) {
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
void this.copySelection();
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
66
72
|
const seq = inputForKeyEvent(e);
|
|
67
73
|
if (seq !== null) {
|
|
68
74
|
e.preventDefault();
|
|
@@ -134,6 +140,14 @@ export class GhosttyRenderer implements RendererAdapter {
|
|
|
134
140
|
return selection && selection.length > 0 ? selection : null;
|
|
135
141
|
}
|
|
136
142
|
|
|
143
|
+
async copySelection(): Promise<boolean> {
|
|
144
|
+
const selection = this.getSelection();
|
|
145
|
+
if (!selection) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return copyText(selection);
|
|
149
|
+
}
|
|
150
|
+
|
|
137
151
|
dispose(): void {
|
|
138
152
|
this.terminal.dispose();
|
|
139
153
|
}
|
|
@@ -93,6 +93,12 @@ export interface RendererAdapter {
|
|
|
93
93
|
/** Returns the currently selected text, or `null` if nothing is selected. */
|
|
94
94
|
getSelection(): string | null;
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Copies the current selection to the system clipboard (best-effort; needs a
|
|
98
|
+
* secure context). Returns true if there was a selection that was copied.
|
|
99
|
+
*/
|
|
100
|
+
copySelection(): Promise<boolean>;
|
|
101
|
+
|
|
96
102
|
/** Tears down the renderer and releases all resources/listeners. */
|
|
97
103
|
dispose(): void;
|
|
98
104
|
}
|
|
@@ -20,16 +20,30 @@ import { Terminal } from "@xterm/xterm";
|
|
|
20
20
|
import { FitAddon } from "@xterm/addon-fit";
|
|
21
21
|
import { LigaturesAddon } from "@xterm/addon-ligatures";
|
|
22
22
|
import { WebglAddon } from "@xterm/addon-webgl";
|
|
23
|
+
import { WebLinksAddon } from "@xterm/addon-web-links";
|
|
24
|
+
import { ClipboardAddon, type IClipboardProvider } from "@xterm/addon-clipboard";
|
|
23
25
|
// xterm ships its own stylesheet; without it the terminal renders with broken
|
|
24
26
|
// cell sizing/positioning. Bundled here so it loads whenever this renderer is.
|
|
25
27
|
import "@xterm/xterm/css/xterm.css";
|
|
26
|
-
import {
|
|
28
|
+
import { copyText } from "../lib/clipboard";
|
|
29
|
+
import { inputForKeyEvent, isCopyChord } from "./keymap";
|
|
27
30
|
import type {
|
|
28
31
|
RendererAdapter,
|
|
29
32
|
TerminalDimensions,
|
|
30
33
|
TerminalFontOptions,
|
|
31
34
|
} from "./RendererAdapter";
|
|
32
35
|
|
|
36
|
+
// OSC 52 handling: WRITE lets a remote app (e.g. Claude Code's copy-on-select)
|
|
37
|
+
// push text to the browser clipboard; READ is denied so a remote app can never
|
|
38
|
+
// exfiltrate the operator's clipboard. Best-effort — an escape-sequence write
|
|
39
|
+
// has no user gesture, so some browsers may reject it.
|
|
40
|
+
const _osc52Provider: IClipboardProvider = {
|
|
41
|
+
readText: async () => "",
|
|
42
|
+
writeText: async (_selection, text) => {
|
|
43
|
+
await copyText(text);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
33
47
|
const DEFAULT_FONT: TerminalFontOptions = {
|
|
34
48
|
fontFamily: "Menlo, Consolas, 'DejaVu Sans Mono', monospace",
|
|
35
49
|
fontSize: 13,
|
|
@@ -80,6 +94,13 @@ export class XtermRenderer implements RendererAdapter {
|
|
|
80
94
|
}
|
|
81
95
|
|
|
82
96
|
private handleKeyEvent(e: KeyboardEvent): boolean {
|
|
97
|
+
// Copy the selection on ⌘C / Ctrl+Shift+C — but only when something is
|
|
98
|
+
// selected, so bare Ctrl+C still reaches the shell as SIGINT.
|
|
99
|
+
if (isCopyChord(e) && this.terminal.hasSelection()) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
void this.copySelection();
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
83
104
|
const seq = inputForKeyEvent(e);
|
|
84
105
|
if (seq !== null) {
|
|
85
106
|
// preventDefault stops the browser from also inserting a newline into
|
|
@@ -116,6 +137,12 @@ export class XtermRenderer implements RendererAdapter {
|
|
|
116
137
|
this.enableWebgl();
|
|
117
138
|
// Now that the terminal is attached, load the ligatures addon if wanted.
|
|
118
139
|
this.applyLigatures(this.ligaturesEnabled);
|
|
140
|
+
// Clickable http(s) links — open in a new tab, severing opener access.
|
|
141
|
+
this.terminal.loadAddon(
|
|
142
|
+
new WebLinksAddon((_event, uri) => window.open(uri, "_blank", "noopener,noreferrer")),
|
|
143
|
+
);
|
|
144
|
+
// OSC 52 (remote-app clipboard writes, e.g. Claude Code copy-on-select).
|
|
145
|
+
this.terminal.loadAddon(new ClipboardAddon(_osc52Provider));
|
|
119
146
|
}
|
|
120
147
|
|
|
121
148
|
// GPU-accelerated rendering. Must run after open(). Best-effort: a failed
|
|
@@ -185,6 +212,14 @@ export class XtermRenderer implements RendererAdapter {
|
|
|
185
212
|
return selection.length > 0 ? selection : null;
|
|
186
213
|
}
|
|
187
214
|
|
|
215
|
+
async copySelection(): Promise<boolean> {
|
|
216
|
+
const selection = this.getSelection();
|
|
217
|
+
if (!selection) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
return copyText(selection);
|
|
221
|
+
}
|
|
222
|
+
|
|
188
223
|
dispose(): void {
|
|
189
224
|
// Dispose the WebGL addon before the terminal so its GPU context/canvas is
|
|
190
225
|
// released cleanly (Terminal.dispose would also drop it, but ordering is
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { inputForKeyEvent } from "./keymap";
|
|
2
|
+
import { inputForKeyEvent, isCopyChord } from "./keymap";
|
|
3
3
|
|
|
4
4
|
function key(init: KeyboardEventInit & { type?: string }): KeyboardEvent {
|
|
5
5
|
const { type = "keydown", ...rest } = init;
|
|
@@ -30,3 +30,20 @@ describe("inputForKeyEvent", () => {
|
|
|
30
30
|
expect(inputForKeyEvent(key({ key: "a", shiftKey: true }))).toBeNull();
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
|
+
|
|
34
|
+
describe("isCopyChord", () => {
|
|
35
|
+
it("recognizes ⌘C and Ctrl+Shift+C", () => {
|
|
36
|
+
expect(isCopyChord(key({ key: "c", metaKey: true }))).toBe(true);
|
|
37
|
+
expect(isCopyChord(key({ key: "C", ctrlKey: true, shiftKey: true }))).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("leaves bare Ctrl+C alone (stays SIGINT)", () => {
|
|
41
|
+
expect(isCopyChord(key({ key: "c", ctrlKey: true }))).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("ignores other keys, plain c, and non-keydown events", () => {
|
|
45
|
+
expect(isCopyChord(key({ key: "v", metaKey: true }))).toBe(false);
|
|
46
|
+
expect(isCopyChord(key({ key: "c" }))).toBe(false);
|
|
47
|
+
expect(isCopyChord(key({ key: "c", metaKey: true, type: "keyup" }))).toBe(false);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -25,3 +25,18 @@ export function inputForKeyEvent(e: KeyboardEvent): string | null {
|
|
|
25
25
|
}
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Whether a key event is the "copy the selection" chord: **Cmd+C** (macOS) or
|
|
31
|
+
* **Ctrl+Shift+C** (Linux/Windows). Bare `Ctrl+C` is deliberately excluded so it
|
|
32
|
+
* stays SIGINT. The renderer only copies when there is actually a selection —
|
|
33
|
+
* otherwise the chord is left alone.
|
|
34
|
+
*/
|
|
35
|
+
export function isCopyChord(e: KeyboardEvent): boolean {
|
|
36
|
+
if (e.type !== "keydown" || (e.key !== "c" && e.key !== "C")) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const cmdC = e.metaKey && !e.ctrlKey && !e.altKey; // macOS ⌘C
|
|
40
|
+
const ctrlShiftC = e.ctrlKey && e.shiftKey && !e.metaKey && !e.altKey; // Linux/Win
|
|
41
|
+
return cmdC || ctrlShiftC;
|
|
42
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.maverick/checkpoints/feature/implementation_complete.json
RENAMED
|
File without changes
|
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.maverick/checkpoints/feature/validation_complete.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.commit.md
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.feature.md
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.initialize.md
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.remote.md
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/commands/speckit.git.validate.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/auto-commit.sh
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/create-new-feature.sh
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/git-common.sh
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/bash/initialize-repo.sh
RENAMED
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/powershell/auto-commit.ps1
RENAMED
|
File without changes
|
|
File without changes
|
{remo_cli-2.2.0rc10 → remo_cli-2.2.0rc12}/.specify/extensions/git/scripts/powershell/git-common.ps1
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|