[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-94932":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":14,"stars30d":14,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":30,"readmeContent":31,"aiSummary":32,"trendingCount":16,"starSnapshotCount":16,"syncStatus":33,"lastSyncTime":34,"discoverSource":35},94932,"vibepulse","niclasvestlund-YT\u002Fvibepulse","niclasvestlund-YT","A shelf-top AMOLED screen showing your Claude Code & Codex usage, live agent activity, and a NEEDS YOU alert when an agent waits for your input. ESP32-S3 + a pure-stdlib Mac service. Nothing leaves your LAN.","https:\u002F\u002Fvibeonchip.com",null,"C",115,20,3,5,0,45.77,"MIT License",false,"main",true,[23,24,25,26,27,28,29],"amoled","claude","claude-code","codex","esp32-s3","lvgl","quota-tracker","2026-08-24 04:01:23","# VibePulse\n\n[![CI](https:\u002F\u002Fgithub.com\u002Fniclasvestlund-YT\u002Fvibepulse\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fniclasvestlund-YT\u002Fvibepulse\u002Factions\u002Fworkflows\u002Fci.yml)\n\n![VibePulse: quota, a NEEDS YOU alert, and the Max Tracker heatmap](docs\u002Fimg\u002Fhero.png)\n\n**A little always-on screen for your shelf that shows what your AI coding\nagents are doing — taps you on the shoulder when one is stuck waiting for\nyou, and (if you want) lets you answer it with a tap on the glass.**\n\nClaude Code and Codex usage, live agent activity, and a full-screen\n**NEEDS YOU** alert you can answer with a tap. A ~$30 ESP32-S3 panel plus a\npure-stdlib Python service on your Mac. No cloud, no accounts, no API keys on the device. Agent data\nnever leaves your LAN; the optional public-repository module makes only\nanonymous GitHub API reads from the Mac.\n\n## The problem\n\nWhen you run coding agents all day, two things are invisible:\n\n- **How much quota is left.** You usually find out you're at the wall when a\n  long task dies halfway through — not before you start it.\n- **When an agent stopped.** It asks one yes\u002Fno question and then just sits\n  there. You're in another window. Sometimes for twenty minutes.\n\nBoth answers already exist, buried in a terminal you're not looking at.\nVibePulse moves them onto a screen you can't miss: one glance from across\nthe room, no window to switch to, no menu bar to squint at.\n\n> **Status:** work in progress. This is an ongoing project for me and plenty\n> of tweaks are still on the list, but enough people asked about it that I'm\n> opening it up now rather than when it feels \"done\". Expect rough edges and\n> frequent commits.\n\n## What's on screen\n\nSix core pages, swipe or auto-rotate, plus the always-present value-multiple\npage (it shows the dollar total once agents log priced usage, but the\nmultiple itself stays dashed — `SET YOUR PLAN COST` — until you pick a named\nplan tier or state your exact cost) and an optional, compile-time-gated\nGitHub project pulse. Every image below is an exact 480×480 frame — the\nsimulator renders\nthe same pixels as the panel.\n\n\u003Ctable>\n\u003Ctr>\n\u003Ctd width=\"50%\">\u003Cimg src=\"docs\u002Fimg\u002Fvibepulse-claude-week.png\" alt=\"Claude weekly quota at 73%\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\n**Usage** — Claude's weekly and heaviest-model-weekly quota, plus Codex's\nweekly quota. Each with a reset countdown and how much you've burned today.\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cimg src=\"docs\u002Fimg\u002Fvibepulse-needs-you.png\" alt=\"Full-screen NEEDS YOU alert\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\n**NEEDS YOU** — when an agent blocks on your input, the whole screen turns\ninto the alert, in that provider's colour, naming the project it's waiting\non. Tap to dismiss — or, with the opt-in Needs You bridge, **tap to answer\nit** without switching windows ([see below](#answer-claude-from-the-panel)).\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cimg src=\"docs\u002Fimg\u002Fvibepulse-agent-working.png\" alt=\"Live header showing the working model and effort\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\n**Live agent monitor** — the header shows which agents are working right\nnow, with model and effort, on every page. `2 CHATS ACTIVE` when several\nare running.\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cimg src=\"docs\u002Fimg\u002Fvibepulse-burn-rate.png\" alt=\"Burn rate forecast\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\n**Burn rate** — a forecast per provider: on pace, running out early (and\nwhen), or how much head-room is left at reset.\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>\u003Cimg src=\"docs\u002Fimg\u002Fvibepulse-max-tracker.png\" alt=\"Max Tracker heatmap for Codex\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\n**Max Tracker** — a GitHub-style heatmap of your daily quota peaks, with\ncoding streaks and max counters, per provider. Red cells are days you\nmaxed out.\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nBoth providers get equal treatment — same pages, same alert, their own\naccent colour:\n\n**Codex weekly quota**\n\n![Codex weekly quota](docs\u002Fimg\u002Fvibepulse-codex-week.png)\n\n**Codex NEEDS YOU alert**\n\n![Codex NEEDS YOU alert](docs\u002Fimg\u002Fvibepulse-codex-needs-you.png)\n\n**Claude Max Tracker**\n\n![Claude Max Tracker](docs\u002Fimg\u002Fvibepulse-max-tracker-claude.png)\n\n### Answer Claude from the panel\n\nThe panel becomes an *input device*. With the opt-in Needs You bridge, when\nClaude Code blocks on a question or a permission the takeover appears and\n**a tap answers it in the same live session** — no window to switch to.\n\n\u003Ctable>\n\u003Ctr>\n\u003Ctd width=\"33%\">\u003Cimg src=\"docs\u002Fimg\u002Fneeds-you\u002Fvibepulse-needs-you-attract.png\" alt=\"A mascot in a depleting countdown ring — something is waiting\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd width=\"33%\">\u003Cimg src=\"docs\u002Fimg\u002Fneeds-you\u002Fvibepulse-needs-you-question.png\" alt=\"The decision screen: the question and Claude's recommended answer\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd width=\"33%\">\u003Cimg src=\"docs\u002Fimg\u002Fneeds-you\u002Fvibepulse-needs-you-payoff.png\" alt=\"A short ON IT payoff beat after you answer\" width=\"100%\">\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n**Attract → decision → done.** A held prompt surfaces as a mascot in a\ndepleting countdown ring; a tap reveals it; **APPROVE** commits Claude's\nrecommended option (or **LEAVE IT** hands it back to the terminal), and the\nflow closes on a short \"ON IT\" beat. The panel signs every verdict with a\ndevice key that lives only on the glass — it can answer a prompt this Mac was\nalready going to ask about, and nothing more. Walking away always costs\nnothing: an unanswered prompt just falls back to the terminal. Setup is in\n[docs\u002Fagent-setup.md](docs\u002Fagent-setup.md).\n\n### Optional GitHub project pulse\n\nOne public `owner\u002Frepository` can add a deliberately sparse seventh page:\nthe current star count is the hero and forks are the only secondary metric.\nThe same raster covers every data provenance, so the glass never lies about\nfreshness:\n\n**Live**\n\n![GitHub tile showing a live star and fork count](docs\u002Fimg\u002Fgithub\u002Fsim-live.png)\n\n**Cached \u002F stale**\n\n![GitHub tile showing a cached star and fork count](docs\u002Fimg\u002Fgithub\u002Fsim-cached.png)\n\n**Waiting (no data)**\n\n![GitHub tile waiting on its first fetch](docs\u002Fimg\u002Fgithub\u002Fsim-missing.png)\n\nThe page and star moments are independent switches. A new star can therefore\nbriefly take over the current VibePulse view even when the GitHub page is not\nin rotation. It covers the previous page with a quiet black stage, shows a\nlarge filled star, the repository, the stargazer when GitHub supplies one,\nthe new total, and `TAP TO DISMISS`; otherwise it returns to the exact\nprevious page after two minutes.\n\n\u003Cimg src=\"docs\u002Fimg\u002Fgithub\u002Fsim-star-popup.png\" alt=\"Full-screen popup celebrating a new GitHub star\" width=\"320\">\n\nThe Mac service polls GitHub's public API and republishes a small, validated\nLAN payload. The ESP32 never talks to GitHub, and a GitHub timeout or rate\nlimit cannot stall the Claude\u002FCodex endpoints. Configure it with:\n\n```\npython3 tools\u002Ftokenserver\u002Ftokenserver.py --github-repo owner\u002Frepository\n```\n\nThen opt into `TK_GITHUB_SCREEN_ENABLED` and\u002For\n`TK_GITHUB_NOTIFICATIONS_ENABLED` in your gitignored `secrets.h`. Both are\noff by default. No GitHub token is required for a public repository.\n\n`TK_GITHUB_SOUND_ENABLED` is a separate default-off gate for the 258 ms\nA5-to-C#6 chime. The sequence and failure-isolated playback contract are in\nplace, but the current target intentionally registers no codec backend until\nthe physical speaker and display-DMA budget have passed device testing. A\nmissing or failed sound backend never delays the popup or any network path.\n\n### It never makes numbers up\n\n\u003Ctable>\n\u003Ctr>\n\u003Ctd width=\"35%\">\u003Cimg src=\"docs\u002Fimg\u002Fvibepulse-no-data.png\" alt=\"No-data state showing dashes instead of zeros\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\nBefore the first successful fetch, and whenever a source is missing, you get\ndashes — never a placeholder `0%` that you might believe. If the service\ngoes away, the last good numbers stay on screen and get marked stale rather\nthan silently drifting.\n\nRun Claude only, or Codex only, and the other half simply shows dashes.\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n### Are you getting your money's worth?\n\n\u003Ctable>\n\u003Ctr>\n\u003Ctd width=\"35%\">\u003Cimg src=\"docs\u002Fimg\u002Fvibepulse-value-ahead.png\" alt=\"Value multiple showing 3.12x — $312 via API against a $100 plan\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\nThe usage pages answer *how much have I spent?*. The\n[**value multiple**](docs\u002Fvalue-multiple.md) answers the question you\nactually have every month: it prices the tokens your agents already logged\nat list API rates and divides by what you pay. It's its own page on the\nswipeable strip, alongside GitHub — neither replaces the other.\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\n```\npython3 tools\u002Ftokenserver\u002Ftokenserver.py --claude-plan max5x --plan-cost-usd 100\n```\n\nIt counts cache tokens, which is the whole point — a real record here reads\n2 input and 4 output against 23 655 cache-read, so pricing only input and\noutput understates it by 577x.\n\nRates are not hand-maintained: they are generated from a public price\ncatalogue by `tools\u002Ftokenserver\u002Fupdate_prices.py` and committed, so the\nserver stays offline and refreshing is one command. An unknown model degrades\nthe figure to a dash rather than being silently free.\n\n## How it works\n\n```\n        your Mac                             your shelf\n┌────────────────────────────┐          ┌──────────────┐\n│ ~\u002F.claude\u002Fprojects\u002F*.jsonl │          │              │\n│ ~\u002F.codex\u002Fsessions\u002F*.jsonl  │ ───────► │   ESP32-S3   │\n│ rate-limit headers         │          │    AMOLED    │\n└────────────────────────────┘          └──────────────┘\n     tokenserver.py :8737           plain JSON over your LAN,\n     pure Python stdlib                polled every 30 s\n```\n\nA tiny Python service on your Mac reads your local Claude Code \u002F Codex logs\nand rate-limit headers, and serves plain numbers over your LAN. The screen\npolls it every 30 seconds. Your OAuth token never leaves the Mac; the screen\nonly ever receives percentages, counts and coarse status.\n\n## What you need\n\n- **[Waveshare ESP32-S3-Touch-AMOLED-2.16](https:\u002F\u002Fwww.waveshare.com\u002Fesp32-s3-touch-amoled-2.16.htm)**\n  (~$30). No soldering, just a USB-C cable. It's the same board Clawdmeter\n  uses, so if you already own one you're 10 minutes away.\n- **A Mac** on the same WiFi (the log-reading service is macOS-only for now)\n- **Claude Code and\u002For Codex.** Either alone is fine.\n- **2.4 GHz WiFi.** The ESP32-S3 can't see 5 GHz networks.\n\n## Setup, the vibecoder way\n\nClone the repo, open your coding agent inside it (Claude Code, Codex,\nCursor, whatever you run), and say:\n\n> Set up VibePulse for me: help me fill in secrets.h, build and flash the\n> board over USB, and start the tokenserver on this Mac.\n\nThe repo is built for this. `CLAUDE.md` and `AGENTS.md` point your agent\nstraight at **[docs\u002Fagent-setup.md](docs\u002Fagent-setup.md)** — an English\nrunbook written for agents, with a verification after every step, the traps\nthat actually cost people an evening, and a symptom→fix table. That's the\nwhole onboarding.\n\nReading rather than running? That runbook is also the fastest way to\nunderstand how the pieces fit together.\n\n## Setup, the manual way\n\n1. Install [ESP-IDF 5.5](https:\u002F\u002Fdocs.espressif.com\u002Fprojects\u002Fesp-idf\u002Fen\u002Fstable\u002Fesp32s3\u002Fget-started\u002Findex.html)\n   and `brew install cmake ninja`\n2. Clone this repo, then:\n\n   ```\n   cp secrets.h.example secrets.h   # fill in WiFi + your Mac's hostname (2 min)\n   . ~\u002Fesp\u002Fesp-idf\u002Fexport.sh\n   idf.py set-target esp32s3\n   idf.py build\n   idf.py -p \u002Fdev\u002Fcu.usbmodem101 flash\n   ```\n\n   **Don't miss this:** in `secrets.h`, point the `TK_VIBEPULSE_BASE_URL`\n   block at your Mac by replacing the `DIN-MAC` placeholder. Those URLs ship\n   active on purpose — a wrong hostname is visible in the log, whereas an\n   undefined URL compiles the fetch out entirely and the screen boots fine\n   and shows dashes forever. Use your Mac's Bonjour name\n   (`scutil --get LocalHostName`) rather than an IP, so the same firmware\n   works on your home network and on a phone hotspot.\n\n   Board not showing up under `\u002Fdev\u002Fcu.usbmodem*`? Hold **BOOT**, tap\n   **RESET**, release **BOOT** and it re-enumerates in download mode.\n\n   **Power matters:** flash with the board in download mode (screen dark).\n   A computer USB port often cannot feed the running firmware. The AMOLED\n   panel's draw makes the board bounce off the bus or hang, which looks\n   like a flaky cable. After flashing, run the screen from its own USB\n   power supply, not your computer.\n3. Start the service on your Mac. Pure Python stdlib, nothing to install:\n\n   ```\n   python3 tools\u002Ftokenserver\u002Ftokenserver.py\n   ```\n\n   Autostart on login: see [tools\u002Ftokenserver\u002FREADME.md](tools\u002Ftokenserver\u002FREADME.md).\n\n## Over-the-air updates\n\nAfter the first USB flash, the screen updates itself over WiFi. The consent\nchain is deliberate and three-factor: a **physical 3-second hold on KEY3**\nopens a ten-minute maintenance window (the glass shows an UPDATES ON ring\nwith the lease draining clockwise), a **64-hex token** from `secrets.h`\nauthenticates the upload, and the window **closes itself** — a short KEY3\npress closes it early. No button, no update; a script can never open the\nwindow for you.\n\n```\nidf.py build\ntools\u002Fota-flash.sh \u003Cdevice-ip>     # waits for your KEY3 hold, then uploads\n```\n\nThe device verifies the image (magic, chip, project, SHA-256), writes it to\nthe **inactive A\u002FB slot** (`ota_0`\u002F`ota_1`, 5 MB each — see\n`partitions.csv`), reboots into it, and a **boot-health gate** must approve\nthe new image within 15 seconds — display, UI, scheduler, NVS and memory\nproofs — or the bootloader rolls back to the previous slot automatically.\nUSB-C remains the rescue path and is never written by an OTA. After an OTA\nreboot the window re-arms itself once, so a build-test-build session needs\none hold, not one per build.\n\nThe tokenserver announces the newest build on your Mac\n(`otaAvailableVersion` on `\u002Fapi\u002Ftokens`); when the screen runs an older\nversion it takes the glass with an **UPDATE READY** notice — hold KEY3 to\nreceive — or answer the on-glass LATER\u002FUPDATE pills by touch; tapping\nUPDATE opens the window just like the hold does. A snooze returns every\nhour until installed. Full lifecycle reference: [docs\u002Fota.md](docs\u002Fota.md).\n\n**If someone tells you \"this project has no OTA\":** they are reading a tree\nwhere `partitions.csv` still has a single `factory` partition. The OTA\nfoundation replaced that table (A\u002FB slots + `otadata`) — check the branch\nyou are on before concluding anything, and never assume the flash layout\nwithout reading `partitions.csv` in the checkout you are actually building.\n\n## No hardware? Run the simulator\n\n```\nbrew install sdl2 cmake ninja\ncmake -S sim -B sim\u002Fbuild -G Ninja && ninja -C sim\u002Fbuild\n.\u002Fsim\u002Fbuild\u002Ftorget-sim\n```\n\n(On Debian\u002FUbuntu: `apt-get install libsdl2-dev cmake ninja-build` instead.)\n\nSame code, same fonts, same pixels as the device — it builds the real\nplatform and VibePulse against the real LVGL, and feeds it the recorded\nfixtures in `sim-fixtures\u002F` through the same parsers the board runs. Every\ndevice screenshot in this README is an unmodified simulator frame (the\nbanner just places three of them side by side), and the physical panel was\nreviewed against them ([review](docs\u002Fsuperpowers\u002Freviews\u002F2026-08-13-max-tracker-physical-static.md)).\n\nKeys: `[` \u002F `]` change VibePulse page, `S` cycles agent status, `M` cycles\nMax Tracker fixtures, `T` re-feeds tokens, `G` simulates a new GitHub star,\n`L` opens the launcher.\n\n## Privacy\n\n- Agent activity and usage stay on your LAN; the screen only ever receives\n  percentages, counts and coarse status — a project name, a model, an effort\n  level.\n- No prompts, no code, no commands, no file contents are stored or served.\n  The service keeps only content-free quota points (at most one per 15\n  minutes, kept 8 days) for the trends.\n- Your OAuth token never leaves the Mac.\n- If the optional GitHub module is enabled, the Mac anonymously reads only\n  public repository and stargazer metadata from GitHub. The ESP32 still\n  talks only to the Mac over your LAN.\n- A lost or stolen screen leaks your WiFi credentials and the LAN hostname\n  of your Mac — both of which you rotate yourself, not in any cloud.\n\n## Tweak it\n\n\u003Ctable>\n\u003Ctr>\n\u003Ctd width=\"30%\">\u003Cimg src=\"docs\u002Fimg\u002Flauncher.png\" alt=\"The Torget launcher showing VibePulse\" width=\"100%\">\u003C\u002Ftd>\n\u003Ctd valign=\"top\">\n\nVibePulse is an app on **Torget**, a deliberately small LVGL 9 app platform\nfor this panel. An app is one component exporting\n`torget_app_t { name, icon, create, enter, leave }`; the platform owns WiFi,\nthe panel, brightness and the launcher.\n\nThis repo ships exactly one app, so that's all you get on the screen — one\nbinary, one thing, nothing to wonder about. The platform can hold several\napps at once (that's what the launcher is for), but any others live in their\nown repos and are only built in if you check them out.\n\n\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftable>\n\nDesign rules: true black background, IBM Plex, dashes instead of invented\nzeros, and provider accents locked to Claude `#D97757` and Codex `#6F78FF`.\n\n```\nplatform\u002F            app contract + launcher + fonts (IBM Plex)\nmain\u002F                ESP32 host layer: boot, WiFi, SNTP, app registry\ncomponents\u002Fapp_*     the app (VibePulse lives in app_tokens\u002F)\ntools\u002Ftokenserver\u002F   the Mac service (Python stdlib)\nsim\u002F                 SDL simulator, the whole platform on your Mac\ntest\u002F                host tests, run with .\u002Ftest\u002Frun.sh (no ESP-IDF needed)\nspec\u002F                hardware truth + UI design system\n```\n\nThe deeper docs (architecture, writing an app, hardware traps) are in\n[README.sv.md](README.sv.md), in Swedish, because this started as a Swedish\nhobby project. Your agent reads Swedish just fine.\n\n## Hardware knowledge\n\nHardware truth — capabilities, sources and which claims are verified on a\nreal unit — lives in the validated registries under `spec\u002F`. Read\n`spec\u002Fhardware.md` before any hardware-dependent work, and don't promote a\ncapability to \"verified\" without a physical check.\n\n`.\u002Ftest\u002Frun.sh` is the host gate that enforces those registries, alongside\nthe C core tests and the Python suites. No ESP-IDF required, but it does\nneed a reproducible Python:\n\n```sh\npython3.12 -m venv .venv\n. .venv\u002Fbin\u002Factivate\npython -m pip install -r requirements-dev.txt\n.\u002Ftest\u002Frun.sh\n```\n\nPython 3.11+ is required. The script uses the activated environment's Python\nby default; set `PYTHON_BIN` to point at a different 3.11+ interpreter.\n\n## FAQ\n\n- **Windows for the Mac service?** The data half works. Claude Code has no\n  keychain there, so `claude login` writes the same\n  `{\"claudeAiOauth\": {...}}` record to\n  `%USERPROFILE%\\.claude\\.credentials.json` and the service reads it; the\n  Codex app-server read and the single-probe lock no longer depend on\n  macOS-only syscalls; state and logs live under `%LOCALAPPDATA%\\VibePulse\\`.\n  What is missing is **autostart** — the launchd plist has no Windows\n  equivalent, so you start it by hand or wire up Task Scheduler yourself.\n  [#3](https:\u002F\u002Fgithub.com\u002Fniclasvestlund-YT\u002Fvibepulse\u002Fissues\u002F3).\n- **Linux for the Mac service?** Not yet —\n  [#2](https:\u002F\u002Fgithub.com\u002Fniclasvestlund-YT\u002Fvibepulse\u002Fissues\u002F2);\n  contributions very welcome.\n- **Other boards or panel sizes?** Not yet. The platform is pinned to this\n  exact panel so one pixel-perfect build stays pixel-perfect, but a port is\n  a contained job (BSP, layout constants, fonts) —\n  [#5](https:\u002F\u002Fgithub.com\u002Fniclasvestlund-YT\u002Fvibepulse\u002Fissues\u002F5).\n- **Cursor, Gemini CLI, other providers?** Not yet —\n  [#4](https:\u002F\u002Fgithub.com\u002Fniclasvestlund-YT\u002Fvibepulse\u002Fissues\u002F4).\n- **Just Claude, no Codex (or vice versa)?** Works. The other half shows\n  dashes.\n- **Does it need internet?** No. The board talks to one host on your LAN.\n\n## License\n\nMIT © Niclas Vestlund\n\nThe \"Claude\" and \"Codex\" names and icons belong to Anthropic and OpenAI.\nThey appear here only to identify which provider a number belongs to, they\nare not covered by the MIT license, and they will be removed on request.\nThe IBM Plex fonts are used under the SIL Open Font License\n([platform\u002Ffonts\u002FLICENSE-OFL.txt](platform\u002Ffonts\u002FLICENSE-OFL.txt)).\n\nThis is my first open source release. Issues and PRs are very welcome, and\nif VibePulse ends up on your shelf, a ⭐ helps others find it.\n\nBuilt by [Niclas Vestlund](https:\u002F\u002Fniclasvestlund.se).\n","VibePulse 是一款本地化 AI 编程代理状态监控硬件终端，通过桌面 AMOLED 屏幕实时展示 Claude Code 和 Codex 的用量配额、实时代理运行状态，并在代理等待用户输入时触发全屏 'NEEDS YOU' 提示。项目由 ESP32-S3 嵌入式设备与 macOS 端纯标准库 Python 服务协同实现，所有数据严格限制在局域网内，不依赖云服务、账户或 API 密钥。适用于高频使用本地 AI 编程助手（如 Claude\u002FCodex）的开发者，帮助及时掌握配额余量、避免任务中断遗漏，并支持触控快速响应阻塞请求。",2,"2026-08-18 02:30:10","CREATED_QUERY"]