remo-cli 2.2.0rc9__tar.gz → 2.2.0rc10__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/PKG-INFO +1 -1
  2. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/web-session-interface.md +5 -2
  3. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/package-lock.json +46 -0
  4. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/package.json +1 -0
  5. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/TerminalCard.css +40 -6
  6. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/TerminalCard.tsx +35 -34
  7. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/WorkspacePane.tsx +94 -60
  8. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/pyproject.toml +1 -1
  9. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/uv.lock +1 -1
  10. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-analyze/SKILL.md +0 -0
  11. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-checklist/SKILL.md +0 -0
  12. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-clarify/SKILL.md +0 -0
  13. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-constitution/SKILL.md +0 -0
  14. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-converge/SKILL.md +0 -0
  15. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-git-commit/SKILL.md +0 -0
  16. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-git-feature/SKILL.md +0 -0
  17. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-git-initialize/SKILL.md +0 -0
  18. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-git-remote/SKILL.md +0 -0
  19. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-git-validate/SKILL.md +0 -0
  20. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-implement/SKILL.md +0 -0
  21. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-plan/SKILL.md +0 -0
  22. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-specify/SKILL.md +0 -0
  23. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-tasks/SKILL.md +0 -0
  24. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.claude/skills/speckit-taskstoissues/SKILL.md +0 -0
  25. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.devcontainer/devcontainer.json +0 -0
  26. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.dockerignore +0 -0
  27. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.github/dependabot.yml +0 -0
  28. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.github/workflows/ci.yml +0 -0
  29. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.github/workflows/provision.yml +0 -0
  30. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.github/workflows/release.yml +0 -0
  31. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.github/workflows/smoke-test-cleanup.yml +0 -0
  32. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.github/workflows/smoke-test.yml +0 -0
  33. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.github/workflows/teardown.yml +0 -0
  34. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.gitignore +0 -0
  35. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.maverick/checkpoints/feature/implementation_complete.json +0 -0
  36. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.maverick/checkpoints/feature/phase_${{ index }}_complete.json +0 -0
  37. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.maverick/checkpoints/feature/validation_complete.json +0 -0
  38. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/.registry +0 -0
  39. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/README.md +0 -0
  40. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/commands/speckit.git.commit.md +0 -0
  41. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/commands/speckit.git.feature.md +0 -0
  42. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/commands/speckit.git.initialize.md +0 -0
  43. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/commands/speckit.git.remote.md +0 -0
  44. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/commands/speckit.git.validate.md +0 -0
  45. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/config-template.yml +0 -0
  46. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/extension.yml +0 -0
  47. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/git-config.yml +0 -0
  48. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/bash/auto-commit.sh +0 -0
  49. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/bash/create-new-feature.sh +0 -0
  50. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/bash/git-common.sh +0 -0
  51. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/bash/initialize-repo.sh +0 -0
  52. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
  53. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/powershell/create-new-feature.ps1 +0 -0
  54. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/powershell/git-common.ps1 +0 -0
  55. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
  56. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/extensions.yml +0 -0
  57. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/feature.json +0 -0
  58. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/init-options.json +0 -0
  59. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/integration.json +0 -0
  60. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/integrations/claude.manifest.json +0 -0
  61. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/integrations/speckit.manifest.json +0 -0
  62. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/memory/constitution.md +0 -0
  63. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/scripts/bash/check-prerequisites.sh +0 -0
  64. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/scripts/bash/common.sh +0 -0
  65. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/scripts/bash/create-new-feature.sh +0 -0
  66. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/scripts/bash/setup-plan.sh +0 -0
  67. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/scripts/bash/setup-tasks.sh +0 -0
  68. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/scripts/bash/update-agent-context.sh +0 -0
  69. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/templates/agent-file-template.md +0 -0
  70. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/templates/checklist-template.md +0 -0
  71. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/templates/constitution-template.md +0 -0
  72. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/templates/plan-template.md +0 -0
  73. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/templates/spec-template.md +0 -0
  74. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/templates/tasks-template.md +0 -0
  75. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/workflows/speckit/workflow.yml +0 -0
  76. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/.specify/workflows/workflow-registry.json +0 -0
  77. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/AGENTS.md +0 -0
  78. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/CLAUDE.md +0 -0
  79. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/CONTRIBUTING.md +0 -0
  80. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/Dockerfile +0 -0
  81. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/LICENSE +0 -0
  82. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/README.md +0 -0
  83. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/.ansible-lint +0 -0
  84. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/README.md +0 -0
  85. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/ansible.cfg +0 -0
  86. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/aws_configure.yml +0 -0
  87. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/aws_resize.yml +0 -0
  88. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/aws_site.yml +0 -0
  89. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/aws_teardown.yml +0 -0
  90. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/group_vars/all.yml +0 -0
  91. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/group_vars/incus_containers.yml +0 -0
  92. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/group_vars/proxmox_containers.yml +0 -0
  93. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/hetzner_configure.yml +0 -0
  94. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/hetzner_provision.yml +0 -0
  95. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/hetzner_resize.yml +0 -0
  96. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/hetzner_site.yml +0 -0
  97. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/hetzner_teardown.yml +0 -0
  98. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/incus_bootstrap.yml +0 -0
  99. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/incus_configure.yml +0 -0
  100. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/incus_provision.yml +0 -0
  101. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/incus_resize.yml +0 -0
  102. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/incus_site.yml +0 -0
  103. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/incus_teardown.yml +0 -0
  104. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/inventory/hosts.yml +0 -0
  105. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/inventory/incus_containers.yml +0 -0
  106. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/proxmox_bootstrap.yml +0 -0
  107. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/proxmox_configure.yml +0 -0
  108. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/proxmox_provision.yml +0 -0
  109. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/proxmox_resize.yml +0 -0
  110. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/proxmox_site.yml +0 -0
  111. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/proxmox_teardown.yml +0 -0
  112. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/requirements.yml +0 -0
  113. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/aws_server/defaults/main.yml +0 -0
  114. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/aws_server/tasks/ebs.yml +0 -0
  115. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/aws_server/tasks/ec2.yml +0 -0
  116. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/aws_server/tasks/main.yml +0 -0
  117. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/aws_server/tasks/patch_manager.yml +0 -0
  118. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/aws_server/tasks/preflight.yml +0 -0
  119. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/aws_server/tasks/security_group.yml +0 -0
  120. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/deacon/defaults/main.yml +0 -0
  121. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/deacon/tasks/main.yml +0 -0
  122. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/devcontainers/tasks/main.yml +0 -0
  123. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/docker/handlers/main.yml +0 -0
  124. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/docker/tasks/main.yml +0 -0
  125. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/fzf/tasks/main.yml +0 -0
  126. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/github_cli/tasks/main.yml +0 -0
  127. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/hetzner_server/defaults/main.yml +0 -0
  128. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/hetzner_server/tasks/main.yml +0 -0
  129. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_bootstrap/defaults/main.yml +0 -0
  130. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_bootstrap/handlers/main.yml +0 -0
  131. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_bootstrap/tasks/main.yml +0 -0
  132. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container/defaults/main.yml +0 -0
  133. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container/handlers/main.yml +0 -0
  134. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container/meta/main.yml +0 -0
  135. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container/tasks/main.yml +0 -0
  136. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container/tasks/preflight.yml +0 -0
  137. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container_teardown/defaults/main.yml +0 -0
  138. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container_teardown/meta/main.yml +0 -0
  139. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/incus_container_teardown/tasks/main.yml +0 -0
  140. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/nodejs/defaults/main.yml +0 -0
  141. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/nodejs/tasks/main.yml +0 -0
  142. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_bootstrap/defaults/main.yml +0 -0
  143. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_bootstrap/meta/main.yml +0 -0
  144. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_bootstrap/tasks/main.yml +0 -0
  145. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container/defaults/main.yml +0 -0
  146. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container/handlers/main.yml +0 -0
  147. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container/meta/main.yml +0 -0
  148. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container/tasks/main.yml +0 -0
  149. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container/tasks/preflight.yml +0 -0
  150. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container_teardown/defaults/main.yml +0 -0
  151. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container_teardown/meta/main.yml +0 -0
  152. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/proxmox_container_teardown/tasks/main.yml +0 -0
  153. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/user_setup/defaults/main.yml +0 -0
  154. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/user_setup/tasks/main.yml +0 -0
  155. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/user_setup/templates/devshell.sh.j2 +0 -0
  156. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/user_setup/templates/project-launch.sh.j2 +0 -0
  157. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/user_setup/templates/project-menu.sh.j2 +0 -0
  158. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/user_setup/templates/remo-host.sh.j2 +0 -0
  159. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/zellij/defaults/main.yml +0 -0
  160. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/zellij/tasks/main.yml +0 -0
  161. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/zellij/templates/config.kdl.j2 +0 -0
  162. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/roles/zellij/templates/layouts/minimal.kdl.j2 +0 -0
  163. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/ansible/tasks/configure_dev_tools.yml +0 -0
  164. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docker/Dockerfile +0 -0
  165. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docker/compose.example.yml +0 -0
  166. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docker/entrypoint.sh +0 -0
  167. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/aws.md +0 -0
  168. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/hetzner.md +0 -0
  169. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/incus.md +0 -0
  170. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/install.sh +0 -0
  171. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/proxmox.md +0 -0
  172. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/remo-web-speckit-input.md +0 -0
  173. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/docs/remo-web.html +0 -0
  174. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/index.html +0 -0
  175. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/public/README.md +0 -0
  176. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/public/dist__ghostty-vt.wasm +0 -0
  177. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/public/ghostty-vt.wasm +0 -0
  178. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/scripts/copy-ghostty-wasm.mjs +0 -0
  179. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/api/client.ts +0 -0
  180. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/AppRoot.tsx +0 -0
  181. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/AppShell.css +0 -0
  182. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/AppShell.tsx +0 -0
  183. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/AwaitingAdoption.css +0 -0
  184. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/AwaitingAdoption.tsx +0 -0
  185. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/OfflineOverlay.css +0 -0
  186. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/OfflineOverlay.tsx +0 -0
  187. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/PairToSync.css +0 -0
  188. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/PairToSync.tsx +0 -0
  189. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/SessionRail.css +0 -0
  190. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/SessionRail.tsx +0 -0
  191. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/SettingsPage.css +0 -0
  192. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/SettingsPage.tsx +0 -0
  193. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/ShortcutsModal.css +0 -0
  194. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/ShortcutsModal.tsx +0 -0
  195. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/TopBar.css +0 -0
  196. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/TopBar.tsx +0 -0
  197. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/WorkspacePane.css +0 -0
  198. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/providerMeta.ts +0 -0
  199. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/components/railModel.ts +0 -0
  200. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/lib/clipboard.ts +0 -0
  201. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/lib/fullscreen.ts +0 -0
  202. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/main.tsx +0 -0
  203. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/state/discovery.ts +0 -0
  204. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/state/fonts.ts +0 -0
  205. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/state/health.ts +0 -0
  206. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/state/settings.ts +0 -0
  207. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/state/useConsoleKeyboard.ts +0 -0
  208. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/state/workspace.test.ts +0 -0
  209. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/state/workspace.ts +0 -0
  210. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/.gitkeep +0 -0
  211. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/GhosttyRenderer.ts +0 -0
  212. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/RendererAdapter.ts +0 -0
  213. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/TerminalConnection.test.ts +0 -0
  214. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/TerminalConnection.ts +0 -0
  215. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/XtermRenderer.ts +0 -0
  216. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/defaultRenderer.ts +0 -0
  217. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/keymap.test.ts +0 -0
  218. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/terminal/keymap.ts +0 -0
  219. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/test/setup.ts +0 -0
  220. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/theme/fonts.ts +0 -0
  221. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/src/theme/tokens.css +0 -0
  222. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/tsconfig.json +0 -0
  223. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/frontend/vite.config.ts +0 -0
  224. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/install.sh +0 -0
  225. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/maverick.yaml +0 -0
  226. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/playwright.config.ts +0 -0
  227. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/project-menu.sh +0 -0
  228. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/remo +0 -0
  229. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/run.sh +0 -0
  230. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/scripts/setup-aws-oidc.sh +0 -0
  231. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/checklists/requirements.md +0 -0
  232. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/checklists/validation.md +0 -0
  233. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/contracts/playbook-interface.yaml +0 -0
  234. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/contracts/role-interface.yaml +0 -0
  235. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/data-model.md +0 -0
  236. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/plan.md +0 -0
  237. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/quickstart.md +0 -0
  238. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/research.md +0 -0
  239. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/spec.md +0 -0
  240. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/001-bootstrap-incus-host/tasks.md +0 -0
  241. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/checklists/requirements.md +0 -0
  242. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/contracts/playbook-interface.yaml +0 -0
  243. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/contracts/role-interface.yaml +0 -0
  244. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/data-model.md +0 -0
  245. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/plan.md +0 -0
  246. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/quickstart.md +0 -0
  247. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/research.md +0 -0
  248. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/spec.md +0 -0
  249. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/002-incus-container-support/tasks.md +0 -0
  250. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/003-python-cli-rewrite/checklists/requirements.md +0 -0
  251. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/003-python-cli-rewrite/data-model.md +0 -0
  252. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/003-python-cli-rewrite/plan.md +0 -0
  253. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/003-python-cli-rewrite/quickstart.md +0 -0
  254. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/003-python-cli-rewrite/research.md +0 -0
  255. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/003-python-cli-rewrite/spec.md +0 -0
  256. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/003-python-cli-rewrite/tasks.md +0 -0
  257. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/004-proxmox-container-support/spec.md +0 -0
  258. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/checklists/requirements.md +0 -0
  259. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/contracts/cli-surface.md +0 -0
  260. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/data-model.md +0 -0
  261. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/plan.md +0 -0
  262. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/quickstart.md +0 -0
  263. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/research.md +0 -0
  264. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/spec.md +0 -0
  265. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/005-provider-snapshots/tasks.md +0 -0
  266. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/checklists/requirements.md +0 -0
  267. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/contracts/remo-host-protocol.md +0 -0
  268. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/contracts/rest-api.md +0 -0
  269. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/contracts/terminal-websocket.md +0 -0
  270. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/data-model.md +0 -0
  271. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/plan.md +0 -0
  272. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/quickstart.md +0 -0
  273. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/research.md +0 -0
  274. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/spec.md +0 -0
  275. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/010-web-session-interface/tasks.md +0 -0
  276. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/checklists/requirements.md +0 -0
  277. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/contracts/cli-web-adopt.md +0 -0
  278. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/contracts/setup-api.md +0 -0
  279. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/data-model.md +0 -0
  280. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/plan.md +0 -0
  281. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/quickstart-results.md +0 -0
  282. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/quickstart.md +0 -0
  283. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/research.md +0 -0
  284. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/spec.md +0 -0
  285. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/011-web-adopt/tasks.md +0 -0
  286. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/contracts/cli-web-adopt.md +0 -0
  287. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/contracts/pairing-api.md +0 -0
  288. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/contracts/setup-api.md +0 -0
  289. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/data-model.md +0 -0
  290. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/plan.md +0 -0
  291. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/quickstart.md +0 -0
  292. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/research.md +0 -0
  293. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/spec.md +0 -0
  294. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/specs/012-web-adopt-pairing/tasks.md +0 -0
  295. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/__init__.py +0 -0
  296. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/__main__.py +0 -0
  297. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/__init__.py +0 -0
  298. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/cp.py +0 -0
  299. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/main.py +0 -0
  300. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/providers/__init__.py +0 -0
  301. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/providers/aws.py +0 -0
  302. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/providers/hetzner.py +0 -0
  303. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/providers/incus.py +0 -0
  304. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/providers/proxmox.py +0 -0
  305. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/shell.py +0 -0
  306. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/cli/web.py +0 -0
  307. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/__init__.py +0 -0
  308. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/ansible_runner.py +0 -0
  309. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/completion.py +0 -0
  310. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/config.py +0 -0
  311. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/known_hosts.py +0 -0
  312. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/output.py +0 -0
  313. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/picker.py +0 -0
  314. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/remo_host_client.py +0 -0
  315. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/rsync.py +0 -0
  316. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/snapshot.py +0 -0
  317. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/ssh.py +0 -0
  318. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/validation.py +0 -0
  319. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/version.py +0 -0
  320. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/core/web_adopt.py +0 -0
  321. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/models/__init__.py +0 -0
  322. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/models/capability.py +0 -0
  323. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/models/discovery.py +0 -0
  324. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/models/host.py +0 -0
  325. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/models/session_target.py +0 -0
  326. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/models/snapshot.py +0 -0
  327. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/providers/__init__.py +0 -0
  328. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/providers/aws.py +0 -0
  329. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/providers/hetzner.py +0 -0
  330. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/providers/incus.py +0 -0
  331. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/providers/proxmox.py +0 -0
  332. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/__init__.py +0 -0
  333. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/api/__init__.py +0 -0
  334. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/api/hosts.py +0 -0
  335. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/api/pairing.py +0 -0
  336. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/api/setup.py +0 -0
  337. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/api/terminals.py +0 -0
  338. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/app.py +0 -0
  339. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/check.py +0 -0
  340. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/config.py +0 -0
  341. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/discovery.py +0 -0
  342. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/health.py +0 -0
  343. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/logging_config.py +0 -0
  344. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/models.py +0 -0
  345. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/operator_auth.py +0 -0
  346. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/pairing.py +0 -0
  347. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/ssh_master.py +0 -0
  348. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/state.py +0 -0
  349. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/terminal.py +0 -0
  350. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/terminal_registry.py +0 -0
  351. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/src/remo_cli/web/tokens.py +0 -0
  352. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/__init__.py +0 -0
  353. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/ansible/__init__.py +0 -0
  354. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/ansible/test_remo_host_idempotency.py +0 -0
  355. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/conftest.py +0 -0
  356. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/e2e/fixtures.ts +0 -0
  357. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/e2e/ghostty-shell-io.spec.ts +0 -0
  358. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/e2e/ghostty-tui-compatibility.spec.ts +0 -0
  359. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/e2e/keyboard-routing.spec.ts +0 -0
  360. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/e2e/mobile.spec.ts +0 -0
  361. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/e2e/reconnect.spec.ts +0 -0
  362. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/e2e/workspace-layout.spec.ts +0 -0
  363. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/image/__init__.py +0 -0
  364. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/image/test_docker_image.py +0 -0
  365. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/__init__.py +0 -0
  366. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/_nine_terminal_fixture.py +0 -0
  367. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/orbstack-cloud-init.yml +0 -0
  368. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/orbstack.sh +0 -0
  369. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/test_nine_terminals.py +0 -0
  370. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/test_nine_terminals_soak.py +0 -0
  371. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/test_remo_host_e2e.py +0 -0
  372. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/test_security_rejections.py +0 -0
  373. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/test_terminal_attach.py +0 -0
  374. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/test_web_adopt_e2e.py +0 -0
  375. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/integration/test_web_cli_parity.py +0 -0
  376. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/perf/__init__.py +0 -0
  377. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/perf/test_latency.py +0 -0
  378. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/__init__.py +0 -0
  379. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/__init__.py +0 -0
  380. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/providers/test_aws_snapshot.py +0 -0
  381. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/providers/test_hetzner_snapshot.py +0 -0
  382. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/providers/test_incus_snapshot.py +0 -0
  383. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/providers/test_proxmox_snapshot.py +0 -0
  384. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/test_cp.py +0 -0
  385. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/test_main.py +0 -0
  386. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/test_shell.py +0 -0
  387. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/cli/test_web_adopt_cmd.py +0 -0
  388. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/__init__.py +0 -0
  389. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_ansible_runner.py +0 -0
  390. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_config.py +0 -0
  391. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_known_hosts.py +0 -0
  392. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_output.py +0 -0
  393. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_picker.py +0 -0
  394. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_remo_host_client.py +0 -0
  395. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_rsync.py +0 -0
  396. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_snapshot.py +0 -0
  397. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_ssh.py +0 -0
  398. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_ssh_controlpath.py +0 -0
  399. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_ssh_identity_opts.py +0 -0
  400. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_validation.py +0 -0
  401. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_version.py +0 -0
  402. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_web_adopt_authorize.py +0 -0
  403. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_web_adopt_code.py +0 -0
  404. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_web_adopt_payload.py +0 -0
  405. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_web_adopt_trust.py +0 -0
  406. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/core/test_web_push.py +0 -0
  407. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/models/__init__.py +0 -0
  408. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/models/test_capability.py +0 -0
  409. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/models/test_discovery.py +0 -0
  410. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/models/test_session_target.py +0 -0
  411. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/providers/__init__.py +0 -0
  412. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/providers/test_aws_snapshot.py +0 -0
  413. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/providers/test_hetzner_snapshot.py +0 -0
  414. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/providers/test_incus_snapshot.py +0 -0
  415. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/providers/test_proxmox_devcontainer_runtime.py +0 -0
  416. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/providers/test_proxmox_snapshot.py +0 -0
  417. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/test_ansible_templates.py +0 -0
  418. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/test_host_model.py +0 -0
  419. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/__init__.py +0 -0
  420. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/_pairing_support.py +0 -0
  421. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/conftest.py +0 -0
  422. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_backpressure.py +0 -0
  423. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_check.py +0 -0
  424. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_csp.py +0 -0
  425. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_discovery.py +0 -0
  426. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_health_states.py +0 -0
  427. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_hosts_mapping.py +0 -0
  428. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_lazy_import.py +0 -0
  429. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_log_redaction.py +0 -0
  430. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_mint_gating.py +0 -0
  431. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_operator_auth.py +0 -0
  432. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_pairing.py +0 -0
  433. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_pairing_origin.py +0 -0
  434. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_setup_api.py +0 -0
  435. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_setup_auth.py +0 -0
  436. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_setup_dormancy.py +0 -0
  437. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_state.py +0 -0
  438. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_terminal_resize.py +0 -0
  439. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_terminals_api.py +0 -0
  440. {remo_cli-2.2.0rc9 → remo_cli-2.2.0rc10}/tests/unit/web/test_tokens.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: remo-cli
