| name | user-preferences |
| description | User preferences — language and settings from preferences.json. |
User Preferences
All user-level preferences for dev-team-agents are stored in a single file:
.dev-team-agents/user-data/preferences.json
This file is gitignored (covered by .dev-team-agents/user-data/ in .gitignore).
Schema and Defaults
Canonical source: scripts/lib/preferences-defaults.json is the single source of truth for the default schema. It is read by install.sh (on install/update) and by the session-start.sh health-check backfill, which fills any missing key on every session. The block below mirrors it — keep them in sync.
{
"language": "pt-BR",
"context_window_percent_warning": 55,
"context_window_percent_limit": 60,
"suppress_notifications": false,
"session_summary_max_days": 30,
"session_summary_max_entries": 30,
"docs_stale_after_days": 30,
"auto_update": true,
"update_check_interval_hours": 24,
"transcript_multiplier": 1.8,
"model_max_tokens": 200000,
"session_no_commit_turns": 8,
"telemetry": true,
"worktree_active": true,
"worktree_base_branch": null,
"worktree_commit_action": "ask",
"auto_learn_before_commit": true,
"worktree_path": ".worktrees",
"worktree_docker_isolate": true,
"qa_browser": null,
"ci_cd_detected": null
}
These defaults apply only to a preferences.json that does not exist yet. An existing file is never rewritten: install.sh merges with existing values winning, and the session-start.sh backfill only adds absent keys.
Consent keys — telemetry and auto_update. Both default to true in a fresh file, where the installer prompts for them. They are never backfilled as true into a preferences.json that already exists: that file's owner never saw the prompt for a field added after they installed, so an absent key is read as "no". Both install and the session-start backfill write false in that case.
| Field | Type | Default | Purpose |
|---|
language | string | "pt-BR" | Conversation language (BCP 47 tag). Docs remain English. |
context_window_percent_warning | number | 55 | % at which agents emit a warning notification |
context_window_percent_limit | number | 60 | % at which agents emit a critical notification |
suppress_notifications | bool or array | false | false = none suppressed; true = all suppressed; ["info"] = suppress by type |
session_summary_max_days | number | 30 | Days before session-summary entries are trimmed |
session_summary_max_entries | number | 30 | Maximum number of entries in session-summary.md |
docs_stale_after_days | number | 30 | Days before project.md, session-summary.md, and the last health check are considered stale |
auto_update | bool | true | Auto-update dev-team-agents when a new version is detected (consent key) |
update_check_interval_hours | number | 24 | Hours between update checks |
transcript_multiplier | number | 1.8 | Deprecated, no longer applied — context is read directly from the transcript's last usage entry |
model_max_tokens | number | 200000 | Context window for the active model |
session_no_commit_turns | number | |
For where each field is actually read and applied, see the "Consumed at" column in CLAUDE-md/preferences.md — the canonical consumer table, kept current whenever a field's wiring changes.
Proposing a new value mid-session. When the user repeatedly corrects the same behavior, CLAUDE.md § Correction Pattern Rule governs whether to propose persisting it here. That rule — not this file — owns the trigger (2+ corrections) and the confirmation step; this file only owns the schema the proposal must map to. Never write a field here without the AskUserQuestion confirmation that rule requires.
Language Policy
Two distinct rules govern language in dev-team-agents:
| Output type | Language rule |
|---|
| Documents (ADRs, session-summary, plans, changelogs, code comments) | Always English — regardless of preferences.json |
| Conversation with the user (responses, questions, explanations, notifications) | Use language from preferences.json — fallback to English if absent or unreadable |
How agents read the user's language:
PREFS=".dev-team-agents/user-data/preferences.json"
USER_LANG="en"
if [ -f "$PREFS" ] && command -v python3 >/dev/null 2>&1; then
USER_LANG=$(python3 -c \
"import json; d=json.load(open('$PREFS')); print(d.get('language','en'))" \
2>/dev/null || echo "en")
fi
For agents: read .dev-team-agents/user-data/preferences.json at the start of each session. Use the language value when writing any response directed at the user. If the file does not exist, use English.
suppress_notifications Handling
| Value | Behavior |
|---|
false | No suppression — all notifications shown |
true | All notifications suppressed |
["info"] | Only info type suppressed |
["warning", "critical"] | warning and critical suppressed |
Any unrecognized value → treat as false (no suppression). Never fail — graceful degradation only.
Missing File Behavior
If preferences.json does not exist:
- Use English as the conversation language
- Use all schema defaults for thresholds and intervals
- Emit a
warning notification at session start prompting the user to run setup-assistant
If a specific field is missing from the file (partial schema), use its default value.
Reading Individual Fields (shell)
_pref() {
local field="$1" default="$2"
python3 -c \
"import json,sys; d=json.load(open('.dev-team-agents/user-data/preferences.json')); \
print(d.get('$field', $default))" 2>/dev/null || echo "$default"
}
LANG=$(_pref language '"en"')
WARN_PCT=$(_pref context_window_percent_warning 55)
LIMIT_PCT=$(_pref context_window_percent_limit 60)
SUPPRESS=$(_pref suppress_notifications false)
STALE_DAYS=$(_pref docs_stale_after_days 30)
AUTO_UPDATE=$(_pref auto_update false)
CHECK_HOURS=$(_pref update_check_interval_hours 24)