Skip to content

Development

This guide covers setting up a development environment and contributing to obx.

  • Go 1.21+: Required for building
  • mise (recommended): For tool management
  • Git: For version control
Terminal window
git clone https://github.com/zach-snell/obx.git
cd obx
Terminal window
mise install

This installs Go and development tools automatically.

Terminal window
mise run build
# or
go build -o bin/obx ./cmd/obx
Terminal window
mise run test
# or
go test -race -cover ./...
obx/
├── cmd/
│ └── server/
│ └── main.go # Entry point
├── internal/
│ ├── server/
│ │ └── server.go # MCP server setup, tool registration
│ └── vault/
│ ├── vault.go # Vault struct, core helpers
│ ├── notes.go # Note CRUD operations
│ ├── search.go # Search tools
│ ├── frontmatter.go # Frontmatter operations
│ ├── tasks.go # Task management
│ ├── periodic.go # Periodic notes
│ ├── templates.go # Template operations
│ ├── graph.go # Link analysis
│ ├── canvas.go # Canvas operations
│ ├── bulk.go # Bulk operations
│ └── *_test.go # Tests
├── docs/ # Documentation site
├── .mise.toml # mise configuration
└── README.md

Available mise tasks:

TaskDescription
mise run buildBuild the binary
mise run devRun with test vault
mise run testRun tests with race detection
mise run lintRun golangci-lint
mise run vulnCheck for vulnerabilities
mise run checkRun lint + test + vuln
mise run fuzzRun all fuzz tests
mise run docs:devRun docs dev server
mise run docs:buildBuild docs for production

Create or update a file in internal/vault/:

internal/vault/myfeature.go
package vault
import (
"context"
"github.com/mark3labs/mcp-go/mcp"
)
func (v *Vault) MyNewToolHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// Get parameters
param := request.Params.Arguments["param"].(string)
// Do the work
result, err := v.doSomething(param)
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
// Return result
return mcp.NewToolResultText(result), nil
}

Add to internal/server/server.go:

// my-new-tool
s.AddTool(
mcp.NewTool("my-new-tool",
mcp.WithDescription("Description of what this tool does"),
mcp.WithString("param",
mcp.Required(),
mcp.Description("Parameter description"),
),
mcp.WithNumber("optional_param",
mcp.Description("Optional parameter"),
),
),
v.MyNewToolHandler,
)
internal/vault/myfeature_test.go
package vault
import (
"testing"
)
func TestMyNewTool(t *testing.T) {
v := setupTestVault(t)
// Test normal case
result, err := v.doSomething("input")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result != expected {
t.Errorf("got %v, want %v", result, expected)
}
}

Add documentation in docs/src/content/docs/tools/.

Terminal window
go test ./internal/vault/... -v
Terminal window
go test -cover -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
Terminal window
# Run all fuzz tests (10s each)
mise run fuzz
# Run specific fuzz test longer
FUZZ_NAME=ParseTask FUZZ_TIME=60s mise run fuzz:one

Test against a real vault:

Terminal window
# Create test vault
mkdir -p test-vault/daily test-vault/templates
echo "# Test" > test-vault/test.md
# Run server
mise run dev
Terminal window
gofmt -w .
Terminal window
mise run lint

Linting checks:

  • Code style
  • Error handling
  • Unused code
  • Security issues

Run before committing:

Terminal window
mise run check
Terminal window
cd docs
pnpm install
pnpm dev
Terminal window
mise run docs:build
  1. Create .mdx file in appropriate directory
  2. Update astro.config.mjs sidebar if needed
  3. Use Starlight components for rich content
  1. Update version in internal/server/server.go
  2. Update CHANGELOG.md
  3. Commit: git commit -m "Release vX.Y.Z"
  4. Tag: git tag vX.Y.Z
  5. Push: git push origin main --tags

GitHub Actions handles:

  • Running tests on PR
  • Building binaries on release
  • Publishing to GitHub Releases
  • Deploying documentation
  1. Fork the repository
  2. Create a feature branch
  3. Make changes with tests
  4. Run mise run check
  5. Submit PR with clear description

Follow conventional commits:

  • feat: Add new tool for X
  • fix: Handle edge case in search
  • docs: Update installation guide
  • test: Add fuzz tests for parser

PRs are reviewed for:

  • Correctness
  • Test coverage
  • Documentation
  • Performance
  • Security