{"id":49240287,"url":"https://github.com/piitaya/pandaroo","last_synced_at":"2026-04-24T19:05:19.119Z","repository":{"id":350263633,"uuid":"1204938875","full_name":"piitaya/pandaroo","owner":"piitaya","description":"Track your Bambu Lab AMS spools by RFID. Self-hosted.","archived":false,"fork":false,"pushed_at":"2026-04-21T21:48:54.000Z","size":878,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-21T23:33:41.223Z","etag":null,"topics":["3d-printing","ams","bambu-lab","bambulab","filament","rfid","self-hosted"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/piitaya.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-08T13:32:18.000Z","updated_at":"2026-04-21T21:48:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/piitaya/pandaroo","commit_stats":null,"previous_names":["piitaya/bambu-spoolman-sync","piitaya/pandaroo"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/piitaya/pandaroo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piitaya%2Fpandaroo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piitaya%2Fpandaroo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piitaya%2Fpandaroo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piitaya%2Fpandaroo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piitaya","download_url":"https://codeload.github.com/piitaya/pandaroo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piitaya%2Fpandaroo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32236772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T13:21:15.438Z","status":"ssl_error","status_checked_at":"2026-04-24T13:21:15.005Z","response_time":64,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d-printing","ams","bambu-lab","bambulab","filament","rfid","self-hosted"],"created_at":"2026-04-24T19:05:16.764Z","updated_at":"2026-04-24T19:05:19.113Z","avatar_url":"https://github.com/piitaya.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pandaroo\n\nA local spool tracker for Bambu Lab printers. Uses the RFID chip on\neach spool to identify what's loaded in your AMS.\n\n\u003e ⚠️ **Preview.** Under active development, no stable release yet.\n\u003e Expect breaking changes and bugs. Use at your own risk.\n\nPandaroo connects to each printer over MQTT and reads the AMS state\nas it changes. Every Bambu spool is identified by the variant id\nstamped on its RFID tag, so the same roll is recognized whether you\nmove it between slots or printers.\n\n## Features\n\n* Live dashboard of every AMS slot: color, material, remaining\n  weight, match status.\n* Inventory of every spool the app has seen, with first-seen and\n  last-used timestamps.\n* Timeline of each spool's loads, unloads, AMS updates, scans, and\n  manual adjustments.\n* Manual remaining-weight adjustment when the AMS isn't reporting one.\n* English and French.\n\n## Why RFID\n\nMost Bambu trackers compare material names and hex colors to guess\nwhich filament is loaded. That's fine until Bambu renames a product\nor ships a slightly different shade, and then you get a wrong match.\nPandaroo reads the RFID variant id printed on every genuine Bambu\nspool and looks it up in a community-maintained catalog\n([`piitaya/bambu-filaments`](https://github.com/piitaya/bambu-filaments)).\nIf the variant is in the catalog, the match is exact. If it isn't,\nthe app tells you.\n\n## Slot statuses\n\n| Badge        | Meaning                                                 |\n| ------------ | ------------------------------------------------------- |\n| Known        | Recognized Bambu spool from the community catalog       |\n| Unknown      | Looks like a Bambu spool, not yet in the catalog        |\n| Third party  | Non-Bambu spool, or a spool without an RFID tag         |\n| Unidentified | Spool detected but the printer has no info about it yet |\n| Empty        | Slot has no filament loaded                             |\n\n## Getting started\n\n### Docker\n\n```bash\ndocker run -d --name pandaroo \\\n  -p 4000:4000 \\\n  -v $(pwd)/data:/data \\\n  ghcr.io/piitaya/pandaroo:beta\n```\n\nThen open [http://localhost:4000](http://localhost:4000).\n\nDocker Compose (save as `docker-compose.yml`, then\n`docker compose up -d`):\n\n```yaml\nservices:\n  pandaroo:\n    image: ghcr.io/piitaya/pandaroo:beta\n    container_name: pandaroo\n    restart: unless-stopped\n    ports:\n      - \"4000:4000\"\n    volumes:\n      - ./data:/data\n```\n\n#### Image tags\n\n| Tag            | Meaning                                                      |\n| -------------- | ------------------------------------------------------------ |\n| `latest`       | Most recent stable release (nothing yet, still in preview)   |\n| `beta`         | Most recent beta release (recommended for now)               |\n| `edge`         | Latest commit on `main`, unstable                            |\n| `0.1.0-beta.2` | Pin to an exact version                                      |\n\n### From source\n\nNeeds Node.js 20 or newer.\n\n```bash\nnpm install\nnpm run dev\n```\n\nFor production: `npm run build \u0026\u0026 npm start`.\n\n## First-time setup\n\n1. Go to **Settings → Printers** and add your printer: name, IP,\n   serial, access code. The serial and access code are on the\n   printer's touchscreen, under *Settings → Device* and\n   *Settings → Network → LAN-only mode*.\n2. Load a spool in the AMS. Pandaroo picks up the RFID reading and\n   starts tracking it.\n\n## Privacy and security\n\n* Outbound connections: your printers on the LAN, and GitHub (once\n  a day) to refresh the filament catalog. Nothing else.\n* No accounts, no analytics, no telemetry.\n* Printer access codes are stored in `config.json` inside `DATA_DIR`.\n* There's no authentication and no rate limiting. Run Pandaroo on\n  your LAN. For remote access, put it behind an authenticated\n  reverse proxy.\n\n## Under the hood\n\n* **Backend**: Fastify + TypeScript. One MQTT client per printer\n  (port 8883, TLS, LAN-only mode), streaming AMS state as it changes.\n  SQLite via Drizzle and better-sqlite3.\n* **Matching**: the RFID variant id is looked up in the cached\n  [`bambu-filaments`](https://github.com/piitaya/bambu-filaments)\n  catalog. No fuzzy name matching, no hex comparisons.\n* **Storage**: a `spools` table (one row per RFID tag), plus\n  `spool_history`, an append-only event log with types `ams_load`,\n  `ams_unload`, `ams_update`, `scan`, and `adjust`. Migrations live\n  in `backend/drizzle/`.\n* **Real-time**: the backend publishes Server-Sent Events on\n  `/api/events`. The frontend subscribes on mount and invalidates\n  the matching TanStack Query caches.\n* **Frontend**: React 19 + Vite + [Mantine](https://mantine.dev) 7,\n  TanStack Query for server state, react-i18next for translations.\n* **API docs**: Swagger UI at `/docs`. Includes\n  `POST /api/spools/scan` if you want to register spools from an\n  external NFC reader.\n\n### Environment variables\n\n| Var          | Default   | Purpose                                                       |\n| ------------ | --------- | ------------------------------------------------------------- |\n| `PORT`       | `4000`    | HTTP port                                                     |\n| `HOST`       | `0.0.0.0` | Bind address                                                  |\n| `DATA_DIR`   | `./data`  | Where the SQLite DB, `config.json`, and `filaments.json` live |\n| `LOG_LEVEL`  | `info`    | `fatal`, `error`, `warn`, `info`, or `debug`                  |\n| `LOG_FORMAT` | `pretty`  | Set to `json` for machine-readable output                     |\n\n### Logging\n\nLogs go to stdout. The default `info` level covers printer\nconnections, new spool detections, errors, and config changes.\n`LOG_LEVEL=debug` adds AMS heartbeats and connection diagnostics.\n\n```yaml\nservices:\n  pandaroo:\n    environment:\n      - LOG_LEVEL=debug\n      - LOG_FORMAT=json\n```\n\nCommon failures:\n\n* `errorCode=\"unauthorized\"`: wrong access code.\n* `Printer not responding`: wrong IP, printer off, or port 8883\n  blocked by a firewall.\n\n## License\n\nMIT, see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiitaya%2Fpandaroo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiitaya%2Fpandaroo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiitaya%2Fpandaroo/lists"}