|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Clockify CLI is a command-line tool for managing time entries and projects on Clockify from the terminal. It's written in Go and built on the Cobra framework for CLI command handling. |
| 8 | + |
| 9 | +**Key Technologies:** |
| 10 | +- Go 1.24+ (module-based) |
| 11 | +- Cobra for CLI commands |
| 12 | +- Viper for configuration management |
| 13 | +- Survey for interactive prompts |
| 14 | +- GoReleaser for releases |
| 15 | + |
| 16 | +## Building and Development |
| 17 | + |
| 18 | +### Installation and Preparation |
| 19 | + |
| 20 | +```bash |
| 21 | +make deps-install # Install Go dependencies |
| 22 | +``` |
| 23 | + |
| 24 | +### Building |
| 25 | + |
| 26 | +```bash |
| 27 | +make go-install # Build and install dev version to $GOBIN |
| 28 | +make dist # Build all versions (darwin, linux, windows) → dist/ |
| 29 | +go run cmd/clockify-cli/main.go <args> # Run directly from source |
| 30 | +``` |
| 31 | + |
| 32 | +### Testing |
| 33 | + |
| 34 | +```bash |
| 35 | +make test # Run all tests with gotestsum |
| 36 | +make test-watch # Run tests with file watcher (fails fast) |
| 37 | +make test-coverage # Run tests with coverage report |
| 38 | +``` |
| 39 | + |
| 40 | +### Code Generation |
| 41 | + |
| 42 | +```bash |
| 43 | +make go-generate # Regenerate mocks using mockery |
| 44 | +``` |
| 45 | + |
| 46 | +## Project Structure |
| 47 | + |
| 48 | +- **`cmd/`** - Main executable packages |
| 49 | + - `cmd/clockify-cli/main.go` - Entry point (version info, error handling, Viper config binding) |
| 50 | + - `cmd/release/` - Release automation |
| 51 | + - `cmd/gendocs/` - Documentation generation |
| 52 | + |
| 53 | +- **`api/`** - Clockify API client implementation |
| 54 | + - `api/client.go` - Main HTTP client for API calls |
| 55 | + - `api/dto/` - Data transfer objects and request builders |
| 56 | + |
| 57 | +- **`pkg/cmd/`** - CLI command implementation (follows directory-based routing) |
| 58 | + - Subdirectories for command groups: `client/`, `config/`, `project/`, `tag/`, `task/`, `time-entry/`, `user/`, `version/`, `workspace/` |
| 59 | + - Pattern: Command at `pkg/cmd/<entity>/<subcommand>/<subcommand>.go` |
| 60 | + - Each command has a `NewCmd<SubCommand>()` factory function returning `*cobra.Command` |
| 61 | + |
| 62 | +- **`pkg/output/`** - Output formatters |
| 63 | + - Pattern: `pkg/output/<entity>/<format>.go` |
| 64 | + - Formats: table (default), json, quiet (ID only), template (Go template), csv |
| 65 | + |
| 66 | +- **`pkg/`** - Shared packages |
| 67 | + - `cmdutil/` - Command utilities, configuration constants (CONF_TOKEN, CONF_WORKSPACE, etc.) |
| 68 | + - `cmdcomplutil/` - Completion utilities |
| 69 | + - `outpututil/` - Shared output logic |
| 70 | + - `timeentryhlp/`, `timehlp/` - Time entry and time helpers |
| 71 | + - `ui/` - UI components (prompts, selections) |
| 72 | + |
| 73 | +- **`internal/`** - Project-specific test utilities |
| 74 | + - `testhlp/` - Test helpers |
| 75 | + - `consoletest/` - Console testing utilities |
| 76 | + - `mocks/` - Generated mocks |
| 77 | + |
| 78 | +## Command Architecture |
| 79 | + |
| 80 | +Commands follow the Cobra pattern: |
| 81 | + |
| 82 | +1. **Factory Functions:** Each command is created via `NewCmd<Name>(factory cmdutil.Factory) *cobra.Command` |
| 83 | +2. **Command Groups:** Parent commands register subcommands (e.g., `pkg/cmd/client/client.go` registers its subcommands) |
| 84 | +3. **Configuration:** Commands access config through `factory.Config()` which reads from: |
| 85 | + - Environment variables (prefix: `CLOCKIFY_`) |
| 86 | + - Config file: `~/.config/clockify-cli/config.yaml` or `~/.clockify-cli` |
| 87 | + - CLI flags (with viper binding) |
| 88 | + |
| 89 | +**Adding a New Command:** |
| 90 | +1. Create `pkg/cmd/<entity>/<subcommand>/<subcommand>.go` |
| 91 | +2. Implement `NewCmd<SubCommand>(factory cmdutil.Factory) *cobra.Command` |
| 92 | +3. Register in parent command's `NewCmd<Entity>()` function |
| 93 | +4. If first command for entity, create output formatters at `pkg/output/<entity>/` for: table, json, quiet, template, csv |
| 94 | + |
| 95 | +## Key Patterns and Conventions |
| 96 | + |
| 97 | +- **Configuration keys:** Defined in `pkg/cmdutil/` (e.g., `CONF_TOKEN`, `CONF_WORKSPACE`, `CONF_USER_ID`) |
| 98 | +- **CLI Flags:** Bound to Viper config via `bindViper()` in main.go, allowing env var and config file overrides |
| 99 | +- **Environment Variables:** Use `CLOCKIFY_` prefix (e.g., `CLOCKIFY_TOKEN`, `CLOCKIFY_WORKSPACE`) |
| 100 | +- **Output:** Commands use output formatters from `pkg/output/` to support multiple formats |
| 101 | +- **Mocks:** Generated by `mockery` during `make go-generate` — run this before testing if interfaces change |
| 102 | + |
| 103 | +## Testing |
| 104 | + |
| 105 | +- **Framework:** testify assertions + gotestsum runner |
| 106 | +- **Test Discovery:** `**/*_test.go` pattern |
| 107 | +- **Mocks:** `internal/mocks/` — regenerate with `make go-generate` when interfaces change |
| 108 | +- **Flags:** Use `-failfast` in `make test-watch` (configured in Makefile) |
| 109 | + |
| 110 | +## Changelog |
| 111 | + |
| 112 | +Every code change **must** be documented in `CHANGELOG.md` under the `## [Unreleased]` section. Follow the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format: |
| 113 | + |
| 114 | +- **Added** — for new features or functionality |
| 115 | +- **Changed** — for changes to existing functionality |
| 116 | +- **Deprecated** — for soon-to-be removed features |
| 117 | +- **Removed** — for removed features |
| 118 | +- **Fixed** — for bug fixes |
| 119 | +- **Security** — for security fixes |
| 120 | + |
| 121 | +Each change is one bullet point written from the user's perspective (what changed, not implementation details). Do not commit changes without updating the changelog first. |
| 122 | + |
| 123 | +## Git Commits |
| 124 | + |
| 125 | +Always ask the user for permission before creating any commit. Do not run `git commit` without explicit user approval — confirm what will be committed and ask for approval before proceeding. |
0 commit comments