- Shell 87.8%
- JavaScript 12.2%
| assistants | ||
| docs | ||
| home | ||
| host | ||
| scripts | ||
| .gitignore | ||
| AGENTS.md | ||
| README.md | ||
AI development workstation
Reproducible user configuration for the code-server development workstation. The
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/
code-server/ Container definition and startup provisioning
nfs/ VM-side NFS mount template
t3/ Host-native T3 Code runtime and systemd service
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 observed on 2026-07-12 is:
- Ubuntu 24.04-based LinuxServer code-server container
- persistent home at
/config - 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 - code-server 4.123.0, Codex CLI 0.144.1, and Claude Code 2.1.207
- host-native Node.js 24.18.0, T3 Code 0.0.28, Codex CLI 0.145.0, and Claude Code 2.1.220
The code-server versions document the observed container. The host-native
runtime versions are pins managed under host/t3/.
Rebuild
On the VM, install the host dependencies:
sudo apt update
sudo apt install git nfs-common tmux fzf jq
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 code-server:
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 the VM/container user must agree on UID/GID 1000:1000.
Do not start code-server against an unmounted /mnt/data; otherwise projects can
be written to the VM's local filesystem under the empty mount point.
Create the code-server environment file and start the container:
cd host/code-server
cp .env.example .env
# Set SUDO_PASSWORD in .env without committing it.
docker compose config
docker compose up -d
docker compose exec code-server /custom-cont-init.d/10-dev-tools.sh
The compose definition mirrors the observed container, including its four volume mounts, bind address, Docker Mods, and immutable code-server image digest. The startup script installs the current CLI releases verified from npm on 2026-07-12: Codex 0.144.1 and Claude Code 2.1.207. Runtime parameters follow the LinuxServer code-server documentation.
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
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.
T3 Code
T3 Code runs directly on dev-workstation as user step. The systemd service
binds to 192.168.20.205:3773, stores T3 state under /home/step/.t3, and uses
the projects under /mnt/data/coding. It reuses the Codex, Claude, Git, and SSH
state from the persistent code-server home through host-side symlinks.
Install or reconcile the pinned host runtime from the repository root:
sudo ./host/t3/install.sh
The installer verifies the pinned Node.js archive checksum, installs the pinned
T3 Code and agent CLI packages under /opt/ai-runtime, and enables
t3code.service. It does not read or copy assistant credentials.
Open http://192.168.20.205:3773. T3 runs in unsafe no-auth mode because the
service is restricted to the trusted homelab interface. The browser opens the
workspace without a pairing token. Anyone who can reach
192.168.20.205:3773 gets the same agent, terminal, file, and repository access
as user step.
Stable T3 Code cannot add projects through a remote GUI. Register a project on the VM instead:
sudo -u step env HOME=/home/step PATH=/usr/local/bin:/usr/bin:/bin \
t3 project add --base-dir /home/step/.t3 /mnt/data/coding/example
Claude Code authentication requires one interactive login when its stored session is absent or expired:
sudo -u step env HOME=/home/step PATH=/usr/local/bin:/usr/bin:/bin \
claude auth login
Inspect the service with sudo systemctl status t3code and restart it with
sudo systemctl restart t3code. Logs are in the system journal under
t3code.service.
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 code-server browser 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.