Automatic transaction categorisation for Actual Budget. Trains local models, serves a CLI/daemon, and ships a Docker image so you can keep categories tidy without leaving your automation stack.
- Embedding + KNN classifier by default, with optional TensorFlow.js model for experimentation.
train,classify, and long-runningdaemonmodes with consistent logging and graceful shutdown.- Cron-based scheduling with optional
actual-eventsstream integration for near real-time updates. - Optional Web UI for triggering runs and checking status (fronted by Traefik for auth).
- Docker image with baked-in health check, Node.js 22 base image, and bind-mount friendly data directory.
- Node.js ≥ 22.
- Actual Budget server credentials (
ACTUAL_SERVER_URL,ACTUAL_PASSWORD,ACTUAL_SYNC_ID). - Writable data directory for embeddings, TensorFlow assets, and the budget cache (defaults to
./data).
git clone https://github.com/rjlee/actual-auto-categorise.git
cd actual-auto-categorise
npm installOptional git hooks:
npm run preparecp .env.example .env
docker build -t actual-auto-categorise .
mkdir -p data/budget
docker run -d --env-file .env \
-p 5007:5007 \
-v "$(pwd)/data:/app/data" \
actual-auto-categorise --mode daemon --ui --http-port 5007Published images live at ghcr.io/rjlee/actual-auto-categorise:<tag> (see Image tags).
docker-compose.ymlincludes Traefik plus the sharedactual-auto-authforwarder (pulled from GHCR). SetAUTH_APP_NAMEto control the login heading shown to operators, override the image withAUTH_FORWARD_IMAGEif you pin a specific tag, and keepAUTH_COOKIE_NAMEin sync with the proxy so the logout button appears when you’re authenticated.
For Compose users, two sample manifests are provided:
docker-compose.no-auth.yml.example– exposes the web UI directly onHTTP_PORT.docker-compose.with-auth.yml.example– bundles Traefik +actual-auto-authso operators must authenticate before accessing the UI (the existingdocker-compose.ymlmirrors this setup for backward compatibility).
.env– primary configuration, copy from.env.example.config.yaml/config.yml/config.json– optional defaults, copy fromconfig.example.yaml.
Precedence: CLI flags > environment variables > config file.
| Setting | Description | Default |
|---|---|---|
BUDGET_DIR (BUDGET_CACHE_DIR) |
Budget cache location | ./data/budget |
DATA_DIR |
Training data + model artefacts | ./data |
CLASSIFIER_TYPE |
ml (embed+KNN) or tf (TensorFlow) |
ml |
LOG_LEVEL |
Pino log level | info |
CLASSIFY_CRON / CLASSIFY_CRON_TIMEZONE |
Classification schedule | 0 * * * * / UTC |
TRAIN_CRON / TRAIN_CRON_TIMEZONE |
Weekly training schedule | 30 6 * * 1 / UTC |
DISABLE_CRON_SCHEDULING |
Disable cron when running daemon | false |
ENABLE_EVENTS / EVENTS_URL / EVENTS_AUTH_TOKEN |
Hook into actual-events SSE stream |
disabled |
HTTP_PORT |
Enables Web UI when set or --ui passed |
3000 |
SSL_KEY, SSL_CERT |
Optional TLS for the Web UI | unset |
AUTH_FORWARD_IMAGE |
Auth proxy image pulled by Docker Compose | ghcr.io/rjlee/actual-auto-auth:latest |
AUTH_APP_NAME |
Text shown on the shared login screen | Actual Auto Categorise |
AUTH_COOKIE_NAME |
Cookie name issued by the shared auth proxy | actual-auth |
TF_TRAIN_*, EMBED_BATCH_SIZE |
Advanced ML tuning knobs | see .env.example |
- Train models:
npm run train(alias fornpm start -- --mode train). - Classify once:
npm run classify(--mode classify). - Cron daemon:
npm run daemonwith optional--ui,--http-port,--classifier-type tf.
Set ENABLE_EVENTS=true and point EVENTS_URL at your actual-events instance to debounce and trigger classification runs shortly after new transactions arrive. Cron remains active as a safety net unless DISABLE_CRON_SCHEDULING=true.
docker run -d --env-file .env \
-p 5007:5007 \
-v "$(pwd)/data:/app/data" \
ghcr.io/rjlee/actual-auto-categorise:latest --mode daemon --ui --http-port 5007npm test
npm run test:coverage
npm run lint
npm run lint:fix
npm run format
npm run format:checkghcr.io/rjlee/actual-auto-categorise:<semver>– pinned to a specific@actual-app/apirelease.ghcr.io/rjlee/actual-auto-categorise:latest– highest supported API version.
See rjlee/actual-auto-ci for release automation and tag policy.
MIT © contributors.