Convert Figma logo to code with AI

muety logowakapi

📊 A minimalist, self-hosted WakaTime-compatible backend for coding statistics

2,542
155
2,542
33

Top Related Projects

The best free and open-source automated time tracker. Cross-platform, extensible, privacy-focused.

15,713

The personal information dashboard for your terminal

Toggl Track browser extension for Chrome and Firefox

Quick Overview

Wakapi is a self-hosted, open-source time tracking application for programmers. It's designed to be a lightweight, privacy-focused alternative to WakaTime, allowing developers to track their coding time and generate insights about their programming habits.

Pros

  • Self-hosted solution, ensuring data privacy and control
  • Compatible with various code editors and IDEs through WakaTime plugins
  • Provides detailed insights and visualizations of coding activity
  • Lightweight and easy to set up using Docker

Cons

  • Requires self-hosting, which may be challenging for some users
  • Limited features compared to more established time-tracking solutions
  • May require additional setup for secure remote access
  • Smaller community and ecosystem compared to commercial alternatives

Getting Started

To get started with Wakapi, follow these steps:

  1. Clone the repository:

    git clone https://github.com/muety/wakapi.git
    
  2. Navigate to the project directory:

    cd wakapi
    
  3. Create a configuration file:

    cp config.default.yml config.yml
    
  4. Edit the config.yml file to set your desired configuration options.

  5. Build and run the Docker container:

    docker build -t wakapi .
    docker run -d -p 3000:3000 -v /path/to/data:/app/data wakapi
    
  6. Access the Wakapi dashboard at http://localhost:3000 and create your account.

  7. Install the WakaTime plugin for your preferred code editor and configure it to use your Wakapi instance URL.

For more detailed instructions and configuration options, refer to the project's README and documentation on GitHub.

Competitor Comparisons

The best free and open-source automated time tracker. Cross-platform, extensible, privacy-focused.

Pros of ActivityWatch

  • More comprehensive tracking across multiple platforms (Windows, macOS, Linux, Android)
  • Extensible architecture with plugins for various applications and services
  • Advanced data visualization and reporting features

Cons of ActivityWatch

  • More complex setup and configuration process
  • Potentially higher resource usage due to its comprehensive tracking capabilities
  • Steeper learning curve for new users

Code Comparison

ActivityWatch (Python):

from aw_core.models import Event
from aw_client import ActivityWatchClient

client = ActivityWatchClient("my-client")
bucket_id = "my-bucket"
client.create_bucket(bucket_id, event_type="app")

event = Event(timestamp=datetime.now(), duration=0, data={"app": "myapp"})
client.insert_event(bucket_id, event)

Wakapi (Go):

import "github.com/muety/wakapi/models"

heartbeat := models.Heartbeat{
    Time:     time.Now(),
    Entity:   "myfile.txt",
    Type:     "file",
    Project:  "myproject",
    Language: "Go",
}
api.SendHeartbeat(heartbeat)

Both projects offer time tracking capabilities, but ActivityWatch provides a more comprehensive solution with cross-platform support and extensive features, while Wakapi focuses on simplicity and ease of use for developers.

15,713

The personal information dashboard for your terminal

Pros of wtf

  • More comprehensive dashboard with various modules for system monitoring, productivity, and information display
  • Highly customizable with a wide range of widgets and configuration options
  • Active development with frequent updates and new features

Cons of wtf

  • Steeper learning curve due to its extensive feature set
  • Requires more system resources to run compared to Wakapi
  • May be overkill for users only interested in time tracking

Code Comparison

wtf configuration example:

wtf:
  colors:
    border:
      focusable: darkslateblue
      focused: orange
      normal: gray
  grid:
    columns: [40, 40]
    rows: [13, 13, 4]

Wakapi configuration example:

[server]
port = 3000
base_path = "/"

[database]
host = "localhost"
port = 5432
user = "wakapi"

While both projects use configuration files, wtf's configuration is more complex due to its wider range of features and customization options. Wakapi's configuration is simpler, focusing primarily on server and database settings.

Toggl Track browser extension for Chrome and Firefox

