No description
  • Shell 87.8%
  • JavaScript 12.2%
Find a file
2026-07-27 19:44:37 +00:00
assistants Expand controlled-writing and verification rules in global instructions 2026-07-27 19:44:37 +00:00
docs Add LLM development roadmap 2026-07-27 19:44:37 +00:00
home Improve tmux workflow for AI agent sessions 2026-07-12 23:07:57 +02:00
host Add host-native T3 Code runtime and systemd service 2026-07-27 19:44:33 +00:00
scripts Add host-native T3 Code runtime and systemd service 2026-07-27 19:44:33 +00:00
.gitignore Initialize ai-development workstation configuration 2026-07-12 22:19:59 +02:00
AGENTS.md Add repository contributor guidelines 2026-07-12 23:07:57 +02:00
README.md Add host-native T3 Code runtime and systemd service 2026-07-27 19:44:33 +00:00

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.