This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Datum Scorecard is a Go CLI tool for collecting KPI metrics from various external APIs (GitHub, Ashby, Datum Cloud). It aggregates data into weekly reports with consistent tabular output formats.
Purpose: Automate the collection of key performance indicators for business metrics reporting.
go build # Build the binary
./scorecard # Run the CLI
go build && ./scorecard <command> # Build and run
# Run a specific command
./scorecard datum active-users
./scorecard github stars datum-cloudnix build # Build via Nix flake
./result/bin/scorecard # Run the built binary
# Or enter dev shell
nix develop
go build && ./scorecardBuild Environment: Go 1.23, uses Cobra for CLI framework.
GITHUB_TOKEN- GitHub personal access token (forgithubandincidentscommands)ASHBY_API_KEY- Ashby HQ API key (forashbycommands)- No env vars needed for
datumcommands (usesdatumctlauthentication)
datumctl- Datum Cloud CLI, must be installed and authenticated viadatumctl auth login- Used by
datumcommands to query audit logs and user data - Can be in
~/bin/datumctlor on PATH - Commands shell out to
datumctl activity queryanddatumctl get users
- Used by
All commands are defined in cmd/ directory using Cobra:
scorecard
├── ashby # Ashby HQ recruiting metrics (cmd/ashby.go)
│ ├── applicants-by-week # Weekly applicant counts with histogram
│ └── applicant-map # Candidate data with geo information
├── datum # Datum Cloud metrics (cmd/datum.go)
│ ├── active-users # Count active users by week from audit logs
│ └── signups # Count new user signups by week
├── github # GitHub metrics (cmd/github.go)
│ └── stars <org> # Repository star counts for an org/user
└── incidents <org/repo> # GitHub incident tracking (cmd/incidents.go)
Entry Point: cmd/root.go defines root command and calls Execute()
-
cmd/weeks.go- Week boundary calculations (Monday-Sunday UTC)getWeekStart(t)- Get Monday of week containing time tgetLast4Weeks()- Return last 4 completed weeksgetCurrentWeekStart()- Get Monday of current in-progress week- Reports show only completed weeks (current week shown separately)
-
cmd/table.go-weeklyTablestruct for consistent tabular outputnewWeeklyTable(labelWidth, weekWidth, weeks)- Create tableprintHeader(label, currentWeek)- Print header with week ending datesprintRow(label, weekValues, currentWeek)- Print data rowprintSeparator(currentWeek)- Print horizontal separator
-
Output Formatting
- Progress/status messages →
stderr(viafmt.Fprintln(os.Stderr, ...)) - Data output →
stdout(viafmt.Println()) - Most commands support
--jsonflag for JSON output - Zero values in tables displayed as "-" instead of "0"
- Progress/status messages →
-
Week Boundaries
- Monday 00:00:00 UTC to Sunday 23:59:59 UTC
- Reports show completed weeks only; current week shown in separate column
- All time parsing uses RFC3339 format
-
Pagination
- All API fetching functions handle pagination internally
- Use
--all-pageswith datumctl for complete data --limitflag available for testing/debugging
-
Error Handling
- Auth errors detected via string matching (oauth2, token, credentials)
- Return user-friendly error messages with remediation steps
- Example: "authentication error: please run 'datumctl auth login' and try again"
-
JSON Structures
- Use anonymous structs for API responses when possible
- Use named structs only when reused across functions
- Example:
auditEvent,auditQueryResult,userInfoin datum.go
Active Users: Counts unique users who performed create/update/patch operations
- Query:
datumctl activity query --platform-wide --filter "verb in ['create', 'update', 'patch'] && user.username.contains('system:') == false && user.uid != '' && objectRef.apiGroup in ['activity.miloapis.com'] == false" - Excludes system accounts and activity API operations
- Supports
--listflag to print user details (UID, Name, Email, Last Activity) - User list sorted by last activity time, oldest first
Signups: Counts new user signups by tracking PATCH operations
- Critical: User signups are tracked as
verb == 'patch'onobjectRef.resource == 'users'byuser.username == 'zitadel-actions-server' - NOT tracked as CREATE operations (this was discovered via debugging)
- Query:
datumctl activity query --platform-wide --filter "verb == 'patch' && objectRef.resource == 'users' && user.username == 'zitadel-actions-server'" - Supports
--debugflag for troubleshooting filters - Supports
--week YYYY-MM-DDflag for debugging specific weeks
- Requires
GITHUB_TOKENenvironment variable - Uses GitHub REST API v3
- Handles pagination via Link headers
- Stars command supports
-sflag for alphabetical sorting (default is by star count)
- Requires
ASHBY_API_KEYenvironment variable applicants-by-week: Shows weekly applicant counts--histoflag displays 6-month histogram
applicant-map: Shows candidate data with geo information--debugflag shows candidate and application structures
- Tracks GitHub issues as incidents for a specific repository
- Uses GitHub API with pagination
- Groups incidents by week of creation
- Create or edit file in
cmd/directory - Define Cobra command with
&cobra.Command{} - Add to parent command in
init()function - Implement
RunEfunction - Follow patterns:
- Use
cmd.Flags().Get*()to retrieve flag values - Output progress to stderr, data to stdout
- Support
--jsonflag for structured output - Use
weeklyTablefor tabular weekly data - Handle auth errors with clear messages
- Use
Example Structure:
var myCmd = &cobra.Command{
Use: "mycommand",
Short: "Brief description",
Long: "Longer description with requirements",
RunE: runMyCommand,
}
func init() {
rootCmd.AddCommand(myCmd)
myCmd.Flags().Bool("json", false, "Output in JSON format")
}
func runMyCommand(cmd *cobra.Command, args []string) error {
outputJSON, _ := cmd.Flags().GetBool("json")
// Implementation
}-
Add
--debugflag support (like in signups command)- Show raw event counts and resource types
- Print sample events to understand data structure
- Count events by resource and verb
-
Use
--week YYYY-MM-DDflag to focus on specific week- Reduces data volume for investigation
- Shows all events in that time range
- Helps identify correct filters
-
Check audit event filters
- Verb (create, update, patch, get, delete)
- Resource type (users, platforminvitations, etc.)
- User (real users vs system accounts like zitadel-actions-server)
- API group (exclude activity.miloapis.com operations)
-
Verify week boundaries
- Monday 00:00:00 UTC to Sunday 23:59:59 UTC
- Use
getWeekStart()to check date calculations - Ensure timestamps parsed as RFC3339
- Check
go.modis up to date:go mod tidy - For Nix builds, update
vendorHashinflake.nixif dependencies change - Ensure Go 1.23+ is available
Based on commit history:
- Feature commits:
feat: description - Bug fixes:
fix: descriptionorfix(scope): description - Documentation:
chore(docs):orfix(docs): - Use conventional commits style
- PRs merged to main branch
- No automated tests currently (no
*_test.gofiles) - Manual testing via building and running commands
- Use
--limitflag to test with smaller data sets - Use
--debugflags for troubleshooting
- "datumctl not found": Ensure datumctl is in ~/bin or PATH, and authenticated
- Auth errors with datum: Run
datumctl auth login - Zero counts in datum signups: Check if using correct filter (PATCH by zitadel-actions-server, not CREATE)
- Missing user details in --list: fetchAllUsers may timeout; falls back to audit event data
- Week boundaries seem off: All times are UTC; verify timezone conversions
When adding features:
- Maintain consistency with
--jsonoutput format - Use
weeklyTablefor weekly reports - Add
--limitflags for large data sets - Consider adding
--debugflags for complex queries - Document any non-obvious API behavior (like the signups PATCH pattern)