dfmc

module
v0.0.0-...-c17f4fc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 5, 2026 License: MIT

README

DFMC — Don't Fuck My Code

DFMC Banner

DFMC is a single-binary code intelligence assistant written in Go. It combines local code analysis (tree-sitter AST, dependency graph, security taint pass) with a multi-provider LLM router behind one tool loop, exposed through five surfaces: CLI, TUI, HTTP/SSE, remote client, and MCP server. Alpha-stage software; pre-1.0 minor bumps may include breaking changes.

Surface model

DFMC is TUI-first. The Bubble Tea workbench is the reference operator surface for terminology, slash-command behavior, panels, and workflow shape. CLI and the React 19 WebUI should match the TUI whenever the medium allows it, preferably by sharing the same package, formatter, API, or store semantics. When a feature is genuinely interactive-only, the other surfaces should say so explicitly and point at the nearest equivalent command instead of silently drifting.

Install

Build from source (Go 1.25.0+):

go build -o bin/dfmc ./cmd/dfmc            # regex AST, works everywhere
CGO_ENABLED=1 go build -o bin/dfmc ./cmd/dfmc   # tree-sitter AST (Go/JS/TS/Python)

Without CGO the binary still runs but the AST layer falls back to regex extraction. dfmc doctor reports the active backend.

Released versions ship as cross-platform archives, a GHCR Docker image, and a Homebrew tap — see CHANGELOG.md and the Releases page.

First run

dfmc init           # creates .dfmc/ with config.yaml + scaffolding
dfmc doctor         # diagnostics: providers, keys, AST backend, store
dfmc status         # one-line summary
dfmc ask "explain this project"

dfmc init is optional — most commands auto-create missing project state at startup.

Provider keys

Two supported ways to set provider API keys. Process env still works but it is no longer the recommended path.

Inside TUI (dfmc tui) — interactive, masked input, persisted:

/key list                            # status of every provider + source
/key set anthropic sk-ant-…          # writes ~/.dfmc/config.yaml (0600)
/key clear anthropic
/key migrate                         # imports existing .env keys

From the CLI:

dfmc config set --global providers.profiles.anthropic.api_key sk-ant-…

--global writes to ~/.dfmc/config.yaml; without it, writes to project .dfmc/config.yaml. Config merge order: defaults → ~/.dfmc/config.yaml → project .dfmc/config.yaml → process env → CLI flags (later wins). The persisted files are the recommended path because they survive shell restarts and the TUI unmasks them on /key list.

Project-root .env is read at startup only to fill missing process env slots — it never overrides anything already set. Treat it as legacy compatibility, not a fresh-setup path.

Known provider env-var aliases (recognised when present): ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_AI_API_KEY, DEEPSEEK_API_KEY, KIMI_API_KEY (or MOONSHOT_API_KEY), MINIMAX_API_KEY, ZAI_API_KEY, ALIBABA_API_KEY.

CLI

Run dfmc help for the live command index. Selected entries:

Group Commands
Query ask, chat, tui, review, explain, refactor, debug, test, doc, audit, onboard
Analysis analyze, scan, map, context, magicdoc
Tools tool list, tool show <name>, tool run <name> [--param k=v]
Config config list|get|set|sync-models|edit
State memory, conversation, agents, drive, prompt, skill, plugin
Serve serve, remote, mcp
Ops doctor, hooks, approvals, status, version, update, completion, man

Global flags must precede the subcommand:

dfmc --provider offline ask "summarise local context"
dfmc --json status
dfmc --data-dir .dfmc-alt doctor

Race two providers for the same prompt:

dfmc ask --race --race-providers anthropic,openai "compare reasoning"

TUI

dfmc tui
Key Panel
F1 Chat (composer + transcript)
F2 Files
F3 Patch
F4 Workflow
F5 Activity
F6 Memory
F7 Conversations
F8 Providers
F9 Status
F10 CodeMap
F11 Tools
F12 Security
Shift+F1..F8 Prompts, Plans, Context, Orchestrate, Shortcuts, Contexts, ProviderLog, Telegram
Ctrl+Shift+T / Alt+O ToolStatus
Ctrl+B Fuzzy panel switcher
Ctrl+P Slash-command palette
Alt+1..8 Mirror F1..F8 (for terminals that swallow F-keys)

Type /help inside Chat for the live slash-command list.

