Configuration

Fred reads from three places: your shell environment, your home config, and the project you're in. None of it is required — defaults work on a fresh machine — but every knob is here when you need to pin a model in CI, add a project rule, or wire up an MCP server.

Home directory layout (~/.config/fred/)

After fred login runs once, your home config looks like this:

~/.config/fred/
├── credentials.json     # mode 0600 — auth state
├── preferences.json     # mode 0644 — model + UI prefs
└── rate-card.json       # cached pricing, refreshed from /api/pricing

credentials.json is written by fred login and read on every CLI invocation. Schema:

{
  "version": 1,
  "api_key": "sk-fred-…",        // empty if stored in keychain
  "email": "you@example.com",
  "base_url": "https://api.fredcode.net/v1",
  "fetched_at": "2026-04-30T17:22:11Z"
}

On macOS, if you installed with the [keychain] extra, the API key is mirrored into the system keychain and the api_key field stays empty. The keychain copy wins on read.

preferences.json is written by /model, /flash, /pro, and the once-per-account pro confirmation. Schema:

{
  "version": 1,
  "main_model": "deepseek-v4-flash",
  "editor_model": "deepseek-v4-flash",
  "weak_model": "deepseek-v4-flash",
  "warned_about_pro": true,
  "preset": "flash"
}

rate-card.json is a runtime cache of the pricing JSON served by /api/pricing. Fred refreshes it on startup if it's missing or older than 24 hours. If the cache is more than 7 days old and the network refresh fails, you'll see a one-line staleness warning at session start — billing still works (pricing is computed server-side), but the local cost line may drift.

Environment variables

Every env var the CLI reads. Anything prefixed DSC_ is a legacy alias that predates the rename — both forms still work, the FRED_ form wins on conflict.

Auth.

VariableUse
FRED_API_KEYAPI key for the Fred proxy. Skips the credentials file entirely. Preferred for CI.
DSC_API_KEYLegacy alias of FRED_API_KEY. Still honored, but FRED_API_KEY wins on conflict.
FRED_BASE_URLOverride the proxy URL. Default: https://api.fredcode.net/v1
DSC_BASE_URLLegacy alias of FRED_BASE_URL.
FRED_AUTH_URLOverride the auth host used by fred login. Default: https://app.fredcode.net
DSC_AUTH_URLLegacy alias of FRED_AUTH_URL.
DEEPSEEK_API_KEYBypass the Fred proxy and talk to DeepSeek directly. Skips metering, balance, and rate-card pricing — diagnostic use only.

Models.

VariableUse
FRED_MAIN_MODELPin the main slot at startup. One of deepseek-v4-flash or deepseek-v4-pro.
DSC_MAIN_MODELLegacy alias of FRED_MAIN_MODEL.
FRED_EDITOR_MODELPin the editor (str_replace) slot. Defaults to the main model.
DSC_EDITOR_MODELLegacy alias of FRED_EDITOR_MODEL.
FRED_WEAK_MODELPin the weak slot used for cheap classifier passes. Defaults to deepseek-v4-flash.
DSC_WEAK_MODELLegacy alias of FRED_WEAK_MODEL.

API behavior.

VariableUse
DSC_API_RETRIESMax retries on a transient HTTP error before giving up. Default: 3.
DSC_API_BACKOFF_BASE_MSInitial backoff in ms; doubles per retry with a small jitter. Default: 100.

Feature toggles.

VariableUse
DSC_REPOMAPSet to 0 to disable the repo-map context primer. Useful in monorepos where the map is too noisy.
DSC_RULESSet to 0 to disable project rules loading from .dsc/rules/.
DSC_CHECKPOINTSShadow-git checkpoints. 1 (default) keeps the last 20 turns recoverable via /restore. Set to 0 to skip.
DSC_AUTO_SEED_TODOSSet to 1 to have Fred propose an initial todo list on the first turn of a new session.
FRED_APPROVAL_MODEDefault approval mode: untrusted | on_request | never. CLI --approval and /sandbox approval m override per session.

Telemetry.

