7.1 KiB
Pull Request: Model Profile Manager (moltbot profiles)
Summary
Add moltbot profiles command for fast switching between authenticated model configurations.
Solves: Users managing multiple AI providers (Anthropic, OpenAI, Google, OpenRouter) need to frequently switch configurations. Currently requires manual editing of moltbot.json and .env files, which is error-prone and time-consuming.
Related Issues
- Partially addresses #2888 (model switching failures during sessions)
- Helps with #2883 (migration from clawdbot)
- Complements #2897 (doctor command request)
Changes
New Files
| Target Location | Description |
|---|---|
src/profiles/profiles.ts |
ProfileManager class - handles profile storage, switching, backup |
src/cli/profiles-cli.ts |
CLI command registration using Commander (lazy-loaded) |
src/profiles/profiles.test.ts |
Unit tests with vitest |
Modified Files
| File | Change |
|---|---|
src/cli/program/register.subclis.ts |
Add "profiles" entry for lazy-loading |
Commands Added
# List all saved profiles
moltbot profiles list
# Save current config as a named profile
moltbot profiles add <name> [-d "description"] [-f]
# Switch to a saved profile (creates backup)
moltbot profiles use <name> [--restart] [--no-backup]
# Delete a profile
moltbot profiles delete <name> [-f]
# Show current active profile
moltbot profiles current
# Show profile manager paths
moltbot profiles status
# Show profile details (or current config if no name)
moltbot profiles show [name] [--json]
Implementation Details
Architecture
This module is designed to complement (not replace) the existing src/cli/profile.ts which handles --profile/--dev CLI flags. The new profiles command manages saved configuration snapshots for quick switching.
Integration with existing CLI structure:
- Uses lazy-loading via
register.subclis.ts(consistent with other commands) - Uses
@clack/promptsfor interactive confirmation (consistent with moltbot style) - Uses
chalkfor terminal output (consistent with other commands)
Storage Location
~/.moltbot/
├── moltbot.json # Active config
├── .env # Active credentials
├── backups/ # Auto-created backups before switching
│ ├── moltbot-2026-01-28T10-30-00-000Z.json
│ └── env-2026-01-28T10-30-00-000Z
└── profiles/
├── .meta.json # Tracks current profile and metadata
├── claude-opus.json
├── gemini-pro.json
└── gpt-4o.json
Profile Format
Each <profile>.json stores:
{
"name": "claude-opus",
"description": "Opus 4 for complex tasks",
"model": "anthropic/claude-opus-4",
"provider": "anthropic",
"createdAt": "2026-01-28T00:00:00.000Z",
"config": { /* full moltbot.json snapshot */ },
"env": "ANTHROPIC_API_KEY=sk-xxx\n..."
}
Meta File Format
.meta.json tracks state across profiles:
{
"currentProfile": "claude-opus",
"profiles": {
"claude-opus": {
"model": "anthropic/claude-opus-4",
"provider": "anthropic",
"createdAt": "2026-01-28T00:00:00.000Z"
}
}
}
Safety Features
- Auto-backup: Creates timestamped backup before switching (unless
--no-backup) - Confirmation prompt: Asks before delete (unless
--force) - Gateway restart: Optional
--restartflag after switching - CLAWDBOT_STATE_DIR support: Honors environment variable for custom state directory
Demo
$ moltbot profiles list
Saved Profiles:
┌─────────────────────┬────────────────────────────────────┬──────────────────┐
│ Name │ Model │ Provider │
├─────────────────────┼────────────────────────────────────┼──────────────────┤
│ ● claude-opus │ anthropic/claude-opus-4 │ anthropic │
│ gemini-pro │ google/gemini-2.5-pro │ google │
│ gpt-4o │ openai/gpt-4o │ openai │
└─────────────────────┴────────────────────────────────────┴──────────────────┘
● Current: claude-opus
$ moltbot profiles use gemini-pro --restart
✓ Current config backed up.
✓ Switched to profile "gemini-pro".
Model: google/gemini-2.5-pro
Restarting gateway...
✓ Gateway restarted.
Testing
pnpm test src/profiles/profiles.test.ts
Test coverage:
- ProfileManager unit tests (constructor, getMeta, saveMeta, listProfiles, profileExists, getProfile, getCurrentConfig, getCurrentEnv, extractModelInfo, saveProfile, useProfile, deleteProfile, getCurrentProfile, backupCurrentConfig, getStatus)
- Factory function tests (createProfileManager)
- CLI command integration tests (marked as TODO for subprocess testing)
Integration Guide
Step 1: Add source files
cp profiles.ts <moltbot>/src/profiles/profiles.ts
cp profiles-cli.ts <moltbot>/src/cli/profiles-cli.ts
cp profiles.test.ts <moltbot>/src/profiles/profiles.test.ts
Step 2: Update register.subclis.ts
Add this entry to the entries array in src/cli/program/register.subclis.ts:
{
name: "profiles",
description: "Model configuration profiles",
register: async (program) => {
const mod = await import("../profiles-cli.js");
mod.registerProfilesCli(program);
},
},
Step 3: Verify
pnpm build
moltbot profiles --help
pnpm test src/profiles/profiles.test.ts
Checklist
- Code follows project style (TypeScript, ESM imports)
- Uses
@clack/promptsfor interactive prompts (consistent with moltbot) - Uses
chalkfor terminal output (consistent with moltbot) - Uses lazy-loading via
register.subclis.ts(consistent with moltbot) - Unit tests added with vitest
- No breaking changes to existing commands
- Works with existing
~/.moltbotdirectory structure - Honors
CLAWDBOT_STATE_DIRenvironment variable - Documentation update (pending review)
Migration from Community Tool
This PR is based on clawd-profile from the moltbot-setup community project, rewritten in TypeScript to match moltbot's codebase style.
Key differences from community version:
- TypeScript instead of JavaScript
- Uses
@clack/promptsinstead ofinquirer - Uses
chalkinstead of custom color functions - Follows moltbot's lazy-loading command registration pattern
- Integrated with moltbot's directory structure conventions
Note: Happy to adjust the implementation based on feedback. The core concept is simple - snapshot configs into named profiles for instant switching.