ocdway/README.md
ocpway ea834a99a5 Initial commit: ocd waybar plugin
Daemon (scripts/ocd-waybar) polls {
  "schema_version": 1,
  "generated_at": "2026-07-30T01:29:37.918330160+00:00",
  "accounts": [
    {
      "account": "legal",
      "workspace": "wrk_01KBJFEAZV7G2FJBE1KAPRQSJN",
      "fetched_at": "2026-07-30T01:27:49.014903087+00:00",
      "status": "cached",
      "limits": {
        "usage_5h": {
          "used": 0.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-07-30T06:27:49.014903087+00:00",
          "status": "ok"
        },
        "usage_week": {
          "used": 88.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-03T00:00:01.014903087+00:00",
          "status": "ok"
        },
        "usage_month": {
          "used": 94.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-21T22:07:23.014903087+00:00",
          "status": "ok"
        },
        "next_update": null
      },
      "balance": {
        "remaining": 0.0,
        "unit": "$"
      }
    },
    {
      "account": "legal2",
      "workspace": "wrk_01KQHV4ZP2SHZHTCTF0HW1BKHA",
      "fetched_at": "2026-07-30T01:27:49.920803926+00:00",
      "status": "cached",
      "limits": {
        "usage_5h": {
          "used": 0.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-07-30T06:27:49.920803926+00:00",
          "status": "ok"
        },
        "usage_week": {
          "used": 100.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-03T00:00:00.920803926+00:00",
          "status": "rate-limited"
        },
        "usage_month": {
          "used": 90.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-23T18:01:33.920803926+00:00",
          "status": "ok"
        },
        "next_update": null
      },
      "balance": {
        "remaining": 0.0,
        "unit": "$"
      }
    },
    {
      "account": "kllr560",
      "workspace": "wrk_01KYJ5B4PM2EGR16ZDC0JTH2CC",
      "fetched_at": "2026-07-30T01:27:50.791975864+00:00",
      "status": "cached",
      "limits": {
        "usage_5h": {
          "used": 0.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-07-30T06:27:50.791975864+00:00",
          "status": "ok"
        },
        "usage_week": {
          "used": 79.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-03T00:00:00.791975864+00:00",
          "status": "ok"
        },
        "usage_month": {
          "used": 39.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-27T16:10:15.791975864+00:00",
          "status": "ok"
        },
        "next_update": null
      },
      "balance": {
        "remaining": 0.0,
        "unit": "$"
      }
    },
    {
      "account": "pj-vendee",
      "workspace": "wrk_01KYNGQCX4XEM0KD3PWVVE636D",
      "fetched_at": "2026-07-30T01:27:51.638144968+00:00",
      "status": "cached",
      "limits": {
        "usage_5h": {
          "used": 0.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-07-30T06:27:51.638144968+00:00",
          "status": "ok"
        },
        "usage_week": {
          "used": 40.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-03T00:00:00.638144968+00:00",
          "status": "ok"
        },
        "usage_month": {
          "used": 20.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-29T01:09:27.638144968+00:00",
          "status": "ok"
        },
        "next_update": null
      },
      "balance": {
        "remaining": 0.0,
        "unit": "$"
      }
    },
    {
      "account": "iyaunalunarovell",
      "workspace": "wrk_01KYNTSGXF7GFXMAMT36N3GH21",
      "fetched_at": "2026-07-30T01:27:52.584601387+00:00",
      "status": "cached",
      "limits": {
        "usage_5h": {
          "used": 94.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-07-30T02:27:25.584601387+00:00",
          "status": "ok"
        },
        "usage_week": {
          "used": 99.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-03T00:00:00.584601387+00:00",
          "status": "ok"
        },
        "usage_month": {
          "used": 49.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-29T02:22:06.584601387+00:00",
          "status": "ok"
        },
        "next_update": null
      },
      "balance": {
        "remaining": 0.0,
        "unit": "$"
      }
    },
    {
      "account": "balensiefenpiwihu2906",
      "workspace": "wrk_01KYQNFP718WP7X9W7RXC2Q133",
      "fetched_at": "2026-07-30T01:27:53.457572405+00:00",
      "status": "cached",
      "limits": {
        "usage_5h": {
          "used": 53.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-07-30T03:43:22.457572405+00:00",
          "status": "ok"
        },
        "usage_week": {
          "used": 21.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-03T00:00:00.457572405+00:00",
          "status": "ok"
        },
        "usage_month": {
          "used": 10.0,
          "total": 100.0,
          "unit": "%",
          "resets_at": "2026-08-29T19:27:31.457572405+00:00",
          "status": "ok"
        },
        "next_update": null
      },
      "balance": {
        "remaining": 0.0,
        "unit": "$"
      }
    }
  ]
} every 30s (no force
flags, so ocd cache/TTL stays in charge), runs a 5s account rotation
in config order, and supports right-click 1h lock. The waybar
custom/ocd module reads a state.json written by the daemon; hover
shows all accounts via the native tooltip. Bars are Pango background
spans (~50px) in the label and plain block chars in the tooltip, since
waybar 0.15.0 renders custom tooltips as plain text.
2026-07-30 04:29:37 +03:00

4.7 KiB

ocpway — waybar plugin for ocd

A waybar module that shows opencode usage limits and balance from the ocd dashboard binary. It rotates through the accounts in your ocd config, one every 5 seconds. Left-click advances at once. Right-click locks the current account for one hour. Hover the bar to see all accounts at once.

What it shows

One line per account:

kllr560  [0%/5h] ▓░░░░░░ 4:59  [79%/1w] █████▌░ 3d 22h  [39%/1m] ██▋░░░░ 28d  $0.00 / 1m ago
  • Account name, and a lock emoji 🔒 while locked.
  • Three bars: the 5-hour, weekly, and monthly usage window.
    • The label holds the used value with its unit, e.g. [79%/1w].
    • The bar is the percentage, drawn as filled cells up to the value.
    • The text after the bar is the time until the window resets.
  • The balance and the age of the last data fetch: $0.00 / 1m ago.

When locked, the bar cells lock to blue and the line starts with 🔒.

The hover tooltip lists every account the same way. The active row is marked with , and the lock emoji shows only on the locked row.

Design decisions

The bar is rectangular. It uses Pango background spans over non-breaking space cells. Seven cells are about 50 px at a normal bar font. The bar in the tooltip uses plain block characters because waybar 0.15.0 renders the custom-module tooltip as plain text. If your waybar gains Pango markup in custom tooltips (see Waybar PR #5034), set TOOLTIP_MARKUP = True in the daemon to get colored background-span bars in the tooltip too.

The daemon polls ocd raw json every 30 seconds. It sends no --force-refresh or --no-cache flags, so ocd keeps full control of politeness: its own cache, TTL, concurrency, and pacing stay in charge. Most polls read the cache and never touch the network. The daemon also polls at once waybar starts

waybar 0.15.0 has no on-hover event for custom modules, so the all-accounts view is the native tooltip, not a separate floating window.

Layout

ocpway/
  scripts/
    ocd-waybar         the daemon (python)
    ocd-waybar-ctl     the click helper (sh) for advance / lock / poll / quit
  config/
    waybar-config.jsonc   the "custom/ocd" module block to add
    waybar-style.css      the CSS to append
    hypr-autostart.conf   the exec-once line to start the daemon
  README.md

Install

Copy the scripts and wiring them into your own config.

  1. Copy the scripts:

    mkdir -p ~/.config/waybar/scripts
    cp scripts/ocd-waybar scripts/ocd-waybar-ctl ~/.config/waybar/scripts/
    chmod +x ~/.config/waybar/scripts/ocd-waybar{,-ctl}
    
  2. Add the custom/ocd module to ~/.config/waybar/config.jsonc. See config/waybar-config.jsonc for the block and where the module name goes in modules-right.

  3. Append the CSS in config/waybar-style.css to ~/.config/waybar/style.css.

  4. Add the exec-once line in config/hypr-autostart.conf to ~/.config/hypr/autostart.conf.

  5. Restart waybar, and start the daemon:

    pkill -x waybar; waybar &
    ~/.config/waybar/scripts/ocd-waybar &
    

    On later logins, the exec-once line starts the daemon for you.

Usage

  • Hover the module: see all accounts.
  • Left-click: advance to the next account at once (resets the 5-second timer).
  • Right-click: lock the current account for one hour.

ocd-waybar-ctl commands

Command Effect
advance Reset the timer and move to the next account.
lock Freeze the current account for one hour.
poll Run an ocd poll now (still respects ocd cache and TTL).
quit Stop the daemon.

The helper tries socat, then nc -U -u, then a small python fallback.

Tunables

At the top of scripts/ocd-waybar:

Name Default Meaning
ROTATE_SECS 5 Auto-advance cadence.
LOCK_SECS 3600 One hour lock duration.
POLL_SECS 30 ocd re-poll cadence.
BAR_WIDTH 7 Bar cells, about 50 px.
TOOLTIP_MARKUP False Set True if your waybar renders Pango in custom tooltips.
C_OK / C_WARN / C_CRIT / C_LOCK / C_TRACK see source Zone colors.
OCD_BIN ocd Path to the ocd binary (or set the OCD_BIN env var).

Zone thresholds: under 70 percent is green, 70 to 90 is amber, over 90 or a rate-limited frame status is red.

Dependencies

  • ocd, built and on PATH (or pointed at with OCD_BIN).
  • python3 (the daemon). Standard library only.
  • waybar. Tested on 0.15.0.
  • For clicks: socat is preferred, nc is a fallback, else the python fallback runs.

State

The daemon writes ~/.local/state/ocd-waybar/state.json. The waybar module reads that file once per second with cat and emits it as a JSON object. The socket lives at $XDG_RUNTIME_DIR/ocd-waybar.sock.