Open with AI
Configuration
sdd reads its settings from three YAML files and merges them. sdd config shows the merged result and the file each value comes from.
Configuration files
Section titled “Configuration files”| Layer | File | Applies to |
|---|---|---|
| User-global | ~/.config/sdd/config.yaml, or $XDG_CONFIG_HOME/sdd/config.yaml when that variable is set |
You, in every project on this machine |
| Project | .sdd/config.yaml |
Everyone on the project. Committed to git. |
| Local | .sdd/config.local.yaml |
You, in this checkout only. sdd init adds it to .gitignore. |
A later row overrides an earlier one: local wins over project, project wins over user-global, and user-global wins over the built-in default. A file sets only the keys it names and inherits the rest. Maps merge entry by entry, so llm.api_keys.openai in the local file keeps llm.api_keys.anthropic from the user-global file. A list replaces the whole list below it. Command-line flags such as --model or --embedding-provider override every file for that one command.
Which keys go where
Section titled “Which keys go where”| Keys | Belong in | Notes |
|---|---|---|
participant, llm.*, embedding.*, sync.* |
User-global | Any file works. Use the local file to override a value for one project. A value in the project file applies to everyone on the project and overrides their user-global value. |
sessions.retention |
User-global | sdd currently ignores it in the project files. |
graph_dir, default_branch, repo_id, language, skill_scope, supported_agents, dependencies |
Project | These describe the repository. sdd ignores them in the user-global file. |
repos |
User-global | sdd ignores it in the project files. |
sdd skips a key it does not know, including a key in a file where it does not belong. Every command then warns ignoring unknown config key and names the key and the file, and sdd config lists these keys at the end. A file written by a newer sdd version therefore still works with an older one.
The sdd config command
Section titled “The sdd config command”| Command | What it does |
|---|---|
sdd config |
Lists every effective value with its source: default, global, project or local. Masks API keys. Add --format json for JSON. |
sdd config get <key> |
Prints one effective value without formatting, for use in scripts. |
sdd config get <prefix> |
Lists the values under a prefix, such as llm. Without an argument, lists all values. |
sdd config set <key> <value> |
Writes the key to the user-global file and creates the file if needed. Works outside a project. |
sdd config set --local <key> <value> |
Writes the key to .sdd/config.local.yaml. Works only inside an sdd project. |
sdd config unset [--local] <key> |
Removes the key from the user-global file, or with --local from the local file. |
- Keys are dotted paths, such as
llm.api_keys.openai. setrefuses a key that does not belong in the target file, such asgraph_dirwithout--local.setwrites8,0.5,trueandfalseas numbers and booleans, and everything else as text. Edit list values, such assupported_agents, in the file.setandunsetchange only the named key and keep the rest of the file, comments included.- No command writes
.sdd/config.yamldirectly.sdd initcreates it,sdd repo addandsdd repo removechangedependencies, and you edit the rest by hand and commit it.
Durations use the units s, m and h, such as 90s, 5m or 1h30m.
Project
Section titled “Project”sdd init writes these keys to .sdd/config.yaml.
| Key | Default | Meaning |
|---|---|---|
graph_dir |
.sdd/graph |
Directory of the entry files, relative to the repository root, or an absolute path. |
default_branch |
The branch checked out during sdd init |
A session that names no branch works on the branch checked out in the project directory, and on this branch when none is checked out. sdd serve does not start without it. |
repo_id |
Derived from the origin remote |
The project’s identity, such as github.com/acme/platform. Other graphs reference an entry here as <repo_id>:<entry-id>. Empty for a repository without a remote. Do not change it by hand. |
language |
English | Language of the entry text, as a locale code such as en, de or de-DE. Translated SDD vocabulary ships for de. |
skill_scope |
Asked by sdd init |
project installs the skill into the repository, such as .claude/skills/. user installs it into your home directory, such as ~/.claude/skills/. |
supported_agents |
[claude] |
The agents sdd init installs the skill for: claude, codex or both. |
dependencies |
None | The repo_ids of other graphs this graph references. See connected repositories. |
Participant
Section titled “Participant”| Key | Default | Meaning |
|---|---|---|
participant |
None | Your name, recorded as the author of the entries you capture. sdd init asks for it, offers your git user.name, and writes it to .sdd/config.local.yaml unless another file already sets it. Every command warns while it is missing. |
Language model
Section titled “Language model”| Key | Default | Meaning |
|---|---|---|
llm.provider |
claude-cli |
anthropic, openai, ollama or claude-cli. See language model providers. |
llm.model |
claude-sonnet-4-6 |
Model name as the provider spells it. sdd uses the default with any provider, so set a model whenever you change the provider. |
llm.api_keys.<provider> |
None | API key for a provider. Required for anthropic and openai. Optional for ollama, which receives it as a bearer token. |
llm.endpoint |
The vendor’s public API | Base URL of a gateway or compatible service, for openai and anthropic only. Accepts the host, a URL ending in /v1, or the full URL ending in /chat/completions for openai or /messages for anthropic. |
llm.ollama_endpoint |
http://localhost:11434 |
Ollama server for the ollama provider. |
llm.timeout |
2m |
Time limit for one model call. |
llm.params.<name> |
None | Provider settings that sdd adds unchanged to every request body, such as reasoning_effort set to low. claude-cli ignores them. |
llm.rate_limit_rps |
See below | Maximum requests per second to anthropic or openai. Raise it on a higher account tier or for a gateway that allows more. |
llm.retry.max_attempts |
5 |
Attempts per call, counting the first. 1 turns retries off. |
llm.retry.base_delay |
2s |
Wait before the first retry. The wait grows with each further retry. |
llm.retry.max_delay |
60s |
Longest wait between two retries. |
llm.concurrency |
4 |
Not applied in this version. sdd summarize --all takes its worker count from --concurrency, which defaults to 4. |
sdd retries a call that failed with a temporary error, such as a rate limit or a dropped connection, and waits as long as the provider asks when it names a time. claude-cli ignores the rate limit and retry keys, since the claude command retries on its own.
Default rate limits:
| Provider | Model name contains | Requests per second |
|---|---|---|
anthropic |
opus |
0.5 |
anthropic |
haiku |
2 |
anthropic |
anything else | 1 |
openai |
mini or nano |
2 |
openai |
anything else | 1 |
ollama, claude-cli |
any | no limit |
Embedding
Section titled “Embedding”| Key | Default | Meaning |
|---|---|---|
embedding.provider |
None | openai or ollama. Without a provider, search matches keywords only. |
embedding.model |
None | Embedding model, such as text-embedding-3-small or qwen3-embedding:8b. Required with a provider. |
embedding.api_keys.openai |
None | API key, required for openai. sdd does not fall back to llm.api_keys.openai. |
embedding.endpoint |
https://api.openai.com |
Base URL of an OpenAI-compatible embeddings service, for openai only. sdd appends /v1/embeddings, so leave /v1 off. |
embedding.ollama_endpoint |
http://localhost:11434 |
Ollama server for the ollama provider. Independent of llm.ollama_endpoint. |
embedding.timeout |
2m |
Time limit for one request. |
embedding.batch_size |
100 for openai, 64 for ollama |
Texts sent in one request. |
embedding.dimensions |
The model’s own size | Shorter vectors, for openai models that support it, such as text-embedding-3-small. ollama ignores it. |
embedding.rate_limit_rps |
5 for text-embedding-3 models, 3 for other openai models |
Maximum requests per second to openai. ollama has no limit. |
embedding.query_template |
None | Template for search queries. See query and document templates. |
embedding.document_template |
None | Template for entries when sdd indexes them. |
Sync and sessions
Section titled “Sync and sessions”| Key | Default | Meaning |
|---|---|---|
sync.cooldown |
15m |
Every sdd command except sdd init runs git fetch in the background at most once per this interval, and reports when your branch is behind or ahead of its upstream. An invalid value counts as 15m. |
sessions.retention |
14d |
When sdd serve starts, it deletes the logs of sessions that ended longer ago than this. Accepts days, such as 14d, or a duration, such as 336h. Set it in the user-global file. An invalid value stops sdd serve from starting. |
Connected repositories
Section titled “Connected repositories”| Key | File | Default | Meaning |
|---|---|---|---|
dependencies |
Project | None | The repo_ids of the graphs this graph references. sdd repo add adds one and commits the change. sdd repo remove removes one. |
repos |
User-global | None | How this machine reaches each connected repository, as a list of repo_id and clone_url pairs. sdd repo add writes it. |
sdd keeps a clone of each connected repository under ~/.cache/sdd/<repo_id>. A read that needs it pulls the clone at most once every 15 minutes. This interval is fixed.
Language model providers
Section titled “Language model providers”sdd calls the language model three times when it records an entry:
- The writing check reads the draft and points out unclear text.
- The pre-flight check compares the entry with the graph.
- The summary step writes the entry’s one-line summary.
| Provider | Sends requests to | Schema sent as | API key |
|---|---|---|---|
anthropic |
The Anthropic Messages API, or llm.endpoint |
output_config.format |
llm.api_keys.anthropic |
openai |
OpenAI chat completions, or any compatible service at llm.endpoint |
response_format of type json_schema, strict |
llm.api_keys.openai |
ollama |
The Ollama server at llm.ollama_endpoint |
The format field |
Optional |
claude-cli |
The local claude command, run as claude -p |
--json-schema |
None, uses your Claude Code login |
A gateway or compatible service must honor the schema field in the third column for the checks to work.
Anthropic
Section titled “Anthropic”OpenAI
Section titled “OpenAI”Opper and other OpenAI-compatible services
Section titled “Opper and other OpenAI-compatible services”With llm.endpoint set, the openai provider sends its requests to any service that implements the OpenAI chat completions protocol. Opper is a gateway that serves hosted open-weight models this way. The SDD evals run this model through this route:
The Opper key goes under openai because the provider is openai. The default limit of 1 request per second assumes OpenAI’s lowest account tier. Raise llm.rate_limit_rps if the service allows more.
Ollama
Section titled “Ollama”Runs models on your machine. The Ollama server must be running when sdd starts, or sdd stops with provider unreachable.
Ollama Cloud does not work, because it ignores the response schema.
Claude Code CLI
Section titled “Claude Code CLI”claude-cli is the fallback when no provider is set. It runs every call through claude -p with your Claude Code login, so it needs no API key, only the claude command on your PATH. Each call starts a new Claude Code process, which is slow, and checks can hit the 2 minute limit. If they do, raise llm.timeout or set up another provider.
Embedding providers
Section titled “Embedding providers”An embedding model turns each entry into a vector, so search finds entries by meaning. Without one, search matches keywords. sdd info shows Search: vector,text with an embedding provider and Search: text without.
Set the embedding provider in the user-global file. A search across connected repositories embeds every repository, the current one included, with the user-global embedding settings, so all results share one vector space.
OpenAI
Section titled “OpenAI”embedding.api_keys.openai is separate from llm.api_keys.openai. Set it even when the language model uses the same key.
OpenAI-compatible services
Section titled “OpenAI-compatible services”For another service that implements POST /v1/embeddings, set embedding.endpoint to its base URL without /v1. The openai provider always sends embedding.api_keys.openai, so for a service without authentication, set any value.
Ollama
Section titled “Ollama”The next section explains query_template.
Query and document templates
Section titled “Query and document templates”Some embedding models expect an instruction or a prefix before the text. A template wraps the text, and {text} stands for it.
embedding.query_templateapplies to search queries.embedding.document_templateapplies to entries when sdd indexes them.
Qwen3 embedding models expect an instruction on queries only, so set query_template as in the Ollama example above and leave document_template empty. Models with a prefix on both sides, such as E5 with query: and passage: or Nomic with search_query: and search_document: , need both templates. OpenAI models need none.
A changed query_template applies to the next search. A changed document_template, provider, model or dimensions starts a new, empty index, which sdd fills on the next search or with sdd index.
The search index
Section titled “The search index”sdd indexembeds every entry the index does not hold yet. Run it once after you set up an embedding provider, or when you join a project with existing entries, so the first search does not have to wait.- Every search by meaning, in the terminal or through your agent, first embeds the entries the index lacks, so new entries need no extra step.
sdd index --forceembeds every entry again.sdd index --repo <repo_id>orsdd index --all-reposalso builds the indexes of connected repositories.
The index lives in ~/.cache/sdd/index/, or $XDG_CACHE_HOME/sdd/index/ when that variable is set, with one directory per project and embedding setup. A project’s directory is named after its repo_id, or after a hash of the repository path when it has none.
The index only grows. It keeps every embedded version of every entry, so sdd versions that share it do not remove each other’s work. sdd index gc lists the stored versions by group, sdd index gc --drop <group> deletes one group, and --drop stale deletes every version this checkout does not search.
Environment variables
Section titled “Environment variables”| Variable | Default | Effect |
|---|---|---|
XDG_CONFIG_HOME |
~/.config |
The user-global file is $XDG_CONFIG_HOME/sdd/config.yaml. |
XDG_CACHE_HOME |
~/.cache |
Search indexes and clones of connected repositories live under $XDG_CACHE_HOME/sdd. |
XDG_STATE_HOME |
~/.local/state |
Session logs live under $XDG_STATE_HOME/sdd. Must be an absolute path. |
SDD_SERVE_TOKEN |
None | The bearer token sdd serve --transport http requires on every request. Same as --auth-token. |