remo-cli 3.1.0__tar.gz → 4.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.devcontainer/devcontainer.json +10 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/release-please.yml +37 -0
- remo_cli-4.0.0/.release-please-manifest.json +3 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/AGENTS.md +4 -5
- {remo_cli-3.1.0 → remo_cli-4.0.0}/CHANGELOG.md +29 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/CLAUDE.md +6 -6
- {remo_cli-3.1.0 → remo_cli-4.0.0}/CONTRIBUTING.md +6 -3
- {remo_cli-3.1.0 → remo_cli-4.0.0}/PKG-INFO +2 -2
- {remo_cli-3.1.0 → remo_cli-4.0.0}/README.md +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/aws_configure.yml +6 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/aws_site.yml +6 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/hetzner_configure.yml +6 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/hetzner_site.yml +6 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/incus_configure.yml +13 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/incus_site.yml +13 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/proxmox_bootstrap.yml +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/proxmox_configure.yml +13 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/proxmox_site.yml +13 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/nodejs/tasks/main.yml +7 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container/defaults/main.yml +6 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container/tasks/main.yml +41 -5
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container/tasks/preflight.yml +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/user_setup/defaults/main.yml +9 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/user_setup/tasks/main.yml +85 -22
- remo_cli-4.0.0/ansible/roles/zellij/defaults/main.yml +27 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/zellij/tasks/main.yml +39 -8
- remo_cli-4.0.0/ansible/tasks/repair_apt_sources.yml +72 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/providers.md +2 -2
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/proxmox.md +37 -30
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/web-session-interface.md +67 -17
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/package-lock.json +0 -7
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/package.json +0 -2
- remo_cli-4.0.0/frontend/src/api/client.test.ts +182 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/api/client.ts +132 -72
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/api/generated/openapi.json +6 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/api/generated/schema.d.ts +9 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/AppShell.tsx +38 -3
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/OfflineOverlay.css +6 -6
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/SessionRail.css +9 -9
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/SessionRail.tsx +5 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/SettingsPage.css +52 -3
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/SettingsPage.tsx +124 -35
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/ShortcutsModal.css +2 -2
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/TerminalCard.css +112 -11
- remo_cli-4.0.0/frontend/src/components/TerminalCard.test.tsx +198 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/TerminalCard.tsx +145 -10
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/TopBar.tsx +32 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/WorkspacePane.tsx +3 -0
- remo_cli-4.0.0/frontend/src/components/railModel.test.ts +121 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/railModel.ts +18 -3
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/main.tsx +5 -8
- remo_cli-4.0.0/frontend/src/state/discovery.test.ts +105 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/discovery.ts +50 -6
- remo_cli-4.0.0/frontend/src/state/health.test.ts +77 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/health.ts +14 -1
- remo_cli-4.0.0/frontend/src/state/settings.test.ts +281 -0
- remo_cli-4.0.0/frontend/src/state/settings.ts +379 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/terminal/RendererAdapter.ts +45 -12
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/terminal/XtermRenderer.ts +19 -7
- remo_cli-4.0.0/frontend/src/terminal/defaultRenderer.ts +26 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/terminal/keymap.ts +2 -2
- remo_cli-4.0.0/frontend/src/theme/terminalThemes.test.ts +146 -0
- remo_cli-4.0.0/frontend/src/theme/terminalThemes.ts +362 -0
- remo_cli-4.0.0/frontend/src/theme/tokens.css +201 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/playwright.config.ts +2 -2
- {remo_cli-3.1.0 → remo_cli-4.0.0}/pyproject.toml +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/providers/factory.py +2 -2
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/shell.py +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/provider_registry.py +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/registry.py +8 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/web_adopt.py +167 -18
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/hetzner.py +8 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/incus.py +11 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/proxmox.py +68 -65
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/proxmox_descriptor.py +17 -14
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/api/hosts.py +13 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/app.py +9 -8
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/discovery.py +6 -1
- remo_cli-4.0.0/tests/ansible/test_apt_sources_repair.py +253 -0
- remo_cli-4.0.0/tests/ansible/test_authorized_keys_bootstrap.py +298 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/e2e/fixtures.ts +4 -26
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/e2e/keyboard-routing.spec.ts +2 -2
- remo_cli-3.1.0/tests/e2e/ghostty-shell-io.spec.ts → remo_cli-4.0.0/tests/e2e/terminal-shell-io.spec.ts +15 -21
- remo_cli-3.1.0/tests/e2e/ghostty-tui-compatibility.spec.ts → remo_cli-4.0.0/tests/e2e/terminal-tui-compatibility.spec.ts +6 -10
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/providers/test_proxmox_sync_all.py +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/surface_baseline.py +9 -9
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_registry_migration.py +2 -2
- remo_cli-4.0.0/tests/unit/core/test_web_push_self_heal.py +419 -0
- remo_cli-4.0.0/tests/unit/providers/test_host_user_consistency.py +289 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_provider_registry_entries.py +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_proxmox_marker.py +6 -6
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_proxmox_provider_protocol.py +1 -1
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_proxmox_resize.py +4 -4
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_proxmox_snapshot.py +17 -2
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_proxmox_sync.py +41 -16
- remo_cli-4.0.0/tests/unit/test_lockfile_version.py +55 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_csp.py +8 -5
- remo_cli-4.0.0/tests/unit/web/test_discovery_refresh_force.py +92 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/uv.lock +1 -1
- remo_cli-3.1.0/.release-please-manifest.json +0 -3
- remo_cli-3.1.0/ansible/roles/zellij/defaults/main.yml +0 -13
- remo_cli-3.1.0/frontend/public/README.md +0 -10
- remo_cli-3.1.0/frontend/public/dist__ghostty-vt.wasm +0 -0
- remo_cli-3.1.0/frontend/public/ghostty-vt.wasm +0 -0
- remo_cli-3.1.0/frontend/scripts/copy-ghostty-wasm.mjs +0 -86
- remo_cli-3.1.0/frontend/src/state/settings.ts +0 -236
- remo_cli-3.1.0/frontend/src/terminal/GhosttyRenderer.ts +0 -194
- remo_cli-3.1.0/frontend/src/terminal/defaultRenderer.ts +0 -65
- remo_cli-3.1.0/frontend/src/theme/tokens.css +0 -128
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/release/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-analyze/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-checklist/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-clarify/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-constitution/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-converge/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-git-commit/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-git-feature/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-git-initialize/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-git-remote/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-git-validate/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-implement/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-plan/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-specify/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-tasks/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.claude/skills/speckit-taskstoissues/SKILL.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.dockerignore +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/CODEOWNERS +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/dependabot.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/ci.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/codeql.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/dependency-review.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/dev-build.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/provision.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/release.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/smoke-test-cleanup.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/smoke-test.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.github/workflows/teardown.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.gitignore +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.maverick/checkpoints/feature/implementation_complete.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.maverick/checkpoints/feature/phase_${{ index }}_complete.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.maverick/checkpoints/feature/validation_complete.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/.registry +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/README.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/commands/speckit.git.commit.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/commands/speckit.git.feature.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/commands/speckit.git.initialize.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/commands/speckit.git.remote.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/commands/speckit.git.validate.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/config-template.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/extension.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/git-config.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/bash/create-new-feature.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/bash/git-common.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/powershell/create-new-feature.ps1 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/extensions.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/feature.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/init-options.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/integration.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/integrations/claude.manifest.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/integrations/speckit.manifest.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/memory/constitution.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/scripts/bash/check-prerequisites.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/scripts/bash/common.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/scripts/bash/create-new-feature.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/scripts/bash/setup-plan.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/scripts/bash/setup-tasks.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/scripts/bash/update-agent-context.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/templates/agent-file-template.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/templates/checklist-template.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/templates/constitution-template.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/templates/plan-template.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/templates/spec-template.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/templates/tasks-template.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/workflows/speckit/workflow.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/.specify/workflows/workflow-registry.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/Dockerfile +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/LICENSE +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/SECURITY.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/.ansible-lint +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/README.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/ansible.cfg +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/aws_resize.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/aws_teardown.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/group_vars/all.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/group_vars/incus_containers.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/group_vars/proxmox_containers.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/hetzner_provision.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/hetzner_resize.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/hetzner_teardown.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/incus_bootstrap.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/incus_provision.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/incus_resize.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/incus_teardown.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/inventory/hosts.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/inventory/incus_containers.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/proxmox_provision.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/proxmox_resize.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/proxmox_teardown.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/requirements.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/aws_server/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/aws_server/tasks/ebs.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/aws_server/tasks/ec2.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/aws_server/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/aws_server/tasks/patch_manager.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/aws_server/tasks/preflight.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/aws_server/tasks/security_group.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/deacon/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/deacon/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/devcontainers/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/docker/handlers/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/docker/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/fzf/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/github_cli/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/hetzner_server/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/hetzner_server/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_bootstrap/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_bootstrap/handlers/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_bootstrap/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container/handlers/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container/meta/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container/tasks/preflight.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container_teardown/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container_teardown/meta/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/incus_container_teardown/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/nodejs/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/nodejs/files/nodesource-repo.gpg.key +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_bootstrap/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_bootstrap/meta/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_bootstrap/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container/handlers/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container/meta/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container_teardown/defaults/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container_teardown/meta/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/proxmox_container_teardown/tasks/main.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/user_setup/templates/devshell.sh.j2 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/user_setup/templates/project-launch.sh.j2 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/user_setup/templates/project-menu.sh.j2 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/user_setup/templates/remo-host.sh.j2 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/zellij/templates/config.kdl.j2 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/roles/zellij/templates/layouts/minimal.kdl.j2 +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/ansible/tasks/configure_dev_tools.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docker/Dockerfile +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docker/compose.example.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docker/entrypoint.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/aws.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/feature-history.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/hetzner.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/incus.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/install.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/maintaining-claude-md.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/maintaining-generated-types.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/remo-web-speckit-input.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/docs/remo-web.html +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/index.html +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/scripts/check-types-fresh.mjs +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/scripts/generate-frame-types.mjs +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/scripts/generate-schema-types.mjs +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/api/generated/README.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/api/generated/terminal-frames.d.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/api/generated/terminal-frames.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/api/generated.test.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/AppRoot.tsx +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/AppShell.css +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/AwaitingAdoption.css +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/AwaitingAdoption.tsx +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/OfflineOverlay.tsx +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/PairToSync.css +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/PairToSync.tsx +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/ShortcutsModal.tsx +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/TopBar.css +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/WorkspacePane.css +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/providerMeta.test.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/components/providerMeta.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/lib/clipboard.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/lib/fullscreen.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/fonts.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/latency.test.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/latency.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/useConsoleKeyboard.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/workspace.test.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/state/workspace.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/terminal/.gitkeep +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/terminal/TerminalConnection.test.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/terminal/TerminalConnection.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/terminal/keymap.test.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/test/setup.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/src/theme/fonts.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/tsconfig.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/frontend/vite.config.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/install.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/maverick.yaml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/project-menu.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/release-please-config.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/remo +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/remo.svg +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/run.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/scripts/export_openapi.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/scripts/setup-aws-oidc.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/checklists/validation.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/contracts/playbook-interface.yaml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/contracts/role-interface.yaml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/001-bootstrap-incus-host/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/contracts/playbook-interface.yaml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/contracts/role-interface.yaml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/002-incus-container-support/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/003-python-cli-rewrite/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/003-python-cli-rewrite/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/003-python-cli-rewrite/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/003-python-cli-rewrite/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/003-python-cli-rewrite/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/003-python-cli-rewrite/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/003-python-cli-rewrite/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/004-proxmox-container-support/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/contracts/cli-surface.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/005-provider-snapshots/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/contracts/remo-host-protocol.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/contracts/rest-api.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/contracts/terminal-websocket.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/010-web-session-interface/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/contracts/cli-web-adopt.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/contracts/setup-api.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/quickstart-results.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/011-web-adopt/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/contracts/cli-web-adopt.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/contracts/pairing-api.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/contracts/setup-api.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/012-web-adopt-pairing/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/contracts/cli-sync.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/contracts/marker-commands.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/013-managed-instance-tags/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/contracts/add-command.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/contracts/remove-command.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/014-register-ssh-host/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/contracts/mirror-payload-v2.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/contracts/registry-accessor-api.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/contracts/registry-file-v2.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/015-registry-v2/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/contracts/cli-sync.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/contracts/provider-probe.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/016-sync-reconcile/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/contracts/cli-web-push.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/contracts/cli-web-status.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/contracts/revocation.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/contracts/setup-status-marker.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/017-web-adopt-simplify/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/baseline-notes.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/contracts/cli-surface.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/contracts/errors.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/contracts/lifecycle-templates.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/contracts/provider-protocol.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/contracts/sync-merge.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/018-provider-abstraction/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/contracts/cli-surface-delta.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/contracts/docs-structure-check.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/019-hygiene-deps-docs/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/checklists/requirements.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/contracts/drift-checks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/contracts/terminal-frames-v1.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/020-openapi-type-generation/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/contracts/cli-surface.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/contracts/descriptor-schema.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/data-model.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/plan.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/quickstart.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/research.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/spec.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/specs/021-cli-plane-separation/tasks.md +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/__main__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/added.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/cp.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/main.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/providers/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/cli/web.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/ansible_runner.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/completion.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/config.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/errors.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/known_hosts.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/lifecycle.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/output.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/picker.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/provider_protocol.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/reconcile.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/remo_host_client.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/rsync.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/ssh.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/validation.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/version.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/core/web_drift.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/models/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/models/capability.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/models/discovery.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/models/host.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/models/session_target.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/models/snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/added.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/aws.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/aws_descriptor.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/builtin.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/hetzner_descriptor.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/providers/incus_descriptor.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/api/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/api/pairing.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/api/setup.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/api/terminals.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/check.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/config.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/frames.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/health.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/logging_config.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/models.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/operator_auth.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/pairing.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/ssh_master.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/state.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/terminal.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/terminal_registry.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/src/remo_cli/web/tokens.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/ansible/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/ansible/test_remo_host_idempotency.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/conftest.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/e2e/mobile.spec.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/e2e/reconnect.spec.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/e2e/workspace-layout.spec.ts +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/image/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/image/test_docker_image.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/_nine_terminal_fixture.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/fish_completion.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/orbstack-cloud-init.yml +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/orbstack.sh +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_nine_terminals.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_nine_terminals_soak.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_registry_concurrency.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_remo_host_e2e.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_security_rejections.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_setup_payload_versions.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_sync_reconcile.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_terminal_attach.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_web_adopt_e2e.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/integration/test_web_cli_parity.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/perf/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/perf/test_latency.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/perf/test_registry_perf.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/providers/test_aws_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/providers/test_hetzner_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/providers/test_incus_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/providers/test_incus_sync_all.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/providers/test_proxmox_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_add_cmd.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_cli_uniformity.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_cp.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_main.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_remove_cmd.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_shell.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_shell_added.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_startup_imports.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_surface_preservation.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/cli/test_web_adopt_cmd.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_ansible_runner.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_completion.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_config.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_errors.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_known_hosts.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_lifecycle.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_migration_tagging_notice.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_output.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_picker.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_provider_registry.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_reconcile.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_registry_format.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_registry_locking.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_remo_host_client.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_rsync.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_ssh.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_ssh_added.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_ssh_controlpath.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_ssh_identity_opts.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_validation.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_version.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_web_adopt_authorize.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_web_adopt_code.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_web_adopt_payload.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_web_adopt_trust.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_web_drift.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/core/test_web_push.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/models/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/models/test_capability.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/models/test_discovery.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/models/test_session_target.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/fake_provider.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_added_add.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_added_provider_guard.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_added_update_remove.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_added_verify.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_aws_provider_protocol.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_aws_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_aws_sync.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_aws_upgrade_resize.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_hetzner_entry_adapters.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_hetzner_http.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_hetzner_label.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_hetzner_resize.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_hetzner_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_hetzner_sync.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_incus_entry_adapters.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_incus_marker.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_incus_resize.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_incus_snapshot.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_incus_sync.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_missing_sdk.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_provider_conformance.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/providers/test_proxmox_devcontainer_runtime.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/test_ansible_templates.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/test_architecture.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/test_docs_structure.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/test_host_model.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/test_host_ssh_type.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/test_schema_drift.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/__init__.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/_pairing_support.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/conftest.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/fixtures/hosts_response.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/fixtures/sessions_response.json +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_backpressure.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_check.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_discovery.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_frames.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_health_states.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_hosts_mapping.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_lazy_import.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_log_redaction.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_mint_gating.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_operator_auth.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_pairing.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_pairing_origin.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_payload_equivalence.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_registry_readonly.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_setup_api.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_setup_auth.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_setup_dormancy.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_state.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_terminal_resize.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_terminals_api.py +0 -0
- {remo_cli-3.1.0 → remo_cli-4.0.0}/tests/unit/web/test_tokens.py +0 -0
|
@@ -27,6 +27,16 @@
|
|
|
27
27
|
"remoteEnv": {
|
|
28
28
|
"GH_PAGER": ""
|
|
29
29
|
},
|
|
30
|
+
"containerEnv": {
|
|
31
|
+
// Put Claude Code's config INSIDE the mounted ~/.claude directory.
|
|
32
|
+
// By default the config lives at ~/.claude.json, OUTSIDE that mount, so
|
|
33
|
+
// every container starts unauthenticated even though .credentials.json is
|
|
34
|
+
// shared. Bind-mounting the file directly does not work: a file bind pins
|
|
35
|
+
// to the inode, so the first atomic rewrite orphans the container's view
|
|
36
|
+
// and silently discards writes. Relocating into the directory mount avoids
|
|
37
|
+
// that entirely and shares auth across every devcontainer on the host.
|
|
38
|
+
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude"
|
|
39
|
+
},
|
|
30
40
|
"customizations": {
|
|
31
41
|
"vscode": {
|
|
32
42
|
"settings": {
|
|
@@ -43,6 +43,7 @@ jobs:
|
|
|
43
43
|
private-key: ${{ secrets.RELEASE_PLEASE_APP_KEY }}
|
|
44
44
|
|
|
45
45
|
- uses: googleapis/release-please-action@v4
|
|
46
|
+
id: release
|
|
46
47
|
with:
|
|
47
48
|
# Token precedence:
|
|
48
49
|
# 1. GitHub App installation token (recommended — see above).
|
|
@@ -55,3 +56,39 @@ jobs:
|
|
|
55
56
|
token: ${{ steps.app-token.outputs.token || secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
|
56
57
|
config-file: release-please-config.json
|
|
57
58
|
manifest-file: .release-please-manifest.json
|
|
59
|
+
|
|
60
|
+
# release-please bumps `pyproject.toml` but knows nothing about uv.lock,
|
|
61
|
+
# which records the project's own version in its `remo-cli` package entry.
|
|
62
|
+
# Left alone the two drift apart at every release (3.1.0 shipped with a
|
|
63
|
+
# lockfile still saying 3.0.0), and the drift then reappears as noise in
|
|
64
|
+
# the next unrelated PR, because any `uv run` regenerates it.
|
|
65
|
+
#
|
|
66
|
+
# Amend the sync onto the release PR itself. release-please force-pushes
|
|
67
|
+
# its branch whenever it refreshes the PR, which would drop this commit —
|
|
68
|
+
# but this job runs immediately after that refresh on every push to main,
|
|
69
|
+
# so the commit is simply re-made. `tests/unit/test_lockfile_version.py`
|
|
70
|
+
# is the backstop that keeps a drifted lockfile from merging at all.
|
|
71
|
+
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
|
|
72
|
+
if: ${{ steps.release.outputs.pr }}
|
|
73
|
+
|
|
74
|
+
- name: Sync uv.lock onto the release PR
|
|
75
|
+
if: ${{ steps.release.outputs.pr }}
|
|
76
|
+
env:
|
|
77
|
+
RELEASE_BRANCH: ${{ fromJSON(steps.release.outputs.pr).headBranchName }}
|
|
78
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.RELEASE_PLEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
|
79
|
+
run: |
|
|
80
|
+
set -euo pipefail
|
|
81
|
+
git clone --branch "$RELEASE_BRANCH" --depth 1 \
|
|
82
|
+
"https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" release-pr
|
|
83
|
+
cd release-pr
|
|
84
|
+
# `uv lock` is not an upgrade: it re-resolves only what the manifest
|
|
85
|
+
# forces, so the sole change here is the bumped project version.
|
|
86
|
+
uv lock
|
|
87
|
+
if git diff --quiet -- uv.lock; then
|
|
88
|
+
echo "uv.lock already matches the bumped version; nothing to do."
|
|
89
|
+
exit 0
|
|
90
|
+
fi
|
|
91
|
+
git config user.name "github-actions[bot]"
|
|
92
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
93
|
+
git commit -m "chore: sync uv.lock with the released version" -- uv.lock
|
|
94
|
+
git push origin "HEAD:${RELEASE_BRANCH}"
|
|
@@ -26,13 +26,13 @@ Principles I, IV, and VIII are machine-enforced — see [Quality Gates](#quality
|
|
|
26
26
|
- Python 3.11+ + Click (CLI framework), InquirerPy (interactive picker), boto3 (unconditional runtime dependency, used by the CLI's own lazy `import boto3` in `providers/aws.py` and by the Ansible `amazon.aws`/`community.aws` collections), hcloud (unconditional runtime dependency, consumed by the Ansible layer, not the CLI's own Python code) (003-python-cli-rewrite)
|
|
27
27
|
- Versioned JSON registry (`~/.config/remo/registry.json`, format v2 — named fields per type, no positional overloading; single accessor `core/registry.py` owns parse/serialize/validate/lock/migrate for CLI, providers, and the web service). Legacy `~/.config/remo/known_hosts` (colon-delimited) is read-only migration input, lazily migrated to v2 on first CLI read and renamed to `known_hosts.v1.bak`. (003-python-cli-rewrite; superseded by 015-registry-v2)
|
|
28
28
|
- Cross-provider snapshot model (`models/snapshot.py`) + shared helpers in `core/snapshot.py` (name generator, validator, table formatter, destroy-time cleanup hook). No new runtime deps. (005-provider-snapshots)
|
|
29
|
-
- FastAPI/Uvicorn + WebSockets (backend, optional `web` extra), TypeScript/Vite/React +
|
|
29
|
+
- FastAPI/Uvicorn + WebSockets (backend, optional `web` extra), TypeScript/Vite/React + xterm.js (frontend), Bash (`remo-host` host command templated by Ansible) (010-web-session-interface)
|
|
30
30
|
- Stdlib `urllib.request` CLI setup client + token-gated `/api/v1/setup/*` FastAPI surface; service state in flat files under the writable `REMO_HOME` volume (`web-identity/` keypair + service known_hosts, `~/.config/remo/web-service.json` saved credentials, `cache_version: 2`) (011-web-adopt; payload versioning updated by 015-registry-v2)
|
|
31
31
|
- `core/registry.py`: stdlib `json` (format), `fcntl` (advisory locking via a `registry.lock` sidecar), `os.replace` (atomic writes). No new runtime deps. Setup API mirror payload moved to v2 (`contracts/mirror-payload-v2.md`) with a `payload_versions` capability handshake; an upgraded service still accepts v1 payloads. (015-registry-v2)
|
|
32
32
|
- `core/reconcile.py`: provider-agnostic sync-reconcile engine (`SyncScope`, `DiscoveredHost`, `ProbeResult`, `build_plan` (pure), `render_plan`, the consent gate, `apply_plan` via the existing `mutate_registry()`, and the `run_sync` driver). No new runtime deps — stdlib only, built on `core/registry.py`/`core/output.py` as-is. (016-sync-reconcile)
|
|
33
33
|
- `core/web_adopt.py` is now the single unified push engine (`run_push`; `run_adopt` is a thin deprecated alias) — first push adopts, later pushes re-sync, plus best-effort `remo-web@` revocation on removal, `--force` full re-authorization, and multi-workstation flap detection against the service's mirror-generation marker. `core/web_drift.py`: new stdlib-only offline registry-vs-push-cache diff (`diff_registry_against_cache`, `select_deployment`, `render_drift`) powering `remo web status` and the shared `out_of_date_notice()`/`emit_out_of_date_notice()` post-mutation nudge (importable without the `web` extra). Push cache bumped to `cache_version: 3` (`~/.config/remo/web-service.json`: per-deployment `{mirror_generation, instances}`, each instance retaining a non-secret connection tuple for revocation). Service side: `web/api/setup.py` writes/serves a `web-identity/mirror-meta.json` marker (generation + last-push descriptor) additively on `/setup/{status,registry}`; `web/state.py` mode detection fixed so a personal `~/.ssh/id_*` no longer forces `mount_configured` (non-writable `REMO_HOME` is the authoritative signal) with a new `REMO_WEB_MODE` override in `web/config.py`. No new runtime deps; no registry schema change. (017-web-adopt-simplify)
|
|
34
34
|
- No new runtime deps or registry schema change. `pyproject.toml`'s existing `hcloud`/`boto3`/`httpx2` entries gained consumer-attribution comments; `tests/unit/test_docs_structure.py` is a new stdlib-only pytest module (parses the structure diagram below, no new dependency). (019-hygiene-deps-docs)
|
|
35
|
-
- No new runtime deps; no registry schema change (the `host_user`/`node_user` JSON keys already matched the new flag spellings). `core/provider_registry.py` gains `ArgumentSpec` (positional-argument metadata) and `CommandSpec.target`; `ProviderDescriptor.update_options` is replaced by `upgrade_options`/`resize_dimensions`/`resize_options`/`tag_options`/`host_commands`. `cli/providers/factory.py` gains `_build_upgrade`/`_build_resize`/`_build_tag`/`_build_host_group` (dropping `_build_update` and flat-mounted `bootstrap`). (021-cli-plane-separation)
|
|
35
|
+
- No new runtime deps; no registry schema change (the `host_user`/`node_user` JSON keys already matched the new flag spellings). Superseded for Proxmox by the `--node-user` → `--host-user` rename: both host-scoped providers now spell the node/host login `--host-user`/`host_user` on the CLI, in the provider kwargs and in `registry.json`; `core/registry.py` still reads a legacy `proxmox.node_user` key so pre-rename registries load unchanged and migrate on the next write. `core/provider_registry.py` gains `ArgumentSpec` (positional-argument metadata) and `CommandSpec.target`; `ProviderDescriptor.update_options` is replaced by `upgrade_options`/`resize_dimensions`/`resize_options`/`tag_options`/`host_commands`. `cli/providers/factory.py` gains `_build_upgrade`/`_build_resize`/`_build_tag`/`_build_host_group` (dropping `_build_update` and flat-mounted `bootstrap`). (021-cli-plane-separation)
|
|
36
36
|
|
|
37
37
|
- Ansible 2.14+ / YAML + `ansible.builtin`, `community.general` (for zypper module) (001-bootstrap-incus-host)
|
|
38
38
|
- Formal provider abstraction: `core/provider_registry.py` (`ProviderDescriptor`/`OptionSpec`/`CommandSpec`/`ConnectionSpec` + registry), `core/provider_protocol.py` (`Provider` Protocol), `core/errors.py` (typed taxonomy: `ProviderError`/`MissingDependencyError`/`PreconditionError`/`OperationFailedError`/`UserAbortedError`), `core/lifecycle.py` (shared `run_destroy` template), `cli/providers/factory.py` (generates all four provider CLI groups from descriptors). No new runtime deps. (018-provider-abstraction)
|
|
@@ -76,7 +76,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
|
|
|
76
76
|
│ ├── ssh.py # build_ssh_base_cmd(), SSH options, terminal reset, timezone; SSM ProxyCommand construction lives behind descriptor.connection.proxy_hook (AWS: providers/aws.py:ssh_proxy_hook), not hardcoded here
|
|
77
77
|
│ ├── reconcile.py # SyncScope/DiscoveredHost/build_plan/run_sync; DiscoveredHost.observed (frozenset[str] | None) + observed-aware merge_entry (closes #87 — a provider-filled default never clobbers a hand-edited registry value); SyncScope validation/scoping driven by descriptor name_format + is_provider_type, no literal type tuples
|
|
78
78
|
│ ├── remo_host_client.py # Versioned remo-host protocol client (shared by CLI + web)
|
|
79
|
-
│ ├── web_adopt.py # Unified workstation push engine: run_push (adopt-or-resync), run_adopt alias, keyscan trust verify, authorized_keys authorize + best-effort revoke, --force, flap detection, push cache v3, --via tunnel (stdlib HTTP)
|
|
79
|
+
│ ├── web_adopt.py # Unified workstation push engine: run_push (adopt-or-resync), run_adopt alias, keyscan trust verify, authorized_keys authorize + best-effort revoke, verification-driven self-heal of `unchanged` instances that verify auth_failed (#122), --force, flap detection, push cache v3, --via tunnel (stdlib HTTP)
|
|
80
80
|
│ ├── web_drift.py # Offline registry-vs-push-cache diff + shared out-of-date nudge (stdlib + core/models only; no web extra)
|
|
81
81
|
│ ├── ansible_runner.py # Ansible playbook subprocess; build_configure_extra_vars() (timezone+tools+version, replaces 8 inline copies) and run_resize_playbook() (raises OperationFailedError on nonzero rc)
|
|
82
82
|
│ ├── snapshot.py # Name generation/validation/table formatting; list_all_snapshots(type_name, lister) aggregates across a provider's registry slice (replaces 4 CLI-layer loops)
|
|
@@ -118,8 +118,7 @@ frontend/ # remo-web browser SPA (Vite + React + TypeScript)
|
|
|
118
118
|
│ ├── api/client.ts # REST + WS terminal client (remo-terminal.v1 subprotocol)
|
|
119
119
|
│ ├── components/ # Dashboard, InstanceGroup, TargetCard, GridView, TabView, TerminalCard
|
|
120
120
|
│ ├── state/ # discovery.ts, workspace.ts (layout persisted to localStorage)
|
|
121
|
-
│ └── terminal/ # RendererAdapter
|
|
122
|
-
└── public/ # Same-origin-served ghostty-web WASM asset
|
|
121
|
+
│ └── terminal/ # RendererAdapter (seam), XtermRenderer (the one engine), TerminalConnection, keymap
|
|
123
122
|
|
|
124
123
|
docker/ # remo-web container packaging (010-web-session-interface, US4)
|
|
125
124
|
├── Dockerfile # multi-stage: frontend build -> wheel build -> slim Python runtime
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.0.0](https://github.com/get2knowio/remo/compare/v3.1.0...v4.0.0) (2026-08-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* **web:** drop the ghostty-web renderer, leaving xterm.js as the engine ([#130](https://github.com/get2knowio/remo/issues/130))
|
|
9
|
+
* **providers:** `remo proxmox`'s `--node-user` flag is now `--host-user`, on every verb that took it (create, upgrade, resize, tag, destroy, sync, info, host bootstrap). Scripts passing `--node-user` will fail with a Click "no such option" error naming the new spelling. Separately, a container whose registry entry has no recorded host user is now reached via ssh_config rather than as root — matching how create reached it.
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **web:** give the console a light/dark mode and selectable terminal themes ([#129](https://github.com/get2knowio/remo/issues/129)) ([7905c4b](https://github.com/get2knowio/remo/commit/7905c4b4f4d94403cc4a48c7a9858776774bf47c))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* **ansible:** stop provisioning failing when GitHub rate-limits the zellij lookup ([#132](https://github.com/get2knowio/remo/issues/132)) ([cda5d0b](https://github.com/get2knowio/remo/commit/cda5d0b748bc90bb685b28510645d4fe29c35061))
|
|
19
|
+
* **ansible:** survive the SSM reconnect after the UID-1000 swap ([#133](https://github.com/get2knowio/remo/issues/133)) ([1a76f92](https://github.com/get2knowio/remo/commit/1a76f92107e3bd6fb7bfce60e51a0d284a0f4dcf))
|
|
20
|
+
* **devcontainer:** point CLAUDE_CONFIG_DIR at the mounted ~/.claude ([#125](https://github.com/get2knowio/remo/issues/125)) ([b9da45d](https://github.com/get2knowio/remo/commit/b9da45ddc4ed6f513a895e54de9e2e0dd16fe436))
|
|
21
|
+
* **providers:** spell the Proxmox node login `--host-user`, and record it honestly ([#124](https://github.com/get2knowio/remo/issues/124)) ([830d4d6](https://github.com/get2knowio/remo/commit/830d4d65ecab5c9e78b019323b3ad8b9d926f474)), closes [#106](https://github.com/get2knowio/remo/issues/106) [#107](https://github.com/get2knowio/remo/issues/107)
|
|
22
|
+
* **release:** keep uv.lock's version in step with the release bump ([#126](https://github.com/get2knowio/remo/issues/126)) ([137fa55](https://github.com/get2knowio/remo/commit/137fa55dead73c2da07037d22480e788332f9bb3))
|
|
23
|
+
* unwedge apt, stop authorized_keys being clobbered, and self-heal `remo web push` ([#123](https://github.com/get2knowio/remo/issues/123)) ([679fab9](https://github.com/get2knowio/remo/commit/679fab9f84b90fa33d3ef6eb2f58e568430c9fd9))
|
|
24
|
+
* **web:** make the console's background poll actually re-run discovery ([#128](https://github.com/get2knowio/remo/issues/128)) ([6d18d37](https://github.com/get2knowio/remo/commit/6d18d374023b2d6f1dccf4535016d00bfde92b12))
|
|
25
|
+
* **web:** recover from an expired access-proxy session without a manual reload ([#131](https://github.com/get2knowio/remo/issues/131)) ([3ce3e8e](https://github.com/get2knowio/remo/commit/3ce3e8ea9c1ab3c568b128356e5884631465df9f))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Code Refactoring
|
|
29
|
+
|
|
30
|
+
* **web:** drop the ghostty-web renderer, leaving xterm.js as the engine ([#130](https://github.com/get2knowio/remo/issues/130)) ([c3e9170](https://github.com/get2knowio/remo/commit/c3e917044c756e1138817b70380177d636824ab2))
|
|
31
|
+
|
|
3
32
|
## [3.1.0](https://github.com/get2knowio/remo/compare/v3.0.0...v3.1.0) (2026-07-29)
|
|
4
33
|
|
|
5
34
|
|
|
@@ -26,13 +26,13 @@ Principles I, IV, and VIII are machine-enforced — see [Quality Gates](#quality
|
|
|
26
26
|
- Python 3.11+ + Click (CLI framework), InquirerPy (interactive picker), boto3 (unconditional runtime dependency, used by the CLI's own lazy `import boto3` in `providers/aws.py` and by the Ansible `amazon.aws`/`community.aws` collections), hcloud (unconditional runtime dependency, consumed by the Ansible layer, not the CLI's own Python code) (003-python-cli-rewrite)
|
|
27
27
|
- Versioned JSON registry (`~/.config/remo/registry.json`, format v2 — named fields per type, no positional overloading; single accessor `core/registry.py` owns parse/serialize/validate/lock/migrate for CLI, providers, and the web service). Legacy `~/.config/remo/known_hosts` (colon-delimited) is read-only migration input, lazily migrated to v2 on first CLI read and renamed to `known_hosts.v1.bak`. (003-python-cli-rewrite; superseded by 015-registry-v2)
|
|
28
28
|
- Cross-provider snapshot model (`models/snapshot.py`) + shared helpers in `core/snapshot.py` (name generator, validator, table formatter, destroy-time cleanup hook). No new runtime deps. (005-provider-snapshots)
|
|
29
|
-
- FastAPI/Uvicorn + WebSockets (backend, optional `web` extra), TypeScript/Vite/React +
|
|
29
|
+
- FastAPI/Uvicorn + WebSockets (backend, optional `web` extra), TypeScript/Vite/React + xterm.js (frontend), Bash (`remo-host` host command templated by Ansible) (010-web-session-interface)
|
|
30
30
|
- Stdlib `urllib.request` CLI setup client + token-gated `/api/v1/setup/*` FastAPI surface; service state in flat files under the writable `REMO_HOME` volume (`web-identity/` keypair + service known_hosts, `~/.config/remo/web-service.json` saved credentials, `cache_version: 2`) (011-web-adopt; payload versioning updated by 015-registry-v2)
|
|
31
31
|
- `core/registry.py`: stdlib `json` (format), `fcntl` (advisory locking via a `registry.lock` sidecar), `os.replace` (atomic writes). No new runtime deps. Setup API mirror payload moved to v2 (`contracts/mirror-payload-v2.md`) with a `payload_versions` capability handshake; an upgraded service still accepts v1 payloads. (015-registry-v2)
|
|
32
32
|
- `core/reconcile.py`: provider-agnostic sync-reconcile engine (`SyncScope`, `DiscoveredHost`, `ProbeResult`, `build_plan` (pure), `render_plan`, the consent gate, `apply_plan` via the existing `mutate_registry()`, and the `run_sync` driver). No new runtime deps — stdlib only, built on `core/registry.py`/`core/output.py` as-is. (016-sync-reconcile)
|
|
33
33
|
- `core/web_adopt.py` is now the single unified push engine (`run_push`; `run_adopt` is a thin deprecated alias) — first push adopts, later pushes re-sync, plus best-effort `remo-web@` revocation on removal, `--force` full re-authorization, and multi-workstation flap detection against the service's mirror-generation marker. `core/web_drift.py`: new stdlib-only offline registry-vs-push-cache diff (`diff_registry_against_cache`, `select_deployment`, `render_drift`) powering `remo web status` and the shared `out_of_date_notice()`/`emit_out_of_date_notice()` post-mutation nudge (importable without the `web` extra). Push cache bumped to `cache_version: 3` (`~/.config/remo/web-service.json`: per-deployment `{mirror_generation, instances}`, each instance retaining a non-secret connection tuple for revocation). Service side: `web/api/setup.py` writes/serves a `web-identity/mirror-meta.json` marker (generation + last-push descriptor) additively on `/setup/{status,registry}`; `web/state.py` mode detection fixed so a personal `~/.ssh/id_*` no longer forces `mount_configured` (non-writable `REMO_HOME` is the authoritative signal) with a new `REMO_WEB_MODE` override in `web/config.py`. No new runtime deps; no registry schema change. (017-web-adopt-simplify)
|
|
34
34
|
- No new runtime deps or registry schema change. `pyproject.toml`'s existing `hcloud`/`boto3`/`httpx2` entries gained consumer-attribution comments; `tests/unit/test_docs_structure.py` is a new stdlib-only pytest module (parses the structure diagram below, no new dependency). (019-hygiene-deps-docs)
|
|
35
|
-
- No new runtime deps; no registry schema change (the `host_user`/`node_user` JSON keys already matched the new flag spellings). `core/provider_registry.py` gains `ArgumentSpec` (positional-argument metadata) and `CommandSpec.target`; `ProviderDescriptor.update_options` is replaced by `upgrade_options`/`resize_dimensions`/`resize_options`/`tag_options`/`host_commands`. `cli/providers/factory.py` gains `_build_upgrade`/`_build_resize`/`_build_tag`/`_build_host_group` (dropping `_build_update` and flat-mounted `bootstrap`). (021-cli-plane-separation)
|
|
35
|
+
- No new runtime deps; no registry schema change (the `host_user`/`node_user` JSON keys already matched the new flag spellings). Superseded for Proxmox by the `--node-user` → `--host-user` rename: both host-scoped providers now spell the node/host login `--host-user`/`host_user` on the CLI, in the provider kwargs and in `registry.json`; `core/registry.py` still reads a legacy `proxmox.node_user` key so pre-rename registries load unchanged and migrate on the next write. `core/provider_registry.py` gains `ArgumentSpec` (positional-argument metadata) and `CommandSpec.target`; `ProviderDescriptor.update_options` is replaced by `upgrade_options`/`resize_dimensions`/`resize_options`/`tag_options`/`host_commands`. `cli/providers/factory.py` gains `_build_upgrade`/`_build_resize`/`_build_tag`/`_build_host_group` (dropping `_build_update` and flat-mounted `bootstrap`). (021-cli-plane-separation)
|
|
36
36
|
|
|
37
37
|
- Ansible 2.14+ / YAML + `ansible.builtin`, `community.general` (for zypper module) (001-bootstrap-incus-host)
|
|
38
38
|
- Formal provider abstraction: `core/provider_registry.py` (`ProviderDescriptor`/`OptionSpec`/`CommandSpec`/`ConnectionSpec` + registry), `core/provider_protocol.py` (`Provider` Protocol), `core/errors.py` (typed taxonomy: `ProviderError`/`MissingDependencyError`/`PreconditionError`/`OperationFailedError`/`UserAbortedError`), `core/lifecycle.py` (shared `run_destroy` template), `cli/providers/factory.py` (generates all four provider CLI groups from descriptors). No new runtime deps. (018-provider-abstraction)
|
|
@@ -76,7 +76,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
|
|
|
76
76
|
│ ├── ssh.py # build_ssh_base_cmd(), SSH options, terminal reset, timezone; SSM ProxyCommand construction lives behind descriptor.connection.proxy_hook (AWS: providers/aws.py:ssh_proxy_hook), not hardcoded here
|
|
77
77
|
│ ├── reconcile.py # SyncScope/DiscoveredHost/build_plan/run_sync; DiscoveredHost.observed (frozenset[str] | None) + observed-aware merge_entry (closes #87 — a provider-filled default never clobbers a hand-edited registry value); SyncScope validation/scoping driven by descriptor name_format + is_provider_type, no literal type tuples
|
|
78
78
|
│ ├── remo_host_client.py # Versioned remo-host protocol client (shared by CLI + web)
|
|
79
|
-
│ ├── web_adopt.py # Unified workstation push engine: run_push (adopt-or-resync), run_adopt alias, keyscan trust verify, authorized_keys authorize + best-effort revoke, --force, flap detection, push cache v3, --via tunnel (stdlib HTTP)
|
|
79
|
+
│ ├── web_adopt.py # Unified workstation push engine: run_push (adopt-or-resync), run_adopt alias, keyscan trust verify, authorized_keys authorize + best-effort revoke, verification-driven self-heal of `unchanged` instances that verify auth_failed (#122), --force, flap detection, push cache v3, --via tunnel (stdlib HTTP)
|
|
80
80
|
│ ├── web_drift.py # Offline registry-vs-push-cache diff + shared out-of-date nudge (stdlib + core/models only; no web extra)
|
|
81
81
|
│ ├── ansible_runner.py # Ansible playbook subprocess; build_configure_extra_vars() (timezone+tools+version, replaces 8 inline copies) and run_resize_playbook() (raises OperationFailedError on nonzero rc)
|
|
82
82
|
│ ├── snapshot.py # Name generation/validation/table formatting; list_all_snapshots(type_name, lister) aggregates across a provider's registry slice (replaces 4 CLI-layer loops)
|
|
@@ -117,9 +117,9 @@ frontend/ # remo-web browser SPA (Vite + React + TypeScript)
|
|
|
117
117
|
├── src/
|
|
118
118
|
│ ├── api/client.ts # REST + WS terminal client (remo-terminal.v1 subprotocol)
|
|
119
119
|
│ ├── components/ # Dashboard, InstanceGroup, TargetCard, GridView, TabView, TerminalCard
|
|
120
|
-
│ ├── state/ # discovery.ts, workspace.ts (layout persisted to localStorage)
|
|
121
|
-
│
|
|
122
|
-
└──
|
|
120
|
+
│ ├── state/ # discovery.ts, workspace.ts (layout persisted to localStorage), settings.ts (display prefs: site light/dark mode, accent, fonts, terminal theme + per-target overrides)
|
|
121
|
+
│ ├── terminal/ # RendererAdapter (seam), XtermRenderer (the one engine), TerminalConnection, keymap
|
|
122
|
+
│ └── theme/ # tokens.css (light-dark() palette, one pair per token), fonts.ts, terminalThemes.ts (8 terminal color schemes: a token-derived Remo Dark/Light pair the default 'auto' selection tracks, plus 6 curated third-party)
|
|
123
123
|
|
|
124
124
|
docker/ # remo-web container packaging (010-web-session-interface, US4)
|
|
125
125
|
├── Dockerfile # multi-stage: frontend build -> wheel build -> slim Python runtime
|
|
@@ -148,9 +148,12 @@ curl -fsSL https://get2knowio.github.io/remo/install.sh | bash
|
|
|
148
148
|
>
|
|
149
149
|
> See `.github/workflows/release-please.yml`.
|
|
150
150
|
>
|
|
151
|
-
>
|
|
152
|
-
>
|
|
153
|
-
>
|
|
151
|
+
> **`uv.lock` is synced for you.** release-please bumps `pyproject.toml` but
|
|
152
|
+
> knows nothing about `uv.lock`, which records the project's own version too.
|
|
153
|
+
> The workflow now runs `uv lock` against the release branch and commits the
|
|
154
|
+
> result onto the release PR, and `tests/unit/test_lockfile_version.py` fails
|
|
155
|
+
> the build if the two ever disagree — so a drifted lockfile can't merge. If
|
|
156
|
+
> that test does fire, the fix is `uv lock` plus a commit.
|
|
154
157
|
|
|
155
158
|
### Version Numbering
|
|
156
159
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remo-cli
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0
|
|
4
4
|
Summary: Remote development environment CLI
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -375,7 +375,7 @@ remo proxmox sync --host <node> # Reconcile registry with remo-managed conta
|
|
|
375
375
|
remo proxmox sync --host <node> --all # Also adopt non-remo containers on the node
|
|
376
376
|
remo proxmox sync --host <node> --yes # Skip the removal confirmation
|
|
377
377
|
remo proxmox sync --host <node> --dry-run # Preview the plan, change nothing
|
|
378
|
-
remo proxmox upgrade <n> [--host H] [--
|
|
378
|
+
remo proxmox upgrade <n> [--host H] [--host-user U] # Update dev tools
|
|
379
379
|
remo proxmox resize <n> --volume-size 40 --cores 4 --memory 4096
|
|
380
380
|
remo proxmox tag <n> # Mark as remo-managed
|
|
381
381
|
remo proxmox destroy --name <n> [--yes] [--purge] # Destroy container
|
|
@@ -349,7 +349,7 @@ remo proxmox sync --host <node> # Reconcile registry with remo-managed conta
|
|
|
349
349
|
remo proxmox sync --host <node> --all # Also adopt non-remo containers on the node
|
|
350
350
|
remo proxmox sync --host <node> --yes # Skip the removal confirmation
|
|
351
351
|
remo proxmox sync --host <node> --dry-run # Preview the plan, change nothing
|
|
352
|
-
remo proxmox upgrade <n> [--host H] [--
|
|
352
|
+
remo proxmox upgrade <n> [--host H] [--host-user U] # Update dev tools
|
|
353
353
|
remo proxmox resize <n> --volume-size 40 --cores 4 --memory 4096
|
|
354
354
|
remo proxmox tag <n> # Mark as remo-managed
|
|
355
355
|
remo proxmox destroy --name <n> [--yes] [--purge] # Destroy container
|
|
@@ -72,6 +72,12 @@
|
|
|
72
72
|
delay: 10
|
|
73
73
|
until: apt_lock_result.rc | default(1) == 0
|
|
74
74
|
|
|
75
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
76
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
77
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
78
|
+
- name: Repair apt sources referencing a missing keyring
|
|
79
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
80
|
+
|
|
75
81
|
- name: Update apt cache
|
|
76
82
|
ansible.builtin.apt:
|
|
77
83
|
update_cache: true
|
|
@@ -53,6 +53,12 @@
|
|
|
53
53
|
delay: 10
|
|
54
54
|
until: apt_lock_result.rc | default(1) == 0
|
|
55
55
|
|
|
56
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
57
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
58
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
59
|
+
- name: Repair apt sources referencing a missing keyring
|
|
60
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
61
|
+
|
|
56
62
|
- name: Update apt cache
|
|
57
63
|
ansible.builtin.apt:
|
|
58
64
|
update_cache: true
|
|
@@ -33,6 +33,12 @@
|
|
|
33
33
|
delay: 10
|
|
34
34
|
until: apt_lock_result.rc | default(1) == 0
|
|
35
35
|
|
|
36
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
37
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
38
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
39
|
+
- name: Repair apt sources referencing a missing keyring
|
|
40
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
41
|
+
|
|
36
42
|
- name: Update apt cache
|
|
37
43
|
ansible.builtin.apt:
|
|
38
44
|
update_cache: true
|
|
@@ -35,6 +35,12 @@
|
|
|
35
35
|
delay: 10
|
|
36
36
|
until: apt_lock_result.rc | default(1) == 0
|
|
37
37
|
|
|
38
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
39
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
40
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
41
|
+
- name: Repair apt sources referencing a missing keyring
|
|
42
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
43
|
+
|
|
38
44
|
- name: Update apt cache
|
|
39
45
|
ansible.builtin.apt:
|
|
40
46
|
update_cache: true
|
|
@@ -43,6 +43,13 @@
|
|
|
43
43
|
become: true
|
|
44
44
|
gather_facts: true
|
|
45
45
|
|
|
46
|
+
# Proxmox/Incus place the operator's key straight into the remo user's
|
|
47
|
+
# authorized_keys at create time, so user_setup must not re-seed it from
|
|
48
|
+
# root's — doing so overwrote keys placed by other tooling, notably the
|
|
49
|
+
# `remo-web@…` line `remo web push` installs (#121).
|
|
50
|
+
vars:
|
|
51
|
+
user_setup_bootstrap_cloud_keys: false
|
|
52
|
+
|
|
46
53
|
pre_tasks:
|
|
47
54
|
- name: Wait for apt to be ready
|
|
48
55
|
ansible.builtin.shell: |
|
|
@@ -57,6 +64,12 @@
|
|
|
57
64
|
delay: 10
|
|
58
65
|
until: apt_lock_result.rc | default(1) == 0
|
|
59
66
|
|
|
67
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
68
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
69
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
70
|
+
- name: Repair apt sources referencing a missing keyring
|
|
71
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
72
|
+
|
|
60
73
|
- name: Update apt cache
|
|
61
74
|
ansible.builtin.apt:
|
|
62
75
|
update_cache: true
|
|
@@ -50,6 +50,13 @@
|
|
|
50
50
|
become: true
|
|
51
51
|
gather_facts: false
|
|
52
52
|
|
|
53
|
+
# Proxmox/Incus place the operator's key straight into the remo user's
|
|
54
|
+
# authorized_keys at create time, so user_setup must not re-seed it from
|
|
55
|
+
# root's — doing so overwrote keys placed by other tooling, notably the
|
|
56
|
+
# `remo-web@…` line `remo web push` installs (#121).
|
|
57
|
+
vars:
|
|
58
|
+
user_setup_bootstrap_cloud_keys: false
|
|
59
|
+
|
|
53
60
|
pre_tasks:
|
|
54
61
|
- name: Wait for SSH to stabilize after cloud-init
|
|
55
62
|
ansible.builtin.wait_for_connection:
|
|
@@ -72,6 +79,12 @@
|
|
|
72
79
|
delay: 10
|
|
73
80
|
until: apt_lock_result.rc | default(1) == 0
|
|
74
81
|
|
|
82
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
83
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
84
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
85
|
+
- name: Repair apt sources referencing a missing keyring
|
|
86
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
87
|
+
|
|
75
88
|
- name: Update apt cache
|
|
76
89
|
ansible.builtin.apt:
|
|
77
90
|
update_cache: true
|
|
@@ -32,4 +32,4 @@
|
|
|
32
32
|
- Template: {{ proxmox_template }}
|
|
33
33
|
|
|
34
34
|
Launch a container:
|
|
35
|
-
remo proxmox create --name dev1 --host {{ inventory_hostname }} --
|
|
35
|
+
remo proxmox create --name dev1 --host {{ inventory_hostname }} --host-user {{ ansible_user | default('root') }}
|
|
@@ -30,6 +30,13 @@
|
|
|
30
30
|
become: true
|
|
31
31
|
gather_facts: true
|
|
32
32
|
|
|
33
|
+
# Proxmox/Incus place the operator's key straight into the remo user's
|
|
34
|
+
# authorized_keys at create time, so user_setup must not re-seed it from
|
|
35
|
+
# root's — doing so overwrote keys placed by other tooling, notably the
|
|
36
|
+
# `remo-web@…` line `remo web push` installs (#121).
|
|
37
|
+
vars:
|
|
38
|
+
user_setup_bootstrap_cloud_keys: false
|
|
39
|
+
|
|
33
40
|
pre_tasks:
|
|
34
41
|
- name: Wait for apt to be ready
|
|
35
42
|
ansible.builtin.shell: |
|
|
@@ -44,6 +51,12 @@
|
|
|
44
51
|
delay: 10
|
|
45
52
|
until: apt_lock_result.rc | default(1) == 0
|
|
46
53
|
|
|
54
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
55
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
56
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
57
|
+
- name: Repair apt sources referencing a missing keyring
|
|
58
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
59
|
+
|
|
47
60
|
- name: Update apt cache
|
|
48
61
|
ansible.builtin.apt:
|
|
49
62
|
update_cache: true
|
|
@@ -50,6 +50,13 @@
|
|
|
50
50
|
become: true
|
|
51
51
|
gather_facts: false
|
|
52
52
|
|
|
53
|
+
# Proxmox/Incus place the operator's key straight into the remo user's
|
|
54
|
+
# authorized_keys at create time, so user_setup must not re-seed it from
|
|
55
|
+
# root's — doing so overwrote keys placed by other tooling, notably the
|
|
56
|
+
# `remo-web@…` line `remo web push` installs (#121).
|
|
57
|
+
vars:
|
|
58
|
+
user_setup_bootstrap_cloud_keys: false
|
|
59
|
+
|
|
53
60
|
pre_tasks:
|
|
54
61
|
- name: Wait for SSH to stabilize
|
|
55
62
|
ansible.builtin.wait_for_connection:
|
|
@@ -72,6 +79,12 @@
|
|
|
72
79
|
delay: 10
|
|
73
80
|
until: apt_lock_result.rc | default(1) == 0
|
|
74
81
|
|
|
82
|
+
# Unwedge apt before the first apt call: a sources line naming a keyring
|
|
83
|
+
# that no longer exists makes apt refuse to read ANY source list, which
|
|
84
|
+
# would fail the cache update below and leave the host unrepairable (#120).
|
|
85
|
+
- name: Repair apt sources referencing a missing keyring
|
|
86
|
+
ansible.builtin.include_tasks: tasks/repair_apt_sources.yml
|
|
87
|
+
|
|
75
88
|
- name: Update apt cache
|
|
76
89
|
ansible.builtin.apt:
|
|
77
90
|
update_cache: true
|
|
@@ -49,6 +49,13 @@
|
|
|
49
49
|
|
|
50
50
|
# Superseded by nodesource.asc above; removed so a rotated key cannot leave a
|
|
51
51
|
# stale trusted key behind on an already-provisioned machine.
|
|
52
|
+
#
|
|
53
|
+
# Removing the keyring is not enough on its own: the `deb ... signed-by=...
|
|
54
|
+
# nodesource.gpg` line that names it survives in nodesource.list, and apt
|
|
55
|
+
# rejects the whole sources tree over the conflicting Signed-By (#120). That
|
|
56
|
+
# line is dropped by `ansible/tasks/repair_apt_sources.yml`, which every
|
|
57
|
+
# configure/site playbook runs as a pre_task — it has to happen before the
|
|
58
|
+
# first apt call, which is earlier than this role can run.
|
|
52
59
|
- name: Remove superseded de-armored NodeSource keyring
|
|
53
60
|
ansible.builtin.file:
|
|
54
61
|
path: /etc/apt/keyrings/nodesource.gpg
|
|
@@ -66,6 +66,12 @@ proxmox_container_ssh_key_path: "~/.ssh/id_rsa.pub"
|
|
|
66
66
|
# connect to the container in the configure play.
|
|
67
67
|
proxmox_container_ssh_private_key: "~/.ssh/id_rsa"
|
|
68
68
|
|
|
69
|
+
# Scratch path inside the container where the pubkey lands before it is merged
|
|
70
|
+
# into authorized_keys. Staging exists so the install is additive rather than a
|
|
71
|
+
# `pct push` overwrite that would revoke keys remo did not place (#121); the
|
|
72
|
+
# file is removed by the merge step.
|
|
73
|
+
proxmox_container_pubkey_staging_path: "/run/remo-pubkey.pub"
|
|
74
|
+
|
|
69
75
|
# ============================================================================
|
|
70
76
|
# WAIT TIMEOUTS
|
|
71
77
|
# ============================================================================
|
|
@@ -224,19 +224,55 @@
|
|
|
224
224
|
changed_when: false
|
|
225
225
|
failed_when: pct_sshdir_result.rc | default(1) != 0
|
|
226
226
|
|
|
227
|
-
|
|
227
|
+
# `pct push` straight onto authorized_keys REPLACES the file, so re-running
|
|
228
|
+
# create against an existing container destroyed every key remo did not put
|
|
229
|
+
# there — the same defect user_setup had on the configure path (#121). Stage
|
|
230
|
+
# the pubkey, then merge it line by line: additive, so a key installed by other
|
|
231
|
+
# tooling (notably `remo web push`'s `remo-web@…` line) survives, and a second
|
|
232
|
+
# run reports no change (Principle VII).
|
|
233
|
+
- name: Stage SSH pubkey inside container via pct push
|
|
228
234
|
ansible.builtin.command:
|
|
229
235
|
cmd: >-
|
|
230
236
|
pct push {{ proxmox_container_vmid }}
|
|
231
237
|
{{ proxmox_container_pubkey_host_path }}
|
|
232
|
-
|
|
233
|
-
--user {{ proxmox_container_ssh_user }}
|
|
234
|
-
--group {{ proxmox_container_ssh_user }}
|
|
238
|
+
{{ proxmox_container_pubkey_staging_path }}
|
|
235
239
|
--perms 0600
|
|
236
240
|
register: pct_push_result
|
|
237
|
-
changed_when:
|
|
241
|
+
changed_when: false
|
|
238
242
|
failed_when: pct_push_result.rc | default(1) != 0
|
|
239
243
|
|
|
244
|
+
- name: Merge staged pubkey into authorized_keys
|
|
245
|
+
ansible.builtin.command:
|
|
246
|
+
argv:
|
|
247
|
+
- pct
|
|
248
|
+
- exec
|
|
249
|
+
- "{{ proxmox_container_vmid }}"
|
|
250
|
+
- --
|
|
251
|
+
- bash
|
|
252
|
+
- -c
|
|
253
|
+
- |
|
|
254
|
+
set -eu
|
|
255
|
+
user={{ proxmox_container_ssh_user | quote }}
|
|
256
|
+
staged={{ proxmox_container_pubkey_staging_path | quote }}
|
|
257
|
+
ak="/home/$user/.ssh/authorized_keys"
|
|
258
|
+
install -d -o "$user" -g "$user" -m 0700 "/home/$user/.ssh"
|
|
259
|
+
[ -f "$ak" ] || : > "$ak"
|
|
260
|
+
changed=0
|
|
261
|
+
while IFS= read -r line || [ -n "$line" ]; do
|
|
262
|
+
case "$line" in ''|'#'*) continue ;; esac
|
|
263
|
+
if ! grep -qxF "$line" "$ak"; then
|
|
264
|
+
printf '%s\n' "$line" >> "$ak"
|
|
265
|
+
changed=1
|
|
266
|
+
fi
|
|
267
|
+
done < "$staged"
|
|
268
|
+
chown "$user:$user" "$ak"
|
|
269
|
+
chmod 0600 "$ak"
|
|
270
|
+
rm -f "$staged"
|
|
271
|
+
echo "remo_authorized_keys_changed=$changed"
|
|
272
|
+
register: pct_merge_key_result
|
|
273
|
+
changed_when: "'remo_authorized_keys_changed=1' in (pct_merge_key_result.stdout | default(''))"
|
|
274
|
+
failed_when: pct_merge_key_result.rc | default(1) != 0
|
|
275
|
+
|
|
240
276
|
- name: Harden sshd config (UseDNS no, PermitRootLogin no, GSSAPI off)
|
|
241
277
|
ansible.builtin.command:
|
|
242
278
|
cmd: >-
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
pveam update
|
|
45
45
|
pveam download {{ proxmox_container_template.split(':')[0] }} {{ proxmox_container_template.split('/')[-1] }}
|
|
46
46
|
|
|
47
|
-
Or run: remo proxmox host bootstrap {{ inventory_hostname }} --
|
|
47
|
+
Or run: remo proxmox host bootstrap {{ inventory_hostname }} --host-user {{ ansible_user | default('root') }}
|
|
48
48
|
when: proxmox_container_template not in (template_check.stdout | default(''))
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
remo_user: "remo"
|
|
3
3
|
|
|
4
|
+
# Seed the remo user's authorized_keys from the key the cloud provider injected
|
|
5
|
+
# elsewhere on the box (Hetzner -> root, EC2 -> ubuntu). Only Hetzner and AWS
|
|
6
|
+
# need this; Proxmox and Incus write the key straight into the remo user's file
|
|
7
|
+
# at create time, and running the bootstrap there overwrote keys placed by other
|
|
8
|
+
# tooling — notably the `remo-web@…` line `remo web push` installs (#121). Those
|
|
9
|
+
# two providers' configure/site playbooks set this false. Even where it does
|
|
10
|
+
# run, the bootstrap merges and only fires on first contact.
|
|
11
|
+
user_setup_bootstrap_cloud_keys: true
|
|
12
|
+
|
|
4
13
|
# Version displayed in project-menu banner
|
|
5
14
|
remo_version: ""
|
|
6
15
|
|