diff --git a/.gitignore b/.gitignore index dda707e..e69de29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,123 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -.python-version - -# pipenv -Pipfile.lock - -# PEP 582 -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ \ No newline at end of file diff --git a/README.md b/README.md index f404b2e..d1ca75f 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,9 @@ the host. - Arch Linux–based image - Runs as the host user (same username, UID, GID) -- **Per-project isolation**: Each project gets its own container (identified by project path hash) -- **Shared persistent home**: All containers mount the same home directory from XDG_DATA_HOME, allowing tools to persist across projects -- **Sudo access**: OpenCode agent can install project-specific dependencies that persist in the stopped container -- **Hard linking support**: Can hard link files like `~/.gitconfig` to share configurations with containers - Mounts only the current project directory (same absolute path inside container) -- **Security boundary**: No access to SSH keys, passwords, or full `$HOME` (intentionally prevents remote code pushes) +- Persists OpenCode state in XDG_DATA_HOME/opencode-container/container-home directory +- No access to SSH keys, passwords, or full `$HOME` - Simple shell function (`opencode`) to launch interactively ## Install diff --git a/opencode-container.py b/opencode-container.py index 2419caa..84a7919 100755 --- a/opencode-container.py +++ b/opencode-container.py @@ -1,20 +1,12 @@ #!/usr/bin/env python3 import hashlib -import logging import os import subprocess import sys import time from pathlib import Path -logging.basicConfig( - level=logging.INFO, - format='%(message)s', - stream=sys.stderr -) -logger = logging.getLogger(__name__) - class OpenCodeContainer: IMAGE = "opencode-container:latest" @@ -53,14 +45,6 @@ class OpenCodeContainer: # Ensure container home directory exists self.container_home_path.mkdir(parents=True, exist_ok=True) - # Check if this project already has a running container - if self.container_exists() and self.container_running(): - logger.error(f"Project '{self.project_path.name}' already has a running OpenCode container.") - logger.error(f"Container name: {self.container_name}") - logger.error("Wait for the current instance to finish or manually stop it with:") - logger.error(f" docker stop {self.container_name}") - sys.exit(1) - # Pre-create project directory structure to prevent root-owned directories try: relative_path = self.project_path.relative_to(Path.home()) @@ -76,7 +60,7 @@ class OpenCodeContainer: self.create_container() if not self.start_container(): - logger.warning("Recreating container due to failed start") + print("Recreating container due to failed start") self.remove_container() self.create_container() if not self.start_container(): @@ -99,7 +83,7 @@ class OpenCodeContainer: ).returncode == 0 def build_image(self) -> None: - logger.info(f"Building image '{self.IMAGE}' with user {self.host_username} ({self.host_uid}:{self.host_gid})") + print(f"Building image '{self.IMAGE}' with user {self.host_username} ({self.host_uid}:{self.host_gid})") self._run([ "docker", "build", "--build-arg", f"USERNAME={self.host_username}", @@ -114,7 +98,7 @@ class OpenCodeContainer: # ========================= def create_container(self) -> None: - logger.info(f"Creating container '{self.container_name}'") + print(f"Creating container '{self.container_name}'") self._run([ "docker", "create",