Kopi
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.
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.
To do
- Update/edit …
- equipment
- coffee
- bag
- cup
- Decommission equipment
- Close bag
- Ask to close bag when finished (based on consumed cups)
- (TODO)
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
- from GitHub
$ git clone git@github.com:mrusme/kopi.git
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.
Links
Enjoyed this? Support me via Monero, Bitcoin, Lightning, or Ethereum! More info.