Skip to main content

Configuration

SCM uses YAML configuration files stored in the .scm/ directory.

Directory Structure

.scm/
├── config.yaml # Main configuration
├── bundles/ # Bundle YAML files
│ ├── my-bundle.yaml
│ └── remote-name/ # Pulled remote bundles
│ └── bundle.yaml
├── profiles/ # Profile YAML files
│ ├── developer.yaml
│ └── team/
│ └── backend.yaml
├── remotes.yaml # Remote registry
├── lock.yaml # Dependency lockfile
└── .auth/ # Git authentication

Config Hierarchy

SCM uses a single source (no merging):

  1. Project: .scm/ at git repository root
  2. Home: ~/.scm/ (fallback if no project .scm)

config.yaml Reference

# Editor configuration
editor:
command: "vim" # Editor command
args: ["-c", "set number"] # Additional arguments
# Fallback: VISUAL env → EDITOR env → nano

# Language model plugins
llm:
plugin_paths: [] # Additional plugin directories
plugins:
claude-code:
model: "claude-opus-4-5" # Default model
binary_path: "/path/to/bin"
args: [] # Plugin-specific arguments
env: # Environment variables
CUSTOM_VAR: "value"
gemini:
model: "gemini-2.0-flash"

# Default settings
defaults:
llm_plugin: "claude-code" # Default LLM plugin
profiles: # Default profiles to load
- scm-main/go-developer
- scm-main/code-reviewer
use_distilled: true # Prefer distilled versions (default: true)

# Sync configuration
sync:
auto_sync: true # Auto-sync on startup (default: true)
lock: true # Update lockfile after sync (default: true)
apply_hooks: true # Apply hooks after sync (default: true)

# Hooks configuration
hooks:
unified: # Backend-agnostic hooks
pre_tool: []
post_tool: []
session_start: []
session_end: []
pre_shell: []
post_file_edit: []
plugins: # Backend-specific hooks
claude-code:
EventName: []

# MCP Server configuration
mcp:
auto_register_scm: true # Auto-register SCM's MCP server
servers: # Unified MCP servers (all backends)
my-server:
command: "npx my-mcp"
args: ["--flag"]
env:
ENV_VAR: "value"
plugins: # Backend-specific servers
claude-code:
server-name:
command: "..."

# Inline profiles (alternative to .scm/profiles/)
profiles:
my-profile:
description: "Inline profile"
default: false
parents: []
tags: []
bundles: []
variables:
VARIABLE: "value"

LM Plugins

Available plugins:

PluginCLIDescription
claude-codeClaude CodeAnthropic's Claude (default)
geminiGemini CLIGoogle's Gemini
codexCodex CLIOpenAI (provisional)

Plugin Configuration

llm:
plugins:
claude-code:
model: "claude-opus-4-5"
args: ["--dangerously-skip-permissions"]
env:
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"

Defaults

SettingDefaultDescription
use_distilledtruePrefer distilled content
auto_synctrueSync remotes on startup
llm_pluginclaude-codeDefault AI backend
auto_register_scmtrueRegister SCM MCP server

Hooks

Hook types available:

HookWhen
pre_toolBefore tool execution
post_toolAfter tool execution
session_startSession initialization
session_endSession cleanup
pre_shellBefore shell execution
post_file_editAfter file edit

Hook structure:

hooks:
unified:
session_start:
- matcher: ".*" # Regex pattern
command: "echo hello" # Shell command
type: "command" # command, prompt, or agent
timeout: 30 # Seconds
async: false # Run in background

Claude Code Integration

The claude-code plugin:

  1. Writes context to .scm/context/[hash].md
  2. Updates CLAUDE.md with managed section

The managed section is delimited by:

<!-- SCM:BEGIN -->
...generated content...
<!-- SCM:END -->

SCM only modifies content within these markers.

Sync Configuration

sync:
auto_sync: true # Sync on MCP server startup
lock: true # Update lock.yaml after sync
apply_hooks: true # Apply hooks after sync

Lockfile

The lock.yaml records installed remote items for reproducible installations:

scm remote lock        # Generate lockfile
scm remote sync # Sync from lockfile