AI Cockpit — Setup Guide

AI Cockpit — New-Machine Setup Guide

        . | .
         \|/
     .--- O ---.
    /    /|\    \
   '    / | \    '
        . | .

  Fresh Linux Mint → Working AI Cockpit

Step-by-step setup for a Linux Mint 22 / Ubuntu 24.04 machine. Each step has a verification checkpoint. Do not skip steps. If a step fails, the Troubleshooting section at the end has fixes.


Table of contents

  1. Before you start
  2. Step 1 — System packages
  3. Step 2 — Node.js (for Claude Code & Gemini CLI)
  4. Step 3 — AI CLI tools
  5. Step 4 — Ollama and local models
  6. Step 5 — Apache PHP setup
  7. Step 6 — Cockpit files
  8. Step 7 — Permissions and sudoers
  9. Step 8 — Built-in capabilities
  10. Step 9 — Tool binaries (optional but recommended)
  11. Step 10 — First launch verification
  12. Step 11 — Worker provider keys (optional)
  13. Step 12 — Personalization
  14. Troubleshooting
  15. Uninstall

Before you start

Required

Optional but useful

What you should download before running these steps

Get this bundle ready in ~/Downloads/:

cockpit-bundle/
├─ index.html
├─ bridge.php
├─ files.php
├─ status.php
├─ models.php
├─ saver.php
├─ session.php
├─ config.php
├─ library.php
├─ paths.json
├─ search.php
├─ export.php
├─ import.php
├─ version.php
├─ VERSION
├─ capabilities.php
├─ orchestrator.php
├─ workers.php
├─ workers_providers.json
├─ tools.php
├─ tools_builtins.tar.gz
├─ cockpit_builtins.tar.gz
├─ install_capabilities.sh
├─ install_cockpit.sh
├─ build_cockpit_tarball.sh
├─ cockpit_start.sh
├─ cockpit_stop.sh
├─ agent_loop.sh
└─ crud_executor.sh

The cockpit ships an automated install_cockpit.sh script that handles most of these steps end-to-end. This guide walks through the manual sequence — useful if you want to understand what’s happening or if the auto-installer fails partway.


Step 1 — System packages

Install Apache, PHP, and the supporting CLI tools that the cockpit depends on:

sudo apt update
sudo apt install -y nala
sudo nala install -y \
    apache2 \
    php8.3 \
    php8.3-cli \
    php8.3-curl \
    php8.3-mbstring \
    php8.3-xml \
    php8.3-zip \
    libapache2-mod-php8.3 \
    tmux \
    jq \
    curl \
    git \
    util-linux \
    xed \
    zsh \
    build-essential \
    ca-certificates

Verification

apache2 -v          # Should show 2.4.x
php -v              # Should show 8.3.x
tmux -V             # Should show 3.x or higher
jq --version        # Should show jq-1.6 or 1.7
which curl          # Should show /usr/bin/curl

If any command says “not found”, re-run the install for that package.

Why each package?


Step 2 — Node.js (for Claude Code & Gemini CLI)

Node.js is needed for npx (which launches MCP servers) and for the official Claude Code and Gemini CLI tools.

# NodeSource repository for current LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo nala install -y nodejs

# Set up a global npm prefix in user-space (avoids sudo for global installs)
mkdir -p "$HOME/.npm-global"
npm config set prefix "$HOME/.npm-global"

# Add to PATH (zsh)
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc

Reload your shell config or open a fresh terminal.

Verification

node --version      # Should show v20.x
npm --version       # Should show 10.x
echo $PATH | tr ':' '\n' | grep npm-global
                    # Should show /home/<you>/.npm-global/bin

Step 3 — AI CLI tools

Install the three CLI tools the cockpit dispatches to:

# Anthropic Claude Code
npm install -g @anthropic-ai/claude-code

# Google Gemini CLI
npm install -g @google/gemini-cli

# (Ollama is installed in Step 4)

You’ll need to authenticate each one before the cockpit can use it:

# Claude — opens a browser for OAuth, you sign in to your Anthropic account
claude

# Gemini — likewise, OAuth flow with your Google account
gemini

After both authenticate successfully, you can Ctrl-D out of each.

Verification

claude --version     # Should show a version string
gemini --version     # Likewise

# Sanity smoke tests
echo "Say hello in one word" | claude --print
echo "Say hello in one word" | gemini --prompt

Both should return a response within 5–15 seconds.


Step 4 — Ollama and local models

# Ollama installer — official one-liner
curl -fsSL https://ollama.com/install.sh | sh

# Configure non-default model storage location
mkdir -p "$HOME/ollama/models"
sudo systemctl edit ollama.service

In the editor that opens, paste:

[Service]
Environment="OLLAMA_MODELS=/home/dario/ollama/models"

Save and exit. Then:

sudo systemctl daemon-reload
sudo systemctl restart ollama
sudo systemctl enable ollama

# Also export for interactive shells
echo 'export OLLAMA_MODELS="$HOME/ollama/models"' >> ~/.zshrc
echo 'export OLLAMA_MODELS="$HOME/ollama/models"' >> ~/.bashrc

Pulling models

The cockpit’s default tier-1 recommendations:

# Tier 1 — best for CRUD and context (3 GB VRAM)
ollama pull qwen2.5-coder:3b
ollama pull qwen2.5-coder:7b

# Optional — tool-calling fine-tune
ollama pull MFDoom/deepseek-r1-tool-calling:7b

Verification

ollama list                     # Should list pulled models
ollama show qwen2.5-coder:3b    # Should show model details

# Smoke test
echo "Say hello in one word" | ollama run qwen2.5-coder:3b

If ollama list shows the storage path is /usr/share/ollama/..., the custom path didn’t take effect. Re-check the systemd override file:

systemctl cat ollama.service | grep OLLAMA_MODELS

Step 5 — Apache PHP setup

The cockpit runs as a normal Apache vhost at /var/www/html/cockpit/.

# Make sure mod_php is enabled
sudo a2enmod php8.3
sudo a2enmod rewrite       # Used by some PHP endpoints

# Set timezone in PHP so dates are correct
sudo bash -c 'cat > /etc/php/8.3/apache2/conf.d/99-cockpit.ini' << 'EOF'
date.timezone = Asia/Jerusalem
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
EOF

# Same settings for CLI PHP
sudo cp /etc/php/8.3/apache2/conf.d/99-cockpit.ini /etc/php/8.3/cli/conf.d/

# Restart Apache
sudo systemctl restart apache2
sudo systemctl enable apache2

Verification

# Apache should respond
curl -I http://localhost/   # Should return HTTP/1.1 200 OK

# PHP should be enabled
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/phpinfo.php > /dev/null
curl -s http://localhost/phpinfo.php | grep "PHP Version"
                            # Should show "PHP Version => 8.3.x"
sudo rm /var/www/html/phpinfo.php

# Verify timezone
php -r 'echo date("c"), "\n";'
                            # Should show current time in your zone

Step 6 — Cockpit files

Deploy the cockpit’s web files to /var/www/html/cockpit/:

# Web root for cockpit
sudo mkdir -p /var/www/html/cockpit

# Copy all PHP files, the HTML, JSON catalogs, and VERSION
cd ~/Downloads/cockpit-bundle
sudo cp \
    index.html \
    bridge.php files.php status.php models.php saver.php \
    session.php config.php library.php paths.json \
    search.php export.php import.php version.php VERSION \
    capabilities.php orchestrator.php workers.php tools.php \
    workers_providers.json \
    /var/www/html/cockpit/

# Extract built-in capability and tool definitions
sudo tar -xzf cockpit_builtins.tar.gz -C /var/www/html/cockpit/
sudo tar -xzf tools_builtins.tar.gz   -C /var/www/html/cockpit/

# Scripts that run as the user via tmux
mkdir -p ~/scripts
cp \
    cockpit_start.sh cockpit_stop.sh \
    agent_loop.sh crud_executor.sh \
    install_capabilities.sh \
    ~/scripts/
