A Docker Mod for the linuxserver/code-server container that installs the following tools on every container start:
| Tool | Package | Description |
|---|---|---|
| tmux | apt (tmux) |
Terminal multiplexer for persistent terminal sessions |
| fd | apt (fd-find) |
Fast and user-friendly alternative to find (use alias fd=fdfind) |
| ripgrep | apt (ripgrep) |
Fast recursive text search (rg) |
| fzf | apt (fzf) |
General-purpose fuzzy finder for the terminal |
| gh | apt (gh, GitHub CLI repo) |
GitHub's official CLI for PRs, issues, and repos (gh command). AI agents can use it without skills or mcp. |
| Tool | Package | Description |
|---|---|---|
| gemini-cli | @google/gemini-cli |
Google Gemini in your terminal |
| Antigravity CLI | official installer | Go-based multi-step agentic CLI (agy command) |
| claude-code | @anthropic-ai/claude-code |
Anthropic Claude agentic coding CLI |
| openclaude | @gitlawb/openclaude |
Open-source Claude-compatible coding agent CLI |
| Cursor Agent CLI | official installer | Cursor editor CLI (cursor-agent command) |
| GitHub Copilot CLI | @github/copilot |
GitHub Copilot in your terminal (copilot command) |
| OpenAI Codex CLI | @openai/codex |
OpenAI Codex local coding agent (codex command) |
Required – this mod depends on
linuxserver/mods:code-server-nvmand must be loaded alongside it. The s6 init graph hard-depends oninit-mod-code-server-nvm-install, so NVM and its bundled npm are guaranteed to be ready before AI tool installation begins.
Just add this repo's image, ghcr.io/gmcouto/code-server-ai-tools:latest, to your container's DOCKER_MODS environment variable. You can do this either in your docker run command or in docker-compose.yml:
docker run -d \
--name=code-server \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Etc/UTC \
-e DOCKER_MODS=linuxserver/mods:code-server-nvm|ghcr.io/gmcouto/code-server-ai-tools:latest \
-p 8443:8443 \
-v /path/to/config:/config \
--restart unless-stopped \
lscr.io/linuxserver/code-server:latestservices:
code-server:
image: lscr.io/linuxserver/code-server:latest
container_name: code-server
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- DOCKER_MODS=linuxserver/mods:code-server-nvm|ghcr.io/gmcouto/code-server-ai-tools:latest
volumes:
- /path/to/config:/config
ports:
- 8443:8443
restart: unless-stoppedDOCKER_MODS=linuxserver/mods:universal-package-install|linuxserver/mods:code-server-extension-arguments|linuxserver/mods:code-server-nodejs|linuxserver/mods:code-server-nvm|linuxserver/mods:universal-docker|linuxserver/mods:code-server-python3|linuxserver/mods:code-server-rust|linuxserver/mods:code-server-pnpm|linuxserver/mods:code-server-golang|ghcr.io/gmcouto/code-server-ai-tools:latest
INSTALL_PACKAGES=pkg-config|libssl-dev|libglib2.0-dev|libgdk-pixbuf-2.0-dev|libpango1.0-dev|libatk1.0-dev|libgtk-3-dev|libjavascriptcoregtk-4.1-dev|libsoup-3.0-dev|libwebkit2gtk-4.1-dev
EXTENSIONS_GALLERY='{"serviceUrl":"https://marketplace.visualstudio.com/_apis/public/gallery","cacheUrl":"https://vscode.blob.core.windows.net/gallery/index","itemUrl":"https://marketplace.visualstudio.com/items"}'
NODEJS_MOD_VERSION=24
The following sections will help you get the most of your code-server instance...
Add the following to your ~/.tmux.conf so tmux command works as expected:
set-option -g default-shell /bin/bash
set -g mouse onThen install tmux-integrated extension, if you want the UI to integrate to your CLI tools (not really necessary).
Using copilot-chat extension, login to github. Then run this in the browser console with code-server tab open, then restart the page, so the copilot-chat consider itself properly setup:
(async () => {
const DB_NAME = 'vscode-web-state-db-global';
const STORE = 'ItemTable';
const db = await new Promise((res, rej) => {
const req = indexedDB.open(DB_NAME);
req.onupgradeneeded = () => req.result.createObjectStore(STORE);
req.onsuccess = () => res(req.result);
req.onerror = () => rej(req.error);
});
const existing = await new Promise((res, rej) => {
const tx = db.transaction(STORE, 'readonly');
const get = tx.objectStore(STORE).get('chat.setupContext');
get.onsuccess = () => res(get.result ? JSON.parse(get.result) : {});
get.onerror = () => rej(get.error);
});
const tx = db.transaction(STORE, 'readwrite');
const store = tx.objectStore(STORE);
store.put(JSON.stringify({ ...existing, completed: true }), 'chat.setupContext');
store.put('true', 'chat.setupContext.migrated.v1');
await new Promise((res, rej) => {
tx.oncomplete = res;
tx.onerror = () => rej(tx.error);
});
console.log('Done! Reload the page.');
db.close();
})();