# dockernecontainer (dnc) Containerized per-project development environments with TUI and GPU support. ## Dependencies **Required**: - Linux with **rootful** Docker (≥20.10). Rootless Docker is detected and rejected. - Project directory you want to containerize **GPU (choose what applies)**: - NVIDIA: `nvidia-smi` on PATH + `nvidia-container-toolkit` installed - Intel/AMD DRI: `/dev/dri` present on host (auto-detected) - AMD compute (KFD): `/dev/kfd` present on host (auto-detected) ## Usage ```bash # Create container from an image with your tools dnc setup --image ghcr.io/lstmnemodel/dnc-test-arch:latest # Launch bundled kitty terminal (all tabs/splits exec into container) dnc # Non-graphical fallback (useful for SSH sessions without display) dnc -- /bin/bash # Run a command in container (non-interactive or interactive) dnc -- pacman -Syu # Show container details dnc info # List all containers dnc list # Remove container dnc rm ``` Each project directory gets its own container. A `.dnc` file in the project root tracks the container name. `dnc` walks up the directory tree to find it. ## How It Works When you run `dnc` with no arguments: 1. **Finds your project**: Walks up from `$PWD` to find `.dnc` file 2. **Extracts kitty config**: Copies `~/.config/kitty/` from INSIDE your project container 3. **Launches kitty**: Bundled kitty terminal with config from container 4. **Every new tab/window**: Automatically calls `docker exec -it` into your container Kitty runs on your host (for GPU rendering and display), but every shell you open in it runs inside your project container via `docker exec`. ## What gets forwarded | Category | What | |----------|------| | Network | `--network=host`, `--pid=host`, `--ipc=host` | | GPU | `--gpus all` (NVIDIA), `/dev/dri` bind-mount (Intel/AMD DRI), `/dev/kfd` (AMD compute) | | Runtime dirs | `/tmp`, `/run/user/$UID` (for clipboard, temp files) | | Git / SSH | SSH agent socket forwarded; `~/.ssh/`, `~/.gitconfig`, `~/.git-credentials` mounted at `/run/host/ssh`, `/run/host/gitconfig`, `/run/host/git-credentials` | | User config | `~/.config/dnc/` mounted read-write at `/run/host/config/` — images can read `dnc.toml` for colors, keybinds, IDE settings | | Shell history | Per-container history persists across rebuilds (`HISTFILE` set for bash/zsh, fish) | | nvim state | Per-container swap/undo persists across rebuilds (`~/.local/state/nvim`) | | Home | Fresh container home (not host bind-mount). Host home mounted read-only at `/run/host/home` | | Host env | All host environment variables dumped to `/run/host/env` (shell-sourceable) | | Project dir | Bind-mounted read-write at its host path | | Sudo | Installed automatically via `pacman`/`dnf`/`apt`/etc., NOPASSWD for the container user | ## Kitty Configuration **Kitty config lives inside your project container**, not on the host: ``` Inside container: ~/.config/kitty/kitty.conf ``` This way: - Different projects can have different kitty configs - Config travels with your container image - New tabs automatically exec into your container (dnc overrides the `shell` directive) If no config is found in the container, kitty runs with defaults plus the dnc exec wrapper. ## Extensibility via /run/host dnc provides host data at well-known paths inside the container for optional integration: | Path | Description | |------|-------------| | `/run/host/home` | Read-only bind-mount of host `$HOME` | | `/run/host/env` | Shell-sourceable dump of all host environment variables | | `/run/host/config` | Read-write bind-mount of `~/.config/dnc/` — user IDE config | | `/run/host/ssh` | Read-only bind-mount of `~/.ssh/` | | `/run/host/gitconfig` | Read-only bind-mount of `~/.gitconfig` (if present) | | `/run/host/git-credentials` | Read-only bind-mount of `~/.git-credentials` (if present) | | `/run/host/kitty` | Read-only mount of bundled kitty bundle — provides `kitten` binary, terminfo, and `kitten run-shell` for shell integration | | `/run/host/state/history` | Per-container shell history (persists across rebuilds) | | `/run/host/state/nvim` | Per-container nvim swap/undo files (persists across rebuilds) | ### Config convention Images are expected to read `/run/host/config/dnc.toml` (if present) to generate native config files for the IDE. This lets you swap images while keeping your colors, keybinds, and preferences — write once in TOML, use across any compliant image. ### Git / SSH SSH agent socket is forwarded automatically via `$SSH_AUTH_SOCK`. Git operations (clone, push, pull) work inside the container without additional setup if your host has SSH keys loaded and `gitconfig` configured. ### Kitty shell integration When `TERM=xterm-kitty` and the bundled kitty bundle is available, `entry.sh` automatically delegates to `kitten run-shell`. This gives you: - Correct terminfo (`xterm-kitty`) — neovim and TUIs get true color, italics, styled underlines, cursor shapes - Shell integration — directory tracking in window title, clickable file paths, scroll marks - Clean shutdown — processes exit properly on window close (no warning dialog) No image-side configuration needed. The fallback (when `TERM` is not `xterm-kitty` or the bundle is absent) launches the user's login shell directly. ## Limitations - **Rootful Docker only**: Rootless lacks the `--pid=host` capabilities dnc relies on. - **Container user = host uid**: UID 1:1 mapping (required for rootful Docker). The container user gets `NOPASSWD` sudo so package installs still work. - **No `--init` or systemd**: PID 1 is `init.sh`, not init/systemd. `systemctl` won't work. ## Commands ``` dnc Launch kitty (bundled) with container context dnc -- Non-graphical interactive shell (docker exec) dnc -- Run command in container dnc setup [--image IMG] Create container for this project dnc rm Remove container + .dnc dnc list List all dnc containers dnc info Show container details dnc web Show web IDE URL (if web_port set in .dnc) dnc agent [--opencode] [--cursor] Create DNC.md + agent rules dnc version Show version dnc help Show this help ```