chmod +x ~/scripts/*.sh

# Cockpit data directory
mkdir -p ~/scripts/cockpit_data/{library,snippets,sources,code,approvals,capabilities/_builtin,plans,workers_state,tools,tools_outputs,_standalone}

# Projects root
mkdir -p ~/Software/Programing/LocalAIProjs

Verification

ls /var/www/html/cockpit/   # Should list all .php and .html files
ls ~/scripts/               # Should list shell scripts
ls ~/scripts/cockpit_data/  # Should show empty subdirs

Step 7 — Permissions and sudoers

Apache (running as www-data) needs read access to the cockpit data and tmux socket. Your user (running as dario) needs write access. The bridge between these is the www-data group.

# Add www-data group membership for shared file access
sudo chgrp -R www-data /var/www/html/cockpit/
sudo chmod -R g+rX /var/www/html/cockpit/

sudo chgrp -R www-data ~/scripts/cockpit_data/
sudo chmod -R g+rwX ~/scripts/cockpit_data/

# tmux socket lives in /tmp; needs group access from www-data
# (cockpit_start.sh creates this on each run with the right perms)

# Add www-data to your group so it can read your home dir prefix
sudo usermod -a -G $USER www-data

# Allow www-data to invoke the cockpit_*.sh scripts without password
sudo bash -c 'cat > /etc/sudoers.d/cockpit' << EOF
www-data ALL=(${USER}) NOPASSWD: ${HOME}/scripts/cockpit_start.sh
www-data ALL=(${USER}) NOPASSWD: ${HOME}/scripts/cockpit_stop.sh
EOF
sudo chmod 440 /etc/sudoers.d/cockpit

Verification

# As www-data, can it read cockpit_data?
sudo -u www-data ls ~/scripts/cockpit_data/
                            # Should list directories without error

# Validate sudoers without breaking the system
sudo visudo -cf /etc/sudoers.d/cockpit
                            # Should say "/etc/sudoers.d/cockpit: parsed OK"

Step 8 — Built-in capabilities

Capability definitions ship as a tarball; deploy them to cockpit_data:

cd ~/Downloads/cockpit-bundle
BUILTINS_SOURCE="$PWD/cockpit_builtins" ~/scripts/install_capabilities.sh

This copies five built-in capabilities (filesystem, git, web-search, web-fetch, ssh) into:

~/scripts/cockpit_data/capabilities/_builtin/

Verification

ls ~/scripts/cockpit_data/capabilities/_builtin/
# Should list 5 directories: filesystem, git, ssh, web-fetch, web-search

# Each should contain CAP.json + README.md
for d in ~/scripts/cockpit_data/capabilities/_builtin/*/; do
    echo "$(basename $d):"
    ls "$d"
done

Without these binaries, the TOOLS card in the cockpit will show “no tools detected”. Install whichever you’ll use:

# Audio/video — almost always wanted
sudo nala install -y ffmpeg

# Speech-to-text — large download, ~1 GB for the base model
sudo nala install -y python3-pip
pip install --user openai-whisper       # Or: nala install whisper

# Document conversion
sudo nala install -y pandoc texlive-xetex texlive-fonts-recommended
                                        # texlive needed for md→pdf

Verification

ffmpeg -version | head -1   # Should show ffmpeg N.x.x
whisper --help | head -3    # Should show Whisper usage
pandoc --version | head -1  # Should show pandoc 3.x

If any are missing, you can still launch the cockpit — Tools will show them as “✗ not found” and you can install later. The cockpit’s Detect button in Tools settings re-scans whenever you click it.

Optional add-ons for later

These don’t ship with built-in tool definitions but you can add them via the “+” button in Tools settings.


Step 10 — First launch verification

Time to start the cockpit:

~/scripts/cockpit_start.sh

You should see output like:

Starting cockpit sessions...
  Claude session: cockpit_claude
  Gemini session: cockpit_gemini
  Ollama session: cockpit_ollama
  tmux socket: /tmp/cockpit_tmux.sock
  Apache: ready
Cockpit ready: http://localhost/cockpit/

Open the cockpit in Brave:

brave-browser http://localhost/cockpit/

