Jovan1666/claude-code-runway

A Claude Code mod that draws Command Code plan allowances above the input, showing the remaining amount and projected position across three usage windows.
Jovan1666/claude-code-runway

runway displays Command Code plan allowance above the input: what remains, how long it may last and whether the current pace will exceed it. Three equally weighted bars (5h / week / month) use color to distinguish used, projected overage and remaining capacity; red means the limit will be exceeded. It provides a detail panel, calculator, /quota and toast messages, and requires Claude Code v2.1.287+. Install through --plugin-dir, CLAUDE_CODE_PLUGIN_DIRS or the marketplace. MIT licensed.
Check the author's README for the marketplace and plugin name first. Commands may change as the repository evolves.
claude plugin marketplace add Jovan1666/claude-code-runway claude plugin install runway
一个 Claude Code mod:把 Command Code 套餐额度画在输入框上方,让你一眼看清 三个额度窗口各自还剩多少、照当前速度会走到哪。
5h ██████████████ 3.0% │ 周 ██████████████ 16% │ 月 ██████████████ 52% 月超 $14.00 1 详情
└ 1 亮 + 13 暗 └ 2 亮 + 12 暗 └ 7 黄 + 7 红(会冲过上限)

<sub>上图由 tools/mock.mjs 调用真实的布局函数渲染,与真机同源;配色是近似值,以实际主题为准。</sub>
Claude Code 的 statusLine 在 Claude Desktop 的 Code tab 里不渲染 —— 你自己写的 statusLine 脚本在终端里正常,切到 Desktop 就是一片空白。
mod 的 AbovePrompt band 是那个表面上唯一能常驻放东西的地方,所以有了这个。
三个窗口等权重地摆在一行,各自一条条,中间用 │ 分隔。
条上全程只用 █ 一个字符,靠颜色区分三段:
| 颜色 | 含义 | |---|---| | 亮色(绿 / 黄 / 红) | 已经花掉的 | | 红色 | 按当前速度还将花掉的(只在会冲过上限时出现) | | 暗色 | 照这个速度会剩下来的(余量) |
会不会爆表不用读字:右半截变红、暗色余量段消失,就是同一件事的两种画法。 轴固定 0→100%,不画刻度 —— 条的末端就是上限。
撑得住时「已用」和「落点」同色合成一根完整的条,于是:
一根条一个颜色 = 安全;出现红色 = 会爆表。
这点和普通的进度条不一样。普通条只说「现在到哪了」;这一根同时说「照这么走下去会到哪」。
早期版本用 █ / ▒ / ░ 表示 100% / 50% / 25% 三种墨量。实际渲染出来,同一根条看起来
像三种不同的东西拼在一起,高矮粗细对不齐,很别扭。现在三段是同一个字形,天然对齐。
同理,没有图标。曾经用 ◑(半填充圆)表示档位,实测在真实字体里会渲染成一个
大圆圈,既不协调也没人认得。档位现在只靠颜色 + 词(宽裕 / 偏紧 / 吃紧 /
断粮 / 采样中)表达。
设计上踩过两次坑,都记在这里:
现在三条给同样的宽度、一起伸缩,谁也不会把谁挤没。挤不下时按这个顺序让位:
先丢档位词 → 再丢落点结论 → 最后干脆不画条,但三个窗口的标签和百分比永不丢。
50 列时退化成 5h 3.0% │ 周 16% │ 月 52% 1 详情,仍然一眼看得全。
如果连这个最精简的骨架都放不下,整行不画(面板和 /quota 照常可用)。
以前会照样交回一行超出列宽的内容,渲染器折行,而「月」恰好在最右边 —— 第一个被切掉的就是主窗口。
填充率 52% 看着安全,但按当前速度会提前 5 天烧完 —— 画成绿色就是骗人。 所以月额度的颜色由节奏决定:
| 情况 | 档位词 | 条的颜色 | |---|---|---| | 还有余量、撑得到周期结束 | 宽裕 | 绿 | | 会提前烧完,但还能撑 > 3 天 | 偏紧 | 黄 | | 会提前烧完,且只剩 ≤ 3 天可撑 | 吃紧 | 红(加粗) | | 余量为零 | 断粮 | 红(加粗) | | 周期太短、样本不足 | 采样中 | 不取色 |
判据是「还能撑多久」,不是「缺口多少天」。 这两者方向相反: 早 13 天烧完比早 1 天烧完严重得多,但按缺口天数判会给前者「偏紧/黄」、 后者「吃紧/红」—— 颜色和紧挨着的数字对着干(「吃紧」配「还能撑 15d」、「偏紧」配「还能撑 2.3d」)。 早期版本就是这么写的,README 和测试都把反向判据一起固化了,所以一直没被发现。
月度用「已过 5% 周期」就能给结论,因为它的消耗是匀速的。 滚动窗口不行 —— 实测 5h 窗口跑了 16 分钟、用了 7.4%,按 5% 门槛恰好放行, 外推出来是 139% 的假警报。
现在滚动窗口要求已过 20% 的窗口长度(5h 要跑满 1 小时、周窗口要过 1.4 天) 才给落点,之前那条只画普通的水平条。
(原版 commandcode-usage 干脆不在状态栏显示 5h 的预测,也是这个原因。)
| 操作 | 效果 |
|---|---|
| 空输入框里按 1 | 打开详情面板(不用点、不用切焦点) |
| 面板里改「试算」的数字 + 回车 | 换一个花法会怎样 —— 纯本地算术,立刻算出新的断粮时刻 |
| 面板里 1 刷新 / 2 复制快照 | 立即取数 / 复制一屏可贴的摘要 |
| /quota | 打印完整的文本快照 |
| Esc | 关面板 |
面板里还有:
03/27 03:16 这个时刻,
并前置到面板第三行。长度可以拖,时刻不能;人会自动把时刻跟日历上别的事对照,
所以它比天数扎心得多。同一件事以前在第 3 行说一遍、第 14 行再说一遍。这样会烧到 04/01 00:13 —— 撑得到周期末,并反推 每天不超过 $1.98 就不会超。额度跨档时主动弹一次 toast(每档每周期只报一次)。读数陈旧超过两个刷新周期时整行转暗。
需要 Claude Code v2.1.287 或更新(mods 是那个版本引入的)。
claude --plugin-dir /path/to/runway
热重载:改完存盘即生效。
Desktop 传不了命令行参数,所以用这个环境变量 —— 它就是为「拿不到 flag 的 app」设计的,
写在 ~/.claude/settings.json 里:
{
"env": {
"CLAUDE_CODE_PLUGIN_DIRS": "/path/to/runway"
}
}
Windows 上多条路径用 ; 分隔,其他平台用 :。撤销就是删掉这一行。
用 claude plugin list 看 runway@inline 是否 loaded。
把本仓库当作 marketplace 加进去:
claude plugin marketplace add Jovan1666/claude-code-runway
claude plugin install runway@claude-code-runway --scope user
打 api.commandcode.ai 的三个端点:
GET /alpha/billing/credits?orgId= → windowLimits.{fiveHour,weekly} + credits
GET /alpha/billing/subscriptions?orgId= → 计划与计费周期
GET /alpha/usage/summary?since=<周期起点> → 花费与均价
/alpha/whoami 省掉了:实测它返回的 org 恒为 null,而 credits 并不需要 orgId。
凭据按顺序找:
COMMAND_CODE_API_KEY / COMMANDCODE_API_KEY / CMD_API_KEYsettings.json 的 env 段中名字含 commandcode 的项access.apiKey + 匹配 commandcode.ai 的 api.baseUrl,
按 ~/.zcode/v2/provider_config.json → ~/.config/opencode/opencode.json →
~/.pi/agent/settings.json → ~/.claude/settings.json 的顺序找读不到凭据就什么都不画 —— 不占位置,也不报错。取数失败保留上一次读数并标注陈旧。
刷新:会话启动取一次,之后每 180 秒一次,每轮对话结束后去抖(15 秒)补一次。
渲染路径永远不发网络请求 —— ui.render 每帧都跑。
滚动窗口的落点用重置时刻倒推窗口起点:
elapsed = 窗口长度 − 距下次重置的时间(5h 窗口 5 小时、周窗口 7 天)。
node tools/preview.mjs # 取真实数据,打印额度条 / 面板 / 命令输出(纯文本)
node tools/preview.mjs --json # 额外 dump 归一化后的对象
node tools/mock.mjs --demo # 用合成数据写出带颜色的视觉稿 tools/mock.html
node tools/mock.mjs --real # 用真实读数出图(默认拒绝,见下)
claude plugin validate . # 静态检查:列出 hooks、$ 调用、读写哪些环境变量
claude plugin test . # 纯函数测试,不需要会话或网络
视觉稿默认拒绝真实读数。 这个工具的产物
tools/mock.html就是拿来截图贴进 本文档的,真实读数一旦落到docs/就跟着仓库一起公开了。 所以不带--demo时必须显式加--real才会取真实数据。视觉稿的每一个候选框都按标注的列数定宽,标注里给出「实宽 / 可用」, 超宽标红。这是为了能看见溢出:早期版本用
overflow-x:auto让浏览器自己横向回流, 于是 58 列的面板和 76 列的面板在视觉稿里一样宽 —— 面板比它声明的列数 宽 12 格这件事从来没被看出来过。框的像素宽度只是近似:中文字体在浏览器里的字宽与终端的「列」不严格相等, 判定以标注里的数字为准。
2.1.288 上的一个坑:本仓库根目录同时有
.claude-plugin/marketplace.json, 而 2.1.288 的claude plugin validate遇到这种情况会只校验 marketplace、 跳过插件本身(不再输出hooks:/calls:那套静态分析)。这是 2.1.289 修掉的 已知 bug。在 2.1.288 上想看静态分析,复制一份去掉 marketplace 清单再校验:T=$(mktemp -d) && cp -r . "$T/" && rm -f "$T/.claude-plugin/marketplace.json" && rm -rf "$T/.git" claude plugin validate "$T"; rm -rf "$T"
tools/mock.mjs 为什么必须存在mod 的 band 只在真实会话里渲染,写代码的模型看不到自己的输出。
这个项目的整个过程就是在证明这一点:早期版本纯靠想象设计,结果条糊成一坨、图标没人
认得、面板还因为一个未定义变量整片空白。后来把 layoutRow / layoutPane 抽成纯函数,
hooks/register.mjs 把「段」变成元素树、tools/mock.mjs 把同一批「段」变成 HTML ——
同一份布局两个出口,于是浏览器里看到的就是屏幕上的,可以反复比对再定稿。
lib/quota.mjs 里不出现 $:mods 的静态检查只允许把 $ 传给同一文件里顶层声明的
函数,跨文件传会验证失败 —— 把纯逻辑分出去正好避开这条约束,顺便让它可测、可预览。
claude -p、云会话不绘制 ——
那些场合用 /quota 命令。ui.render 交回坏树可能让整个会话以
unrecoverable interface error 结束(2.1.289 才改成引擎自己兜底)。本 mod 在渲染层
做了 try/catch,但建议用 2.1.289 或更新。plugin.json 里声明了 dependencies: ["token-weather@claude-code-playground-mods"]。
band 的多个 mod 是一条中间件链,某个 hook 返回自己的树而不调 next(e) 就短路了排在它
后面的所有 mod。token-weather
在有读数时正是这么做的,会把排在它后面的 band mod 整个吃掉 —— 表现是「装了但永远不显示」,
而且极难排查。
而「装了 mod 的插件里,声明了 dependencies 的那个先跑」,所以这是唯一能保证顺序的手段。
代价是 token-weather 会被连带启用。
本 mod 一定 await next(e) 并把别人的树嵌进外层 Box,不会反过来吃掉谁。
不想装 token-weather 的话,把这行删掉即可 —— 但如果它在你之后加载,这行就不会显示。
MIT。见 LICENSE。
Command Code 是其各自所有者的商标;本项目与它没有隶属关系。