Skip to content

Per-user settings via /settings command #201

@dcellison

Description

@dcellison

Problem

Per-user settings (model, budget, timeout) are currently global env vars (CLAUDE_MODEL, CLAUDE_MAX_BUDGET_USD, CLAUDE_TIMEOUT_SECONDS). In multi-user, each user needs their own defaults. The existing /model command changes the model for the current session, but there is no way for a user to set persistent defaults that survive restarts, nor any command for budget or timeout.

Parent issue: #196 (sub-issue #3)

Proposal

Add a /settings command with subcommands for all per-user preferences. Settings are stored in the database via the existing settings table (sessions.py) and take precedence over users.yaml defaults and env var globals.

Commands

/settings                       - show all current settings with effective values and their source
/settings model <name>          - set default model (opus/sonnet/haiku)
/settings budget <n>            - set budget ceiling in USD
/settings timeout <n>           - set timeout in seconds
/settings reset                 - clear all overrides, revert to users.yaml/env defaults
/settings reset <key>           - clear a single override (e.g., /settings reset model)

Display

/settings with no arguments shows a summary like:

Model: sonnet (user override)
Budget: $10.00 (users.yaml)
Timeout: 300s (global default)

Each line shows the effective value and where it comes from (database override, users.yaml baseline, env var default, or hardcoded default). This makes the precedence model visible and debuggable.

Storage

Uses the existing settings table with the established namespace convention:

  • model:{chat_id} - model name
  • budget:{chat_id} - budget in USD
  • timeout:{chat_id} - timeout in seconds

This follows the pattern already used by voice settings (voice_mode:{chat_id}, voice_name:{chat_id}).

Precedence (highest to lowest)

  1. Database (set via /settings commands)
  2. users.yaml (admin-set baseline per user)
  3. Env file (global defaults: CLAUDE_MODEL, CLAUDE_MAX_BUDGET_USD, CLAUDE_TIMEOUT_SECONDS)
  4. Hardcoded defaults (in config.py)

Relationship to existing /model command

The existing /model and /models commands change the model for the current session. /settings model sets the persistent default. These should be unified: /model should write to the settings table so the choice persists across restarts. The /models inline keyboard should do the same. This is a behavior change but matches user expectations (nobody expects their model choice to reset on restart).

Boundaries

  • max_budget in users.yaml acts as a ceiling. /settings budget cannot exceed it. If a user tries, show the admin-set limit.
  • timeout should have a reasonable maximum (e.g., 600s) to prevent runaway sessions.
  • Model choices are validated against _AVAILABLE_MODELS.

Context

  • Settings table: sessions.py lines 432-459 (get_setting, set_setting, delete_setting)
  • Current model handling: bot.py /model and /models commands, pool.set_model()
  • UserConfig dataclass: config.py lines 86-111
  • No /settings command currently exists

Not in scope

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions