A self-hosted code-progress dashboard. A local FastAPI server analyses a codebase on your machine (commit activity, cyclomatic complexity, file-type mix) and pushes the results to a small cloud dashboard you can hit from anywhere.
A demo instance is running at https://localytics-tae6.onrender.com
currently analysing tiangolo/fastapi.
Open the URL, paste this read-only API key into the API Key field near the top of the dashboard, and click Load data:
8cdb1fa5cf9d6a275a82fc5dd8bdf40e
localytics/
├── server/ Local FastAPI server that scans your code and serves metrics
├── dashboard/ Cloud FastAPI app that caches and displays the metrics
└── helpers/ Config template + macOS launchers (LaunchAgent / .command)
Requires uv — that's the only tool you need;
Python, the venv, and every dependency are fetched on demand via the PEP 723
header at the top of server/local_server.py.
-
Configure. Copy the template and fill it in:
cp helpers/config.example.json helpers/config.json
Open
helpers/config.jsonand edit the following fields:LOCAL_API_KEYandCLOUD_API_KEY— two random hex strings. Either generate them locally withopenssl rand -hex 16(run twice for two distinct values), or let Render generate them for you when you set up env vars in step 4 (click the Generate button next to each field) and copy the values back here. Both sides must end up with the same strings.CODE_PATH— the codebase you want analysed. Absolute path on your machine, or a subpath within a cloned GitHub repo (see local vs GitHub).REPO_PATH— the git repo that containsCODE_PATH. Absolute path or a.gitURL.
Leave
CLOUD_SERVER_URLas the placeholder for now — it gets updated in step 5 once the Render dashboard is live.helpers/config.jsonis gitignored so your real keys never commit. -
Generate a TLS cert pair. TLS is a security measure: it encrypts the API-key headers used to authenticate between the local server and the cloud dashboard, so the keys can't be sniffed off the network. Plain HTTP is only safe if the local server is reachable from
localhostalone.openssl req -x509 -newkey rsa:4096 -nodes -sha256 -days 365 \ -keyout cert.key -out cert.pem -subj "/CN=localhost"The defaults in
config.example.json(./cert.key,./cert.pem) match the files produced above.*.key/*.pemare gitignored so the certs never commit. -
Run the local server:
uv run server/local_server.py
First run downloads Python 3.12 + deps into uv's cache (~30–60s), then starts on port
51515. TLS is on ifSSL_KEYFILE/SSL_CERTFILEpoint at a valid cert pair; otherwise plain HTTP. -
Deploy the cloud dashboard to Render. Two Render services are needed: a Key Value (Redis) store for caching, and a Web Service for the dashboard itself. Put them both in the same region — the Key Value's Internal URL only resolves to services in the same region.
-
Push this repo to GitHub (public or private — Render's GitHub App can read private repos you grant it access to).
-
Sign up at https://render.com and connect your GitHub repo. (Or use Render's "Public Git repository" option — no GitHub App needed, but you lose auto-deploy on push.)
-
Service 1 — Render → + New → Key Value. Name it, pick a region, Free plan. Once provisioned, open the service and copy the Internal Redis URL (starts with
redis://red-…). -
Service 2 — Render → + New → Web Service. Pick the
localyticsrepo, same region as Service 1, then:Field Value Root Directory dashboardRuntime Python 3 Build Command pip install -r requirements.txtStart Command uvicorn main:app --host 0.0.0.0 --port $PORTHealth Check Path /health_checkPlan Free Under Environment Variables add four entries:
Key Value LOCAL_API_KEYsame string as in your local helpers/config.jsonCLOUD_API_KEYsame string as in your local helpers/config.jsonLOCAL_SERVER_PORT51515REDIS_URLInternal Redis URL from step 3 CLOUD_READ_KEY(optional, only for public demos) a second hex string, distinct from CLOUD_API_KEY. Grants GET-only access to dashboard endpoints. Safe to publish. -
When the deploy log shows
Uvicorn running on …and no tracebacks, click the public URL at the top of the Web Service's page (ends in.onrender.com). You should see the dashboard UI with empty chart placeholders — that's the correct empty state before the local server starts pushing data.
-
-
Connect local → cloud.
-
In Render, open your Web Service. At the top of the page, copy the public URL (ends in
.onrender.com). -
Open
helpers/config.jsonand replace theCLOUD_SERVER_URLplaceholder with that URL (no trailing slash):"CLOUD_SERVER_URL": "https://your-service-name.onrender.com"
-
Stop the local server if it's already running (
Ctrl-Cin its terminal). -
Start it again:
uv run server/local_server.py
-
In the logs you should see
📤 Pushing metrics to cloud: .../ingestfollowed by✅ Successfully pushed metrics to cloud. Reload the Render dashboard URL — it now shows your data.
-
The main use case is keeping the code on your machine — nothing leaves except aggregated metrics — but localytics will also analyse a public GitHub repo if you'd rather not keep the code locally.
Local code — set REPO_PATH to an absolute path on your machine and
CODE_PATH to the specific subtree to analyse (absolute path, normally
inside REPO_PATH).
"REPO_PATH": "/Users/you/code/myproject",
"CODE_PATH": "/Users/you/code/myproject/src"GitHub repo — set REPO_PATH to a git URL. On startup, the local server
clones the repo into .cache/<repo-name>/ at the root of this project
(git pulled on subsequent runs). CODE_PATH is a sub-path within the
clone, same as local mode — give it relative to the clone root.
"REPO_PATH": "https://github.com/tiangolo/fastapi.git",
"CODE_PATH": "fastapi"The git pull only happens when local_server.py starts. If you want the
tree refreshed on a schedule, run the server on a schedule — use the macOS
LaunchAgent / .command templates in helpers/ (see below).
Three launcher options, all uv-based out of the box. If you prefer conda,
server/environment.yaml has the dep list and each launcher is a few lines
long — edit to taste.
Detached background run (screen session, survives closing the terminal):
./server/start_localytics.sh
screen -r localytics_server # attach to view logs; Ctrl-A d to detachDouble-clickable launcher. Copy the template, make it executable, then double-click it in Finder:
cp helpers/run_localytics.command.example ~/run_localytics.command
chmod +x ~/run_localytics.commandLaunchAgent (starts automatically at login):
cp helpers/com.localytics.server.plist.example ~/Library/LaunchAgents/com.localytics.server.plist
# edit the plist to point at the absolute path of this repo, then:
launchctl load ~/Library/LaunchAgents/com.localytics.server.plistMIT — see LICENSE.




