Thank you for your interest in contributing to DFMT. This document outlines the development workflow, test requirements, and architectural decision-making process.
- Go 1.25 or later (matches
go.mod) - Make (for running build targets)
- Git
golangci-lintif you intend to runmake lint
-
Clone the repository:
git clone https://github.com/ersinkoc/dfmt.git cd dfmt -
Install dependencies:
go mod download
-
Build the project:
make build
-
Run tests:
make test
dfmt/
├── cmd/
│ ├── dfmt/ # CLI binary entry point
│ └── dfmt-bench/ # Token-savings benchmark binary
├── internal/
│ ├── capture/ # FS watcher + git hooks + shell integration
│ ├── cli/ # CLI command implementations + dispatch
│ ├── client/ # CLI ↔ daemon RPC client
│ ├── config/ # YAML configuration loading
│ ├── content/ # Ephemeral content store for raw tool output
│ ├── core/ # Events, journal, BM25 index, classifier
│ ├── daemon/ # Daemon lifecycle + lockfile + idle exit
│ ├── logging/ # Internal logging
│ ├── project/ # Project discovery + per-user registry
│ ├── redact/ # Secret redaction (AWS, GitHub, Anthropic, …)
│ ├── retrieve/ # Recall-snapshot building + markdown rendering
│ ├── safefs/ # Symlink-safe atomic write helper
│ ├── sandbox/ # exec/read/fetch/glob/grep/edit/write policy gate
│ ├── setup/ # Agent auto-detection + MCP config writers
│ └── transport/ # MCP stdio + JSON-RPC HTTP + Unix socket
├── docs/
│ ├── ARCHITECTURE.md # System architecture overview
│ └── adr/ # Architecture Decision Records
├── install.sh # POSIX one-line installer
├── install.ps1 # Windows one-line installer
├── dev.ps1 # Developer reset + build + install + smoke test
├── AGENTS.md # Canonical agent-onboarding doc
├── CLAUDE.md # Pointer to AGENTS.md (Claude Code's filename)
├── CONTRIBUTING.md # This file
└── README.md # Project entry point
-
Fork the repository and create a feature branch:
git checkout -b feature/your-feature-name
-
Make your changes following the coding standards:
- Run
make lintto check code style - Run
make fmtto format code
- Run
-
Write tests for new functionality (see Test Requirements below)
-
Ensure all tests pass:
make test -
Commit your changes using descriptive commit messages:
git commit -m "description of changes" -
Push and create a Pull Request on GitHub
- All new functionality must include tests
- Bug fixes must include a regression test
- Test coverage must not decrease below the current threshold
# Run all tests
make test
# Run tests with coverage (raw `go test` flags)
go test -cover ./...
# Run specific package tests
go test ./internal/core/...
# Run tests with race detector (Linux/macOS)
go test -race ./...
# On Windows the race detector needs cgo:
CGO_ENABLED=1 go test -race ./...Tests are co-located with the code they test:
internal/core/
├── events.go # Implementation
├── events_test.go # Tests
Generate an HTML coverage report:
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
# Open coverage.html in your browserTarget coverage by package:
internal/core: 90%+internal/transport: 85%+internal/daemon: 80%+internal/cli: 75%+
DFMT uses ADRs to document significant architectural decisions. This helps:
- Track the reasoning behind design choices
- Onboard contributors to the project
- Avoid repeating past mistakes
- Maintain consistency across the codebase
Create an ADR when your change:
- Adds a new architectural component
- Changes how components interact
- Adopts a new external library or technology
- Modifies existing behavior in a breaking way
- Affects the dependency policy
- Propose: Create a new ADR in
docs/adr/with the next sequential number - Template: Use
0000-adr-process.mdas the template - Review: Open a PR for discussion
- Decide: Merge when consensus is reached
- Implement: Changes can proceed after ADR merge
See ADR-INDEX.md for a list of all ADRs and their status.
- ADR-0001: Per-Project Daemon — Why one daemon per project
- ADR-0004: Stdlib-Only Dependencies — Dependency philosophy
- ADR-0006: Sandbox Scope — Sandboxed tool execution design
- ADR-0007: Content Store Separation — Ephemeral vs durable storage
DFMT follows a stdlib-first policy. See ADR-0004 for the full rationale.
Adding a new dependency requires:
- An ADR explaining why the stdlib cannot fulfill the requirement
- Justification of the library's stability and maintenance status
- Security review of the dependency
- No SQLite or other database drivers
- No ORMs
- No web frameworks (Echo, Gin, Fiber, etc.)
- No CLI frameworks (Cobra, Kingpin, etc.)
- No logging frameworks (Zap, Logrus, etc.)
- Standard library (
net,http,os,io, etc.) golang.org/x/sys— syscalls not in stdlibgopkg.in/yaml.v3— YAML configuration
That's it. The runtime tree currently has exactly two third-party
modules (go.mod is the source of truth). golang.org/x/crypto,
golang.org/x/text, and similar were considered but are not used —
proposing them requires an ADR.
Some functionality is bundled (no external import):
- HTML parser
- BM25 implementation
- Porter stemmer
- MCP protocol
- JSON-RPC 2.0
These are vendored directly to avoid version conflicts and ensure long-term stability.
Follow Effective Go and the Go Code Review Comments style guide.
- Error handling: Return errors, don't log and return
- Context: Use
context.Contextfor cancellation and timeouts - Interfaces: Define interfaces where needed, not prematurely
- Mutex: Use
sync.Mutexfor simple mutual exclusion - Slices: Preallocate when size is known
DFMT uses golangci-lint. Run before committing:
make lintThe lint configuration is in .golangci.yml.
Include:
- DFMT version (
dfmt --version) - OS and architecture
- Steps to reproduce
- Expected vs actual behavior
- Relevant log output
Useful debugging commands when filing an issue:
dfmt --version # version + build SHA
dfmt doctor # project state + per-agent wire-up
dfmt stats # event counts and byte savings
dfmt config # active configurationPaste the relevant output into the issue body.
- Describe the problem you're solving
- Explain why existing functionality is insufficient
- Provide concrete use cases
- Consider backward compatibility impact
By contributing to DFMT, you agree that your contributions will be licensed under the MIT License.