VariableUse
DSC_TELEMETRY_DB_URLOpt in to local telemetry by pointing this at a SQLite or Postgres URL. Off by default; nothing leaves your machine unless you set this.
DSC_TELEMETRY_NO_TEXTSet to 1 to record turn metadata (timings, tokens, tool calls) without storing prompt or response bodies.

UI.

VariableUse
NO_COLORIndustry-standard. Set anything truthy to disable ANSI color output.
FRED_NO_BANNERSkip the banner block on REPL start.
FRED_REDUCED_MOTIONSet to 1 to disable spinners and progress animations.
FRED_NO_UPDATE_CHECKSkip the once-per-day PyPI version poll on startup.

Prompt.

VariableUse
FRED_NO_CONFIRM_PROSet to 1 to skip the once-per-account confirmation prompt when switching to deepseek-v4-pro.
Note

FRED_* always wins over DSC_* (the legacy prefix). DSC_*aliases will stay supported for a long time so existing CI configs don't break.

Project memory: AGENTS.md / CLAUDE.md

At startup, Fred looks for AGENTS.md in the current working directory (and falls back to CLAUDE.mdif it's missing). The contents are injected as a system-prompt addendum every turn, so it's the right place for repo conventions, sharp edges, and things every session should know without you having to repeat yourself.

Good things to put in there:

  • House style — "use Drizzle, not raw SQL", "tabs not spaces".
  • Sharp edges — "the worker can't import from src/, mirror with sync-pricing.ts".
  • Where things live — a one-paragraph map of the package layout.
  • What not to touch — "migrations 0001 and 0002 are already in prod".

If both AGENTS.md and CLAUDE.md are present, AGENTS.md wins. Pick one and stick with it.

Keep it short

AGENTS.md gets re-tokenized every turn. A 200-line file is fine; a 2,000-line file will eat into your context window for no benefit. Move long-form rules into .dsc/rules/ so they only attach when relevant.

Project rules: .dsc/rules/*.md

Rules are Markdown files inside .dsc/rules/ with optional YAML front-matter. They split into three categories based on how they attach:

  • Always-on — no front-matter, or alwaysApply: true. Loaded every turn, like an extension of AGENTS.md.
  • Glob-triggered — front-matter sets a glob pattern. Auto-attaches the moment a matching file shows up in the turn (read, edited, or grepped).
  • Request-only — front-matter has a description but no glob and alwaysApply: false. The model sees the title and description in its tool list and pulls the rule in via the request_ruletool when it decides it's relevant.

Example front-matter:

---
description: Conventions for Drizzle migrations
glob: src/db/migrations/*.sql
alwaysApply: false
---

# Migration rules

- New migrations are numbered 0NNN_<slug>.sql.
- Never edit a migration that has run in prod — write a new one instead.
- ...

See project rules for the full schema and authoring tips.

Hooks and MCP: .dsc/settings.json

Per-project hooks (commands the harness runs on lifecycle events) and MCP servers (extra tools Fred can call) both live in .dsc/settings.json. Same file, two top-level keys:

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "bash", "command": "./scripts/audit.sh" }
    ],
    "Stop": [
      { "command": "npm run lint --silent" }
    ]
  },
  "mcp": {
    "servers": {
      "linear": {
        "command": "npx",
        "args": ["-y", "@linear/mcp-server"],
        "env": { "LINEAR_API_KEY": "lin_api_…" }
      }
    }
  }
}

Hooks let you run lint, audit, or telemetry shell scripts at well-defined points in the loop. MCP gives Fred access to tools beyond the built-ins (issue trackers, databases, your own scripts). Both are loaded once per session — restart the REPL after editing the file.

Drill-down docs: hooks · MCP servers.

Permission rules

Permission rules — "always allow git status", "always deny rm -rf" — live in ~/.dsc/settings.local.json. They're per-user, not per-project, because they encode trust decisions you've already made.

Edit them via slash command rather than by hand: /perms add bash "git status", /perms remove bash "git status", or just /permsto list. The in-prompt "Always allow this command?" option writes to the same file.

Full details on the gating model: permissions & yolo.

Tip

Most users never touch any of this. The defaults are fine. Drop down to env vars when you need CI predictability or want to pin a model across machines; reach for AGENTS.md and rules when a session keeps making the same wrong assumption.