Task-store views are exposed as /tasks list, /tasks tree, /tasks roots, /tasks show <id>, and /tasks clear. The CLI chat slash layer and WebUI Tasks panel intentionally mirror those views.

HTTP, remote, MCP

dfmc serve --host 127.0.0.1 --port 7777
DFMC_WEB_TOKEN=secret dfmc serve --auth token

DFMC_REMOTE_TOKEN=secret dfmc remote start --auth token --ws-port 7779
dfmc remote ask --url http://127.0.0.1:7779 --token secret --message "…"

dfmc mcp           # MCP server on stdio for IDE hosts

The embedded WebUI is built from the React 19/Vite app under ui/web/src. It uses Tailwind CSS v4, shadcn-style local primitives, lucide-react icons, and a responsive dark/light theme while keeping the same TUI-first surface contract:

cd ui/web
npm install
npm run check
npm run build

npm run build writes the embedded assets to ui/web/static/.

serve and remote start share the same HTTP+WebSocket API. Non-loopback hosts refuse --auth=none unless --insecure is passed. MCP exposes the regular tool registry plus six synthetic Drive control tools.

Context injection in queries

Both work in ask, chat, review, the TUI composer, and the web /api/v1/chat SSE:

[[file:internal/auth/middleware.go]]
[[file:internal/auth/middleware.go#L10-L80]]

Triple-backtick fenced blocks inside the query are also pulled in as explicit context.

Defaults worth knowing

From internal/config/defaults.go:

context:
  max_files: 20
  max_tokens_total: 12000
  max_tokens_per_file: 2000
  max_history_tokens: 24000
  max_history_messages: 120

agent:
  max_tool_steps: 60
  max_tool_tokens: 250000
  max_tool_result_chars: 3200
  parallel_batch_size: 4
  autonomous_resume: auto
  auto_continue: auto

Operational env vars (still honoured): DFMC_WEB_TOKEN, DFMC_REMOTE_TOKEN, DFMC_TELEGRAM_TOKEN, DFMC_TELEGRAM_ALLOWED_USERS, DFMC_APPROVE, DFMC_APPROVE_DESTRUCTIVE, DFMC_NO_COLOR, NO_COLOR, DFMC_PROFILE, VISUAL, EDITOR.

Hooks and safety

Lifecycle shell hooks (user_prompt_submit, pre_tool, post_tool, session_start, session_end) fire best-effort and never block a tool call. Project-local hooks are disabled by default; enable per-repo with hooks.allow_project: true only after auditing the hook list.

Agent-initiated write / shell / network-sensitive tools route through the approval gate. CLI prompts on stdin; TUI surfaces a modal; web and MCP surfaces require pre-authorised allowlists (they can't ask interactively).

Secret-shaped parent env vars (*_API_KEY, *_TOKEN, AWS_*, ...) are scrubbed before every hook and plugin child process so a hook can't exfiltrate provider keys. This scrubbing is unconditional — there is no env-passthrough escape hatch today.

Separately, DFMC refuses to run hooks loaded from a group/world-writable config, since anyone who can edit it gains arbitrary command execution. Set DFMC_UNSAFE_HOOKS=1 to override that refusal — only after you've audited the config and accept the risk. It does not affect env scrubbing.

Build, test, lint

go test -count=1 ./...
CGO_ENABLED=1 go test -race -count=1 ./...      # requires gcc on PATH
go vet ./...
staticcheck ./...
gofmt -l $(git ls-files '*.go')

CI gates on go vet + staticcheck. The bundled Makefile is Windows-oriented (NUL, rmdir /s /q); direct go invocations are the portable path.

Additional tooling (optional):

golangci-lint run          # comprehensive linting (see .golangci.yml)
govulncheck ./...          # dependency vulnerability scan

See CONTRIBUTING.md for the full development workflow, branch naming, and PR process. See SECURITY.md for vulnerability reporting and security best practices.

Project layout (selected)

cmd/dfmc              binary entrypoint
internal/ast          tree-sitter + regex AST extraction
internal/codemap      symbol / dependency graph
internal/config       config loading, defaults, env hydration
internal/conversation JSONL conversations + branches
internal/context      ranked snippet selection, prompt budgeting
internal/drive        autonomous plan / execute runner
internal/engine       orchestration, agent loop, lifecycle
internal/hooks        lifecycle shell hooks
internal/intent       state-aware turn classifier
internal/memory       working / episodic / semantic tiers
internal/mcp          MCP server + bridge
internal/provider     provider implementations + router
internal/security     scanner (regex + AST taint)
internal/skills       skill registry
internal/storage      bbolt store
internal/tools        tool registry + meta-tool layer
ui/cli                CLI surface
ui/tui                Bubble Tea TUI
ui/web                HTTP / SSE / WebSocket server
pkg/types             shared public types

Other supporting packages live under internal/ (applog, bot, coach, commands, errors, langintel, pathsafe, planning, pluginexec, promptlib, providerlog, repolint, sessionutil, supervisor, taskstore, tokens). For a deeper architecture map see CLAUDE.md.

Specification-Driven Development (SDD)

The sdd skill (internal/skills/sdd/) provides autonomous specification-driven development: it clarifies vague requests through AI-guided questions, produces a SPEC.md, generates implementation tasks, and executes them in order until done — like Drive agent but full-cycle. Activate via the skill system or /skill sdd in the TUI.

License

MIT — see LICENSE.

Directories

Path Synopsis
cmd
dfmc command
Package errors provides sentinel errors for the DFMC project.
Package errors provides sentinel errors for the DFMC project.
ast
bot
coach
Package coach is a tiny rule-based observer that turns a completed agent turn into short user-facing notes.
Package coach is a tiny rule-based observer that turns a completed agent turn into short user-facing notes.
commands
Package commands provides a shared metadata registry that all three DFMC surfaces (CLI, TUI, web) consult so command help text, categories, aliases, and surface availability stay in sync without being hand-copied across layers.
Package commands provides a shared metadata registry that all three DFMC surfaces (CLI, TUI, web) consult so command help text, categories, aliases, and surface availability stay in sync without being hand-copied across layers.
context
Package context — trajectory.go is the rule engine for the trajectory coach.
Package context — trajectory.go is the rule engine for the trajectory coach.
drive
Package drive implements the autonomous drive loop.
Package drive implements the autonomous drive loop.
hooks
Package hooks dispatches user-configured shell commands in response to DFMC lifecycle events (prompt submit, tool call, session start).
Package hooks dispatches user-configured shell commands in response to DFMC lifecycle events (prompt submit, tool call, session start).
intent
Package intent runs a small, state-aware sub-LLM before every user Ask.
Package intent runs a small, state-aware sub-LLM before every user Ask.
langintel
Package langintel hosts per-language knowledge bases used to surface relevant tips, patterns, and warnings during analysis.
Package langintel hosts per-language knowledge bases used to surface relevant tips, patterns, and warnings during analysis.
mcp
Package mcp implements the Model Context Protocol server surface for DFMC.
Package mcp implements the Model Context Protocol server surface for DFMC.
pathsafe
Package pathsafe owns the single canonical implementation of "is this path safely contained inside that root, symlinks and all".
Package pathsafe owns the single canonical implementation of "is this path safely contained inside that root, symlinks and all".
planning
Package planning — deterministic task decomposition.
Package planning — deterministic task decomposition.
pluginexec
Package pluginexec spawns script plugins as child processes and talks to them over line-delimited JSON-RPC 2.0 on stdin/stdout.
Package pluginexec spawns script plugins as child processes and talks to them over line-delimited JSON-RPC 2.0 on stdin/stdout.
providerlog
Package providerlog persists every provider:complete event to a daily-rotated JSONL file under <data-dir>/provider_calls/.
Package providerlog persists every provider:complete event to a daily-rotated JSONL file under <data-dir>/provider_calls/.
tokens
Package tokens provides token count estimation for prompts, context chunks, and tool results.
Package tokens provides token count estimation for prompts, context chunks, and tool results.
toolhistory
Package toolhistory persists learned coding patterns the assistant can replay across sessions.
Package toolhistory persists learned coding patterns the assistant can replay across sessions.
tools
benchmark.go — Phase 7 tool for running and parsing Go benchmark results.
benchmark.go — Phase 7 tool for running and parsing Go benchmark results.
pkg
jsonutil
Package jsonutil provides ergonomic helpers around stdlib encoding/json.
Package jsonutil provides ergonomic helpers around stdlib encoding/json.
ui
cli
tui
web

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL