---
name: update-config
description: Use this skill to configure sema via its settings files. Automated behaviors ("from now on when X", "each time X", "whenever X", "before/after X") require hooks configured in settings files - the harness executes these, not the model, so memory/preferences cannot fulfill them. Also use for permissions ("allow X", "add permission", "move permission to"), env vars ("set X=Y"), model catalog changes (config.d/models.json), hook troubleshooting, or any changes to settings.json/settings.local.json files.
---

# Updating sema configuration

sema is configured through layered JSON settings files plus a model catalog. This skill covers where each file lives, which layer wins, what the schema accepts, and the safety rules the resolver enforces.

## Config home directory

All user-level configuration lives under the sema config home, resolved in this priority order:

1. `SEMA_CONFIG_DIR` env var (explicit override)
2. `CLAUDE_CONFIG_DIR` env var (upstream-CLI compatibility fallback)
3. `~/.sema` — the default. sema does NOT silently read `~/.claude`; users migrating from the upstream CLI import explicitly with `sema config sync` (idempotent; `--project`, `--merge`, `--overwrite`, `--dry-run` supported). Setting `SEMA_CLAUDE_FALLBACK=1` opts back in to automatic `~/.claude` reads.

Below, `<config-home>` means the directory resolved above.

## Settings file locations and precedence

Choose the file by scope. Later layers override earlier ones on value conflicts:

| Precedence | Layer | File | Git | Use for |
|---|---|---|---|---|
| 1 (lowest) | userSettings | `<config-home>/settings.json` | N/A | Personal preferences for all projects |
| 2 | projectSettings | `<project>/.claude/settings.json` | Commit | Team-wide hooks, permissions, env |
| 3 | localSettings | `<project>/.claude/settings.local.json` | Gitignore | Personal overrides for this project |
| 4 | flagSettings | `--settings <file>` CLI flag | N/A | One-shot launch overrides |
| 5 (highest) | policySettings | `managed-settings.json` + `managed-settings.d/*.json` (admin-owned), or remote managed settings | N/A | Managed/MDM policy ceiling |

Project-scoped files intentionally keep the `.claude/` directory name for upstream ecosystem compatibility.

## Trust model (independent of precedence)

sema separates "whose value wins" (precedence above) from "who is allowed to set a key" (trust). Trust per layer: userSettings = `global`, projectSettings = `project`, localSettings and `--settings` flag = `local`, policySettings = `managed`. The resolver fails CLOSED with an error (never silently applies) when:

- **SettingsTrustViolation** — a layer sets a key above its trust ceiling (e.g. a committed project file trying to set a global-trust security key).
- **OverrideLockViolation** — a tighten-only key would be LOOSENED by a later layer. Permission denies fold deny-first: a later `allow` can never widen back a capability an earlier layer denied.
- `permissionMode: "bypassPermissions"` in ANY settings file is rejected outright — bypass is a launch-flag-only mode, never file-configurable.
- `disableBypassPermissionsMode` and `disableAutoMode` are managed-only kill switches: only the policy layer may set them, and `true` (the strict pole) cannot be relaxed by lower layers.

When an edit you made produces one of these errors, move the key to a sufficiently trusted file instead of fighting the resolver.

## Settings schema

The core resolved units (`SemaSettings`):

```json
{
  "permissions": {
    "allow": ["Bash(npm:*)", "Read"],
    "deny": ["Bash(rm -rf:*)"],
    "ask": ["Write(/etc/*)"],
    "defaultMode": "default" | "acceptEdits" | "plan",
    "additionalDirectories": ["/extra/dir"],
    "disableBypassPermissionsMode": true,
    "disableAutoMode": true
  },
  "hooks": {
    "PreToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "./check.sh", "timeout": 30 }] }],
    "PostToolUse": [],
    "UserPromptSubmit": []
  },
  "env": { "DEBUG": "true" },
  "model": "model-name",
  "outputStyle": "style-name",
  "webSearch": { "provider": "brave" | "tavily" | "searxng", "apiKey": "...", "endpoint": "...", "maxResults": 5 },
  "ultracode": true
}
```

Notes:

- **Permission rule syntax** is upstream-compatible: exact match `"Bash(npm run test)"`, prefix wildcard `"Bash(git:*)"`, tool-only `"Read"`.
- `webSearch` and `ultracode` are sema-only keys (no upstream equivalent).
- Settings files accept the wider upstream settings.json superset; unknown keys are tolerated, but the units above are what the sema resolver folds across layers.

## Model configuration (sema-specific)

Models are NOT configured via a bare `"model": "sonnet"` alias. Two channels, both under the user layer:

1. **Model catalog** — `<config-home>/config.d/models.json`: a multi-slot catalog of entries `{ name, id, api, baseUrl, apiKeyEnv, contextWindow, maxTokens }` where `api` is `"anthropic-messages"` or `"openai-completions"`. A catalog with enabled models REPLACES the env catalog, and the FIRST enabled entry is the default model. Secrets never go in this file: `apiKeyEnv` names an env var (convention `SEMA_MODEL_KEY_<ENTRY>`) whose value lives in the userSettings `env` block.
2. **Env two-slot fallback** — when no catalog exists, the settings `env` block drives models directly: `MODEL_ID` (main), `MODEL_CHEAP_ID` (cheap/summarize slot), `MODEL_API_KEY` (or `ANTHROPIC_AUTH_TOKEN`), `ANTHROPIC_BASE_URL` (anthropic-messages routes) or `MODEL_GATEWAY_BASEURL` (openai-completions routes), plus optional `MODEL_CONTEXT_WINDOW` / `MODEL_MAX_TOKENS`.

Prefer editing the catalog when it exists; only touch the env slots for catalog-less installs.

## How to apply a change

1. Pick the narrowest file that satisfies the scope and trust rules above.
2. Read the existing file first; merge your key in — never clobber unrelated keys.
3. Settings files are watched: edits hot-reload without a restart. If a change appears ignored, check for a resolver rejection (trust/tighten violation) before assuming a bug.
4. For "do X automatically every time Y" requests, configure a hook — do not promise behavior from memory.
