This document outlines code structure, design choices, testing expectations, and development conventions for the mydocs Go CLI app.
- Use idiomatic Go structure:
cmd/mydocs/main.go: entry pointinternal/folder for core logic (create.go,publish.go,utils.go)
- All commands should follow a standard signature:
func Run(args []string) error
- Graceful error handling and clear exit codes.
- Use
charmbracelet/bubbleteafor rich terminal UI (TUI) where applicable. - Follow charmbracelet ecosystem tools for coloring, prompts, etc.
- Keep
helpand feedback output readable and friendly.
- All commands must have unit tests using Goβs testing framework.
- Follow table-driven tests where appropriate.
- Aim for testable functions β avoid hardcoded
os.Args/os.Exitinside logic.
func CreateEntry(date string) error
func PublishHome() error- Add
*_test.gofiles withBenchmarkXxxfunctions for:- File scanning
- Markdown generation
- Sorting logic
- Example:
func BenchmarkPublishHome(b *testing.B) { ... }
Use:
go test -bench=.- Use Go modules (
go.mod) - Keep dependencies minimal and purposeful
- Prefer standard library unless justified
- Use
golangci-lint:golangci-lint run
- Format all code using:
gofmt -s -w . - Run
go vetregularly.
Include a Makefile with the following targets:
build:
go build -o mydocs ./cmd/mydocs
run:
go run ./cmd/mydocs
test:
go test ./...
bench:
go test -bench=. ./...
lint:
golangci-lint run
fmt:
gofmt -s -w .
vet:
go vet ./...
help:
@echo "Available commands: build, run, test, bench, lint, fmt, vet"Follow Conventional Commits if this grows:
feat:New featurefix:Bug fixrefactor:Code change without behavior changetest:Testing changeschore:Linting, tooling, deps
func TestCreateEntry(t *testing.T) {
tests := []struct {
name string
date string
wantErr bool
}{
{"valid date", "2025-12-25", false},
{"invalid date", "invalid-date", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := CreateEntry(tt.date)
if (err != nil) != tt.wantErr {
t.Errorf("got error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}