3
- Version: 2.2.0rc9
3
+ Version: 2.2.0rc10
4
4
  Summary: Remote development environment CLI
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -100,8 +100,11 @@ The SPA is a two-pane **web console**:
100
100
  target as a grid.
101
101
  - **Terminal pane** (right). Clicking a row opens that target **solo** (single view); ⌘/Ctrl-click a
102
102
  row (or its `+` button) **adds** it to a responsive grid (1/2/3 columns by count). In a grid, **drag
103
- a tile's header onto another to swap their positions** (the arrangement persists until the grid is
104
- rebuilt); the **◻** control solos a tile; **Esc** collapses the grid back to the focused terminal;
103
+ a tile's header onto another to swap their positions** a window outline follows the cursor and the
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, **hovering a tile focuses it**
106
+ (focus-follows-mouse) so keystrokes go where the pointer is — no click needed. The **◻** control solos
107
+ a tile; **Esc** collapses the grid back to the focused terminal;
105
108
  number keys **1–9** jump to the numbered sessions (⌘ 1–9 add to the grid). Hidden terminals stay
106
109
  connected and keep their scrollback. Each terminal header shows `provider · instance · region`
107
110
  (doubling as the drag handle), connection state, and a
@@ -8,6 +8,7 @@
8
8
  "name": "remo-web-frontend",
9
9
  "version": "0.0.0",
10
10
  "dependencies": {
11
+ "@dnd-kit/core": "^6.3.1",
11
12
  "@fontsource/fira-code": "^5.2.7",
12
13
  "@fontsource/ibm-plex-mono": "^5.2.7",
13
14
  "@fontsource/jetbrains-mono": "^5.2.8",
@@ -559,6 +560,45 @@
559
560
  "node": ">=20.19.0"
560
561
  }
561
562
  },
563
+ "node_modules/@dnd-kit/accessibility": {
564
+ "version": "3.1.1",
565
+ "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
566
+ "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==",
567
+ "license": "MIT",
568
+ "dependencies": {
569
+ "tslib": "^2.0.0"
570
+ },
571
+ "peerDependencies": {
572
+ "react": ">=16.8.0"
573
+ }
574
+ },
575
+ "node_modules/@dnd-kit/core": {
576
+ "version": "6.3.1",
577
+ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
578
+ "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
579
+ "license": "MIT",
580
+ "dependencies": {
581
+ "@dnd-kit/accessibility": "^3.1.1",
582
+ "@dnd-kit/utilities": "^3.2.2",
583
+ "tslib": "^2.0.0"
584
+ },
585
+ "peerDependencies": {
586
+ "react": ">=16.8.0",
587
+ "react-dom": ">=16.8.0"
588
+ }
589
+ },
590
+ "node_modules/@dnd-kit/utilities": {
591
+ "version": "3.2.2",
592
+ "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
593
+ "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
594
+ "license": "MIT",
595
+ "dependencies": {
596
+ "tslib": "^2.0.0"
597
+ },
598
+ "peerDependencies": {
599
+ "react": ">=16.8.0"
600
+ }
601
+ },
562
602
  "node_modules/@esbuild/aix-ppc64": {
563
603
  "version": "0.21.5",
564
604
  "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
@@ -3462,6 +3502,12 @@
3462
3502
  "node": ">=20"
3463
3503
  }
