Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Punchcard Logo

Punchcard - Daily Time Tracker

A simple daily time tracking webapp built with Go and HTMX.

Daily View Monthly Overview
Daily Time Tracking Monthly Calendar
Track your daily tasks with real-time timers Visual monthly overview with calendar grid

Features

  • OIDC Authentication: Secure login with any OIDC provider (Keycloak, Auth0, Google, etc.)
  • Billable Tracking: Mark time entries as billable/non-billable with visual indicators
  • Kimai JSON export: Times can be exported as Kimai-compatible JSON (see Importing to Kimai)
  • Billable/Unbillable: Each time entry has a billable checkbox
  • API keys & CLI: Personal API keys (profile page) unlock a JSON API and the punch CLI for starting/stopping timers and exporting timesheets from the terminal or scripts

All time entries (both billable and non-billable) are included in exports with correct status. Unbillable don't count towards the monthly and weekly total in the UI.

Configuration

Punchcard is configured via environment variables (.env file will be automatically loaded).

PORT=8080                                    # Server port (default: 8080)
DATABASE_URL=punchcard.db                    # Database file path (default: punchcard.db)
OIDC_ISSUER_URL=https://your-provider.com    # OIDC provider URL
OIDC_CLIENT_ID=your-client-id                # OAuth client ID
OIDC_CLIENT_SECRET=your-client-secret        # OAuth client secret
OIDC_REDIRECT_URL=http://domain.tld/callback # OAuth redirect URL

For local development you can bypass OIDC entirely:

PUNCHCARD_DEV_USER=dev@example.com  # Log every request in as this user (never use in production)

CLI (punch)

Create an API key on your profile page (API Keys section), then configure the CLI once. The key is never passed as a command line argument; use a password manager command or the PUNCHCARD_TOKEN environment variable:

punch setup --url https://punchcard.example.com --token-command "pass show punchcard"
# or: PUNCHCARD_TOKEN=pc_... punch setup --url https://punchcard.example.com

Day-to-day usage:

punch start "write report"      # start a timer (stops any other running timer)
punch status                    # show running timer and today's totals
punch stop                      # stop the running timer
punch entries --from 2026-03-01 --to 2026-03-31   # list entries (with IDs)
punch edit 42 --duration 1:30 --billable false    # fix up an entry
punch delete 42                                   # delete an entry
punch export --month 2026-03 -o march.json        # Kimai-compatible export

Every command accepts --json for stable, machine-readable output, which also makes the CLI easy to drive from scripts and LLM agents. Configuration lives in ~/.config/punchcard/config.json; the environment variables PUNCHCARD_URL and PUNCHCARD_TOKEN override it.

HTTP API

All endpoints live under /api/v1 and authenticate with Authorization: Bearer <api-key>:

Endpoint Description
GET /api/v1/status Running timer and today's totals
POST /api/v1/timers/start Start a timer: {"description": "task", "date": "2026-03-02"} (date optional)
POST /api/v1/timers/stop Stop all running timers
GET /api/v1/entries?from=YYYY-MM-DD&to=YYYY-MM-DD List entries (default: today)
PATCH /api/v1/entries/{id} Update description, duration, billable, and/or date
DELETE /api/v1/entries/{id} Delete an entry (returns it as a receipt)
GET /api/v1/export?month=YYYY-MM Kimai-compatible JSON export (default: current month)

Importing to Kimai

Download the JSON export from the punchcard UI (daily or monthly), then import each entry to Kimai using curl:

export KIMAI_API_TOKEN="<your token>"
export KIMAI_INSTANCE="https://your-kimai-instance"
export PUNCHCARD_EXPORT="punchcard-export-2026-03.json"

jq -c '.[]' $PUNCHCARD_EXPORT | while IFS= read -r entry; do
  curl -s -X POST "$KIMAI_INSTANCE/api/timesheets" \
    -H "Authorization: Bearer $KIMAI_API_TOKEN" \
    -H "Content-Type: application/json" \
    -H "Accept: application/json" \
    -d "$entry"
  echo
done

To create an API token, go to your Kimai profile page → API tab → create a new token.

Note: Kimai has no deduplication - importing the same file twice will create duplicate entries. The billable field requires the edit_billable permission in Kimai; if your user lacks it, strip the field with jq -c '.[] | del(.billable)' instead.

About

Simple time tracking for small teams built with Go and HTMX with OIDC support

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages