Getting Started
Two ways to install — pick whichever fits your workflow.
MCP Server (Recommended)
Register Preamp as an MCP server in Claude Code, then launch a session to complete setup. This gives you natural language control directly in your coding session.
1. Add the MCP server
claude mcp add --transport http preamp https://api.preamp.ai/mcp
2. Start a Claude session
claude
3. Set up Preamp
/preamp
Or just say "set up preamp" — natural language works too.
After setup, Claude Code can manage your backups with natural language commands like “backup now” or “show my backup status”.
CLI Installer
Works with any AI tool on macOS, Linux, and Windows. Single file, zero dependencies beyond Node.js.
# Download the CLI
curl -fsSL https://preamp.ai/preamp.cjs -o preamp.cjs
# Run setup
node preamp.cjs setup
The setup wizard prompts for your email, discovers AI tool directories, and configures automatic backups.
What the Installer Does
- Email verification — Sends a 6-digit code to your email. Confirms your identity and creates your account.
- Device registration — Generates a cryptographic device token and stores it in your OS credential store.
- Auto-discovery — Scans for Claude Code, Cursor, Windsurf, Gemini CLI, Codex, Amp, Aider, Continue, and GitHub Copilot.
- Setup generation — Creates Preamp settings files with your discovered paths and backup preferences.
- Cron setup — Adds an hourly cron job to run incremental backups automatically.
- First backup — Runs an immediate backup of all discovered files.
Configuration Options
Backup frequency
Default is hourly. Adjust to any interval from 15 minutes to daily.
node preamp.cjs schedule 30min # Every 30 minutes
node preamp.cjs schedule hourly # Every hour
node preamp.cjs schedule daily # Once per day
Custom directories
Add any additional paths to your backup. Useful for project-level agent files or custom tool settings.
# Via Claude Code
"Also back up ~/my-project/.claude"
# Or via MCP
claude mcp add preamp -- npx ... --include ~/my-project/.claude Credential Storage
Your device token is stored securely using your OS credential manager.
| Platform | Storage Method | Details |
|---|---|---|
| macOS | Keychain | Uses the macOS Keychain via the security command. Token is stored as a generic password. |
| Linux (GNOME) | secret-tool | Uses GNOME Keyring via secret-tool. Integrates with your desktop session. |
| Windows | Token file | Stored in ~/.preamp/ with restricted permissions. |
| Fallback | Token file | Protected file in ~/.preamp/ when no OS secret manager is available. |
CLI Reference
| Command | Description |
|---|---|
preamp setup | Interactive setup wizard (signup, discovery, schedule) |
preamp status | Check backup status, health, and device info |
preamp backup | Run an immediate backup |
preamp snapshots | List all snapshots with file counts and sizes |
preamp changes | View file changes since a date |
preamp tag "name" | Tag the current snapshot for easy reference |
preamp tags | List all tags |
preamp untag "name" | Remove a tag |
preamp restore-init [id] | Start a restore (sends verification code) |
preamp restore-complete [id] [code] | Complete the restore with verification code |
preamp devices list | List all registered devices |
preamp health | Run a health check on your agents |
preamp suggestions | View smart restore suggestions |
preamp dismiss "id" | Dismiss a suggestion |
preamp verify | Verify backup integrity with HMAC checks |
preamp insights | Get 30-day usage analysis |
preamp webhook-add "url" "events" | Register a new webhook endpoint |
preamp webhooks | List registered webhooks |
preamp webhook-remove "id" | Delete a webhook |
preamp schedule [interval] | Set backup frequency (15min, 30min, hourly, daily) |
preamp feedback "message" | Send feedback or bug reports |
Webhooks
Subscribe to events and receive HTTP POST notifications at your endpoint. See the API reference for webhook CRUD endpoints.
Event Types
| Event | Fires when |
|---|---|
backup-complete | A backup finished successfully |
backup-failed | A backup failed |
restore-complete | A restore finished successfully |
device-added | A new device was registered to the account |
device-revoked | A device was revoked |
health-warning | A health warning was generated |
suggestion-created | A new actionable suggestion was created |
Payload Format
Every delivery is an HTTP POST with Content-Type: application/json.
{
"event": "backup-complete",
"timestamp": "2026-03-25T10:30:00.000Z",
"userId": "usr_abc123",
"data": {
"action": "backup_complete",
"deviceId": "dev_xyz789",
"metadata": {
"snapshotId": "snap_abc123",
"fileCount": 42,
"totalBytes": 1048576
}
}
}
| Event | Metadata fields |
|---|---|
backup-complete | snapshotId, fileCount, totalBytes |
backup-failed | error, snapshotId |
restore-complete | snapshotId, restoredFiles |
device-added | deviceName |
device-revoked | deviceName |
health-warning | warning, severity |
suggestion-created | suggestionId, type, message |
Signature Verification
Always verify the X-Preamp-Signature header before processing a webhook.
Node.js
import crypto from 'node:crypto';
function verifyWebhook(secret, body, signature) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expected, 'hex'),
);
}
// In your HTTP handler:
app.post('/webhooks/preamp', (req, res) => {
const signature = req.headers['x-preamp-signature'];
const rawBody = req.body; // must be raw string
if (!verifyWebhook(WEBHOOK_SECRET, rawBody, signature)) {
return res.status(401).send('Invalid signature');
}
const payload = JSON.parse(rawBody);
console.log(`Received: ${payload.event}`);
res.status(200).send('OK');
});
Python
import hmac
import hashlib
def verify_webhook(secret: str, body: bytes, signature: str) -> bool:
expected = hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
# In your Flask handler:
@app.route('/webhooks/preamp', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Preamp-Signature', '')
raw_body = request.get_data()
if not verify_webhook(WEBHOOK_SECRET, raw_body, signature):
return 'Invalid signature', 401
payload = request.get_json()
print(f"Received: {payload['event']}")
return 'OK', 200
Slack Integration
If your webhook URL points to hooks.slack.com, Preamp automatically formats the payload as a Slack message:
{
"text": "[Preamp Backup] *backup-complete*: `backup_complete` (device: dev_xyz789)"
} Limits & Behavior
| Constraint | Value |
|---|---|
| Max webhooks per user | 10 |
| Max events per webhook | 10 |
| Webhook URL scheme | HTTPS only |
| Max URL length | 2,000 characters |
| Delivery timeout | 10 seconds |
| Retry on failure | No automatic retries |
Deliveries are dispatched asynchronously. Failed deliveries are not retried — use the test endpoint to verify connectivity before subscribing to production events.