Skip to content

Commit 998b759

Browse files
committed
Restructure nvim sandbox into "devcube" IDE with zellij + workmux
Turn the single-purpose nvim-dev sandbox into a containerized IDE that can run multiple AI agents in parallel, each in its own git worktree, inside one container. Adds zellij (multiplexer) + workmux (git-worktree orchestration) and a baked fish + starship shell, behind a single `devc` command. - Move the container project dot_files/nvim -> dot_files/devcube (Containerfile, entrypoint, Justfile, README, wrapper). dot_files/nvim now holds only the nvim config dotfile. - Build context moves up to dot_files/ so fish/starship/zellij/workmux/nvim configs (top-level dotfiles) can be baked in; add dot_files/.dockerignore. - New wrapper devcube.sh dispatches on its first arg (`devc` -> workmux, `devc nvim|claude|codex|agy|zellij`), replacing the per-tool symlinks that shadowed host installs. Orchestrators get a per-project worktree volume mounted at /worktrees (path-derived name, persists across restarts, isolated per project) with workmux state redirected there via XDG_STATE_HOME. - New baked configs: zellij Tokyo Night Moon theme + workmux layout, workmux config (worktree_dir: /worktrees). - Full rename: image -> devcube, workflow -> build-devcube.yml, ujust recipes -> devcube-*, just file -> 61-devcube.just, env -> DEVCUBE_*, sentinel -> DEVCUBE, state volume -> hypercube-devcube-home. - Update nvim-launcher/desktop to open `devc nvim`, plus docs and the build test reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K44UxeGUD7Peow4F4ipmXz
1 parent cfceb01 commit 998b759

24 files changed

Lines changed: 551 additions & 354 deletions

File tree

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Build and publish nvim-dev container image
2-
# Triggered on changes to dot_files/nvim/ or manual dispatch
3-
# Image published to: ghcr.io/binarypie-dev/nvim-dev:latest
1+
# Build and publish the devcube container image
2+
# Triggered on changes to the baked dot_files configs or manual dispatch
3+
# Image published to: ghcr.io/binarypie-dev/devcube:latest
44

5-
name: Build nvim-dev Image
5+
name: Build devcube Image
66

77
concurrency:
88
group: ${{ github.workflow }}-${{ github.ref }}
@@ -13,20 +13,30 @@ on:
1313
branches:
1414
- main
1515
paths:
16-
# Config is baked into the image, so any config change must rebuild.
16+
# Configs are baked into the image, so any config change must rebuild.
17+
- 'dot_files/devcube/**'
1718
- 'dot_files/nvim/**'
18-
- '.github/workflows/build-nvim-dev.yml'
19+
- 'dot_files/fish/**'
20+
- 'dot_files/starship/**'
21+
- 'dot_files/zellij/**'
22+
- 'dot_files/workmux/**'
23+
- '.github/workflows/build-devcube.yml'
1924
pull_request:
2025
paths:
26+
- 'dot_files/devcube/**'
2127
- 'dot_files/nvim/**'
22-
- '.github/workflows/build-nvim-dev.yml'
28+
- 'dot_files/fish/**'
29+
- 'dot_files/starship/**'
30+
- 'dot_files/zellij/**'
31+
- 'dot_files/workmux/**'
32+
- '.github/workflows/build-devcube.yml'
2333
workflow_dispatch:
2434
schedule:
2535
# Rebuild daily to get updated packages
2636
- cron: '0 6 * * *'
2737

2838
env:
29-
IMAGE_NAME: nvim-dev
39+
IMAGE_NAME: devcube
3040
IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
3141

3242
jobs:
@@ -85,8 +95,8 @@ jobs:
8595
- name: Build and push
8696
uses: docker/build-push-action@v7
8797
with:
88-
context: dot_files/nvim
89-
file: dot_files/nvim/Containerfile
98+
context: dot_files
99+
file: dot_files/devcube/Containerfile
90100
platforms: ${{ matrix.platform }}
91101
push: ${{ github.event_name != 'pull_request' }}
92102
tags: ${{ steps.meta.outputs.tags }}
@@ -129,12 +139,12 @@ jobs:
129139
130140
- name: Generate build summary
131141
run: |
132-
echo "## nvim-dev Image Built" >> $GITHUB_STEP_SUMMARY
142+
echo "## devcube Image Built" >> $GITHUB_STEP_SUMMARY
133143
echo "" >> $GITHUB_STEP_SUMMARY
134144
echo "**Image:** \`${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY
135145
echo "" >> $GITHUB_STEP_SUMMARY
136146
echo "### Usage" >> $GITHUB_STEP_SUMMARY
137147
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
138-
echo "ujust nvim-setup # pull image + install the 'nvim' wrapper" >> $GITHUB_STEP_SUMMARY
139-
echo "nvim # launch the AI-first editor" >> $GITHUB_STEP_SUMMARY
148+
echo "ujust devcube-setup # pull image + install the 'devc' wrapper" >> $GITHUB_STEP_SUMMARY
149+
echo "devc # launch the parallel-agent workspace (workmux)" >> $GITHUB_STEP_SUMMARY
140150
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

CONTRIBUTING.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ hypercube/
3333
│ │ ├── hyprlock.conf # Lock screen
3434
│ │ ├── hypridle.conf # Idle management
3535
│ │ └── hyprpaper.conf # Wallpaper
36+
│ ├── devcube/ # devcube IDE image (Containerfile, devc wrapper)
3637
│ ├── lazygit/ # Lazygit config
37-
│ ├── nvim/ # Neovim/LazyVim setup
38+
│ ├── nvim/ # Neovim/LazyVim config (baked into devcube)
3839
│ ├── qt6ct/ # Qt6 theming
40+
│ ├── workmux/ # workmux parallel-agent config (baked into devcube)
41+
│ ├── zellij/ # zellij multiplexer config (baked into devcube)
3942
│ ├── quickshell/ # App launcher
4043
│ └── starship/ # Shell prompt
4144

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
> Cloud-native development environment with vim keybindings
44
55
[![Build](https://github.com/binarypie-dev/hypercube/actions/workflows/build.yml/badge.svg)](https://github.com/binarypie-dev/hypercube/actions/workflows/build.yml)
6-
[![nvim-dev](https://github.com/binarypie-dev/hypercube/actions/workflows/build-nvim-dev.yml/badge.svg)](https://github.com/binarypie-dev/hypercube/actions/workflows/build-nvim-dev.yml)
6+
[![devcube](https://github.com/binarypie-dev/hypercube/actions/workflows/build-devcube.yml/badge.svg)](https://github.com/binarypie-dev/hypercube/actions/workflows/build-devcube.yml)
77
[![Copr](https://copr.fedorainfracloud.org/coprs/binarypie/hypercube/package/datacube/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/binarypie/hypercube/)
88
[![GHCR](https://img.shields.io/badge/GHCR-ghcr.io%2Fbinarypie--dev%2Fhypercube-blue)](https://ghcr.io/binarypie-dev/hypercube)
99

build_files/hypercube/03-hypercube-configs.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ source = /usr/share/hypercube/config/hypr/hyprland.conf
5555
5656
EOF
5757

58-
### Neovim - AI-first sandbox overrides
59-
# The editor config + AI agents ship baked into the podman image
60-
# (ujust nvim-setup). Users keep ONLY personal plugin overrides here; this
58+
### Neovim - devcube sandbox overrides
59+
# The editor config + AI agents ship baked into the devcube podman image
60+
# (ujust devcube-setup). Users keep ONLY personal plugin overrides here; this
6161
# directory is bind-mounted into the container's baked LazyVim config and
6262
# layered on top of it.
6363
mkdir -p /etc/skel/.config/hypercube/nvim/lua/plugins

build_files/hypercube/99-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ REQUIRED_FILES=(
5757
# DX config
5858
"/etc/distrobox/distrobox.ini"
5959
"/usr/share/ublue-os/just/60-hypercube.just"
60-
"/usr/share/ublue-os/just/61-nvim.just"
60+
"/usr/share/ublue-os/just/61-devcube.just"
6161
)
6262

6363
for file in "${REQUIRED_FILES[@]}"; do

dot_files/.dockerignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Build context for the devcube image is dot_files/. Exclude everything by
2+
# default and re-include only the dirs the Containerfile bakes, so the heavy
3+
# desktop configs (hypr backgrounds, quickshell assets, ...) never enter the
4+
# build context.
5+
*
6+
!devcube/
7+
!nvim/
8+
!fish/
9+
!starship/
10+
!zellij/
11+
!workmux/
12+
13+
# Noise inside the kept dirs.
14+
**/.git
15+
**/.DS_Store
16+
**/Thumbs.db
17+
**/*.log
18+
**/*.swp
19+
**/*.swo
20+
**/*~
21+
22+
# Neovim lock/runtime data shouldn't be baked (mounted/managed at runtime).
23+
nvim/lazy-lock.json
Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
# Hypercube AI-first Neovim sandbox
1+
# Hypercube devcube — containerized IDE + parallel-agent orchestration
22
#
3-
# A self-contained, portable podman image: LazyVim (baked in), the full dev
4-
# toolchain (LSPs/formatters/linters), and AI coding agents (Claude Code, OpenAI
5-
# Codex, Antigravity, GitHub CLI). Agents are launched from inside nvim.
3+
# A self-contained, portable podman image: Neovim/LazyVim (baked in), the full
4+
# dev toolchain (LSPs/formatters/linters), AI coding agents (Claude Code, OpenAI
5+
# Codex, Antigravity, GitHub CLI), plus zellij + workmux for running multiple
6+
# agents in parallel (each in its own git worktree) and a fish + starship shell.
67
#
7-
# Build: podman build -t nvim-dev .
8-
# Run: podman run --rm -it nvim-dev (see scripts/sandbox.sh for mounts)
8+
# The build context is the parent dot_files/ dir so the fish/starship/zellij/
9+
# workmux/nvim configs (top-level dotfiles) can be baked in.
10+
#
11+
# Build: cd dot_files && podman build -t devcube -f devcube/Containerfile .
12+
# Run: devc (see devcube/scripts/devcube.sh for mounts + dispatch)
913

1014
FROM registry.fedoraproject.org/fedora-toolbox:44
1115

@@ -131,11 +135,17 @@ RUN brew install \
131135
# =============================================================================
132136
# LAYER 6: Infrastructure tools via Homebrew
133137
# =============================================================================
138+
# zellij (terminal multiplexer) + workmux (git-worktree -> multiplexer
139+
# orchestration; a brew tap, auto-tapped by the fully-qualified name) power the
140+
# parallel-agent workflow. starship renders the fish prompt baked in below.
134141
RUN brew install \
135142
opentofu \
136143
helm \
137144
sqlfluff \
138-
fish
145+
fish \
146+
starship \
147+
zellij \
148+
raine/workmux/workmux
139149

140150
# =============================================================================
141151
# LAYER 7: Rust toolchain (as linuxbrew user)
@@ -251,21 +261,35 @@ RUN mkdir -p /etc/profile.d /etc/fish/conf.d \
251261
# The full LazyVim config is baked into $HOME/.config/nvim. Personal overrides
252262
# are bind-mounted at runtime from the host (~/.config/hypercube/nvim) and
253263
# layered on top via the runtimepath (see lua/config/lazy.lua).
254-
COPY config/ /root/.config/nvim/
264+
# NOTE: the build context is dot_files/, so the nvim config lives under nvim/.
265+
COPY nvim/config/ /root/.config/nvim/
255266

256267
# Pre-install all plugins + build treesitter parsers so first launch is fast and
257268
# offline. HOME=/root and PATH already include the brew nvim binary.
258269
RUN nvim --headless "+Lazy! sync" +qa
259270

271+
# =============================================================================
272+
# LAYER 14b: Bake the shell / multiplexer / orchestrator configs
273+
# =============================================================================
274+
# fish + starship give a good in-container shell/prompt; zellij + workmux drive
275+
# the parallel-agent workflow. These seed into the persisted home volume on
276+
# first run (podman copy-up), like the nvim config above. starship.toml lands at
277+
# the exact path dot_files/fish/config.fish hardcodes for STARSHIP_CONFIG, so
278+
# fish needs no edits (and it lives outside /root, so it's always present).
279+
COPY fish/ /root/.config/fish/
280+
COPY zellij/ /root/.config/zellij/
281+
COPY workmux/ /root/.config/workmux/
282+
COPY starship/ /usr/share/hypercube/config/starship/
283+
260284
# =============================================================================
261285
# LAYER 15: Entrypoint
262286
# =============================================================================
263-
COPY entrypoint.sh /usr/local/bin/hypercube-nvim-entrypoint
264-
RUN chmod +x /usr/local/bin/hypercube-nvim-entrypoint
265-
ENTRYPOINT ["/usr/local/bin/hypercube-nvim-entrypoint"]
287+
COPY devcube/entrypoint.sh /usr/local/bin/devcube-entrypoint
288+
RUN chmod +x /usr/local/bin/devcube-entrypoint
289+
ENTRYPOINT ["/usr/local/bin/devcube-entrypoint"]
266290
CMD ["nvim"]
267291

268292
# Labels for GitHub Container Registry
269293
LABEL org.opencontainers.image.source="https://github.com/binarypie/hypercube"
270-
LABEL org.opencontainers.image.description="AI-first Neovim sandbox: LazyVim + dev toolchain + Claude Code, Codex, Antigravity, gh"
294+
LABEL org.opencontainers.image.description="devcube: containerized IDE (Neovim/LazyVim + dev toolchain + Claude Code, Codex, Antigravity, gh) with zellij + workmux parallel-agent orchestration"
271295
LABEL org.opencontainers.image.licenses="MIT"
Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
# Hypercube Neovim sandbox — local development and testing commands
1+
# Hypercube devcube — local development and testing commands
2+
#
3+
# The build context is the parent dot_files/ dir (so fish/starship/zellij/
4+
# workmux/nvim configs can be baked), hence `-f Containerfile ..` below.
25

3-
local_image := "localhost/nvim-dev"
4-
remote_image := "ghcr.io/binarypie-dev/nvim-dev:latest"
5-
# Throwaway volume so local testing never touches the real hypercube-nvim-home.
6-
test_volume := "hypercube-nvim-test"
6+
local_image := "localhost/devcube"
7+
remote_image := "ghcr.io/binarypie-dev/devcube:latest"
8+
# Throwaway volumes so local testing never touches the real per-project state.
9+
test_volume := "hypercube-devcube-test"
10+
test_wt_prefix := "devcube-wt-test"
711

812
# Default recipe - show help
913
default:
@@ -13,16 +17,16 @@ default:
1317
# Image Building
1418
# =============================================================================
1519

16-
# Build the container image locally
20+
# Build the container image locally (context is the parent dot_files/ dir)
1721
build:
18-
@echo "Building nvim-dev image locally..."
19-
podman build -t {{local_image}} .
22+
@echo "Building devcube image locally..."
23+
podman build -t {{local_image}} -f Containerfile ..
2024
@echo "Done! Image: {{local_image}}"
2125

2226
# Build without cache
2327
build-no-cache:
24-
@echo "Building nvim-dev image (no cache)..."
25-
podman build --no-cache -t {{local_image}} .
28+
@echo "Building devcube image (no cache)..."
29+
podman build --no-cache -t {{local_image}} -f Containerfile ..
2630
@echo "Done! Image: {{local_image}}"
2731

2832
# Push to GHCR (requires: podman login ghcr.io)
@@ -34,30 +38,27 @@ push:
3438
# Usage (against the LOCAL image)
3539
# =============================================================================
3640

37-
# Launch the sandbox (nvim) from the local image, using a throwaway test volume
41+
# Launch devcube from the local image (e.g. `just run` for workmux, `just run nvim`),
42+
# using throwaway test volumes.
3843
run *args:
39-
HYPERCUBE_NVIM_IMAGE={{local_image}} HYPERCUBE_NVIM_VOLUME={{test_volume}} ./scripts/sandbox.sh {{args}}
44+
DEVCUBE_IMAGE={{local_image}} DEVCUBE_VOLUME={{test_volume}} DEVCUBE_WT_PREFIX={{test_wt_prefix}} ./scripts/devcube.sh {{args}}
4045

41-
# Launch an agent directly (e.g. `just run-agent claude`) from the local image
46+
# Launch a specific tool directly (e.g. `just run-agent claude`) from the local image
4247
run-agent agent *args:
43-
#!/usr/bin/bash
44-
set -euo pipefail
45-
link="$(mktemp -d)/{{agent}}"
46-
ln -s "$(pwd)/scripts/sandbox.sh" "$link"
47-
HYPERCUBE_NVIM_IMAGE={{local_image}} HYPERCUBE_NVIM_VOLUME={{test_volume}} "$link" {{args}}
48+
DEVCUBE_IMAGE={{local_image}} DEVCUBE_VOLUME={{test_volume}} DEVCUBE_WT_PREFIX={{test_wt_prefix}} ./scripts/devcube.sh {{agent}} {{args}}
4849

4950
# Open a shell in the local image
5051
shell:
5152
podman run --rm -it --init --user 0:0 --security-opt label=disable \
52-
-e HYPERCUBE_NVIM=1 -e TERM \
53+
-e DEVCUBE=1 -e TERM \
5354
-v {{test_volume}}:/root \
5455
{{local_image}} bash
5556

5657
# =============================================================================
5758
# Tests
5859
# =============================================================================
5960

60-
# Verify the image: nvim config loads and the toolchain + AI CLIs are present
61+
# Verify the image: nvim config loads and the toolchain + AI CLIs + orchestrators are present
6162
test-build: build
6263
@echo "Testing container..."
6364
podman run --rm {{local_image}} nvim --headless +qa
@@ -70,6 +71,10 @@ test-build: build
7071
podman run --rm {{local_image}} claude --version
7172
podman run --rm {{local_image}} codex --version
7273
podman run --rm {{local_image}} agy --version
74+
podman run --rm {{local_image}} zellij --version
75+
podman run --rm {{local_image}} workmux --version
76+
podman run --rm {{local_image}} starship --version
77+
podman run --rm {{local_image}} fish --version
7378
@echo ""
7479
@echo "All tests passed!"
7580

@@ -81,6 +86,7 @@ test-build: build
8186
clean-image:
8287
-podman rmi {{local_image}}
8388

84-
# Remove the throwaway test volume
89+
# Remove the throwaway test volumes (home + any per-project worktree volumes)
8590
clean-volume:
8691
-podman volume rm -f {{test_volume}}
92+
-podman volume ls -q | grep '^{{test_wt_prefix}}-' | xargs -r podman volume rm -f
File renamed without changes.

0 commit comments

Comments
 (0)