Configuration — API reference¶
Registry¶
Setting
dataclass
¶
Setting(
key: str,
env: str,
default: str,
requires_migration: bool = False,
secret: bool = False,
help: str = "",
kind: str = "str",
settable: bool = True,
advanced: bool = False,
derive: Callable[[], str] | None = None,
validate: Callable[[str], str | None] | None = None,
choices: tuple[str, ...] | None = None,
)
One configuration knob shown by mait-code settings.
Most settings are settable: backed by an environment variable, with a value resolved env → file → default. Two extra flavours exist:
- Derived (
settable=False): a read-only value computed at display time by :attr:derive(e.g. database paths derived fromdata-dir). These have no environment variable and never appear as an assignable line in the settings file. - Advanced (
advanced=True): a real settable knob that is written commented-out in the generated settings file, so the hardcoded default stays authoritative until the user deliberately uncomments it.
| ATTRIBUTE | DESCRIPTION |
|---|---|
key |
Stable, kebab-case identifier shown by
TYPE:
|
env |
The environment variable that backs it (empty for derived).
TYPE:
|
default |
Display string for the default value (
TYPE:
|
requires_migration |
TYPE:
|
secret |
TYPE:
|
help |
One-line description.
TYPE:
|
kind |
Value type for typed accessors —
TYPE:
|
settable |
TYPE:
|
advanced |
TYPE:
|
derive |
For derived settings, a zero-arg callable returning the
computed value as a string. Must lazy-import any heavy deps so
TYPE:
|
validate |
Optional callable taking the raw string value and returning
an error message, or
TYPE:
|
choices |
Optional fixed set of valid values for an enum-like setting
(e.g.
TYPE:
|
SETTINGS
module-attribute
¶
SETTINGS: tuple[Setting, ...] = (
Setting(
"data-dir",
"MAIT_CODE_DATA_DIR",
DEFAULT_DATA_DIR_DISPLAY,
help="Where memories, logs and personalised files live.",
),
Setting(
"log-level",
"MAIT_CODE_LOG_LEVEL",
DEFAULT_LOG_LEVEL,
help="Log verbosity: DEBUG, INFO, WARNING or ERROR.",
validate=_log_level,
choices=_LOG_LEVELS,
),
Setting(
"log-file",
"MAIT_CODE_LOG_FILE",
"<state-dir>/mait-code.jsonl",
help="Override the log file path.",
),
Setting(
"theme",
"MAIT_CODE_THEME",
DEFAULT_THEME,
help="TUI colour theme; any registered theme, unknown names fall back to mait-dark.",
validate=_non_empty,
),
Setting(
"bridge",
"MAIT_CODE_BRIDGE",
"disabled",
kind="bool",
help="Bridge capture/notify channel: 'enabled' or 'disabled'. Off by default — enable via the hub or here to allow network access.",
validate=_bridge_gate,
choices=_BRIDGE_GATE,
),
Setting(
"bridge-type",
"MAIT_CODE_BRIDGE_TYPE",
"ntfy",
help="Which Bridge channel to use (configured in the Bridge screen).",
validate=_bridge_type,
),
Setting(
"mods",
"MAIT_CODE_MODS",
"disabled",
kind="bool",
help="The mait-companion Claude Code mod (/capture + status bar): 'enabled' or 'disabled'. Off by default — early-access mods API.",
validate=_mods_gate,
choices=_MODS_GATE,
),
Setting(
"status-bar-style",
"MAIT_CODE_STATUS_BAR_STYLE",
"blocks",
help="How the mod's status bar draws: 'blocks' or 'slim'.",
validate=_status_bar_style,
choices=_STATUS_BAR_STYLES,
),
Setting(
"jira-base-url",
"MAIT_CODE_JIRA_BASE_URL",
"",
help="Jira site the status bar links card keys to (https://acme.atlassian.net).",
validate=_jira_base_url,
),
Setting(
"embedding-provider",
"MAIT_CODE_EMBEDDING_PROVIDER",
DEFAULT_EMBEDDING_PROVIDER,
requires_migration=True,
help="Embedding backend: 'local' or 'bedrock'.",
validate=_embedding_provider,
choices=_EMBEDDING_PROVIDERS,
),
Setting(
"embedding-model",
"MAIT_CODE_EMBEDDING_MODEL",
DEFAULT_EMBEDDING_MODEL,
requires_migration=True,
help="Local embedding model (used when provider is 'local').",
),
Setting(
"bedrock-model-id",
"MAIT_CODE_BEDROCK_MODEL_ID",
DEFAULT_BEDROCK_MODEL_ID,
requires_migration=True,
help="Bedrock model id (used when provider is 'bedrock').",
),
Setting(
"bedrock-region",
"MAIT_CODE_BEDROCK_REGION",
DEFAULT_BEDROCK_REGION,
help="AWS region for the Bedrock embedding client.",
),
Setting(
"log-backup-count",
"MAIT_CODE_LOG_BACKUP_COUNT",
"14",
kind="int",
advanced=True,
validate=_positive_int,
help="Days of rotated log files to keep.",
),
Setting(
"extraction-model",
"MAIT_CODE_EXTRACTION_MODEL",
"haiku",
advanced=True,
help="Model used for memory extraction (fast/cheap by default).",
),
Setting(
"reflection-model",
"MAIT_CODE_REFLECTION_MODEL",
"haiku",
advanced=True,
help="Model used for reflection synthesis.",
),
Setting(
"llm-timeout",
"MAIT_CODE_LLM_TIMEOUT",
"90",
kind="int",
advanced=True,
validate=_positive_int,
help="Timeout (seconds) for subprocess LLM calls.",
),
Setting(
"reflection-batch-size",
"MAIT_CODE_REFLECTION_BATCH_SIZE",
"50",
kind="int",
advanced=True,
validate=_positive_int,
help="Default entries processed per reflection (--batch-size overrides).",
),
Setting(
"reflection-novelty-gate",
"MAIT_CODE_REFLECTION_NOVELTY_GATE",
"3",
kind="int",
advanced=True,
validate=_non_negative_int,
help="Default new entries required to trigger reflection (--min-new overrides).",
),
Setting(
"git-timeout",
"MAIT_CODE_GIT_TIMEOUT",
"5",
kind="int",
advanced=True,
validate=_positive_int,
help="Timeout (seconds) for git context probes.",
),
Setting(
"dashboard-tile-timeout",
"MAIT_CODE_DASHBOARD_TILE_TIMEOUT",
"5",
kind="int",
advanced=True,
validate=_positive_int,
help="Timeout (seconds) for home-hub shell-command tiles.",
),
Setting(
"score-weight-recency",
"MAIT_CODE_SCORE_WEIGHT_RECENCY",
"0.3",
kind="float",
advanced=True,
validate=_unit_interval,
help="Scoring weight for recency (the three weights must sum to 1.0).",
),
Setting(
"score-weight-importance",
"MAIT_CODE_SCORE_WEIGHT_IMPORTANCE",
"0.3",
kind="float",
advanced=True,
validate=_unit_interval,
help="Scoring weight for importance (the three weights must sum to 1.0).",
),
Setting(
"score-weight-relevance",
"MAIT_CODE_SCORE_WEIGHT_RELEVANCE",
"0.4",
kind="float",
advanced=True,
validate=_unit_interval,
help="Scoring weight for relevance (the three weights must sum to 1.0).",
),
Setting(
"half-life-episodic",
"MAIT_CODE_HALF_LIFE_EPISODIC",
"3.0",
kind="float",
advanced=True,
validate=_positive_float,
help="Recency half-life (days) for episodic memories (events, tasks).",
),
Setting(
"half-life-semantic",
"MAIT_CODE_HALF_LIFE_SEMANTIC",
"90.0",
kind="float",
advanced=True,
validate=_positive_float,
help="Recency half-life (days) for semantic memories (facts, preferences).",
),
Setting(
"half-life-procedural",
"MAIT_CODE_HALF_LIFE_PROCEDURAL",
"180.0",
kind="float",
advanced=True,
validate=_positive_float,
help="Recency half-life (days) for procedural memories (workflows, how-tos).",
),
Setting(
"dedup-string-threshold",
"MAIT_CODE_DEDUP_STRING_THRESHOLD",
"0.85",
kind="float",
advanced=True,
validate=_unit_interval,
help="String-similarity threshold above which a memory is a duplicate.",
),
Setting(
"review-threshold",
"MAIT_CODE_REVIEW_THRESHOLD",
"0.5",
kind="float",
advanced=True,
validate=_unit_interval,
help="Recall probability below which a memory is surfaced for review (0.5 = one half-life since last review).",
),
Setting(
"review-min-importance",
"MAIT_CODE_REVIEW_MIN_IMPORTANCE",
"5",
kind="int",
advanced=True,
validate=_positive_int,
help="Minimum importance (1-10) for a memory to be surfaced for review; lower-value memories decay without nagging.",
),
Setting(
"dedup-vector-threshold",
"MAIT_CODE_DEDUP_VECTOR_THRESHOLD",
"0.92",
kind="float",
advanced=True,
validate=_unit_interval,
help="Cosine-similarity threshold above which a memory is a duplicate.",
),
Setting(
"dedup-conflict-threshold",
"MAIT_CODE_DEDUP_CONFLICT_THRESHOLD",
"0.60",
kind="float",
advanced=True,
validate=_unit_interval,
help="Lower edge of the contradiction band. Cosine similarity in [this, dedup-vector-threshold) flags a possible conflict rather than merging or storing silently.",
),
Setting(
"scope-boost-global",
"MAIT_CODE_SCOPE_BOOST_GLOBAL",
"0.7",
kind="float",
advanced=True,
validate=_unit_interval,
help="Relevance multiplier applied to global-scoped memories.",
),
Setting(
"scope-boost-cross-project",
"MAIT_CODE_SCOPE_BOOST_CROSS_PROJECT",
"0.3",
kind="float",
advanced=True,
validate=_unit_interval,
help="Relevance multiplier applied across project boundaries.",
),
Setting(
"embedding-dim",
"",
"",
settable=False,
kind="int",
derive=_derive_embedding_dim,
help="Embedding vector size (derived from provider + model).",
),
Setting(
"memory-db-path",
"",
"",
settable=False,
derive=lambda: _display_path("memory.db"),
help="SQLite store for memories (derived from data-dir).",
),
Setting(
"reminders-db-path",
"",
"",
settable=False,
derive=lambda: _display_path("reminders.db"),
help="SQLite store for reminders (derived from data-dir).",
),
Setting(
"bridge-config-path",
"",
"",
settable=False,
derive=lambda: _display_path("bridge.json"),
help="Bridge channel config — server, topics, token (derived from data-dir).",
),
Setting(
"model-cache-dir",
"",
"",
settable=False,
derive=lambda: _display_path("models"),
help="Local embedding-model cache (derived from data-dir; can be ~550MB).",
),
Setting(
"observations-dir",
"",
"",
settable=False,
derive=lambda: _display_path(
"memory", "observations"
),
help="Observation JSONL logs (derived from data-dir).",
),
Setting(
"project-aliases-path",
"",
"",
settable=False,
derive=lambda: _display_path(
"project-aliases.json"
),
help="Project-alias map (derived from data-dir).",
),
Setting(
"dashboard-config-path",
"",
"",
settable=False,
derive=lambda: _display_path("dashboard.toml"),
help="Home-hub start-page layout — widgets & command tiles (derived from data-dir).",
),
)
resolve
¶
resolve(setting: Setting) -> tuple[str, str]
Return (value, source) for a setting.
Resolution order (highest priority wins):
- Environment variable —
source = "env" - Settings file —
source = "settings" - Hardcoded default —
source = "default"
Derived settings (settable=False) short-circuit to their computed
value with source "derived".
This reports configuration; it does not validate it — that is
doctor's job.
get
¶
Return the resolved value for a setting by its kebab-case key.
Convenience wrapper around :func:resolve that discards the source.
| RAISES | DESCRIPTION |
|---|---|
KeyError
|
If key is not a registered setting. |
get_int
¶
Return a setting coerced to int.
Falls back to the setting's hardcoded default (logging a warning) when
the resolved value cannot be parsed, so a fat-fingered settings file
degrades to stock behaviour rather than crashing a hook. doctor is
responsible for surfacing the bad value loudly.
| RAISES | DESCRIPTION |
|---|---|
KeyError
|
If key is not a registered setting. |
get_float
¶
Return a setting coerced to float.
Like :func:get_int, falls back to the hardcoded default on a bad value.
| RAISES | DESCRIPTION |
|---|---|
KeyError
|
If key is not a registered setting. |
get_bool
¶
Return a setting coerced to bool.
Accepts the usual truthy/falsey spellings plus enabled/disabled
(case-insensitive). Like :func:get_int, an unrecognised value falls back
to the setting's hardcoded default (logging a warning) so a fat-fingered
gate degrades to its default rather than crashing a hook.
| RAISES | DESCRIPTION |
|---|---|
KeyError
|
If key is not a registered setting. |
validate_settings
¶
Return a list of human-readable validation errors (empty when healthy).
Runs every setting's per-value :attr:Setting.validate callable, plus
the cross-field invariants below. Called by doctor; it reads the
resolved configuration but never mutates it.
Settings file I/O¶
read_settings_file
¶
Read the settings TOML file.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Override the settings file path (defaults to
:func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, str]
|
A flat |
dict[str, str]
|
values. Returns |
dict[str, str]
|
Tables (notably |
dict[str, str]
|
the env table with :func: |
write_settings_file
¶
write_settings_file(
values: dict[str, str],
*,
path: Path | None = None,
env: dict[str, str] | None = None,
) -> Path
Write the settings TOML file atomically.
Generates a fully commented TOML with all registered settings. Values not in values are written with their defaults.
| PARAMETER | DESCRIPTION |
|---|---|
values
|
Setting values to write (kebab-case keys).
TYPE:
|
path
|
Override the settings file path (defaults to
:func:
TYPE:
|
env
|
Custom
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Path
|
The path the file was written to. |
reset_cache
¶
Forget the cached settings-file contents.
Call after writing the settings file in-process so a subsequent
:func:get reflects the new value rather than the stale cache.
Env injection¶
read_env_table
¶
Read the [env] table of custom environment variables.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Override the settings file path (defaults to
:func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, str]
|
A |
dict[str, str]
|
Returns |
dict[str, str]
|
no |
dict[str, str]
|
func: |
apply_env
¶
Inject the settings [env] table into :data:os.environ.
Called from each entry point's startup path (via
:func:mait_code.logging.setup_logging and the mait-code CLI), so
user-defined variables — e.g. AWS_PROFILE for Bedrock embeddings —
are present however a tool is invoked, not only inside Claude Code
sessions.
Variables already present in the real environment are left alone, so a
one-off AWS_PROFILE=other mc-tool-… override keeps working — and
repeat calls are naturally no-ops. MAIT_CODE_* keys are skipped
with a warning: first-class settings already resolve env → file →
default, and injecting them would create a second, conflicting
resolution path. doctor flags those too.
| RETURNS | DESCRIPTION |
|---|---|
list[str]
|
The names of the variables actually injected. |
Resolvers¶
data_dir
¶
Return the mait-code data directory — the canonical resolver.
Honours $MAIT_CODE_DATA_DIR when set to a non-empty value;
otherwise ~/.claude/mait-code-data. Computed at call time so tests
that relocate $HOME are honoured.
A leading ~ in the override is expanded — otherwise a value like
~/.claude/mait-code-data (a literal, unexpanded tilde from the
environment) would resolve relative to the cwd, scattering data into a
stray ~ directory instead of $HOME.
Settings view¶
ResolvedSetting
dataclass
¶
A setting with its resolved value and provenance, for display.
SettingsSnapshot
dataclass
¶
SettingsSnapshot(
settings: tuple[ResolvedSetting, ...],
drift: str | None = None,
)
All resolved settings, plus any detected configuration drift.
collect_settings
¶
collect_settings() -> SettingsSnapshot
Resolve every setting for display, and flag embedding-provider drift.
Drift is detected when the env var overrides the settings file value
for embedding-provider — this means the runtime provider differs
from what was configured, and memories may need re-embedding.
| RETURNS | DESCRIPTION |
|---|---|
SettingsSnapshot
|
A read-only :class: |
render
¶
render(snapshot: SettingsSnapshot) -> None
Print the snapshot to the shared console (read-only, provenance-aware).
Imports rich lazily so this module stays a light, stdlib-only leaf for
the hook/tool processes that import it only for :func:data_dir.
render_json
¶
render_json(snapshot: SettingsSnapshot) -> str
Render the snapshot as a JSON document.