Pros of Track-extension

  • Integrates directly with Toggl Track, a popular time tracking service
  • Offers browser extension functionality for easy time tracking across websites
  • Provides a more comprehensive time tracking solution with reporting features

Cons of Track-extension

  • Limited to browser-based activities, unlike Wakapi's system-wide tracking
  • Requires a Toggl account and may have associated costs
  • Less focus on developer-specific metrics compared to Wakapi

Code Comparison

Track-extension (JavaScript):

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'timeEntry') {
    startTimeEntry(request.data);
  }
});

Wakapi (Go):

func (h *Handler) HandleHeartbeat(c echo.Context) error {
    var heartbeat models.Heartbeat
    if err := c.Bind(&heartbeat); err != nil {
        return err
    }
    // Process heartbeat...
}

The code snippets show different approaches: Track-extension uses browser-specific APIs for time entry, while Wakapi implements a server-side handler for processing heartbeats from various sources.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

A minimalist, self-hosted WakaTime-compatible backend for coding statistics.

Installation instructions can be found below and in the Wiki.

🚀 Features

  • ✅ Free and open-source
  • ✅ Built by developers for developers
  • ✅ Statistics for projects, languages, editors, hosts and operating systems
  • ✅ Badges
  • ✅ Weekly E-Mail reports
  • ✅ REST API
  • ✅ Partially compatible with WakaTime
  • ✅ WakaTime integration
  • ✅ Support for Prometheus exports
  • ✅ Lightning fast
  • ✅ Self-hosted

⌨️ How to use?

There are different options for how to use Wakapi, ranging from our hosted cloud service to self-hosting it. Regardless of which option choose, you will always have to do the client setup in addition.

☁️ Option 1: Use wakapi.dev

If you want to try out a free, hosted cloud service, all you need to do is create an account and then set up your client-side tooling (see below).

📦 Option 2: Quick-run a release

$ curl -L https://wakapi.dev/get | bash

Alternatively using eget:

$ eget muety/wakapi

🐳 Option 3: Use Docker

# Create a persistent volume
$ docker volume create wakapi-data

$ SALT="$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w ${1:-32} | head -n 1)"

# Run the container
$ docker run -d \
  -p 3000:3000 \
  -e "WAKAPI_PASSWORD_SALT=$SALT" \
  -v wakapi-data:/data \
  --name wakapi \
  ghcr.io/muety/wakapi:latest

Alternatively, you can use Docker Compose (docker compose up -d) for a more straightforward deployment. See compose.yml for configuration details. If you prefer to persist data in a local directory while using SQLite as the database, make sure to set the correct user option in the Docker Compose configuration to avoid permission issues.

Note: By default, SQLite is used as a database. To run Wakapi in Docker with MySQL or Postgres, see Dockerfile and config.default.yml for further options.

If you want to run Wakapi on Kubernetes, there is wakapi-helm-chart for quick and easy deployment.

🧑‍💻 Option 4: Compile and run from source

# Build and install
# Alternatively: go build -o wakapi
$ go install github.com/muety/wakapi@latest

# Get default config and customize
$ curl -o wakapi.yml https://raw.githubusercontent.com/muety/wakapi/master/config.default.yml
$ vi wakapi.yml

# Run it
$ ./wakapi -config wakapi.yml

Note: Check the comments in config.yml for best practices regarding security configuration and more.

💡 When running Wakapi standalone (without Docker), it is recommended to run it as a SystemD service.

💻 Client setup

Wakapi relies on the open-source WakaTime client tools. In order to collect statistics for Wakapi, you need to set them up.

  1. Set up WakaTime for your specific IDE or editor. Please refer to the respective plugin guide
  2. Edit your local ~/.wakatime.cfg file as follows.
[settings]

# Your Wakapi server URL or 'https://wakapi.dev/api' when using the cloud server
api_url = http://localhost:3000/api

# Your Wakapi API key (get it from the web interface after having created an account)
api_key = 406fe41f-6d69-4183-a4cc-121e0c524c2b

Optionally, you can set up a client-side proxy in addition.

🔧 Configuration options

You can specify configuration options either via a config file (default: config.yml, customizable through the -c argument) or via environment variables. Here is an overview of all options.

