Track & Graph: personal data tracking that stays on the device
An android app for tracking personal data and creating custom graphs
At a glance
- What is it?
- Track & Graph is an Android app for logging personal data and building your own graphs, distributed through Google Play, F-Droid and IzzyOnDroid, with a privacy policy that promises nothing is recorded online. The interesting engineering is in the tooling, where a Makefile drives deep links into the app and validates the in-app changelog.
- Who is it for?
- Track & Graph fits a person who wants to log a specific measurement over time and see a graph of it, and who does not want a health or habit tracker uploading their data to a server. It is the wrong choice if you need multi-language support, because the maintainer states there is no intention of supporting other languages, and the wrong choice if you want a third-party app store release path beyond the ones listed.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Lua, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A tracker for numbers you log yourself
The README describes the project in one line: an android app for tracking personal data and creating custom graphs, with a link to a documentation site at samamco.github.io/track-and-graph.
That is a narrow description and it is worth staying inside it. This is not a fitness platform with a social feed, and it is not a health device integration. It is a place where you record a value, and where the app turns a series of values into a graph you define. The customisation is in the graph, which is what separates it from a fixed set of charts, and the tracking is manual, which is what makes the privacy claim possible.
The distribution is unusually broad for an app of this kind, and the README carries the badges for all three channels: Google Play, F-Droid and IzzyOnDroid. That third one matters more than it looks. An app on F-Droid and on an independent repository is one whose build pipeline and release provenance a reader can inspect, which is a reasonable proxy for the privacy claim.
The repository is also laid out in a way that tells you the technology. The primary language is Lua, and the root holds a `lua` directory, an `app` directory, a `database-extract` directory, a `fastlane` directory for store metadata, a `changelogs` directory, `configuration`, `runbooks`, `scripts` and `docs`.
The privacy promise is specific and checkable
The Privacy Policy section makes two claims, and the second one is more interesting than the first.
The first is that the app does not record any of your personal information, anything you track or anything you do in the app, and that nothing is recorded or stored anywhere online by the app or by any third party library used by the app. That last clause is the one that matters, because a tracker that is careful about itself but links a library with analytics would break the promise without the user ever seeing it.
The second claim is a feature rather than a restriction: you can easily back up your data at any time to your own device or cloud storage service from within the app.
Put together, those two sentences describe a local-first design. The data is on the device, the backup is an export you control, and the cloud storage you might use is one you chose. That is a materially different privacy model from a service with an account, and it is the reason the app can ship the way it does while still being distributed through a commercial store.
It also explains a constraint. Because there is no server component, there is no cross-device sync in the product sense, and no account to recover a lost phone from. The backup is the safety net, and it is manual.
A Makefile that documents itself
The Makefile at the repository root is the most developer-facing file in the project, and it is written to be read rather than memorised.
The default goal is help, and the help target parses its own comment lines with awk to print the available targets and their purposes:
## help: List the available Make targets and their purpose.That convention, a line of the form `## target: description` above each target, is what makes the target list self-documenting, and it is a pattern worth borrowing whatever else you think of the project.
The rest of the visible targets fall into three groups. There are the deep link targets, which get a file into the running app. There are the validation targets, which check the checked-in configuration and the in-app changelog. And there are the translation targets, listed together in a single .PHONY line along with translations-audit and translations-apply-failure.
The scale of the tooling is worth noting. An app that people install and use without touching the source still carries a Makefile with a help target, a JSON schema check and an adb integration script, which is a sign of what the maintainer expects from contributors.
Deep links are how a file reaches the running app
Two targets exist to move a file into the app, and they take different routes.
The first serves the file over the local network and opens its deep link on a connected device:
## deep-link-serve-local: Serve FILE over the local network and open its deep link on a connected device.The implementation calls a Python script:
python3 scripts/serve-and-deep-link-lua.py $(FILE)The second injects the file directly into the app through an adb deep link:
## deep-link-inject: Inject FILE directly into the app through an adb deep link.with the shell script doing the work:
@./scripts/deep-link-inject.sh $(FILE)Both targets require the FILE parameter and fail loudly without it, printing a usage line such as:
@echo "Usage: make deep-link-serve-local FILE=<file_path>"The distinction between the two is the interesting part. Serving over the local network needs no debugging connection, so it works against a device that is simply on the same wifi, which is the path a user or a tester would take. The adb route needs the device attached and authorised, which is the path that does not depend on the network at all.
The in-app changelog is schema-validated, not just edited
The changelog targets show a project that treats the content shown inside the app as data with a contract.
There is a target to rebuild the index, and it takes a VERSION parameter:
## in-app-changelog-index-update: Discover VERSION's Markdown locales and update the in-app changelog index.The parameter is checked before anything runs:
@test -n "$(VERSION)" || (echo "Usage: make in-app-changelog-index-update VERSION=<version>" && exit 1)and then the index is regenerated with a Python script:
@python3 -B scripts/in_app_changelog_index.py update "$(VERSION)"The separate validate target checks the result against a JSON schema and then re-validates with the same script:
@jsonschema-cli validate changelogs/index.schema.json -i changelogs/index.json
@python3 -B scripts/in_app_changelog_index.py validateThe second line is the one to notice. Validating against a schema catches malformed JSON, but it cannot catch an index that is well-formed and wrong, which is why the script validates the index independently against the changelog files themselves. A changelog inside an app is the sort of thing that rots quietly, and this is a project that has decided to make it fail a check instead.
The remote configuration is validated the same way, by a target that runs a shell script against the checked-in configuration and the assets it references.
Contributions are welcome, with the boundaries stated up front
The Contributing section is short and unusually candid about what the maintainer will and will not take on.
Small contributions are welcome, but the preference is that you raise an issue first to discuss the changes you would like to make, because the time available to work on the project is limited and the maintainer may not be able to respond to an issue or a pull request immediately.
The sharper boundary is language support. The README states there is no intention of supporting other languages at this time, and gives the reason: even if you have translated all the current copy, supporting multiple languages adds significant overhead to developing and maintaining the project going forwards.
That is a decision an adopter should weigh, not just a contributor. An app with a single language is one you cannot hand to a team with mixed languages, and the overhead argument is about the maintainer's time rather than about the cost of translation itself, so the restriction is about the project's capacity rather than a technical limit.
The repository layout also shows the automation in place around the project, with an AGENTS.md and a CLAUDE.md at the root and directories named .agents, .claude and .codex, alongside a Gemfile for the documentation tooling and a .all-contributorsrc for the contributors table the README carries.
GPL-3.0, frequent releases, and release candidates in the list
The licence section reproduces the GNU General Public License, version 3 of the License or, at your option, any later version, with the copyright line reading Copyright (C) 2019-2020 SamAmco. The repository carries a LICENSE.txt file, and the disclaimer of warranty comes with the standard terms.
For an end user the GPL matters little, since the app is distributed as a binary through stores. For anyone who wants to look at the code, read it, or build a variant, it is the part that matters, and the LICENSE.txt file is where that text lives.
The release pattern shows an active project. The recent releases are v10.5.1 from 2026-10-11, rc-v10.5.0 from 2026-10-03 and rc-v10.4.0 from 2026-09-07, so two of the three are release candidates, and the rc prefix in the tag name is what tells you that.
That is a slightly unusual way to version an app, and it is worth understanding before you follow a channel. A release candidate tag is published first so that people can install and test it before the final build reaches the store, and the naming makes it obvious which is which. The repository is not archived and the last push was on 2026-10-18, so the branch is ahead of the newest tag, which is the normal state for a project that ships a candidate before it ships a release.
The fastlane directory holds the store metadata and screenshots, which is how the Play Store and F-Droid listings are produced from the same source.
Editorial conclusion
Track & Graph fits a person who wants to log a specific measurement over time and see a graph of it, and who does not want a health or habit tracker uploading their data to a server. It is the wrong choice if you need multi-language support, because the maintainer states there is no intention of supporting other languages, and the wrong choice if you want a third-party app store release path beyond the ones listed. Verify first which store you can install from, since the app is distributed through three different channels, and read the privacy statement and the in-app changelog before importing a year of data.
Frequently asked questions
What does Track & Graph do with my data?
The README states that the app does not record any of your personal information, anything you track or anything you do in the app, and that nothing is recorded or stored anywhere online by the app or by any third party library it uses. You can back up your data to your own device or cloud storage from within the app.
Where can I install Track & Graph?
The README carries badges for three channels: Google Play, F-Droid and IzzyOnDroid, each with its own listing. The application id is com.samco.trackandgraph.
How do I get a file into the running Track & Graph app while developing?
The Makefile offers two targets. make deep-link-serve-local FILE=<file_path> serves the file over the local network and opens its deep link on a connected device, while make deep-link-inject FILE=<file_path> injects the file directly through an adb deep link.
Does Track & Graph support multiple languages?
The README states there is no intention of supporting other languages at this time, and gives the reason: even if the current copy has been translated, supporting multiple languages adds significant overhead to developing and maintaining the project going forwards.
What licence is Track & Graph released under?
The GNU General Public License, version 3 of the License or, at your option, any later version, with the copyright line Copyright (C) 2019-2020 SamAmco and the licence text in the LICENSE.txt file at the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/samamco-track-and-graph)Was this useful?