@tspappsen/elamax
v1.6.3
Published
Max — a personal AI assistant for developers, built on the GitHub Copilot SDK
Maintainers
Readme
Max
AI orchestrator powered by Copilot SDK — control multiple Copilot CLI sessions from Telegram or a local terminal.
Install
curl -fsSL https://raw.githubusercontent.com/burkeholland/max/main/install.sh | bashOr install directly with npm:
npm install -g @tspappsen/elamaxQuick Start
1. Run setup
max setupThis creates ~/.max/ and walks you through configuration (Telegram bot token, etc.). Telegram is optional — you can use Max with just the terminal UI.
If you're running Max from a local clone instead of a global install, use:
npm run build
node dist/cli.js setupYou can also run setup directly from source without building first:
npx tsx src/setup.ts2. Make sure Copilot CLI is authenticated
copilot login3. Start Max
max startFrom a local clone, use:
node dist/cli.js start4. Connect via terminal
In a separate terminal:
max tuiFrom a local clone, use:
npm run tui5. Talk to Max
From Telegram or the TUI, just send natural language:
- "Start working on the auth bug in ~/dev/myapp"
- "What sessions are running?"
- "Check on the api-tests session"
- "Kill the auth-fix session"
- "Restart yourself"
- "What's the capital of France?"
Commands
| Command | Description |
|---------|-------------|
| max start | Start the Max daemon |
| max tui | Connect to the daemon via terminal |
| max setup | Interactive first-run configuration |
| max update | Check for and install updates |
| max help | Show available commands |
Flags
| Flag | Description |
|------|-------------|
| --profile <name> | Run as a named profile (e.g. --profile watchdog) |
| --self-edit | Allow Max to modify his own source code (use with max start) |
TUI commands
| Command | Description |
|---------|-------------|
| /model [name] | Show or switch the current model |
| /memory | Show stored memories |
| /skills | List installed skills |
| /workers | List active worker sessions |
| /copy | Copy last response to clipboard |
| /status | Daemon health check |
| /restart | Restart the daemon (under pm2, exit and let pm2 restart it) |
| /cancel | Cancel the current in-flight message |
| /clear | Clear the screen |
| /help | Show help |
| /quit | Exit the TUI |
| Escape | Cancel a running response |
Restarting Max
You can restart Max in any of these ways:
- TUI: run
/restart - Telegram: send
/restart - Discord: use
/restart - Natural language: ask Max something like "restart yourself" or "restart and come back online"
If Max is running under pm2, a restart request does not spawn a replacement process directly.
Instead, Max detects pm2 by checking PM2_HOME or pm_id, logs a message, and exits cleanly.
pm2 then starts the daemon again.
So the behavior is:
- pm2-managed → exit only, let pm2 restart
- non-pm2 → spawn a detached replacement process, then exit
How it Works
Max runs a persistent orchestrator Copilot session — an always-on AI brain that receives your messages and decides how to handle them. For coding tasks, it spawns worker Copilot sessions in specific directories. For simple questions, it answers directly.
You can talk to Max from:
- Telegram — remote access from your phone (authenticated by user ID)
- TUI — local terminal client (no auth needed)
Memory and QMD
Max keeps conversational continuity in the persistent orchestrator session and can also pull in relevant context from its wiki-backed memory.
- Session context lives in the long-running orchestrator session, with recovery support from recent conversation history and a compact wiki summary.
- Wiki memory is stored separately and can be searched explicitly via memory/wiki tools.
- QMD is an optional hybrid-search layer for the wiki. When enabled, Max uses it automatically to retrieve relevant wiki pages for normal prompts, and also for explicit recall/wiki search operations.
If Max runs under a restricted macOS service environment (for example pm2 or launchd) and cannot find qmd, set QMD_BIN in ~/.max/.env to the absolute binary path, such as /opt/homebrew/bin/qmd or ~/.bun/bin/qmd.
In short: QMD improves wiki retrieval, but it does not replace the session store.
Architecture
Telegram ──→ Max Daemon ←── TUI
│
Orchestrator Session (Copilot SDK)
│
┌─────────┼─────────┐
Worker 1 Worker 2 Worker N- Daemon (
max start) — persistent service running Copilot SDK + Telegram bot + HTTP API - TUI (
max tui) — lightweight terminal client connecting to the daemon - Orchestrator — long-running Copilot session with custom tools for session management
- Workers — child Copilot sessions for specific coding tasks
Development
When developing locally, npm run dev starts the daemon in watch mode, but it does not register the max command on your system. Use the built CLI directly:
# One-time install
git clone https://github.com/burkeholland/max.git
cd max
npm install
# Run setup locally
npm run build
node dist/cli.js setup
# Start the daemon in watch mode
npm run dev
# In a second terminal, connect the TUI
npm run tuiIf you want the max command while developing locally, link the package after building:
npm run build
npm link
max setup
max start
max tuiOn Windows, prefer node dist/cli.js setup for local development rather than the shell installer.
Publish to npm
npm version patch
npm publish
npm publish --access publicThe package is published as @tspappsen/elamax, and prepublishOnly runs npm run build automatically.
Running as a background service with pm2
To keep Max running even after you close the terminal, use pm2:
When Max restarts under pm2, it no longer spawns a second process itself.
It checks for PM2_HOME or pm_id, exits cleanly, and lets pm2 bring it back.
This avoids duplicate daemon instances during restart.
# Install pm2 globally
npm install -g pm2
# Start Max with pm2
pm2 start "npm run dev" --name max
# Check status
pm2 list
# Stop it
pm2 stop max
# Restart it manually
pm2 restart max
# Auto-start on login (macOS uses launchd)
pm2 startup # follow the printed instructions
pm2 savepm2 works on macOS, Linux, and Windows.
Watchdog
Max-Watchdog is a second, ops-only Max instance that monitors and repairs the main Max daemon. When main Max goes down, you message the watchdog over Telegram (or Discord) to diagnose, read logs, and restart — no SSH required.
How it works
┌────────────────────────┐ ┌─────────────────────────┐
│ Main Max (~/.max) │ │ Watchdog Max │
│ Port 7777 │ │ (~/.max-watchdog) │
│ @MaxBot on Telegram │ │ Port 7778 │
│ General-purpose AI │ │ @WatchdogBot │
│ Skills, workers, etc. │ │ Ops-only: health, │
└────────────────────────┘ │ restart, logs, shell │
└─────────────────────────┘Two fully isolated instances: separate home directories, separate SQLite databases, separate bot tokens, separate ports, separate pm2 processes. Zero shared state.
Watchdog setup
Create a second Telegram bot via @BotFather (e.g. "Max Watchdog 🔧").
Run the watchdog setup wizard:
max setup --profile watchdogThis creates ~/.max-watchdog/ and prompts for the watchdog bot token, your user ID, API port (default 7778), and the main Max pm2 process name.
- Start the watchdog:
max start --profile watchdogWatchdog tools
The watchdog has its own Copilot-powered AI session with these ops tools:
| Tool | Description |
|------|-------------|
| check_main_max | Check if main Max is running (pm2 status + HTTP health) |
| restart_main_max | Restart the main Max pm2 process |
| read_main_logs | Read the last N lines of main Max's daemon log |
| server_health | Report hostname, uptime, memory, disk, load average |
| run_shell | Run a shell command (30s timeout, output capped) |
| update_main_max | Stop main Max, update via npm, restart |
The watchdog does not have workers, skills, or long-term memory — it's purpose-built for ops.
Dual-instance pm2 deployment
# Main Max
pm2 start "max start" --name max
# Watchdog
pm2 start "max start --profile watchdog" --name max-watchdog
pm2 saveRecovery example
You → Watchdog: "is Max alive?"
Watchdog: "Main Max is down. Last log: [ERROR] Copilot SDK auth expired."
You → Watchdog: "show me the last 50 log lines"
Watchdog: (tails ~/.max/daemon.log)
You → Watchdog: "restart main Max"
Watchdog: "Main Max is back online (pid 4521)."Configuration
| Env var | Default | Description |
|---------|---------|-------------|
| MAX_PROFILE | (unset) | Profile name; watchdog for the ops instance |
| MAX_HOME | ~/.max or ~/.max-<profile> | Override the home directory |
| MAIN_MAX_PM2_NAME | max | pm2 process name of the main Max instance |
| MAIN_MAX_HOME | ~/.max | Home directory of the main Max instance |
| MAIN_MAX_API_PORT | 7777 | HTTP API port of the main Max instance |