What to verify

  1. The topbar shows the brand mark (control-yoke logo + “AI Cockpit” wordmark + version + “by Dario Ruggi”) on the left
  2. Five supplier cards appear: CLAUDE, GEMINI, OLLAMA, WORKERS, TOOLS
  3. CLAUDE is the default active card (expanded with model dropdown)
  4. Stop / Restart buttons appear on the right
  5. Info bar below the strip shows project/chat/path
  6. The chat console is the large central area
  7. Right sidebar has 9 vertical icon tabs

First prompt smoke test

  1. Type “say hello in one word” in the prompt area
  2. Press Ctrl-Enter
  3. Within a few seconds, “Hello” or similar appears as a streamed response

If this works, you’re done. The next steps are optional personalization.


Step 11 — Worker provider keys (optional)

If you want to use online LLM providers as workers:

  1. Click the gear icon next to WORKERS → settings modal
  2. For each provider you want:
  3. Close the modal — the workers dropdown is now populated

Recommended starting point: Groq is free with generous limits and makes a good first test. Once you have a key, smoke-test it via:

  1. Click the WORKERS card
  2. Pick a Groq model (e.g. “Llama 3.3 70B Versatile”)
  3. Type a prompt → press Execute
  4. Response should appear within a few seconds

Step 12 — Personalization

Brave as default browser

xdg-settings set default-web-browser brave-browser.desktop

Auto-start cockpit on login

Create a desktop entry that launches cockpit_start.sh and opens Brave to the cockpit URL:

mkdir -p ~/.config/autostart

cat > ~/.config/autostart/cockpit.desktop << 'EOF'
[Desktop Entry]
Type=Application
Name=AI Cockpit
Exec=bash -c '/home/dario/scripts/cockpit_start.sh && sleep 2 && brave-browser http://localhost/cockpit/'
Icon=preferences-system
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
StartupNotify=false
EOF

Dark theme (you’ve already got this — Linux Mint dark variant)

The cockpit has its own dark theme baked in. No system-level config needed.

Default project

Edit ~/scripts/cockpit_data/last_project.txt to set the project that opens by default each time:

echo "myproject" > ~/scripts/cockpit_data/last_project.txt

Troubleshooting

Apache returns 403 Forbidden

# Permissions on the cockpit directory
sudo chown -R dario:www-data /var/www/html/cockpit/
sudo chmod -R g+rX /var/www/html/cockpit/

# Apache config — make sure /var/www/html is allowed
grep -A3 "Directory /var/www/" /etc/apache2/apache2.conf
                            # Should include "Require all granted"

“Bridge.php returned no response”

The PHP error log usually has the answer:

sudo tail -50 /var/log/apache2/error.log

Common causes:

“Agent session not found in tmux”

# Check what sessions exist
tmux -S /tmp/cockpit_tmux.sock ls 2>&1

# If empty, restart cockpit
~/scripts/cockpit_stop.sh && ~/scripts/cockpit_start.sh

# If permission denied, the socket has wrong group
sudo chgrp www-data /tmp/cockpit_tmux.sock
sudo chmod 660 /tmp/cockpit_tmux.sock

Claude / Gemini OAuth fails

Both CLIs need a working browser OAuth flow:

# From a desktop environment with a browser available
claude   # Will print an auth URL; open it in your browser, sign in
gemini   # Same flow, separate auth

If you’re SSHing in headlessly, you’ll need to do the auth on the machine’s actual desktop session first.

Ollama: “no models” in cockpit dropdown

# Confirm models exist
ollama list

# If empty, pull the defaults:
ollama pull qwen2.5-coder:3b

# Confirm OLLAMA_MODELS is being honored
ls ~/ollama/models/  # Should show downloaded blobs

# If models live in /usr/share/ollama/.ollama/, the systemd override didn't apply
sudo systemctl edit ollama.service   # Re-set the Environment line
sudo systemctl daemon-reload && sudo systemctl restart ollama

Tool detection always says “not found”

# Verify the binaries are in PATH that Apache can see
sudo -u www-data which ffmpeg
sudo -u www-data which whisper
sudo -u www-data which pandoc

# If www-data can't see them but you can, the binaries are in a path
# www-data doesn't search. Either:
#   (a) Use Tools settings to set absolute path
#   (b) Add the path to /etc/environment so it's system-wide

Workers HTTP 401 / 403

API key issue. Re-generate the key on the provider’s site, paste it into Workers settings, save.

Workers HTTP 429

Rate limited. Wait a few minutes or switch providers. The cockpit’s usage tracker shows your call counts per provider in the settings modal.

Plans tab is empty after Plan-mode submit

Check the chat for system messages like “Plan creation failed”. Most common cause is one of the voter agents being unauthenticated or unreachable. Run claude --print "test" and gemini --prompt "test" from a terminal to confirm both are working.

IPv6 / wget bug on Linux Mint

A known bug — wget defaults to IPv6 and times out on some Mint installs. Already absorbed into cockpit_start.sh, but if you see the symptom elsewhere:

# Force IPv4 globally for wget
echo 'inet4_only = on' >> ~/.wgetrc

Apache logs filling up

The cockpit polls the bridge every 200 ms during streams, which generates a lot of access-log entries. If you don’t need them:

# Disable access logging for /cockpit/bridge.php specifically
sudo bash -c 'cat > /etc/apache2/conf-available/cockpit-quiet.conf' << 'EOF'
SetEnvIf Request_URI "/cockpit/bridge\.php" cockpit_quiet
CustomLog ${APACHE_LOG_DIR}/access.log combined env=!cockpit_quiet
EOF
sudo a2enconf cockpit-quiet
sudo systemctl reload apache2

Uninstall

If you ever need to wipe the cockpit:

# Stop everything
~/scripts/cockpit_stop.sh 2>/dev/null

# Web root
sudo rm -rf /var/www/html/cockpit/

# Scripts
rm -rf ~/scripts/cockpit_*.sh ~/scripts/agent_loop.sh ~/scripts/crud_executor.sh ~/scripts/install_capabilities.sh

# Data (this is destructive — projects under here are gone forever)
# Keep this if you want to preserve your chats/library/snippets
rm -rf ~/scripts/cockpit_data/

# Sudoers fragment
sudo rm /etc/sudoers.d/cockpit

# Apache PHP override (optional — only do this if no other PHP apps need it)
sudo rm /etc/php/8.3/apache2/conf.d/99-cockpit.ini
sudo systemctl restart apache2

The Claude / Gemini / Ollama installations stay — they’re independent of the cockpit and you may want them for direct CLI use.


That’s it. If you’ve followed all 12 steps, you have a fully working AI Cockpit. The User Guide covers what to do once it’s running.


Update — June 2026: Additional setup for new features

The base install above is unchanged. These extra steps enable features added later. All are optional — the cockpit runs without them, and each feature degrades gracefully (with a hint) when its tool is missing.

A. uv / uvx — for MCP capabilities (Claude & Gemini)

Capabilities that run an MCP server (e.g. the bundled time capability) launch it via uvx, which ships with uv (Astral’s Python tool).

# Official installer (adds ~/.local/bin to PATH)
curl -LsSf https://astral.sh/uv/install.sh | sh
# new shell, then verify:
uvx --version

B. whisper.cpp + a model — for offline voice input

The 🎤 Voice button transcodes mic audio with ffmpeg (already installed) and transcribes it locally with whisper.cpp.

git clone https://github.com/ggerganov/whisper.cpp ~/whisper.cpp
cd ~/whisper.cpp
cmake -B build && cmake --build build -j --config Release
# Grab a model — large-v3-turbo is the best balance and fits a 4 GB GPU:
./models/download-ggml-model.sh large-v3-turbo

C. Prism (syntax highlighting) — already vendored

No install needed. prism.js ships in the web root (offline, MIT). It is loaded with Prism.manual = true so it only highlights the cockpit’s code editor, not the chat console.

D. New config files (created on first use)

Under cockpit_data/: directives_global*.md, directives_config.json, claude_controls.json, gemini_controls.json, whisper_config.json, global_caps.json, help.json. All are plain JSON/Markdown and editable in-app (the relevant panel’s edit button opens them in the floating editor).