3464
3504
  },
3505
+ "node_modules/tslib": {
3506
+ "version": "2.8.1",
3507
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
3508
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
3509
+ "license": "0BSD"
3510
+ },
3465
3511
  "node_modules/typescript": {
3466
3512
  "version": "5.9.3",
3467
3513
  "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
@@ -15,6 +15,7 @@
15
15
  "test:e2e": "playwright test --config ../playwright.config.ts"
16
16
  },
17
17
  "dependencies": {
18
+ "@dnd-kit/core": "^6.3.1",
18
19
  "@fontsource/fira-code": "^5.2.7",
19
20
  "@fontsource/ibm-plex-mono": "^5.2.7",
20
21
  "@fontsource/jetbrains-mono": "^5.2.8",
@@ -53,20 +53,54 @@
53
53
  .terminal-card--grid .terminal-card-grip {
54
54
  gap: 8px;
55
55
  }
56
- .terminal-card-grip[draggable="true"] {
56
+ .terminal-card-grip--handle {
57
57
  cursor: grab;
58
+ touch-action: none; /* let the TouchSensor own press-and-hold drags */
58
59
  }
59
- .terminal-card-grip[draggable="true"]:active {
60
+ .terminal-card-grip--handle:active {
60
61
  cursor: grabbing;
61
62
  }
62
63
 
63
- /* Reorder drag feedback. */
64
+ /* Reorder drag feedback. The source tile dims; the tile the drop will land on
65
+ * (swap target) gets a bold dashed outline showing where the window will go. */
64
66
  .terminal-card--dragging {
65
- opacity: 0.5;
67
+ opacity: 0.4;
66
68
  }
67
69
  .terminal-card--drop-target {
68
- border-color: color-mix(in oklch, var(--accent) 65%, var(--border));
69
- box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 22%, transparent);
70
+ outline: 2px dashed color-mix(in oklch, var(--accent) 85%, white);
71
+ outline-offset: -3px;
72
+ background: color-mix(in oklch, var(--accent) 12%, var(--bg-term));
73
+ }
74
+
75
+ /* The floating window-outline ghost rendered in the dnd-kit DragOverlay while
76
+ * dragging. Fills the overlay box (sized to the dragged tile), so it reads as
77
+ * the window itself following the cursor. */
78
+ .terminal-drag-ghost {
79
+ width: 100%;
80
+ height: 100%;
81
+ box-sizing: border-box;
82
+ display: flex;
83
+ align-items: flex-start;
84
+ border-radius: var(--radius-lg);
85
+ border: 2px dashed color-mix(in oklch, var(--accent) 80%, white);
86
+ background: color-mix(in oklch, var(--accent) 16%, transparent);
87
+ box-shadow: 0 12px 30px oklch(0 0 0 / 0.35);
88
+ cursor: grabbing;
89
+ overflow: hidden;
90
+ }
91
+ .terminal-drag-ghost-title {
92
+ margin: 8px 12px;
93
+ padding: 3px 10px;
94
+ font-family: var(--font-mono);
95
+ font-weight: 600;
96
+ font-size: 12px;
97
+ color: var(--text);
98
+ background: color-mix(in oklch, var(--bg-header) 85%, transparent);
99
+ border-radius: 6px;
100
+ white-space: nowrap;
101
+ overflow: hidden;
102
+ text-overflow: ellipsis;
103
+ max-width: calc(100% - 24px);
70
104
  }
71
105
 
72
106
  .terminal-card-provider-dot {
@@ -10,6 +10,7 @@
10
10
  // terminal surface (which would tear down the live connection).
11
11
 
12
12
  import { useCallback, useEffect, useRef, useState } from "react";
13
+ import { useDraggable, useDroppable } from "@dnd-kit/core";
13
14
  import type { SessionTarget, TypedError } from "../api/client";
14
15
  import { providerMeta } from "./providerMeta";
15
16
  import {
@@ -42,18 +43,6 @@ export type TerminalCardMode = "single" | "grid";
42
43
  * Drives the window-control cluster's active/disabled state. */
43
44
  export type TerminalViewState = "normal" | "grid" | "fullscreen";
44
45
 
45
- /** Drag-to-reorder wiring for a grid tile. Present only when reordering is
46
- * possible (a grid of two-plus); the header acts as the drag handle and the
47
- * whole tile is a drop target — dropping swaps the two tiles' positions. */
48
- export interface TerminalReorder {
49
- isDragging: boolean;
50
- isDropTarget: boolean;
51
- onDragStart: () => void;
52
- onDragEnter: () => void;
53
- onDrop: () => void;
54
- onDragEnd: () => void;
55
- }
56
-
57
46
  interface TerminalCardProps {
58
47
  target: SessionTarget;
59
48
  /** Registry region for this target's instance (badge only). */
@@ -66,8 +55,9 @@ interface TerminalCardProps {
66
55
  /** The display mode this card is currently in (window-control cluster state). */
67
56
  viewState: TerminalViewState;
68
57
  onClose: () => void;
69
- /** Drag-to-reorder wiring; present only for a reorderable grid tile. */
70
- reorder?: TerminalReorder;
58
+ /** When true, the header acts as a dnd-kit drag handle and the tile is a drop
59
+ * target (grid reorder). The DndContext + swap live in WorkspacePane. */
60
+ reorderEnabled?: boolean;
71
61
  /** Window-control "Normal": solo this terminal into the single view. */
72
62
  onNormal: () => void;
73
63
  /** Window-control "Grid": show the grid — omitted when none is available. */
@@ -76,6 +66,9 @@ interface TerminalCardProps {
76
66
  onToggleFullscreen: () => void;
77
67
  /** Called when the user clicks into the surface (focus this terminal). */
78
68
  onFocusRequest?: () => void;
69
+ /** Focus-follows-mouse: called when the pointer enters this tile (grid only),
70
+ * so hovering changes focus without a click. No-op'd mid-drag by the caller. */
71
+ onHoverFocus?: () => void;
79
72
  /** Called when output arrives while this card is hidden (rail activity dot). */
80
73
  onActivity?: () => void;
81
74
  /** Called when the remote process exits (session may have ended) or the
@@ -100,11 +93,12 @@ export function TerminalCard({
100
93
  isFocused,
101
94
  viewState,
102
95
  onClose,
103
- reorder,
96
+ reorderEnabled,
104
97
  onNormal,
105
98
  onGrid,
106
99
  onToggleFullscreen,
107
100
  onFocusRequest,
101
+ onHoverFocus,
108
102
  onActivity,
109
103
  onEnded,
110
104
  }: TerminalCardProps): JSX.Element {
@@ -130,6 +124,22 @@ export function TerminalCard({
130
124
  const [needsManualReconnect, setNeedsManualReconnect] = useState(false);
131
125
  const [error, setError] = useState<TypedError | null>(null);
132
126
 
127
+ // dnd-kit reorder: the tile is both a draggable (handle = header grip, below)
128
+ // and a droppable (swap target). Disabled outside a reorderable grid. We use
129
+ // the DragOverlay pattern (WorkspacePane), so the source stays put (dimmed)
130
+ // and we never apply `draggable.transform`.
131
+ const draggable = useDraggable({ id: target.id, disabled: !reorderEnabled });
132
+ const droppable = useDroppable({ id: target.id, disabled: !reorderEnabled });
133
+ const setDraggableRef = draggable.setNodeRef;
134
+ const setDroppableRef = droppable.setNodeRef;
135
+ const setTileRef = useCallback(
136
+ (node: HTMLDivElement | null) => {
137
+ setDraggableRef(node);
138
+ setDroppableRef(node);
139
+ },
140
+ [setDraggableRef, setDroppableRef],
141
+ );
142
+
133
143
  useEffect(() => {
134
144
  isFocusedRef.current = isFocused;
135
145
  }, [isFocused]);
@@ -299,38 +309,29 @@ export function TerminalCard({
299
309
  const prov = providerMeta(target.instance_type);
300
310
  const badge = [prov.label, target.instance_name, region].filter(Boolean).join(" · ");
301
311
 
302
- const dragClasses = reorder
303
- ? `${reorder.isDragging ? " terminal-card--dragging" : ""}${reorder.isDropTarget ? " terminal-card--drop-target" : ""}`
304
- : "";
312
+ const isDragging = draggable.isDragging;
313
+ // Highlight the tile the drop will land on (swap target) but not the source.
314
+ const isDropTarget = Boolean(reorderEnabled) && droppable.isOver && !isDragging;
315
+ const dragClasses = `${isDragging ? " terminal-card--dragging" : ""}${isDropTarget ? " terminal-card--drop-target" : ""}`;
305
316
 
306
317
  return (
307
318
  <div
319
+ ref={setTileRef}
308
320
  className={`terminal-card terminal-card--${mode}${isFocused ? " terminal-card--focused" : ""}${dragClasses}`}
309
321
  data-testid={`terminal-card-${target.id}`}
310
322
  data-focused={isFocused}
311
323
  data-connection-state={connectionState}
312
324
  style={{ display: isVisible ? undefined : "none" }}
313
- // Whole tile is the drop target for a reorder drag (see the header grip).
314
- onDragOver={reorder ? (e) => e.preventDefault() : undefined}
315
- onDragEnter={reorder ? (e) => { e.preventDefault(); reorder.onDragEnter(); } : undefined}
316
- onDrop={reorder ? (e) => { e.preventDefault(); reorder.onDrop(); } : undefined}
325
+ onMouseEnter={onHoverFocus}
317
326
  >
318
327
  <header className="terminal-card-header">
319
328
  {/* The header (left of the controls) is the drag handle for reordering
320
329
  * grid tiles; it no longer solos on click — the ◻ control does that. */}
321
330
  <div
322
- className="terminal-card-grip"
323
- draggable={reorder ? true : undefined}
324
- onDragStart={
325
- reorder
326
- ? (e) => {
327
- e.dataTransfer.setData("text/plain", target.id);
328
- e.dataTransfer.effectAllowed = "move";
329
- reorder.onDragStart();
330
- }
331
- : undefined
332
- }
333
- onDragEnd={reorder ? () => reorder.onDragEnd() : undefined}
331
+ ref={reorderEnabled ? draggable.setActivatorNodeRef : undefined}
332
+ className={`terminal-card-grip${reorderEnabled ? " terminal-card-grip--handle" : ""}`}
333
+ {...(reorderEnabled ? draggable.listeners : {})}
334
+ {...(reorderEnabled ? draggable.attributes : {})}
334
335
  >
335
336
  <span className="terminal-card-provider-dot" style={{ background: prov.color }} />
336
337
  <div className="terminal-card-identity">
@@ -3,6 +3,18 @@
3
3
  // laid out as a single view (one visible) or a responsive grid (two-plus).
4
4
 
5
5
  import { useMemo, useState } from "react";
6
+ import {
7
+ DndContext,
8
+ DragOverlay,
9
+ KeyboardSensor,
10
+ PointerSensor,
11
+ TouchSensor,
12
+ closestCenter,
13
+ useSensor,
14
+ useSensors,
15
+ type DragEndEvent,
16
+ type DragStartEvent,
17
+ } from "@dnd-kit/core";
6
18
  import type { SessionTarget } from "../api/client";
7
19
  import { requestBrowserFullscreen } from "../lib/fullscreen";
8
20
  import { useWorkspace } from "../state/workspace";
@@ -46,10 +58,16 @@ export function WorkspacePane({
46
58
  const workspace = useWorkspace();
47
59
  const { attached, visible, focusedId, prevGrid, maximizedId } = workspace;
48
60
 
49
- // Transient drag-to-reorder state (which tile is being dragged, and which it's
50
- // hovering over). Not persisted — only the resulting order (`visible`) is.
51
- const [dragId, setDragId] = useState<string | null>(null);
52
- const [overId, setOverId] = useState<string | null>(null);
61
+ // dnd-kit reorder: `activeId` is the tile currently being dragged (drives the
62
+ // floating DragOverlay ghost). Only the resulting order (`visible`) persists.
63
+ const [activeId, setActiveId] = useState<string | null>(null);
64
+ const sensors = useSensors(
65
+ // A small move starts a drag, so plain clicks (buttons, focus) still work.
66
+ useSensor(PointerSensor, { activationConstraint: { distance: 6 } }),
67
+ // Touch: a short press-and-hold starts a drag, leaving taps/scroll intact.
68
+ useSensor(TouchSensor, { activationConstraint: { delay: 180, tolerance: 8 } }),
69
+ useSensor(KeyboardSensor),
70
+ );
53
71
 
54
72
  // Render visible tiles in `visible` order (so the grid layout follows the
55
73
  // reorderable order + the number badges), then the hidden-but-attached cards
@@ -111,69 +129,85 @@ export function WorkspacePane({
111
129
 
112
130
  // Reordering is possible only within a real grid (two-plus visible tiles).
113
131
  const reorderable = !maximized && mode === "grid" && visible.length > 1;
114
- const clearDrag = (): void => {
115
- setDragId(null);
116
- setOverId(null);
132
+ const activeTarget = activeId ? targetsById.get(activeId) : undefined;
133
+
134
+ const onDragStart = (e: DragStartEvent): void => setActiveId(String(e.active.id));
135
+ const onDragEnd = (e: DragEndEvent): void => {
136
+ const { active, over } = e;
137
+ setActiveId(null);
138
+ if (over && active.id !== over.id) {
139
+ workspace.swapVisible(String(active.id), String(over.id));
140
+ }
117
141
  };
118
142
 
119
143
  return (
120
144
  <main className="workspace" data-testid="workspace">
121
- <div
122
- className={`workspace-body workspace-body--${mode}${maximized ? " workspace-body--maximized" : ""}`}
123
- style={
124
- mode === "grid"
125
- ? {
126
- gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))`,
127
- gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`,
128
- }
129
- : undefined
130
- }
145
+ <DndContext
146
+ sensors={sensors}
147
+ collisionDetection={closestCenter}
148
+ onDragStart={onDragStart}
149
+ onDragEnd={onDragEnd}
150
+ onDragCancel={() => setActiveId(null)}
131
151
  >
132
- {orderedTargets.map((target) => {
133
- const id = target.id;
134
- const isVisible = maximized ? id === maximized : visible.includes(id);
135
- const viewState = maximized === id ? "fullscreen" : mode === "grid" ? "grid" : "normal";
136
- const reorder =
137
- reorderable && isVisible
152
+ <div
153
+ className={`workspace-body workspace-body--${mode}${maximized ? " workspace-body--maximized" : ""}`}
154
+ style={
155
+ mode === "grid"
138
156
  ? {
139
- isDragging: dragId === id,
140
- isDropTarget: overId === id && dragId !== null && dragId !== id,
141
- onDragStart: () => setDragId(id),
142
- onDragEnter: () => {
143
- if (dragId && dragId !== id) {
144
- setOverId(id);
145
- }
146
- },
147
- onDrop: () => {
148
- if (dragId && dragId !== id) {
149
- workspace.swapVisible(dragId, id);
150
- }
151
- clearDrag();
152
- },
153
- onDragEnd: clearDrag,
157
+ gridTemplateColumns: `repeat(${cols}, minmax(0, 1fr))`,
158
+ gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`,
154
159
  }
155
- : undefined;
156
- return (
157
- <TerminalCard
158
- key={id}
159
- target={target}
160
- region={regionByKey.get(`${target.instance_type}::${target.instance_name}`)}
161
- mode={mode}
162
- isVisible={isVisible}
163
- isFocused={focusedId === id}
164
- viewState={viewState}
165
- reorder={reorder}
166
- onClose={() => workspace.closeTerm(id)}
167
- onNormal={() => workspace.soloTile(id)}
168
- onGrid={canGrid ? workspace.backToGrid : undefined}
169
- onToggleFullscreen={() => toggleFullscreen(id)}
170
- onFocusRequest={() => workspace.setFocused(id)}
171
- onActivity={() => workspace.markUnread(id)}
172
- onEnded={() => onTerminalEnded(target)}
173
- />
174
- );
175
- })}
176
- </div>
160
+ : undefined
161
+ }
162
+ >
163
+ {orderedTargets.map((target) => {
164
+ const id = target.id;
165
+ const isVisible = maximized ? id === maximized : visible.includes(id);
166
+ const viewState =
167
+ maximized === id ? "fullscreen" : mode === "grid" ? "grid" : "normal";
168
+ return (
169
+ <TerminalCard
170
+ key={id}
171
+ target={target}
172
+ region={regionByKey.get(`${target.instance_type}::${target.instance_name}`)}
173
+ mode={mode}
174
+ isVisible={isVisible}
175
+ isFocused={focusedId === id}
176
+ viewState={viewState}
177
+ reorderEnabled={reorderable && isVisible}
178
+ onClose={() => workspace.closeTerm(id)}
179
+ onNormal={() => workspace.soloTile(id)}
180
+ onGrid={canGrid ? workspace.backToGrid : undefined}
181
+ onToggleFullscreen={() => toggleFullscreen(id)}
182
+ onFocusRequest={() => workspace.setFocused(id)}
183
+ onHoverFocus={
184
+ mode === "grid" && !maximized
185
+ ? () => {
186
+ // Focus-follows-mouse: hovering a grid tile focuses it,
187
+ // but never while dragging (would fight the reorder).
188
+ if (!activeId && focusedId !== id) {
189
+ workspace.setFocused(id);
190
+ }
191
+ }
192
+ : undefined
193
+ }
194
+ onActivity={() => workspace.markUnread(id)}
195
+ onEnded={() => onTerminalEnded(target)}
196
+ />
197
+ );
198
+ })}
199
+ </div>
200
+
201
+ {/* Floating "window outline" ghost that follows the cursor while dragging
202
+ * a grid tile. dropAnimation off — the tiles swap instantly on drop. */}
203
+ <DragOverlay dropAnimation={null}>
204
+ {activeTarget ? (
205
+ <div className="terminal-drag-ghost" aria-hidden="true">
206
+ <span className="terminal-drag-ghost-title">{activeTarget.project}</span>
207
+ </div>
208
+ ) : null}
209
+ </DragOverlay>
210
+ </DndContext>
177
211
  </main>
178
212
  );
179
213
  }
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "remo-cli"
7
- version = "2.2.0rc9"
7
+ version = "2.2.0rc10"
8
8
  description = "Remote development environment CLI"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1038,7 +1038,7 @@ wheels = [
1038
1038
 
1039
1039
  [[package]]
1040
1040
  name = "remo-cli"
1041
- version = "2.2.0rc9"
1041
+ version = "2.2.0rc10"
1042
1042
  source = { editable = "." }
1043
1043
  dependencies = [
1044
1044
  { name = "ansible-core" },
File without changes
File without changes