YAML key / Env. variableDefaultDescription
env /
ENVIRONMENT
devWhether to use development- or production settings
app.leaderboard_enabled /
WAKAPI_LEADERBOARD_ENABLED
trueWhether to enable the public leaderboard
app.leaderboard_scope /
WAKAPI_LEADERBOARD_SCOPE
7_daysAggregation interval for public leaderboard (see here for allowed values)
app.leaderboard_generation_time /
WAKAPI_LEADERBOARD_GENERATION_TIME
0 0 6 * * *,0 0 18 * * *One or multiple times of day at which to re-calculate the leaderboard
app.aggregation_time /
WAKAPI_AGGREGATION_TIME
0 15 2 * * *Time of day at which to periodically run summary generation for all users
app.report_time_weekly /
WAKAPI_REPORT_TIME_WEEKLY
0 0 18 * * 5Week day and time at which to send e-mail reports
app.data_cleanup_time /
WAKAPI_DATA_CLEANUP_TIME
0 0 6 * * 0When to perform data cleanup operations (see app.data_retention_months)
app.import_enabled /
WAKAPI_IMPORT_ENABLED
trueWhether data imports from WakaTime or other Wakapi instances are permitted
app.import_batch_size /
WAKAPI_IMPORT_BATCH_SIZE
50Size of batches of heartbeats to insert to the database during importing from external services
app.import_backoff_min /
WAKAPI_IMPORT_BACKOFF_MIN
5"Cooldown" period in minutes before user may attempt another data import
app.import_max_rate /
WAKAPI_IMPORT_MAX_RATE
24Minimum number of hours to wait after a successful data import before user may attempt another one
app.inactive_days /
WAKAPI_INACTIVE_DAYS
7Number of days after which to consider a user inactive (only for metrics)
app.heartbeat_max_age /
WAKAPI_HEARTBEAT_MAX_AGE
4320hMaximum acceptable age of a heartbeat (see ParseDuration)
app.custom_languages-Map from file endings to language names
app.avatar_url_template /
WAKAPI_AVATAR_URL_TEMPLATE
(see config.default.yml)URL template for external user avatar images (e.g. from Dicebear or Gravatar)
app.date_format /
WAKAPI_DATE_FORMAT
Mon, 02 Jan 2006Go time format strings to format human-readable date (see Time.Format)
app.datetime_format /
WAKAPI_DATETIME_FORMAT
Mon, 02 Jan 2006 15:04Go time format strings to format human-readable datetime (see Time.Format)
app.support_contact /
WAKAPI_SUPPORT_CONTACT
hostmaster@wakapi.devE-Mail address to display as a support contact on the page
app.data_retention_months /
WAKAPI_DATA_RETENTION_MONTHS
-1Maximum retention period in months for user data (heartbeats) (-1 for unlimited)
app.max_inactive_months /
WAKAPI_MAX_INACTIVE_MONTHS
12Maximum number of inactive months after which to delete user accounts without data (-1 for unlimited)
server.port /
WAKAPI_PORT
3000Port to listen on
server.listen_ipv4 /
WAKAPI_LISTEN_IPV4
127.0.0.1IPv4 network address to listen on (set to '-' to disable IPv4)
server.listen_ipv6 /
WAKAPI_LISTEN_IPV6
::1IPv6 network address to listen on (set to '-' to disable IPv6)
server.listen_socket /
WAKAPI_LISTEN_SOCKET
-UNIX socket to listen on (set to '-' to disable UNIX socket)
server.listen_socket_mode /
WAKAPI_LISTEN_SOCKET_MODE
0666Permission mode to create UNIX socket with
server.timeout_sec /
WAKAPI_TIMEOUT_SEC
30Request timeout in seconds
server.tls_cert_path /
WAKAPI_TLS_CERT_PATH
-Path of SSL server certificate (leave blank to not use HTTPS)
server.tls_key_path /
WAKAPI_TLS_KEY_PATH
-Path of SSL server private key (leave blank to not use HTTPS)
server.base_path /
WAKAPI_BASE_PATH
/Web base path (change when running behind a proxy under a sub-path)
server.public_url /
WAKAPI_PUBLIC_URL
http://localhost:3000URL at which your Wakapi instance can be found publicly
security.password_salt /
WAKAPI_PASSWORD_SALT
-Pepper to use for password hashing
security.insecure_cookies /
WAKAPI_INSECURE_COOKIES
falseWhether or not to allow cookies over HTTP
security.cookie_max_age /
WAKAPI_COOKIE_MAX_AGE
172800Lifetime of authentication cookies in seconds or 0 to use Session cookies
security.allow_signup /
WAKAPI_ALLOW_SIGNUP
trueWhether to enable user registration
security.signup_captcha /
WAKAPI_SIGNUP_CAPTCHA
falseWhether the registration form requires solving a CAPTCHA
security.invite_codes /
WAKAPI_INVITE_CODES
trueWhether to enable registration by invite codes. Primarily useful if registration is disabled (invite-only server).
security.disable_frontpage /
WAKAPI_DISABLE_FRONTPAGE
falseWhether to disable landing page (useful for personal instances)
security.expose_metrics /
WAKAPI_EXPOSE_METRICS
falseWhether to expose Prometheus metrics under /api/metrics
security.trusted_header_auth /
WAKAPI_TRUSTED_HEADER_AUTH
falseWhether to enable trusted header authentication for reverse proxies (see #534). Use with caution!
security.trusted_header_auth_key /
WAKAPI_TRUSTED_HEADER_AUTH_KEY
Remote-UserHeader field for trusted header authentication. Caution: proxy must be configured to strip this header from client requests!
security.trust_reverse_proxy_ips /
WAKAPI_TRUST_REVERSE_PROXY_IPS
-Comma-separated list of IPv4 or IPv6 addresses or CIDRs of reverse proxies to trust to handle authentication (e.g. 172.17.0.1, 192.168.0.0/24, [::1]).
security.signup_max_rate /
WAKAPI_SIGNUP_MAX_RATE
5/1hRate limiting config for signup endpoint in format <max_req>/<multiplier><unit>, where unit is one of s, m or h.
security.login_max_rate /
WAKAPI_LOGIN_MAX_RATE
10/1mRate limiting config for login endpoint in format <max_req>/<multiplier><unit>, where unit is one of s, m or h.
security.password_reset_max_rate /
WAKAPI_PASSWORD_RESET_MAX_RATE
5/1hRate limiting config for password reset endpoint in format <max_req>/<multiplier><unit>, where unit is one of s, m or h.
db.host /
WAKAPI_DB_HOST
-Database host
db.port /
WAKAPI_DB_PORT
-Database port
db.socket /
WAKAPI_DB_SOCKET
-Database UNIX socket (alternative to host) (for MySQL only)
db.user /
WAKAPI_DB_USER
-Database user
db.password /
WAKAPI_DB_PASSWORD
-Database password
db.name /
WAKAPI_DB_NAME
wakapi_db.dbDatabase name
db.dialect /
WAKAPI_DB_TYPE
sqlite3Database type (one of sqlite3, mysql, postgres, cockroach, mssql)
db.charset /
WAKAPI_DB_CHARSET
utf8mb4Database connection charset (for MySQL only)
db.max_conn /
WAKAPI_DB_MAX_CONNECTIONS
2Maximum number of database connections
db.ssl /
WAKAPI_DB_SSL
falseWhether to use TLS encryption for database connection (Postgres and CockroachDB only)
db.automgirate_fail_silently /
WAKAPI_DB_AUTOMIGRATE_FAIL_SILENTLY
falseWhether to ignore schema auto-migration failures when starting up
mail.enabled /
WAKAPI_MAIL_ENABLED
trueWhether to allow Wakapi to send e-mail (e.g. for password resets)
mail.sender /
WAKAPI_MAIL_SENDER
Wakapi <noreply@wakapi.dev>Default sender address for outgoing mails
mail.provider /
WAKAPI_MAIL_PROVIDER
smtpImplementation to use for sending mails (one of [smtp])
mail.smtp.host /
WAKAPI_MAIL_SMTP_HOST
-SMTP server address for sending mail (if using smtp mail provider)
mail.smtp.port /
WAKAPI_MAIL_SMTP_PORT
-SMTP server port (usually 465)
mail.smtp.username /
WAKAPI_MAIL_SMTP_USER
-SMTP server authentication username
mail.smtp.password /
WAKAPI_MAIL_SMTP_PASS
-SMTP server authentication password
mail.smtp.tls /
WAKAPI_MAIL_SMTP_TLS
falseWhether the SMTP server requires TLS encryption (false for STARTTLS or no encryption)
mail.smtp.skip_verify /
WAKAPI_MAIL_SMTP_SKIP_VERIFY
falseWhether to allow invalid or self-signed certificates for TLS-encrypted SMTP
sentry.dsn /
WAKAPI_SENTRY_DSN
–DSN for to integrate Sentry for error logging and tracing (leave empty to disable)
sentry.environment /
WAKAPI_SENTRY_ENVIRONMENT
(env)Sentry environment tag (defaults to env / ENV)
sentry.enable_tracing /
WAKAPI_SENTRY_TRACING
falseWhether to enable Sentry request tracing
sentry.sample_rate /
WAKAPI_SENTRY_SAMPLE_RATE
0.75Probability of tracing a request in Sentry
sentry.sample_rate_heartbeats /
WAKAPI_SENTRY_SAMPLE_RATE_HEARTBEATS
0.1Probability of tracing a heartbeat request in Sentry
quick_start /
WAKAPI_QUICK_START
falseWhether to skip initial boot tasks. Use only for development purposes!
enable_pprof /
WAKAPI_ENABLE_PPROF
falseWhether to expose pprof profiling data as an endpoint for debugging

Supported databases

Wakapi uses GORM as an ORM. As a consequence, a set of different relational databases is supported.

🔐 Authentication

Wakapi supports different types of user authentication.

  • Cookie: This method is used in the browser. Users authenticate by sending along an encrypted, secure, HTTP-only cookie (wakapi_auth) that was set in the server's response upon login.
  • API key:
    • Via header: This method is inspired by WakaTime's auth. mechanism and is the common way to authenticate against API endpoints. Users set the Authorization header to Basic <BASE64_TOKEN>, where the latter part corresponds to your base64-hashed API key.
    • Vis query param: Alternatively, users can also pass their plain API key as a query parameter ( e.g. ?api_key=86648d74-19c5-452b-ba01-fb3ec70d4c2f) in the URL with every request.
  • Trusted header: This mechanism allows to delegate authentication to a reverse proxy (e.g. for SSO), that Wakapi will then trust blindly. See #534 for details.
    • Must be enabled via trusted_header_auth and configuring trust_reverse_proxy_ip in the config
    • Warning: This type of authentication is quite prone to misconfiguration. Make sure that your reverse proxy properly strips relevant headers from client requests.

🔧 API endpoints

See our Swagger API Documentation.

Generating Swagger docs

$ go install github.com/swaggo/swag/cmd/swag@latest
$ swag init -o static/docs

🤝 Integrations

Prometheus export

You can export your Wakapi statistics to Prometheus to view them in a Grafana dashboard or so. Here is how.

# 1. Start Wakapi with the feature enabled
$ export WAKAPI_EXPOSE_METRICS=true
$ ./wakapi

# 2. Get your API key and hash it
$ echo "<YOUR_API_KEY>" | base64

# 3. Add a Prometheus scrape config to your prometheus.yml (see below)

Scrape config example

# prometheus.yml
# (assuming your Wakapi instance listens at localhost, port 3000)

scrape_configs:
  - job_name: 'wakapi'
    scrape_interval: 1m
    metrics_path: '/api/metrics'
    bearer_token: '<YOUR_BASE64_HASHED_TOKEN>'
    static_configs:
      - targets: [ 'localhost:3000' ]

Grafana

There is also a nice Grafana dashboard, provided by the author of wakatime_exporter.

WakaTime integration

Wakapi plays well together with WakaTime. For one thing, you can forward heartbeats from Wakapi to WakaTime to effectively use both services simultaneously. In addition, there is the option to import historic data from WakaTime for consistency between both services. Both features can be enabled in the Integrations section of your Wakapi instance's settings page.

GitHub Readme Stats integrations

Wakapi also integrates with GitHub Readme Stats to generate fancy cards for you. Here is an example. To use this, don't forget to enable public data under Settings -> Permissions.

Click to view code
![](https://github-readme-stats.vercel.app/api/wakatime?username={yourusername}&api_domain=wakapi.dev&bg_color=2D3748&title_color=2F855A&icon_color=2F855A&text_color=ffffff&custom_title=Wakapi%20Week%20Stats&layout=compact)

Github Readme Metrics integration

There is a WakaTime plugin for GitHub Metrics that is also compatible with Wakapi. To use this, don't forget to enable public data under Settings -> Permissions.

Preview:

Click to view code
- uses: lowlighter/metrics@latest
  with:
    # ... other options
    plugin_wakatime: yes
    plugin_wakatime_token: ${{ secrets.WAKATIME_TOKEN }}      # Required
    plugin_wakatime_days: 7                                   # Display last week stats
    plugin_wakatime_sections: time, projects, projects-graphs # Display time and projects sections, along with projects graphs
    plugin_wakatime_limit: 4                                  # Show 4 entries per graph
    plugin_wakatime_url: http://wakapi.dev                    # Wakatime url endpoint
    plugin_wakatime_user: .user.login                         # User


Browser Plugin (Chrome & Firefox)

The browser-wakatime plugin enables you to track your web surfing in WakaTime (and Wakapi, of course). Visited websites will appear as "files" in the summary. Follow these instructions to get started:

  1. Install the browser extension from the official store (Firefox, Chrome)
  2. Open the extension settings dialog
  3. Configure it like so (see screenshot below):
    • API Key: Your personal API key (get it at wakapi.dev)
    • Logging Type: Only the domain
    • API URL: https://wakapi.dev/api/compat/wakatime/v1 (alternatively, replace wakapi.dev with your self-hosted instance hostname)
  4. Save
  5. Start browsing!

Note: the plugin will only sync heartbeats once in a while, so it might take some time for them to appear on Wakapi. To "force" it to sync, simply bring up the plugin main dialog.

Gnome Extension

If you're using the GNOME desktop, there is a quick way to display your today's coding statistics in the status bar.

Simply install the Executor extension and add the following command as a status bar indicator:

~/.wakatime/wakatime-cli-linux-amd64 --today

📦 Data Export

You can export your coding activity from Wakapi to CSV in the form of raw heartbeats. While there is no way to accomplish this directly through the web UI, we provide an easy-to-use Python script instead.

$ pip install requests tqdm
$ python scripts/download_heartbeats.py --api_key API_KEY [--url URL] [--from FROM] [--to TO] [--output OUTPUT]
Example
python scripts/download_heartbeats.py --api_key 04648d14-15c9-432b-b901-dbeec70d4eaf \
  --url https://wakapi.dev/api \
  --from 2023-01-01 \
  --to 2023-01-31 \
  --output wakapi_export.csv

👍 Best practices

It is recommended to use wakapi behind a reverse proxy, like Caddy or nginx, to enable TLS encryption (HTTPS).

However, if you want to expose your wakapi instance to the public anyway, you need to set server.listen_ipv4 to 0.0.0.0 in config.yml.

🧪 Tests

Unit tests

Unit tests are supposed to test business logic on a fine-grained level. They are implemented as part of the application, using Go's testing package alongside stretchr/testify.

How to run

$ CGO_ENABLED=0 go test `go list ./... | grep -v 'github.com/muety/wakapi/scripts'` -json -coverprofile=coverage/coverage.out ./... -run ./...

API tests

API tests are implemented as black box tests, which interact with a fully-fledged, standalone Wakapi through HTTP requests. They are supposed to check Wakapi's web stack and endpoints, including response codes, headers and data on a syntactical level, rather than checking the actual content that is returned.

Our API (or end-to-end, in some way) tests are implemented as a Postman collection and can be run either from inside Postman, or using newman as a command-line runner.

To get a predictable environment, tests are run against a fresh and clean Wakapi instance with a SQLite database that is populated with nothing but some seed data (see data.sql). It is usually recommended for software tests to be safe, stateless and without side effects. In contrary to that paradigm, our API tests strictly require a fixed execution order (which Postman assures) and their assertions may rely on specific previous tests having succeeded.

Prerequisites (Linux only)

# 1. sqlite (cli)
$ sudo apt install sqlite  # Fedora: sudo dnf install sqlite

# 2. newman
$ npm install -g newman

How to run (Linux only)

$ ./testing/run_api_tests.sh

🤓 Developer notes

Building web assets

To keep things minimal, all JS and CSS assets are included as static files and checked in to Git. TailwindCSS and Iconify require an additional build step. To only require this at the time of development, the compiled assets are checked in to Git as well.

$ yarn
$ yarn build  # or: yarn watch

New icons can be added by editing the icons array in scripts/bundle_icons.js.

Precompression

As explained in #284, precompressed (using Brotli) versions of some of the assets are delivered to save additional bandwidth. This was inspired by Caddy's precompressed directive. gzipped.FileServer checks for every static file's .br or .gz equivalents and, if present, delivers those instead of the actual file, alongside Content-Encoding: br. Currently, compressed assets are simply checked in to Git. Later we might want to have this be part of a new build step.

To pre-compress files, run this:

# Install brotli first
$ sudo apt install brotli  # or: sudo dnf install brotli

# Watch, build and compress
$ yarn watch:compress

# Alternatively: build and compress only
$ yarn build:all:compress

# Alternatively: compress only
$ yarn compress

❔ FAQs

Since Wakapi heavily relies on the concepts provided by WakaTime, their FAQs largely apply to Wakapi as well. You might find answers there.

What data are sent to Wakapi?
  • File names
  • Project names
  • Editor names
  • Your computer's host name
  • Timestamps for every action you take in your editor
  • ...

See the related WakaTime FAQ section for details.

If you host Wakapi yourself, you have control over all your data. However, if you use our webservice and are concerned about privacy, you can also exclude or obfuscate certain file- or project names.

What happens if I'm offline?

All data are cached locally on your machine and sent in batches once you're online again.

How did Wakapi come about?

Wakapi was started when I was a student, who wanted to track detailed statistics about my coding time. Although I'm a big fan of WakaTime I didn't want to pay $9 a month back then. Luckily, most parts of WakaTime are open source!

How does Wakapi compare to WakaTime?

Wakapi is a small subset of WakaTime and has a lot less features. Cool WakaTime features, that are missing Wakapi, include:

  • Leaderboards
  • Embeddable Charts
  • Personal Goals
  • Team- / Organization Support
  • Additional Integrations (with GitLab, etc.)
  • Richer API

WakaTime is worth the price. However, if you only need basic statistics and like to keep sovereignty over your data, you might want to go with Wakapi.

How are durations calculated?

Inferring a measure for your coding time from heartbeats works a bit differently than in WakaTime. While WakaTime has timeout intervals, Wakapi essentially just pads every heartbeat that occurs after a longer pause with 2 extra minutes.

Here is an example (circles are heartbeats):

|---o---o--------------o---o---|
|   |10s|      3m      |10s|   |

It is unclear how to handle the three minutes in between. Did the developer do a 3-minute break, or were just no heartbeats being sent, e.g. because the developer was staring at the screen trying to find a solution, but not actually typing code?

  • WakaTime (with 5 min timeout): 3 min 20 sec
  • WakaTime (with 2 min timeout): 20 sec
  • Wakapi: 10 sec + 2 min + 10 sec = 2 min 20 sec

Wakapi adds a "padding" of two minutes before the third heartbeat. This is why total times will slightly vary between Wakapi and WakaTime.

👥 Community contributions

👏 Support

Coding in open source is my passion and I would love to do it on a full-time basis and make a living from it one day. So if you like this project, please consider supporting it 🙂. You can donate either through buying me a coffee or becoming a GitHub sponsor. Every little donation is highly appreciated and boosts my motivation to keep improving Wakapi!

🙏 Thanks

I highly appreciate the efforts of @alanhamlett and the WakaTime team and am thankful for their software being open source.

Moreover, thanks to server.camp for sponsoring server infrastructure for Wakapi.dev.

📓 License

MIT @ Ferdinand Mütsch