- Shell 100%
| assistants | ||
| docs | ||
| home | ||
| host | ||
| scripts | ||
| .gitignore | ||
| AGENTS.md | ||
| README.md | ||
AI development workstation
Reproducible configuration for the browser development workstation. Projects live
on a TrueNAS NFS export mounted at /mnt/data. Persistent Codex and Claude Code
sessions run inside tmux.
Layout
assistants/
claude/ Claude Code global instructions and status line
codex/ Codex global instructions
home/
bin/ Agent notification, clipboard, and session helpers
bash/ Interactive shell additions
tmux/ tmux configuration
host/
agents/ Host Node.js, Codex, and Claude Code installer
development/ Host Go, Orca, and Docker Engine installer
nfs/ VM-side NFS mount template
desktop/ Native XFCE and GPU-accelerated Selkies desktop
scripts/
install.sh Install user configuration with backups
verify.sh Check commands, links, and the project mount
The repository intentionally does not track credentials, histories, logs,
databases, ~/.codex/config.toml, or ~/.claude/settings.json. Those files mix
authentication, per-machine trust, installed plugins, and mutable application
state. Only durable instructions and workstation behavior belong here. The
installer makes one targeted, idempotent edit to settings.json — pointing
statusLine at the managed script — but never tracks or overwrites the file.
Current topology
The state reconciled on 2026-08-30 is:
- Debian 13 VM on Proxmox node
px03 - dedicated Intel Iris Xe GPU through PCI passthrough
- native XFCE X.Org desktop at
https://code.home.step1.ro - workspace root at
/mnt/data - NFSv4.2 source
192.168.20.20:/mnt/fast-pool/coding-vm - NFS ownership mapped to UID/GID
1000:1000 - Node.js 24.20.0, Codex CLI 0.151.0, and Claude Code 2.1.251
- Go 1.27.0, Orca 1.4.192, and Docker Engine 29.7.2 with Buildx and Compose
- up to 8 GiB of compressed zram swap and the
Europe/Viennatimezone - Selkies source pinned by commit under
host/desktop/install.sh
The runtime versions are pins under host/agents/, host/development/, and
host/desktop/.
Rebuild
Terraform and cloud-init create the VM, mount the workspace, and install the Intel firmware. The first boot then restarts before repository provisioning. The repository installs native XFCE, X.Org, Selkies, and the development tools. For a manual repair, start with the base host packages:
sudo apt update
sudo apt install ca-certificates curl firmware-intel-graphics git intel-media-va-driver-non-free jq linux-image-amd64 nfs-common qemu-guest-agent sudo
jq is used by the installer to wire the Claude Code status line into
settings.json; without it the installer prints the block to add by hand.
Create /mnt/data, copy the entry from
host/nfs/fstab.example into /etc/fstab, then mount and verify it before
starting the desktop:
sudo mkdir -p /mnt/data
sudo mount /mnt/data
findmnt -T /mnt/data
touch /mnt/data/.write-test && rm /mnt/data/.write-test
The TrueNAS dataset and VM user must agree on UID/GID 1000:1000. Do not start
the desktop against an unmounted /mnt/data. Projects could otherwise be written to
the VM's local filesystem under the empty mount point.
Clone this repository anywhere on the mounted workspace and install the user configuration:
git clone ssh://git@git.step1.ro:2222/stanta/ai-development.git
cd ai-development
./scripts/install.sh
./scripts/verify.sh
sudo ./host/agents/install.sh
sudo ./host/development/install.sh
sudo ./host/desktop/install.sh
The installer creates symlinks for the managed files and installs pinned
tmux-resurrect, tmux-yank, and tmux-continuum revisions under
~/.config/ai-development/tmux/plugins/. If a destination already
exists, it is moved beside itself with a timestamped .pre-ai-development-*
suffix. It adds one guarded source line to ~/.bashrc; it does not replace the
distribution-provided file.
Restart Codex and Claude Code after changing their global instruction files.
host/agents/install.sh verifies the Node.js archive checksum. It installs the
agent CLIs under /opt/agent-runtime/npm-global and links them through
/usr/local/bin. Authentication and mutable agent state remain in
/home/step/.codex and /home/step/.claude. The installer does not read or
copy credentials.
host/development/install.sh verifies the Go and Orca download checksums. It
installs the pinned Orca AppImage and XFCE launcher for step. It also installs
the pinned Docker packages from Docker's signed Debian repository and adds
step to the docker group. Start a new login session after the first install
so the desktop inherits that group. Docker is available for development
workloads; the native desktop and Selkies services do not depend on it.
The development installer also installs Debian's python3, python3-venv, and
pipx. It installs graphifyy from the 0.9 release series in an isolated pipx
environment for step, exposes graphify in ~/.cargo/bin, and registers its
skills for Claude Code and Codex. Re-running the installer selects the newest
patch in that series. Restart the assistants after installation.
To add these tools to an existing workstation, run
sudo ./host/development/install.sh, then ./scripts/verify.sh as step.
The custom homelab Graphify backend is not part of the upstream package or this
repository. Its configuration and any custom backend code must be restored
separately before using --backend homelab.
Browser desktop
XFCE runs as a native X.Org session on Debian. LightDM logs in the step user
automatically. The passed-through Intel GPU is the primary X.Org device and
drives the laptop panel. It also provides VAAPI encoding and accelerated OpenGL.
The Proxmox console uses serial0, so recovery does not depend on the GPU. The
installer discovers the Intel render node instead of relying on a fixed device
number.
Traefik exposes only https://code.home.step1.ro and protects it with the normal
homelab authentication middleware. Selkies listens on 192.168.20.205:3000.
TLS terminates at Traefik, so browser clipboard, pointer lock, and file transfer
APIs run in a secure browser context. Selkies supports text and image clipboard
transfer plus uploads and downloads rooted at /mnt/data.
The desktop and agent tools run as the native step user. Authentication state
remains in /home/step. Code and other durable data must remain under
/mnt/data.
The Selkies launcher disables X11 screen blanking and display power management. The remote desktop therefore remains available after long idle periods.
Inspect the desktop with:
systemctl status lightdm selkies
journalctl -u selkies -n 100 --no-pager
vainfo --display drm --device /dev/dri/renderD128
Status line
assistants/claude/statusline-combined.sh renders the Claude Code status line by
concatenating two plugin status lines onto a single row: the caveman mode
indicator and claude-hud (context, path, usage, weekly). It reads the session
JSON once from stdin and feeds it to each. Plugin paths are resolved from the
cache at runtime, so the script survives plugin version bumps; a missing plugin
is skipped rather than fatal.
The installer symlinks the script into ~/.claude/ and sets
settings.json's statusLine.command to bash ~/.claude/statusline-combined.sh.
The status line still depends on the caveman and claude-hud plugins being
installed, which — like the rest of settings.json — is not tracked here.
tmux quick guide
Ctrl-b is the tmux prefix: press it, release it, then press the next key. New
agent sessions start with agent and shell tabs in the current directory.
| Action | Command or keys | Result |
|---|---|---|
| Start Codex | cdev or cdev -s NAME |
Create or attach to a Codex session. |
| Start Claude | ccdev or ccdev -s NAME |
Create or attach to a Claude session. |
| List work | dagents |
Show sessions and tabs, with attention states first. |
| Pick session | dattach or Ctrl-b f |
Open the fzf session picker. |
| Detach | Ctrl-b d |
Leave the session running in the background. |
| New tab | Ctrl-b c |
Create a tab in the current directory. |
| Change tab | Alt-1 to Alt-9, or Ctrl-b n / Ctrl-b p |
Select a numbered, next, or previous tab. |
| Split left/right | Ctrl-b, then the vertical bar key |
Create a pane beside the current pane. |
| Split top/bottom | Ctrl-b - |
Create a pane below the current pane. |
| Change pane | Ctrl-b then an arrow key |
Focus an adjacent pane. |
| Close pane | Ctrl-b x, then y |
Remove the current pane. exit alone leaves an EXITED pane. |
| Zoom pane | Ctrl-b z |
Toggle the current pane between full-screen and tiled. |
| Copy text | Ctrl-b [, select text, then y |
Copy through tmux-yank to the browser clipboard. |
| Clear alert | Ctrl-b a |
Clear APPROVAL, DONE, or FAILED from the tab. |
| Save layout | Ctrl-b Ctrl-s |
Save sessions, tabs, panes, and working directories. |
| Restore layout | Ctrl-b Ctrl-r |
Restore the last saved tmux layout. |
| Full help | dhelp |
Show all managed commands and bindings. |
The top bar shows tabs and attention states: APPROVAL, DONE, FAILED, and
EXITED.
Codex turn completion and approval events and Claude notification, stop, and
failure hooks feed agent-notify. The helper updates tmux, rings the terminal
bell, and can publish a generic message to a self-hosted ntfy endpoint. To
enable ntfy without tracking its token:
cp ~/.config/ai-development/notifications.env.example \
~/.config/ai-development/notifications.env
chmod 600 ~/.config/ai-development/notifications.env
# Edit NTFY_URL, NTFY_TOPIC, and optionally NTFY_TOKEN.
Notifications contain only the agent name, tmux session/tab, and repository basename. Prompt and response text is never forwarded.
tmux-yank uses OSC 52 to write to the connected client clipboard.
Ctrl-b y copies the current command line and Ctrl-b Y copies the pane
working directory.
Tmux layouts are saved every 15 minutes and restored after the tmux server
restarts. Pane contents are deliberately excluded because they may contain
source or secrets. Restoring a layout does not resume an AI conversation; use
codex resume or claude --resume explicitly in the restored agent tab.
ccdev preserves the current workstation behavior and launches Claude Code with
--dangerously-skip-permissions. Use it only inside the isolated development
environment.