A CLI tool for managing oh-my-opencode configuration profiles.
omo-switch is designed as a simple, lightweight tool dedicated purely to switching between different configurations for oh-my-opencode or oh-my-opencode-slim. It focuses on making profile management as easy as a single command, which is perfect for most daily development workflows.
If you have more complex configuration needs or require advanced orchestration, we highly recommend using ocx. While omo-switch excels at direct profile swapping, ocx provides a more comprehensive set of tools for sophisticated setup management.
-
🔄 Profile Switching - Seamlessly switch between multiple
oh-my-opencodeconfigurations -
✅ Schema Validation - Automatic validation against the official JSON schema
-
📦 Dual Scope Support - Manage both global (
user) and project-local (project) profiles -
💾 Automatic Backups - Your configuration is always backed up before changes
-
🖥️ Cross-Platform - Works on Windows (PowerShell/CMD), Linux, and macOS (XDG compatible)
-
🔀 Dual Mode Support - Seamlessly switch between
oh-my-opencode(OMO) andoh-my-opencode-slim(SLIM) configurations
- Node.js >= 22.0.0
npm install -g omo-switch-cliNote: You can also use the shorter alias omos after installation.
git clone https://github.com/Aykahshi/omo-switch.git
cd omo-switch
npm install
npm run build
npm link# Initialize the profile store
omo-switch init
# Import your first profile
omo-switch add ./my-config.jsonc --name "My Setup"
# List available profiles
omo-switch list
# Apply a profile
omo-switch apply my-setupInitializes the ~/.config/omo-switch directory, sets up the internal structure, and downloads the latest configuration schema.
omo-switch initWhat it does:
- Creates the store directory structure
- Downloads the latest
oh-my-opencodeschema from GitHub (falls back to bundled if offline) - Creates a default profile if no existing config is detected
Get or set the active configuration type (omo or slim). This determines how omo-switch interprets your configuration and where it applies changes.
# Show current type and scope overrides
omo-switch type
# Set global type to SLIM (uses oh-my-opencode-slim.json)
omo-switch type slim
# Set global type to OMO (uses oh-my-opencode.jsonc)
omo-switch type omo
# Set project-specific type override (creates .opencode/settings.json)
omo-switch type slim --scope project
# Clear project-specific override
omo-switch type --clear-project
# Interactive selection
omo-switch type --selectOptions:
| Option | Description |
|---|---|
--scope <scope> |
Target scope: user (global) or project (local) |
--select |
Interactively select from available types |
--clear-project |
Remove project-level override to use global default |
Configuration Types:
| Type | Description | File Pattern |
|---|---|---|
omo |
Classic Mode (Default) - Uses multiple profile files. | oh-my-opencode.jsonc |
slim |
Slim Mode - Uses a single file with multiple presets. | oh-my-opencode-slim.json |
Imports a configuration file as a new profile.
# Basic usage - profile ID is derived from filename
omo-switch add ./my-config.jsonc
# With custom name (ID auto-derived from name)
omo-switch add ./config.json --name "Development Mode"
# With explicit ID and name
omo-switch add ./config.json --id dev --name "Dev Config"
# Add to project scope instead of global
omo-switch add ./config.jsonc --scope project
# Overwrite existing profile with same ID
omo-switch add ./config.jsonc --id existing-id --forceOptions:
| Option | Description |
|---|---|
--id <id> |
Custom profile ID (defaults to derived from name or filename) |
--name <name> |
Custom display name (defaults to ID) |
--scope <scope> |
Target scope: user (global) or project (local). Prompts if not specified |
--force |
Overwrite if a profile with the same ID exists |
OMOS behavior:
- When the active type is
slim,addwill insert the imported configuration as a new preset under thepresetsobject insideoh-my-opencode-slim.jsoninstead of creating a separate profile file.
Profile ID and filename:
- If neither
--idnor--nameis provided: ID is derived from the input filename - If only
--nameis provided: ID is derived from the name (lowercase, hyphenated) - If only
--idis provided: name defaults to the ID - Stored filename:
<profile-id>.<original-extension>(e.g.,config.json+--name test→test.json)
Lists all available profiles and shows which one is currently active.
# List all profiles (default)
omo-switch list
# List only global profiles
omo-switch list --scope user
# List only project profiles
omo-switch list --scope projectOptions:
| Option | Description |
|---|---|
--scope <scope> |
Filter by scope: user, project, or all (default: all) |
OMOS behavior:
- In
slimmode,listdisplays available presets from thepresetsobject insideoh-my-opencode-slim.jsonand indicates the currently selectedpreset.
Displays the configuration content. Supports merged view of applied configs.
# Show merged view of currently applied configs (default)
omo-switch show
# Show a specific profile from store
omo-switch show my-setup --scope user
# Show project profile
omo-switch show dev --scope projectOptions:
| Option | Description |
|---|---|
--scope <scope> |
View scope: user, project, or merged (default: merged) |
Scope behavior:
merged: Shows the actual applied configs from target paths, with diff highlighting if both global and project configs existuser: Shows a profile from the global storeproject: Shows a profile from the project store
OMOS behavior:
- When in
slimmode,showwill display the OMOS single-file configuration (oh-my-opencode-slim.json) or a specific preset from itspresetsobject when an identifier is provided.
Validates and applies the selected profile to the oh-my-opencode target configuration.
# Apply a profile (searches both scopes, prefers project)
omo-switch apply my-setup
# Apply from global store specifically
omo-switch apply my-setup --scope user
# Apply to project target path
omo-switch apply dev --scope projectOptions:
| Option | Description |
|---|---|
--scope <scope> |
Target scope: user or project (default: user) |
Note: A backup is automatically created before any changes.
OMOS behavior:
- In
slimmode,applysets thepresetfield insideoh-my-opencode-slim.jsonto the selected preset ID instead of copying a profile file.
Removes a saved profile from the store.
# Remove with confirmation prompt
omo-switch rm my-old-profile
# Remove without confirmation
omo-switch rm my-old-profile --force
# Remove from specific scope
omo-switch rm dev --scope projectOptions:
| Option | Description |
|---|---|
--scope <scope> |
Target scope: user or project |
--force |
Skip confirmation prompt |
Behavior without --scope:
- Checks project scope first, then global scope
- Prompts for confirmation before deletion
OMOS behavior:
- When in
slimmode,rmremoves the corresponding preset from thepresetsobject insideoh-my-opencode-slim.json.
Refreshes the cached oh-my-opencode JSON schema.
# Download latest schema from GitHub
omo-switch schema refresh
# Use offline/bundled schema
omo-switch schema refresh --offlineOptions:
| Option | Description |
|---|---|
--offline |
Skip network request; use cached or bundled schema |
omo-switch supports two configuration formats:
- Multi-file architecture: Each profile is stored as a separate
.jsonor.jsoncfile - Profile switching: Copy selected profile to target configuration path
- Best for: Users who want isolated, independent profile files
- Single-file architecture: All presets are managed within a single
oh-my-opencode-slim.jsonfile. - Preset switching: Switching is done by modifying the
presetfield at the top level of the file. - Best for: Users who prefer a unified configuration and want to switch "on-the-fly" without copying files.
- Usage: Set your type to
slimusingomo-switch type slim.
- List Presets:
omo-switch listshows all presets defined in your slim config. - Add Preset:
omo-switch add ./my-preset.jsonreads a JSON file containing a preset definition and appends it to thepresetsobject in your slim config. - Apply Preset:
omo-switch apply preset-idupdates thepresetfield in the slim config to point topreset-id.
| Command | OMO Mode | OMOS Mode |
|---|---|---|
type |
Show/set current mode | Same |
list |
List profile files | List presets in presets object |
add |
Import file as new profile | Add preset to presets object |
apply |
Copy profile to target path | Set preset field |
rm |
Delete profile file | Remove preset from presets |
show |
Display profile content | Display OMOS config |
omo-switch supports two scopes for profile management:
| Scope | Storage Location | Target Config Path | Use Case |
|---|---|---|---|
user |
~/.config/omo-switch/ |
~/.config/opencode/oh-my-opencode.jsonc (OMO) / ~/.config/opencode/oh-my-opencode-slim.json (OMOS) |
Global profiles/presets shared across all projects |
project |
<project>/.opencode/ |
<project>/.opencode/oh-my-opencode.jsonc (OMO) / <project>/.opencode/oh-my-opencode-slim.json (OMOS) |
Project-specific profiles/presets, ideal for team sharing via Git |
~/.config/omo-switch/
├── index.json # Profile registry with active profile ID (OMO)
├── configs/ # Profile configuration files (*.json, *.jsonc) (OMO)
├── cache/
│ └── schema/ # Cached oh-my-opencode.schema.json
└── backups/ # Timestamped configuration backups
<project>/.opencode/
├── .omorc # Project-specific active profile (OMO)
├── omo-configs/ # Project-specific profiles (OMO)
├── oh-my-opencode.jsonc # Applied project config (target) (OMO)
└── oh-my-opencode-slim.json # Applied project config (target) (OMOS)
When applying a profile, omo-switch writes to:
| Scope | Platform | Primary Path | Fallback Path |
|---|---|---|---|
user |
Windows | %USERPROFILE%\.config\opencode\oh-my-opencode.jsonc (OMO) / %USERPROFILE%\.config\opencode\oh-my-opencode-slim.json (OMOS) |
%APPDATA%\opencode\oh-my-opencode.json |
user |
Linux/macOS | $XDG_CONFIG_HOME/opencode/oh-my-opencode.jsonc (OMO) / $XDG_CONFIG_HOME/opencode/oh-my-opencode-slim.json (OMOS) |
~/.config/opencode/oh-my-opencode.jsonc |
project |
All | <project>/.opencode/oh-my-opencode.jsonc (OMO) / <project>/.opencode/oh-my-opencode-slim.json (OMOS) |
- |
- Node.js >= 22.0.0
git clone https://github.com/Aykahshi/omo-switch.git
cd omo-switch
npm install| Command | Description |
|---|---|
npm run build |
Compile TypeScript to dist/ |
npm run dev -- <args> |
Run CLI directly with ts-node |
npm test |
Run unit tests with Vitest |
npm run test:watch |
Run tests in watch mode |
npm run test:coverage |
Run tests with coverage report |
# Run in development mode
npm run dev -- init
npm run dev -- list
npm run dev -- add ./test-config.jsonc --name "Test"
# Build and link for global testing
npm run build
npm link
omo-switch --help- File I/O: Never use
fsdirectly in command files. UseStoreManagerorProjectStoreManager. - Safety: Always create backups before overwriting configurations.
- Validation: Validate all configs against the JSON schema before applying.
- Testing: Use Vitest with
memfsfor filesystem mocking. - Error Handling: Use
oraspinners for user feedback. Exit withprocess.exit(1)on failure.
omo-switch/
├── src/
│ ├── index.ts # CLI entry point
│ ├── commands/ # Command implementations
│ │ ├── init.ts
│ │ ├── add.ts
│ │ ├── list.ts
│ │ ├── show.ts
│ │ ├── apply.ts
│ │ ├── rm.ts
│ │ └── schema.ts
│ ├── store/ # Data persistence (global & project)
│ ├── utils/ # Helper functions
│ └── __tests__/ # Test fixtures
├── shared/ # Shared assets (schema, templates)
└── dist/ # Compiled output
If the tool cannot reach GitHub, it automatically falls back to a bundled schema. Use --offline if you're in an air-gapped environment.
Ensure your terminal has write permissions to:
~/.config/omo-switch/~/.config/opencode/or%APPDATA%/opencode/
If something goes wrong, find your original configuration in:
- Global:
~/.config/omo-switch/backups/<ISO_TIMESTAMP>__oh-my-opencode.jsonc - Project:
<project>/.opencode/backups/<ISO_TIMESTAMP>__oh-my-opencode.jsonc
By default, omo-switch keeps backups for 30 days. Old backup files are automatically scanned and removed whenever a new backup is created (e.g., when running apply).
You can customize the retention period by editing your global settings.json file:
File: ~/.config/omo-switch/settings.json
{
"activeType": "omo",
"backupRetentionDays": 14
}Set backupRetentionDays to a larger number to keep backups longer, or a smaller number to save space.
