Kopi

From Malay kopi (“coffee”) and Hokkien 咖啡 (ko-pi); the latter is also
derived from the former.
-- Wiktionary
Kopi is a command-line (CLI) coffee journal (or habit tracker), designed for
coffee enthusiasts. It lets you track coffee beans, equipment usage, brewing
methods, and individual cups.
The tracked data offers insights into bean and roast preferences, caffeine and
dairy consumption, and equipment usage patterns. This helps users refine their
coffee choices while managing caffeine intake for a more enjoyable and
responsible experience.
Kopi focuses on meticulously tracking every step of the coffee preparation
process. Unlike standard coffee or caffeine tracking apps, it requires more
detailed input to function effectively. If you only want to track the cups of
coffee you drink without monitoring the beans/roasts and the preparation methods
used, Kopi may not be the best fit for you. Think of Kopi as a coffee
journal that lets you rate individual roasts and analyze how different roasts,
brewing methods, and drink types influence your preferences.
Kopi stores everything locally and does not send any data to third-party
services unless explicitly mentioned before an operation (e.g. requesting
current exchange rates from the ECB, for price input/conversions of individual
coffee bags). Kopi does not employ analytics libraries/services.
Status
Kopi is still in its early stages. Some features might not be working as
expected and others might very well be missing. If you depend on your coffee
journal, do not use Kopi at this stage, as things might change and, in the
worst case, randomly break. If you're feeling adventurous or you're looking to
contribute to the project, please find all the relevant information down below.
Install
From Release
Download the latest release
and unpack it:
▲ tar -xzf ./kopi_*.tar.gz
The binary kopi can be moved wherever you please.
From Source
Clone this repository
Then cd into the cloned directory and run:
$ make
The binary will be available at ./build/kopi and can be moved wherever you
please.
Use
Kopi follows a structured three-step workflow for tracking coffee consumption,
essential for its functionality and insights. The first step is typically done
once — during setup or when equipment changes. The second step is performed
regularly, while the third step, tracking actual consumption, is done for every
cup.
Steps
Step 1: Add equipment
Coffee equipment is the first piece of information that Kopi requires. Most
coffee enthusiasts will usually have at least two pieces of coffee equipment at
their disposal:
- A coffee grinder
- A coffee maker
This equipment needs to be added to Kopi before tracking coffee brewing and
consumption. To do so, the following command is used:
▲ kopi equipment add

The command will guide the user through the adding process. It is also possible
to provide all required fields as flags to the command. For more information on
how to do so, check the output of kopi equipment add --help.
Note: If you don’t have coffee brewing equipment and typically get your
coffee from a barista, add their brewing method as a dummy entry. For
espresso-based drinks, add an espresso maker; for pour-overs or AeroPress, add
a coffee maker. However, keep in mind that Kopi is not designed for
tracking individual cups from various coffee shops—there are better tools for
that. Instead, Kopi is aimed at coffee enthusiasts who want to document their
coffee experiences, ideally using their brewing methods.
Step 2: Open a bag of coffee
Coffee bags are the second key element in tracking brewing and consumption.
Every cup requires a designated bag of coffee. Previously opened bags can be
used until their beans are depleted, at which point a new bag must be opened.
Multiple bags can be open at the same time, but only one can be selected per
cup. For blends, a dedicated bag must be prepared and then opened.
To open a new bag of coffee the following command is used:
▲ kopi bag open

The command will guide the user through the opening process. It is also possible
to provide all required fields as flags to the command. For more information on
how to do so, check the output of kopi bag open --help.
To list all open bags, the following command can be used:
▲ kopi bags list
The command accepts the --all parameter to list all bags, instead of only the
open ones.
Note: bags is an alias of the bag command that helps with making the
command read more naturally. The command kopi bag list works and can also be
used.
Step 3: Drink a cup of coffee
To track a cup of coffee, the following command is used:
▲ kopi cup drink

The command will guide the user through the tracking process. It is also
possible to provide all required fields as flags to the command. For more
information on how to do so, check the output of kopi cup drink --help.
Insights
A wide range of insights can be extracted from the data that has been tracked
over time. The kopi insights command aggregates the information and displays
it. It supports multiple output formats and custom periods. For more information
check the output of kopi insights --help.

Ranking
The database calculates an overall ranking for each coffee based on ratings from
individually tracked cups. Use the kopi coffee ranking command to view the
ranking:

(ltr: Rank, coffee name, roaster, score calculated from individually rated
cups)
"Mobile App"
Kopi does not have a mobile app to track coffee consumption. Instead, Kopi
is using a new approach to tackle this need: Pen and paper.
With Kopi it is possible to track cups of coffee using a simple notebook, by
writing down consumed cups in a structured format:

Kopi uses an Ollama backend to read
photos of such notes using llama3.2-vision and extract all the information
necessary to automatically import these entries into its database.
For more information on this approach,
head over to this post.
Ollama
The Ollama service can either be run locally (on a powerful enough machine) or
remotely. On an AMD Ryzen 9 5950X CPU (no GPU) extracting data from such a photo
usually takes around a minute. On an AMD Ryzen 7 5800U (no GPU), however, it's
almost always 20x slower. Given a
supported GPU these
numbers change drastically.
Development
Kopi is written in Go and uses
mattn/go-sqlite3 to store all its data.
Because of this, building Kopi requires gcc to be available and
CGO_ENABLED=1 to be set.
Whether you're a developer looking to contribute, or you're interested in
understanding the inner workings of the project, this section will guide you
through the development setup, the architecture of the code, and how you can get
involved. If you plan to contribute or make modifications, feel free to follow
along and dive into the Go codebase to help improve this tool!
CGO
Before building Kopi, make sure that CGO is enabled inside your Go
environment:
go env | grep CGO_ENABLED
If CGO is not enabled (0) try manually enabling it:
go env -w CGO_ENABLED=1
If this command fails with something along the lines of
cgo: C compiler "gcc" not found: exec: "gcc": executable file not found your
Go installation cannot seem to find the gcc compiler. Make sure you have gcc
installed and available in your $PATH.
Build
Kopi can be built using the standard go build command, although it is
preferable to use make build (or simply make).
Implementation
The following section gives an overview of how the application is built and how
its features are implemented, providing an in-depth look at the decisions and
structure behind the code.
Database & database access
Kopi uses Sqlite3 to store all its data locally. The database structure and
seed data are available within the migrations folder and are
being baked into the binary using Go's EmbedFS.
The Go code is built around a minimal Database Abstraction Layer (DAL), as
well as individual entities (Bag, Coffee, Cup, etc.) that have models
that are built upon generic Data Access Objects (DAOs). This data
architecture uses generics to reduce the required boilerplate and keep the
implementation as lightweight and DRY as possible. The concept was documented
by James Kirk in this repository and
contains a write-up with the implementation details.
Coffee and caffeine
Kopi makes some assumptions about coffee and its caffeine content. It uses a
formula to approximate the caffeine content in a coffee drink based on the
amount of ground coffee, brewing method, and roast level:
C = G \times E_m \times R \times (1 - L_m)
Where:
- $( C )$ = estimated caffeine content in milligrams (mg)
- $( G )$ = mass of ground coffee used (grams)
- $( E_m )$ = base extraction yield (mg of caffeine per gram of coffee,
dependent on brewing method)
- $( R )$ = roast level adjustment factor
- $( L_m )$ = loss factor due to filtration, retention, or degradation
(fractional value, dependent on brewing method)
The following values for $( E_m )$ (Base Extraction Yield by Brewing Method)
are assumed:
| Brewing Method |
Base Extraction Yield $(E_m)$ (mg/g) |
| Espresso |
8-12 mg/g |
| Drip Coffee (Filter, Pour-over, Machine) |
6-10 mg/g |
| French Press (Immersion Brewing) |
6-9 mg/g |
| AeroPress |
7-10 mg/g |
| Cold Brew |
5-8 mg/g |
| Turkish Coffee (Cezve) |
10-13 mg/g |
| Moka Pot |
8-12 mg/g |
The following values for $( L_m )$ (Loss Factor by Brewing Method) are
assumed:
| Brewing Method |
Approximate Loss Factor $(L_m)$ |
| Espresso |
0.05 |
| Drip Coffee (Filter, Pour-over, Machine) |
0.10 |
| French Press (Immersion Brewing) |
0.05 |
| AeroPress |
0.10 |
| Cold Brew |
0.15 |
| Turkish Coffee (Cezve) |
0.05 |
| Moka Pot |
0.08 |
The following values for $( R )$ (Roast Level Adjustment Factor) are assumed:
| Roast Level |
Adjustment Factor $(R)$ |
| Light Roast |
0.95 |
| Medium Roast |
1.00 |
| Dark Roast |
1.10 |
Further, the following assumptions are made:
- Light roasts have a slightly lower extraction efficiency $(R = 0.95)$.
- Medium roasts serve as the baseline $(R = 1.00)$.
- Dark roasts extract more caffeine per gram due to their porous structure $(R
= 1.10)$.
The Approximate Extraction Yields $(E_m)$, as well as the Approximate Loss
Factors $(L_m)$ for different brewing methods, are stored within each
method's database entry.
Example
For a drip coffee using 20g of lightly roasted $(R)$ ground coffee $(G)$,
an extraction yield of (on average) 8mg $(E_m)$, and a loss factor $(L_m)$
of 0.10, the calculation looks as follows:
\begin{align}
C = 20 \times 8 \times 0.95 \times (1 - 0.10) \\
C = 20 \times 8 \times 0.95 \times 0.90 \\
C = 136.8 \text{ mg}
\end{align}
A cup would hence contain roughly 137 mg of caffeine.
Currency
Kopi allows users to enter prices for the coffee that they add to the
database. Kopi stores all prices in USD, rather than in the currency of the
user. This allows for easier price comparisons at a later stage. To support
different currencies and convert them into USD the tool uses a conversion
document published by the European Central Bank:
https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
If the user adds a price to a coffee bag, they will be prompted with whether
they would like to query the service to retrieve up-to-date currency conversion
information.
There is an ongoing effort of dedollarisation by also storing the price in
1/100000000 of a Bitcoin (Satoshis, or Sats) for use as a base currency at a
later stage.