Meet alter
A lightweight, self-hosted process manager with a beautiful web dashboard. Manage your servers, scripts, and services from a single place.
Overview
alter is a single-binary process manager for Windows, Linux, and macOS. It ships with a full-featured web UI, a built-in terminal, Telegram bot integration, AI assistant, tunnel support, and more — all without requiring Node.js, Python, or any additional runtime.
Process Management
Start, stop, restart, and monitor processes. Auto-restart on crash with configurable policies.
Built-in Terminal
Full xterm.js terminal with multi-tab, split pane, and persistent command history.
Log Streaming
Real-time log streaming via SSE. Search, filter, and download logs for any process.
Cron Jobs
Schedule tasks using cron expressions. Visual next-run indicator and execution history.
Telegram Bot
Control processes and receive crash alerts via Telegram — from anywhere.
AI Assistant
Chat with your process manager. Ask about logs, crashes, or config. Supports Ollama, Claude, OpenAI, Copilot.
Tunnels
Expose local ports via Cloudflare Tunnel, ngrok, or any custom provider.
Security
Password auth with PIN quick-unlock, session tokens, inactivity lock, and rate limiting.
alter web dashboard — process list view
Installation
Windows
Download the alter-windows-x86_64.exe installer from the
latest release.
Run the installer — it will place the alter.exe binary and register it on your PATH.
alter.exe binary and add it to a folder on your PATH (e.g. C:\tools\).Linux / macOS
Download the appropriate binary for your platform from GitHub Releases and make it executable:
# Linux x86_64
curl -Lo alter https://github.com/thechandanbhagat/alter-pm/releases/latest/download/alter-linux-x86_64
chmod +x alter
sudo mv alter /usr/local/bin/
# macOS arm64
curl -Lo alter https://github.com/thechandanbhagat/alter-pm/releases/latest/download/alter-macos-arm64
chmod +x alter
sudo mv alter /usr/local/bin/
Build from Source
Requires Rust 1.77+.
git clone https://github.com/thechandanbhagat/alter-pm
cd alter-pm
cargo build --release
# Binary at: target/release/alter (Linux/macOS)
# target/release/alter.exe (Windows)
First Launch
-
Start the daemon
Run
alter daemon startto launch the background daemon. It listens on127.0.0.1:2999by default.$ alter daemon startalter daemon started on http://127.0.0.1:2999 -
Open the web dashboard
Navigate to
http://127.0.0.1:2999in your browser. On first visit you will be asked to set a password. -
Set your password
Choose a strong password for the dashboard. This password is stored as an argon2id hash — it is never stored in plain text.
-
You're in!
The process list is empty on first run. Click Start new process to add your first process.
%APPDATA%\alter-pm2\ on Windows, or ~/.alter-pm2/ on Linux/macOS.Daemon CLI reference
alter daemon start # Start in background
alter daemon stop # Stop gracefully
alter daemon status # Check running status
alter daemon start --port 4000 # Use custom port
Interface Tour
Navigation Bar (top)
The top bar contains the main navigation links. Clicking a section header (e.g. Processes ▼) opens a dropdown with grouped views.
| Link | Description |
|---|---|
| Processes ▼ | List and manage all running/stopped processes. Dropdown shows namespace groups. |
| Cron Jobs ▼ | Scheduled tasks with cron expressions. |
| Log Library | Browse and search logs from every process in one place. |
| Log Volume | Visual chart of log output volume over time, per process. |
| TOOLS ▼ | Tunnels and Port Finder. |
Filter Bar (sidebar)
The sidebar shows active filters and namespace groups. Click a namespace to show only processes in that group. Click ACTIVE to show all running processes regardless of namespace.
Status Bar (bottom)
The bottom status bar always shows:
- Server indicator — current daemon (Local or remote) and connection status
- GitHub star widget — quick link to star the project
- Discord link — community Discord server
- Notifications bell — process events (crash, restart, start, stop)
- Terminal toggle — show/hide the bottom terminal panel
- AI Assistant — open the AI chat panel
- System stats — host CPU and memory usage
Sidebar controls (footer)
At the bottom-left of the sidebar:
- Server switcher — switch between local and remote alter daemons
- Settings — open the settings page
- Save state — persist all current processes to disk so they restart after a daemon reboot
- Lock screen — immediately lock the dashboard
- Shutdown daemon — gracefully shut down the daemon
Process Management
Starting a New Process
- Click Start new process in the top navigation bar.
-
Fill in the details:
- Name — identifier for this process (e.g.
web-server) - Command — the executable to run (e.g.
node,python) - Arguments — command-line arguments after
--(e.g.server.js) - Working directory — directory from which the process runs
- Namespace — optional group label (e.g.
servers,workers) - Environment variables —
KEY=VALUEpairs, one per line - Auto-restart — restart automatically on crash or exit
- Name — identifier for this process (e.g.
- Click Start process. The process appears in the list immediately.
Process Status Indicators
| Status | Color | Meaning |
|---|---|---|
| running | Green | Process is alive and healthy. |
| errored | Red | Process exited with a non-zero code or crashed. |
| stopped | Gray | Process was manually stopped. |
| disabled | Gray (row tint) | Process is excluded from auto-start. Row appears with a subtle gray background. |
| launching | Orange | Process is in the process of starting. |
Process Actions
Each process row has action buttons on the right:
- Start / Stop — toggle the process on or off
- Restart — stop and immediately restart the process
- Logs — open the log viewer for this process (also accessible via process name click)
- Edit — modify command, args, env vars, and restart policy
- Delete — remove the process permanently (with optional confirmation dialog)
Enable / Disable Processes
Disabling a process excludes it from the auto-start list. This is useful for seasonal scripts or processes you want to keep configured but not running. Disabled processes:
- Have a subtle gray tint on their row
- Show a disabled (grayed) Start button
- Will not be restarted by the auto-restart policy
- Are skipped when loading saved state on daemon startup
To enable/disable: click the process name to open the Process Detail page, then toggle the Enabled switch.
Namespaces
Namespaces are labels that group related processes in the sidebar. For example:
web-server → namespace: "servers"
api-worker → namespace: "workers"
bg-sync → namespace: "workers"
Click a namespace in the sidebar to filter the list to that group only. Processes without a namespace appear under default.
Process Detail Page
Click a process name to open its detail page. Here you can:
- View live log output (stdout + stderr)
- See CPU and memory charts over time
- Inspect the full process configuration
- Toggle enable/disable
- Trigger manual restart
Log Viewer
The log viewer streams new lines in real time via Server-Sent Events (SSE). Controls:
- Search — filter log lines by keyword or regex
- Tail lines — how many recent lines to load on open (configurable in Settings → General)
- Download — save the full log file to disk
- Clear — delete the current log file for this process
- Auto-scroll — toggle whether the view scrolls to the latest line
View Modes
Toggle between Table view (compact) and Card view (expanded with graphs) using the view mode button in the top-right of the process list. Your preference is persisted in the daemon settings.
Terminal
alter includes a full xterm.js terminal at the bottom of the screen. Open it with the Terminal button in the status bar or press Ctrl+T.
Tabs
Each terminal tab is an independent shell session. Tabs are labeled by their shell name and working directory. Switch tabs by clicking them or use keyboard shortcuts.
Split Pane
Press Ctrl+Shift+T to split the current tab into two side-by-side panes. Each pane is an independent shell.
Command History
Command history is automatically persisted to the daemon data directory (%APPDATA%\alter-pm2\terminal-history.json on Windows). Up to 150 commands per session are stored, and history is restored when you reopen the same terminal tab.
- Press ↑ / ↓ to navigate history
- Click the Command history button in the terminal toolbar to browse history in a popup
Resize
Drag the terminal panel's top edge to resize it vertically. Minimize and maximize buttons are also available in the terminal toolbar.
Log Library
The Log Library (Log Library in the navigation) provides a unified view of all process logs in one searchable interface.
Features
- Process selector — choose which process (or all) to view
- Search — filter lines by text or regular expression across all logs
- Stream / Tail toggle — switch between live streaming and static tail view
- Log level coloring — ERROR, WARN, INFO lines are color-coded
- Timestamps — each line shows its exact timestamp
- Download — export filtered or full logs as a text file
Log Volume
Log Volume shows a bar chart of log output volume per hour. Useful for spotting noisy processes or identifying when a crash wave occurred. Filter by process and time range.
Log Storage
Logs are stored at:
- Windows:
%APPDATA%\alter-pm2\logs\<process-name>\out.loganderr.log - Linux/macOS:
~/.alter-pm2/logs/<process-name>/out.log
Log Rotation (automatic)
Log rotation runs in the background — no configuration needed:
| Setting | Value |
|---|---|
| Max file size | 10 MB per log file |
| Retained copies | 5 rotated files per process |
| Daily rotation | Midnight rollover |
| Archive retention | 30 days of dated archives |
Cron Jobs
Create scheduled tasks that run on a cron schedule. Navigate to Cron Jobs in the top bar, then click New cron job.
Creating a Cron Job
| Field | Description | Example |
|---|---|---|
| Name | Identifier for the job | db-backup |
| Schedule | Standard 5-field cron expression | 0 2 * * * (2am daily) |
| Command | Executable to run | bash |
| Arguments | Args after -- | backup.sh |
| Working dir | Directory to run from | /opt/scripts |
| Namespace | Grouping label | maintenance |
Common Cron Expressions
| Expression | Meaning |
|---|---|
* * * * * | Every minute |
0 * * * * | Every hour (on the hour) |
0 9 * * * | Every day at 9:00 AM |
0 9 * * 1-5 | Weekdays at 9:00 AM |
0 2 * * 0 | Every Sunday at 2:00 AM |
0 0 1 * * | First day of every month at midnight |
Cron Job List
The cron jobs list shows each job with:
- Status (running, idle, failed)
- Next scheduled run time
- Last run time and exit code
- Actions: Run now, Edit, Delete
Ecosystem Files
Ecosystem files let you define multiple processes (and their configurations) in a single JSON or YAML file — similar to PM2's ecosystem files.
Format
{
"apps": [
{
"name": "web-server",
"command": "node",
"args": ["server.js"],
"cwd": "/opt/app",
"namespace": "production",
"instances": 1,
"env": { "PORT": "3000", "NODE_ENV": "production" },
"autorestart": true
},
{
"name": "worker",
"command": "python",
"args": ["worker.py"],
"cwd": "/opt/app",
"instances": 4,
"autorestart": true
}
]
}
Multi-Instance Support
Set "instances": N (where N > 1) to spawn multiple copies of a process. Instances are named worker-0, worker-1, etc.
Loading an Ecosystem File
# Via CLI
alter ecosystem start /path/to/ecosystem.json
# Via API (POST /api/v1/ecosystem/start)
curl -X POST http://127.0.0.1:2999/api/v1/ecosystem/start \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d @ecosystem.json
Rolling Restart
For multi-instance process groups, trigger a rolling restart (one instance at a time with a brief delay) to achieve zero-downtime deploys:
# Via API (POST /api/v1/processes/group/{name}/rolling-restart)
curl -X POST http://127.0.0.1:2999/api/v1/processes/group/worker/rolling-restart \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"config": {...}}'
Tunnels
Expose local ports to the public internet using Cloudflare Tunnel, ngrok, or a custom provider. Navigate to TOOLS → Tunnels.
Creating a Tunnel
- Click New tunnel on the Tunnels page.
- Enter the local port you want to expose (e.g.
3000). - Choose a provider: Cloudflare, ngrok, or Custom.
- Click Start. alter launches the tunnel process and captures the public URL from its output.
Providers
| Provider | Free tier | Auth required |
|---|---|---|
| Cloudflare | ✅ Yes (with account) | Cloudflare auth token |
| ngrok | ✅ Limited (1 tunnel) | ngrok auth token |
| Custom | Varies | Configure binary path + args |
Configure provider credentials in Settings → Tunnels.
Port Finder Integration
The Port Finder page lists all active TCP listeners on the host. LISTENING ports show a Tunnel button — click it to instantly create a tunnel for that port without navigating away.
Port Finder
Navigate to TOOLS → Port Finder to see all active TCP listeners on the host machine.
What it shows
- Port — TCP port number
- Protocol — TCP/UDP
- State — LISTENING, ESTABLISHED, TIME_WAIT, etc.
- Local address — bound interface (127.0.0.1, 0.0.0.0, etc.)
- Remote address — for established connections
- PID & process name — which process owns the socket
- Protocol filter — filter by TCP, UDP, or all
Tunnel button
Every row with a LISTENING port shows a Tunnel action button. Clicking it pre-fills the Tunnels page with that port, so you can expose it publicly in one click without leaving the Port Finder.
Refresh
Click Refresh to rescan — the list updates in real time. Use the search bar to filter by port number, process name, or address.
Remote Servers
Connect to alter daemons running on remote machines from one dashboard. Click the server switcher in the sidebar footer to manage connections.
Adding a Remote Server
Click the server name in the sidebar footer, then Add server. Two connection types are available:
| Type | When to use |
|---|---|
| Direct | alter daemon is accessible directly on its HTTP port (LAN, VPN, or public IP). |
| SSH | The remote machine is only accessible via SSH. alter creates a local port forward. |
Direct connection fields
- Host — IP or hostname of the remote machine
- Port — daemon port (default: 2999)
SSH tunnel fields
- SSH host — remote machine hostname/IP
- SSH port — SSH server port (default: 22)
- SSH user — username for SSH login
- SSH key path — path to your private key (optional; uses SSH agent if omitted)
- Local forward port — which local port to bind for the tunnel
- Remote daemon port — daemon port on the remote machine (default: 2999)
After adding, click the server name to switch to it. The tunnel command is shown so you can run it manually if needed.
remote-servers.json), not in browser localStorage. They persist across browser sessions and are shared between browsers.AI Assistant
The AI Assistant panel (accessible from the status bar) lets you chat about your processes, logs, and configuration using a local or cloud-hosted LLM.
Supported Providers
| Provider | Type | Notes |
|---|---|---|
| Ollama | Local | Runs on your machine. No internet required. Fast, private. |
| GitHub Copilot | Cloud | Uses your existing Copilot subscription. OAuth Device Flow sign-in. |
| Claude (Anthropic) | Cloud | Requires an Anthropic API key from console.anthropic.com. |
| OpenAI | Cloud | Requires an OpenAI API key. Supports custom base URLs (Azure, Groq, LM Studio). |
Setup (Ollama example)
- Install Ollama and pull a model:
ollama pull llama3.2 - In alter, go to Settings → AI
- Select provider: Ollama (local)
- Set base URL:
http://localhost:11434(default) - Click Refresh next to the model selector to load available models
- Enable the AI assistant toggle and save
What to Ask
- "Why did the
api-workerprocess crash?" - "Show me the last 20 error lines from
web-server" - "How do I configure auto-restart for a process?"
- "What processes are currently running?"
Settings → General
Polling & Refresh
- Auto-refresh — toggle automatic polling on/off
- Process refresh interval — how often the process list updates (1s–60s)
- Health check interval — how often the daemon connection status is checked
Behaviour
- Confirm before delete — show a confirmation dialog before deleting a process
- Confirm before shutdown — show a confirmation dialog before shutting down the daemon
Log Viewer
- Default tail lines — how many lines to load when opening a process log (50–5000)
Process Defaults
- Default namespace — pre-filled namespace when creating new processes
Storage
- Data directory — root path where alter stores state, PID file, and daemon logs (read-only display)
- Log directory — where process stdout/stderr files are written; override with
ALTER_LOG_DIRenv var
Daemon
- Restart daemon — restarts the HTTP server only; running processes are unaffected
Updates
Click Check for updates to query GitHub Releases for a newer version. If an update is available, click Update Now (binary self-update) or Download & Install (installer). The daemon restarts automatically after the update.
Settings → UI
Customize the visual appearance of the dashboard.
- Theme — Dark, Light, or System (follows OS setting)
- Accent color — choose a primary color for buttons, active states, and highlights
- Font size — base font size for the dashboard
- Process view mode — default view (Table or Card) for the process list
- Compact mode — reduce padding and row heights for higher density
- Show PID column — show/hide the PID column in table view
Settings → Security
Password
Change your dashboard login password. The new password must be at least 8 characters. A strength meter indicates password quality.
PIN (Quick-unlock)
Set a 4 or 6 digit numeric PIN for the lock screen. The PIN is faster to type than a full password and is stored as an argon2id hash. To remove the PIN, click Remove after setting one.
Session Lock
Configure automatic inactivity lock:
- Disabled — never auto-lock
- 5 minutes through 1 hour — lock after the chosen period of inactivity
Inactivity is detected via mouse movement, keyboard input, clicks, and scroll events. Locking uses the PIN if configured, otherwise the full password.
You can also lock immediately at any time using the Lock screen button in the sidebar footer.
alter binary itself) never expires.Settings → AI
Enable AI Assistant
Toggle the AI panel visibility. When disabled, the AI button in the status bar is hidden.
Provider Configuration
Ollama (local)
- Set Ollama base URL (default:
http://localhost:11434) - Click Refresh to load the list of locally pulled models
- Select the desired model (e.g.
llama3.2,codellama)
GitHub Copilot
- Requires an active GitHub Copilot subscription
- Click Sign in with GitHub — alter uses the OAuth Device Flow
- A code appears — visit
github.com/login/deviceand enter it - After authorization, alter is linked to your account. Model list loads automatically.
Claude (Anthropic)
- Get an API key from console.anthropic.com
- Paste it into the Anthropic API key field and save
- After saving, the key is masked — only a hint (e.g.
sk-ant-…XYZ) is shown
OpenAI / OpenAI-compatible
- Enter your OpenAI API key (
sk-…) - Optionally override the API base URL for Azure OpenAI, Groq, LM Studio, or other compatible endpoints
Model Selector
After configuring a provider, click Refresh (↺) next to the model dropdown to fetch available models. The selector is populated with models returned by the provider's API.
Settings → Telegram
Configure a Telegram bot to control your processes and receive notifications from anywhere.
Setup Guide
- Message @BotFather on Telegram, run
/newbot, and copy the bot token. - Paste the token into the Bot Token field and click Validate. alter will confirm the bot identity.
- Message your bot (to create the chat). Then message @userinfobot to get your numeric Chat ID.
- Add your Chat ID (one per line) to Allowed Chat IDs. alter silently ignores messages from any other ID.
- Configure notification preferences (crash, start, stop, restart).
- Enable the bot and click Save.
- Click Send Test Message to confirm everything works.
Bot Commands
Notification Events
| Event | Default | Description |
|---|---|---|
| Crash | ✅ On | Sent when a process exits unexpectedly (non-zero exit code). |
| Start | Off | Sent when a process is started manually or via auto-restart. |
| Stop | Off | Sent when a process is stopped. |
| Restart | ✅ On | Sent when a process is restarted (auto or manual). |
Settings → Log Alerts
Configure pattern-based log monitoring. When a process log line matches a defined pattern, alter can send an alert via Telegram (if configured) or display a desktop notification.
- Add alert patterns as regular expressions (e.g.
ERROR|CRITICAL|OOM) - Choose the alert channel: in-app notification, Telegram, or both
- Set a cooldown period to avoid alert storms
- Enable/disable per-pattern without deleting it
Settings → Tunnels
Configure your tunnel provider credentials and default settings.
- Provider — choose Cloudflare, ngrok, or Custom as the default
- Cloudflare token — your
cloudflaredauth token - ngrok auth token — your ngrok authentication token
- Custom binary — path to a custom tunnel binary
- Custom args — arguments template (use
{port}as a placeholder for the local port)
Settings → Terminal
Customize the built-in terminal panel.
- Shell — default shell to launch (
bash,zsh,powershell,cmd) - Font size — terminal font size in pixels
- Font family — monospace font for terminal text
- Scrollback lines — number of lines kept in the terminal buffer
- Default height — initial terminal panel height in pixels
- Cursor style — block, underline, or bar cursor
- Cursor blink — toggle cursor blink animation
Settings → System
Start on Login
Automatically start the alter daemon when you log in to the operating system.
- Windows — registers a SCHTASKS entry that runs at logon with highest privilege
- Linux — creates a systemd user unit (
~/.config/systemd/user/alter-daemon.service) and enables it - macOS — installs a launchd plist in
~/Library/LaunchAgents/
Click Enable to register, Disable to remove the registration. The current status (enabled/disabled) and method are shown.
Log Rotation
Informational summary of the automatic log rotation settings (not configurable from the UI):
| Setting | Value |
|---|---|
| Size limit | 10 MB per log file |
| Retained files | 5 rotated copies per process |
| Daily rotation | Logs rotated at midnight |
| Retention period | 30 days of dated archives |
Data Directory
All alter data is stored in a single directory:
- Windows:
%APPDATA%\alter-pm2\ - Linux/macOS:
~/.alter-pm2/
This directory contains: state.json, auth.json, settings.json, ui-settings.json, telegram.json, tunnel.json, remote-servers.json, terminal-history.json, and the logs/ subdirectory.
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| Ctrl+T | Open new terminal tab |
| Ctrl+Shift+T | Split terminal pane |
| Ctrl+W | Close current terminal tab |
| ↑ / ↓ | Navigate terminal command history |
| Ctrl+L | Clear terminal screen |
| Ctrl+C | Interrupt running command (in terminal) |
Telegram Commands Reference
| Command | Description | Example |
|---|---|---|
| /list | List all processes and their status | /list |
| /start <name> | Start a stopped or errored process | /start web-server |
| /stop <name> | Stop a running process | /stop api-worker |
| /restart <name> | Restart a process | /restart web-server |
| /logs <name> [lines] | Show recent log lines (default 20) | /logs api-worker 50 |
| /status <name> | Show detailed status (PID, uptime, restarts) | /status web-server |
| /ping | Check if the bot is reachable | /ping |
| /help | Show all available commands | /help |
Troubleshooting
Dashboard won't load
- Check that the daemon is running:
alter daemon status - Verify the port is correct (default: 2999):
curl http://127.0.0.1:2999/api/v1/health - Check firewall rules if accessing from a remote browser
Can't build/update the daemon (Windows)
If cargo build fails with a "locked file" error, the daemon is running and has locked alter.exe. Stop it first:
curl -X POST http://127.0.0.1:2999/api/v1/system/shutdown \
-H "Authorization: Bearer <master-token>"
The master token is stored in %APPDATA%\alter-pm2\auth.json.
Process keeps crashing
- Open the process log to see the error message
- Check that the working directory exists and the command path is correct
- Verify that required environment variables are set in the process config
- Check system resources (disk full, out of memory)
Telegram bot not responding
- Confirm the bot token is valid (click Validate in Settings → Telegram)
- Ensure your Chat ID is listed in Allowed Chat IDs
- The bot only polls when the daemon is running — check daemon status
- Use Send Test Message to verify end-to-end delivery
Settings not saving
Settings are saved to the daemon's API at /api/v1/system/ui-settings. Confirm:
- The daemon is running and reachable
- Your session token is valid (try logging out and back in)
- The data directory is writable
Auto-restart not working
- Confirm Auto-restart is enabled in the process config (edit the process)
- Check that the process is not disabled (disabled processes skip auto-restart)
- Verify the process is actually crashing (exit code ≠ 0) vs. exiting cleanly
OS startup not registering (Windows)
Run as administrator if SCHTASKS fails. Verify with:
schtasks /query /tn alter-daemon
Logs directory is full
Log rotation runs automatically, but if you're in a high-throughput scenario:
- Clear logs for a specific process from its detail page
- Override the log directory to a volume with more space using the
ALTER_LOG_DIRenv var