This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
ShellTime CLI is a Go-based command-line tool for tracking DevOps work. It consists of two main binaries:
shelltime: The main CLI tool for command tracking and managementshelltime-daemon: A background service for asynchronous command tracking, synchronization, and OTEL data collection
Requires Go 1.26+
# Build the CLI binary
go build -o shelltime ./cmd/cli/main.go
# Build the daemon binary
go build -o shelltime-daemon ./cmd/daemon/main.go
# Build with all ldflags (version, commit, AI service config)
go build -ldflags "-X main.version=v0.1.0 -X main.commit=$(git rev-parse HEAD) -X main.date=$(date -u +%Y-%m-%d) -X main.ppEndpoint=<endpoint> -X main.ppToken=<token>" -o shelltime ./cmd/cli/main.go# Run all tests with coverage
go test -timeout 3m -coverprofile=coverage.txt -covermode=atomic ./...
# Run tests for a specific package
go test ./commands/...
go test ./daemon/...
go test ./model/...
# Run a single test
go test -run TestHandlerName ./daemon/Tests use testify (assertions + suites). Suite-based tests use suite.Suite with SetupTest/TearDownTest lifecycle hooks (see daemon/cc_info_handler_test.go for example). Simple functions use table-driven tests.
# Generate mocks (uses .mockery.yml configuration, Mockery v3)
mockery
# Generate PromptPal types (requires pp CLI and API token)
pp gCI runs both mockery and pp g before tests. Generated files: model/pp.types.g.go (PromptPal types), model/mock_*.go (testify mocks for service interfaces).
go vet ./...
go fmt ./...- cmd/cli/: CLI entry point - registers all commands, initializes services via dependency injection
- cmd/daemon/: Daemon entry point - sets up pub/sub, socket handler, and optional AICodeOtel gRPC server
- commands/: CLI command implementations - each command in its own file,
base.goholds injected services - daemon/: Daemon internals - socket handler, Watermill pub/sub channel, AICodeOtel gRPC server/processor
- model/: Business logic - API clients, config, crypto, shell hooks, service installers, dotfile handlers
Three key interfaces with dependency injection:
ConfigService: Reads and merges config fromconfig.tomlandconfig.local.tomlAIService: PromptPal integration for AI-powered command suggestions (shelltime q)CommandService: Executable lookup with fallback paths (handles daemon's limited PATH)
Injection happens in cmd/*/main.go via commands.InjectVar() and commands.InjectAIService().
- SocketHandler: Unix domain socket server accepting JSON messages from CLI
- GoChannel: Watermill pub/sub for decoupled message processing
- SocketTopicProcessor: Consumes messages and routes to appropriate handlers
Optional daemon services (feature-gated via config):
- CCInfoTimerService: Lazy-fetch background timer for Claude Code statusline data (cost, quota, git info)
- SyncCircuitBreakerService: Retry failed syncs with file-based persistence (
sync_pending.log) and hourly recovery timer - AICodeOtelServer: gRPC OTEL collector for AI coding CLI metrics/logs (Claude Code, Codex)
- HeartbeatResyncService: Periodic resync of failed heartbeats (30-min interval)
- CleanupTimerService: Periodic log file cleanup (24-hour interval)
- CCUsageService: Integration with ccusage CLI
Services initialize in cmd/daemon/main.go: check enabled flag → create → start → defer stop. All run concurrently with graceful shutdown on SIGINT/SIGTERM.
- Shell hooks capture commands → CLI stores locally (file-based buffer)
- CLI sends sync message to daemon via Unix socket
- Daemon's pub/sub routes to sync handler
- Batch sync to shelltime.xyz API with optional encryption
- Main config:
$HOME/.shelltime/config.toml - Local overrides:
$HOME/.shelltime/config.local.toml(merged, gitignored) - Daemon socket:
/tmp/shelltime.sock(configurable viasocketPath) - AICodeOtel gRPC port: configurable via
aiCodeOtel.grpcPort(default: 54027)
Follow Conventional Commits with scope: fix(daemon): ..., feat(cli): ..., refactor(model): ...
- CLI Framework:
urfave/cli/v2 - Message Queue:
ThreeDotsLabs/watermill(in-process pub/sub for daemon) - AI Integration:
PromptPal/go-sdkwith generated types frompromptpal.yml - Telemetry:
uptrace-gofor OTEL - Config:
pelletier/go-toml/v2 - Git:
go-git/v5for branch/dirty detection - gRPC: OTEL collector protos for AICodeOtel server
Releases use Release-Please (always-bump-patch) + Goreleaser. macOS builds include code signing/notarization via Quill when credentials are present. CI config in .github/workflows/.
- Daemon is optional but recommended (<8ms latency vs ~100ms+ direct)
- Encryption requires daemon mode and a token with encryption capability
- Shell hooks are platform-specific (bash, zsh, fish) - test on target shells
- CC statusline quota display is macOS-only (requires Keychain access to Claude Code OAuth token)
- AICodeOtel feature enables AI coding CLI metrics/logs passthrough via gRPC (port 54027) - supports Claude Code, Codex, and other OTEL-compatible CLIs