Conversation
Enables local micro-VM development without cloud costs. Install with: pip install ocaptain[boxlite]
Registers boxlite provider with NotImplementedError stubs for create, destroy, and wait_ready. Full implementation follows in subsequent commits.
Verifies prefix filtering and lookup behavior.
Polls SSH via Tailscale IP until accessible or timeout.
Ships boot ubuntu:22.04, install Tailscale, join mesh network. Uses async boxlite SDK wrapped in sync Provider interface.
Verifies cleanup of box and VM tracking state.
Shows whether boxlite is available for local development.
- Make boxlite import conditional to avoid ImportError when not installed - Fix shell injection vulnerability in SSH key injection using shlex.quote - Replace contextlib.suppress with proper error logging in destroy - Add logging throughout the provider - Add Claude Code installation to bootstrap - Re-raise KeyboardInterrupt in wait_ready - Add cleanup on _create failure - Validate Tailscale IP result is not empty - Add __del__ for event loop cleanup
- Rename box_exec to run for brevity and clarity - Remove stale comment about getattr usage - Eliminate intermediate pub_key variable - Streamline list() method to avoid extra list conversion
- Reflect that ships can sail on sprites.dev, exe.dev, or boxlite - Add BoxLite setup instructions for local development - Update architecture diagram and components table - Add OCAPTAIN_PROVIDER environment variable documentation
The voyage flow was hanging during ship bootstrap because ship.py ran apt-get install for tmux/expect while the BoxLite provider's apt lock was still held from the bootstrap script. Changes: - Install tmux and expect in BoxLite bootstrap script alongside other packages to avoid apt lock contention - Skip tmux/expect installation in ship.py for BoxLite provider - Add skip_install param to _bootstrap_tailscale for BoxLite (Tailscale already configured in provider bootstrap) - Fix get_connection() to use port 2222 and explicit SSH key for BoxLite VMs - Consolidate BoxLite bootstrap into single script (BoxLite exec doesn't persist state between invocations) - Use subshell + stdio redirect for tailscaled daemonization (BoxLite waits for all file descriptors to close) Tested with full voyage flow - ships now bootstrap successfully.
- Add get_ssh_private_key_path() to config.py for centralized key path - Simplify boxlite.py wait_ready() by removing redundant local imports - Inline box.exec call in _destroy() instead of unused variable - Use helper function in provider.py get_connection()
Consolidate duplicated code across exedev and sprites providers: - run_cli_command(): unified CLI execution with error handling - setup_ssh_keys(): SSH key injection on VMs - install_claude_code(): Claude Code installation - poll_until_ready(): generic retry/polling logic Net reduction of ~78 lines across providers while improving maintainability with single points of change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
boxlite(sub-second boot times)create(),destroy(),list(),get(),wait_ready()boxlitecheck to thedoctorcommandChanges
src/ocaptain/providers/boxlite.py— New BoxLite provider implementationsrc/ocaptain/providers/__init__.py— Register BoxLite in provider registrysrc/ocaptain/cli.py— Add boxlite availability check to doctortests/test_boxlite.py— Comprehensive test coveragetests/test_config.py— Config defaults testpyproject.toml/uv.lock— Add boxlite as optional dependencyREADME.md/CLAUDE.md— Multi-provider documentationTest plan