Show HN:Weatherdeck——面向 AI 编码 Agent 工作通道的只读状态看板
英文标题:🔶 Show HN: Weatherdeck – a read-only status board for AI coding agent lanes
Weatherdeck 是一个本地运行、只读的状态看板,用于汇总多台机器及其工作任务的状态,适合常驻电视或手机页面查看。它通过 HTTP 接收各类工具推送的 JSON 数据,自动发现来源,并明确标识等待人工处理、延期事项、真实进度及失联数据源。项目不依赖 LLM、CDN、遥测或管理员权限,仅使用 Python 标准库、SQLite 和原生 HTML/JS/CSS。对开发者而言,它提供了一个轻量、可审计的跨工具工作状态展示层,但并非监控、告警或托管服务。
2.4 KB
234.7 KB
309.3 KB
286.4 KB
273.4 KB
101.6 KB
中文
Weatherdeck 是一个用于展示机器及其上运行工作的状态看板(一个由小型推送程序供给的电视或手机页面),不是天气应用,也不是监控或告警系统。
你看到的内容。 此处每张图片均来自演示模式(页面地址中运行 weatherdeck run --demo 并附加 #theme=ship-deck)。其中的数据源均为虚构,不代表任何真实信息。
- 等待你处理。 琥珀色面板统计需要人工介入的事项,并显示每项已等待多久。
- 已搁置,不计入统计。 带有日期的暂缓事项,以及由他人负责的行,不会被计入“等待你处理”。在手机页面上,它们位于待处理事项下方的一条折叠行中(“Deferred 2 · skipper's turn 3”);点击后会列出每项的日期或负责人,以及原因。
- 诚实的进度。 当数据源提供区间时,进度显示为百分比范围(例如 38-42%)。看板无法读取的工作通道会计入“无法判断”(“+10 more”这一行会显示 1),而不会被展示为一切正常。
- 明确点出安静的数据源。 时钟旁的指示灯统计在线数据源。当某个来源停止上报时,显示为“2/3 live”,对应机器的船会被绘制在雾中并标注为 silent。
- 一块看板适配电视和手机。 同一个页面在宽屏上呈现为开阔海面,在手机上则为单列布局。
在这段动画中,Cinder(一个虚构数据源)停止了上报。静态画面。
演示开始数分钟后截取的手机页面,画面裁切在 ALL FINE 磁贴之后:先是待处理事项,再是用于显示已搁置内容的折叠行,接着是问题列表,最后是该磁贴。只有在没有任何待处理事项或问题、且所有数据源都在上报时,该磁贴才会点亮。
展开后的折叠行。延期事项显示重新回到待办的日期及原因;其他事项显示负责人以及自何时开始由其负责。它们都不会计入上方的“Needs you”。
这是一个用于一览多个来源上报工作状态的看板,旨在常驻于电视或手机上:哪些事项在等待你处理、哪些工作正在推进及其真实进度、已完成什么、接下来是什么,以及你是否能信任当前所见的信息。
- 任何工具都可以留下卡片。 将一个小型 JSON 文件放入投递目录,即可生成一个状态磁贴;看板只读取该文件(docs/ADDINS.md)。
- 任何工具都可以向它供给数据。 数据源可以是任何能够通过 HTTP 发送一份 JSON 文档的对象。数据源会被自动发现,无需配置;机器和事项会自行出现。
- 可核查。 主机接收到的每一次推送都会记录为接收日志中的一行(
weatherdeck received --diff):包括每个数据源发送了什么,以及看板上发生了哪些变化。 - 诚实呈现缺口。 停止上报的数据源仍会留在屏幕上,并被标记为 silent 和雾化。看板绝不会将过期数据展示为新鲜数据;当缺少数据源时也会明确说明。在未测量数值之前,它不会宣称自身或任何工具具有某种价值(docs/honesty.md)。
- 只读、本地、轻量。 仅使用 Python 标准库、一个 SQLite 文件和一个纯 HTML/JS/CSS 页面。没有构建步骤、没有 CDN、没有遥测、也不需要 root 权限。
- 可在任意平台运行。 Windows、macOS 和 Linux 都可通过相同命令原生运行,无需管理员权限。可以同时运行多个主机;每个页面都会说明由哪台主机提供服务。
- 确定性。 不会在任何地方调用模型或 LLM;唯一的出站流量是适配器向你指定的主机推送数据。
这不是什么。 它不是监控或告警系统:它从不呼叫任何人,只展示数据源主动推送给它的信息。它不是托管服务:由你自行在选定机器上运行。它也是 1.0 之前的业余软件,之所以开源,是因为它解决了作者自身的问题:细节可能会变化,支持仅尽力而为。
你需要 Python 3.9 至 3.14(较旧版本会在启动时用一行提示终止;Microsoft Store 版本适合用于试用;如需在登录时运行或运行定时任务,请参阅 docs/runbook-windows.md)。无需安装:可直接从源码检出目录或发布 zip 包运行。获取代码的方式是克隆本仓库(执行 git clone,然后 cd 进入文件夹),或者解压由 scripts/build-package 从克隆仓库构建的 zip 包。暂不支持 pip install,执行后会显示相应提示并停止。下文中,macOS/Linux 上的 weatherdeck 指 python3 bin/weatherdeck,Windows(cmd 或 PowerShell)上则指 bin\weatherdeck.cmd。
- 使用合成数据查看效果。
打开 http://127.0.0.1:8787/。三个虚构数据源会进行上报;其中一个会在约两分半钟后停止上报,大约在 2:40 时显示为延迟,并在启动约三分钟后显示为 silent,以便你看到离线状态。按 Ctrl-C 停止。(使用 --port N 可修改端口。)
-
实际运行。
weatherdeck on # 后台运行;输出 URL weatherdeck status weatherdeck off
数据保存在你的用户数据目录中(使用 --data DIR 或 $WEATHERDECK_DATA 可选择其他目录)。在 Windows 上,weatherdeck startup install 还会让它在每次登录时自动启动,无需管理员权限。
-
向它发送数据。 任意工具均可通过一次 POST 完成(从同一台机器发送,无需额外设置):
curl -X POST http://127.0.0.1:8787/api/ingest -H 'Content-Type: application/json' -d '{ "schema": "lookout.feed", "schema_version": "1.0", "source": { "id": "my-laptop" }, "items": [{ "id": "build", "title": "Nightly build", "state": "running" }] }'
架构 ID 有意使用 lookout.feed:这是每个适配器已经使用的线缆协议名称,产品更名后仍保持不变(参见 docs/feed-spec.md 中的“Schema ids”)。
如需持续供给数据,可运行示例适配器:它会将手工编辑的列表与本机运行状况转换为数据源,并推送给列表中的每一台主机:
cp examples/adapter/work.example.json work.json
cp examples/adapter/sinks.example.txt sinks.txt # 编辑主机列表
python3 examples/adapter/push_example.py --work work.json --sinks sinks.txt
如需从你自己的工具供给数据,请参阅 docs/adapters.md 中的“Write a pusher for your tool”。
- 让其他设备访问它。 在配置文件的
hosts.bind中添加地址(LAN 地址、VPN 网段或两者),为每个数据源创建一个 token(weatherdeck token new my-laptop),然后在手机上打开页面。一旦存在任意 token,推送请求就必须携带Authorization: Bearer <token>。对于电视,可在任何能访问主机的机器上全屏打开页面,或直接在主机上以 kiosk 模式运行。
配置文件位于 <data>/config.json,其中数据目录与步骤 2 相同(weatherdeck status 会打印该目录;--config FILE 或 $WEATHERDECK_CONFIG 可指定其他文件)。在你创建它之前,该文件不存在。最小配置如下:
{ "hosts": { "bind": ["localhost", "auto:192.168.1.0/24"] } }
编辑后重启主机(weatherdeck restart)。所有配置项均见 docs/hosting.md。
- 移除它。 使用
weatherdeck off停止主机,然后删除你解压或克隆的文件夹以及数据目录(weatherdeck status会显示该目录)。如果在 Windows 上执行过startup install,请先运行weatherdeck startup remove。不会安装其他内容:没有服务、没有注册表项、也不会在其他位置写入文件。
| Windows 11 | macOS(Apple Silicon) | Linux(Ubuntu、WSL2)
---|---|---|---
主机(weatherdeck run、on、ingest) | 支持 | 支持 | 支持
Python | 3.9 至 3.14(不支持 3.8) | 3.9 至 3.14(不支持 3.8) | 3.9 至 3.14(不支持 3.8)
GitHub 托管 Runner 上的测试套件(2026-10-16;453 项测试,.github/workflows/test.yml,手动运行) | Python 3.9 至 3.14 均通过。同日早些时候的首次运行中,每个 Windows 任务有 13 项测试失败(其中 9 项通过 Windows 拒绝执行的超长命令行启动 Node;其余为假定 Linux 机器、代码页解码以及 Windows 无法删除临时克隆目录的测试);修复后,第二次运行全部 18 个任务均通过 | Python 3.9 至 3.14 均通过 | Python 3.9 至 3.14 均通过
页面:Chrome、Edge | 支持 | 支持 | 支持
页面:Safari(macOS)、iPhone | 已于 2026-10-16 通过无头 WebKit(Playwright)检查;不是真实 Mac 或 iPhone 上的 Safari。在 1920 x 1080 和 390 x 844 下,除页面看板的海面面板在 1440 px 及以上宽度不绘制外(已知问题),其余与 Chromium 一致。维护者已于 2026-10-10 在 Safari、iPhone 和一台 4K 电视上检查并确认仪表盘景深场景;这些设备上的其他内容尚未检查(docs/device-checklist.md) | 同左 | 同左
页面:Firefox | 已于 2026-10-16 在 Linux 上通过无头 Firefox(Playwright)以 1920 x 1080 和 390 x 844 检查(窄窗口,不模拟手机):海面、页面看板及其折叠内容、Copy、密钥、预览和主题 hash、tv 视图及静态演示均与 Chromium 一致;但并非真实屏幕上的桌面 Firefox,且不会在每次发布时运行(docs/device-checklist.md) | 同左 | 同左
自上次查看以来(浏览器存储) | 按浏览器区分;阻止站点数据的浏览器不会显示“since”面板 | 同左 | 同左
读取的数据源架构 | 1.0 至 1.12 | 1.0 至 1.12 | 1.0 至 1.12
每台机器一艘船(0.4.0) | 电视:最多六艘船,之后显示船队;手机:船队条可在自身区域内滚动 | 同左 | 同左
开阔海面(0.4.1) | 电视(船甲板):没有待处理事项时,一条横幅线和海面会占据整个上部区域;已在 1920 x 1080 和 3840 x 2160 下检查 | 同左 | 同左
每台机器的版本(0.5.0) | 上报者行、watch 条、信任行和手机端 SOFTWARE 区域会显示每个数据源的适配器版本,或“version unknown”;仅会标记会改变含义的版本缺口 | 同左 | 同左
最后查看时间和重放密钥(0.4.1) | 按浏览器标签页区分(session storage);阻止它的标签页会以“not yet on this screen”开始 | 同左 | 同左
有意放慢(0.7.0) | 仅限文字(信任行、Crow's nest);除阅读外无需检查 | 同左 | 同左
托管运行是该测试套件首次在 macOS 和 Windows 镜像上运行;此前它已在 Linux、WSL2、维护者的一台 Windows 11 PC 和一台 Mac 上运行。托管 Windows 镜像是 Windows Server,而不是 Windows 11;该套件使用 Node 执行页面脚本测试。维护者自己的 Windows 11 PC 每天运行主机,这不是托管运行所覆盖的内容。
每个版本实际在哪些环境上运行,均记录在 CHANGELOG.md 中;其中只有人工才能完成的检查(真实 Safari、iPhone 和电视;目前仅仪表盘景深场景已获得确认,参见 docs/device-checklist.md)也会被明确列出。测试命令:python3 -m unittest discover -s tests(参见 CONTRIBUTING.md)。
- Safari、iPhone 和电视:仅仪表盘景深场景已于 2026-10-10 获得确认;这些设备上的其他内容均未检查(见上方支持表、docs/device-checklist.md)。
- Firefox 仅在 2026-10-16 通过无头模式检查,未在真实屏幕上检查,而且该检查是手动运行的,不会在每次发布时执行。
- 无头 WebKit 在宽度为 1440 px 及以上、列表分为两列或三列时,不会绘制页面看板的海面面板(包括它的图片和说明文字):它会占据空间,但保持空白。在 390 px 的单列布局下则会绘制,且不影响开阔海面。Chromium 和 Firefox 均可正常绘制。尚不清楚 Mac 上的 Safari 是否也存在同样问题(docs/device-checklist.md)。
English / 原文
Weatherdeck is a status board for machines and the work running on them (a TV or phone page fed by small pushers), not a weather app and not a monitoring or alerting system.
What you see. Every picture here is the demo (weatherdeck run --demo, with #theme=ship-deck on the page address). Its sources are invented and nothing in it is real.
- Waiting on you. The amber plate counts the calls that need a person and says how long each has waited.
- Set aside, not counted. A hold with a date on it, and a row that someone else owns, are not counted as waiting on you. On the phone page they sit under the calls in a folded line ("Deferred 2 · skipper's turn 3"); tapping it lists each with its date or its owner, and why.
- Honest progress. Progress shows as a percent range where the source gives one (for example 38-42%). A lane the board cannot read is counted as "can't tell" (the "+10 more" line says 1), not shown as fine.
- A quiet source is named. The lamp by the clock counts live sources. When one stops reporting it reads "2/3 live", and that machine's ship is drawn in fog and labelled silent.
- One board for TV and phone. The same page is the open sea on a wide screen and one column on a phone.
In the clip, Cinder (one of the invented sources) stops reporting. Still frame.
The phone page from a few minutes into the demo, cropped after the ALL FINE tile: the calls, a folded line for what is set aside, then the problems, then that tile, which is lit only when no call or problem is open and every feed reports.
The folded line opened. Deferred rows show the date they come back and the reason; the other rows show who owns them and since when. None of them is counted in "Needs you" above.
It is an at-a-glance board for work reported by many sources, meant to be left on a TV or a phone: what is waiting on you, what is moving and how far along it honestly is, what got done, what is next, and whether you can trust what you are looking at.
- Any tool can leave a card. One small JSON file in a drop directory becomes a status tile; the board only reads it (docs/ADDINS.md).
- Any tool can feed it. A source is anything that can send one JSON document over HTTP. Sources are discovered, never configured; machines and items appear on their own.
- Checkable. Every push a host receives is one line in its received log (
weatherdeck received --diff): what each source sent and what changed on the board. - Honest about gaps. A source that stops reporting stays on screen, marked silent and fogged. The board never shows stale data as fresh, and says so when a source is missing. It claims no value for itself or any tool until a number is measured (docs/honesty.md).
- Read-only, local, tiny. Python standard library only, one SQLite file, one plain HTML/JS/CSS page. No build step, no CDN, no telemetry, no root.
- Runs anywhere. The same command natively on Windows, macOS and Linux, no admin needed. Run several hosts at once; every page says which host serves it.
- Deterministic. No model or LLM call anywhere; the only outbound traffic is an adapter pushing to a host you name.
What this is not. It is not a monitoring or alerting system: it never pages anyone, and it shows only what sources push to it. It is not a hosted service: you run it yourself, on machines you choose. And it is pre-1.0 hobby software, open-sourced because it solved a problem the author had: details may change, and support is best effort.
You need Python 3.9 to 3.14 (an older one stops at startup with a one-line message; the Microsoft Store one is fine for trying it; to run it at logon or run the beat, see docs/runbook-windows.md). Nothing to install: run it from a source checkout or the release zip. Get the code by cloning this repository (git clone it, then cd into the folder), or by unzipping the zip that scripts/build-package builds from a clone. pip install is not supported yet and stops with a message saying so. Below, weatherdeck means python3 bin/weatherdeck on macOS/Linux and bin\weatherdeck.cmd on Windows (cmd or PowerShell).
- See it with synthetic data.
Open http://127.0.0.1:8787/. Three invented sources report; one stops reporting after about two and a half minutes, shows late from about 2:40 and silent about three minutes after start, so you can see the offline state. Ctrl-C stops it. (--port N to change the port.)
-
Run it for real.
weatherdeck on # background; prints the URLs weatherdeck status weatherdeck off
The data lives in your per-user data directory (--data DIR or $WEATHERDECK_DATA to choose another). On Windows, weatherdeck startup install also starts it at every logon, with no admin rights.
-
Send it something. Any tool, one POST (from the same machine, no setup needed):
curl -X POST http://127.0.0.1:8787/api/ingest -H 'Content-Type: application/json' -d '{ "schema": "lookout.feed", "schema_version": "1.0", "source": { "id": "my-laptop" }, "items": [{ "id": "build", "title": "Nightly build", "state": "running" }] }'
The schema id reads lookout.feed on purpose: it is the wire name every adapter already speaks, kept unchanged when the product was renamed (see docs/feed-spec.md, "Schema ids").
To feed it continuously, run the example adapter, which turns a hand-edited list plus this machine's vitals into a feed and pushes it to every host in a list:
cp examples/adapter/work.example.json work.json
cp examples/adapter/sinks.example.txt sinks.txt # edit the hosts
python3 examples/adapter/push_example.py --work work.json --sinks sinks.txt
To feed it from your own tool, see docs/adapters.md, "Write a pusher for your tool".
- Let other devices see it. Add addresses to
hosts.bindin your config file (a LAN address, a VPN range, or both), create a token per source (weatherdeck token new my-laptop), and open the page from your phone. Once any token exists, pushes needAuthorization: Bearer <token>. For a TV, open the page full-screen on any machine that can reach the host, or in kiosk mode on the host itself.
The config file is <data>/config.json, in the data directory from step 2 (weatherdeck status prints that directory; --config FILE or $WEATHERDECK_CONFIG names another file). It does not exist until you create it. A minimal one:
{ "hosts": { "bind": ["localhost", "auto:192.168.1.0/24"] } }
Restart the host after editing it (weatherdeck restart). Every key is in docs/hosting.md.
- Remove it. Stop the host with
weatherdeck off, then delete the folder you unpacked or cloned and the data directory (whereweatherdeck statussays it is). On Windows, runweatherdeck startup removefirst if you ranstartup install. Nothing else is installed: no service, no registry entry, no files elsewhere.
| Windows 11 | macOS (Apple Silicon) | Linux (Ubuntu, WSL2)
---|---|---|---
Host (weatherdeck run, on, ingest) | supported | supported | supported
Python | 3.9 to 3.14 (3.8 is not supported) | 3.9 to 3.14 (3.8 is not supported) | 3.9 to 3.14 (3.8 is not supported)
Test suite on GitHub's hosted runners (2026-10-16; 453 tests, .github/workflows/test.yml, run by hand) | passes on Python 3.9 to 3.14. The first run the same morning failed 13 tests on every Windows leg (nine started Node with a command line Windows refuses as too long; the rest were tests assuming a Linux machine, a code-page decode, and a scratch clone Windows would not delete); they were fixed and the second run passed all 18 jobs | passes on Python 3.9 to 3.14 | passes on Python 3.9 to 3.14
Page: Chrome, Edge | supported | supported | supported
Page: Safari (macOS), iPhone | headless WebKit (Playwright) checked on 2026-10-16; not a real Safari on a Mac or iPhone. At 1920 x 1080 and 390 x 844 it matched Chromium except that the page board's sea panel is not drawn at 1440 px and wider (Known issues). The dashboard depth scene was checked and signed off on Safari, iPhone and a 4K TV on 2026-10-10 by the maintainer, and nothing else on those devices has been (docs/device-checklist.md) | same | same
Page: Firefox | headless Firefox (Playwright, on Linux) checked on 2026-10-16 at 1920 x 1080 and 390 x 844 (a narrow window, no phone emulation): the sea, the page board and its folds, Copy, the key, the preview and theme hashes, the tv view and the static demo matched Chromium; not a desktop Firefox on a real screen, and not run each release (docs/device-checklist.md) | same | same
Since you last looked (browser storage) | per browser; a browser that blocks site data shows no since plate | same | same
Feed schema read | 1.0 to 1.12 | 1.0 to 1.12 | 1.0 to 1.12
One ship per machine (0.4.0) | TV: up to six ships, then a convoy; phone: the convoy strip scrolls inside itself | same | same
The open sea (0.4.1) | TV (ship deck): with nothing waiting, one banner line and the sea across the whole upper area; checked at 1920 x 1080 and 3840 x 2160 | same | same
Versions per machine (0.5.0) | reporter rows, the watch strip, the trust line and the phone's SOFTWARE section say each source's adapter, or "version unknown"; only a gap that changes meaning is flagged | same | same
Last seen and the replay key (0.4.1) | per browser tab (session storage); a tab that blocks it starts with "not yet on this screen" | same | same
Slowed on purpose (0.7.0) | words only (trust line, Crow's nest); nothing to check beyond reading them | same | same
The hosted runs are the first runs of the test suite on macOS and Windows images; before them it had been run on Linux and WSL2 and on one Windows 11 PC and one Mac by the maintainer. The hosted Windows image is Windows Server, not Windows 11, and the suite runs the page-script tests with Node; the maintainer's own Windows 11 PC runs the host day to day, which the hosted run does not cover.
What each release was actually run on is in CHANGELOG.md, with the checks only a person can make (a real Safari, iPhone and TV; only the dashboard depth scene has been signed off so far, see docs/device-checklist.md) listed as such. Tests: python3 -m unittest discover -s tests (see CONTRIBUTING.md).
-
Safari, iPhone and the TV: only the dashboard depth scene was signed off (2026-10-10); nothing else has been checked on those devices (the Support table above, docs/device-checklist.md).
-
Firefox has been checked headless only (2026-10-16), not on a real screen, and that check is run by hand, not each release.
-
Headless WebKit does not draw the page board's sea panel (its picture and captions) at 1440 px and wider, where the lists are in two or three columns: it takes its space but stays empty. At 390 px (one column) it is drawn, and the open sea is not affected. Chromium and Firefox draw it. Whether Safari on a Mac does the same is not known (docs/device-checklist.md).
-
A source that cuts a name before it sends it (with its own ellipsis) stays cut on the board: lane rows show the title as sent, and the TV log's single line cuts it at a whole word (docs/theme-spec.md, section 24).
-
A machine's lane count adds up only the homes that send one; a home that sends nothing for that machine is not in it, so the row can show fewer lanes than the machine runs, and its "N homes" counts only those that sent one (docs/feed-spec.md, "Whose turn, dated holds and lanes per machine").
-
The hosted Windows test runs use Windows Server, not Windows 11 (see the note under the Support table).
-
docs/honesty.md: the honesty contract on one page: what the board never does (green when silent, zero for unknown, a made-up event), where every number, creature and light comes from in the feed, the machine-alert debounce (two feeds to raise, two to clear, one keepalive of latency), and why no value number is shown until it is measured.
-
docs/ledger-spec.md: the tool value ledger: one append-only file per tool, unknown written as unknown with its reason, the honest verbs (surfaced, refused, placed, landed, not dispatched), and the reading rule that turns fourteen days of lines into KEEP, QUIET, CUT-CANDIDATE or UNMEASURED. No value number is shown until it is measured.
-
docs/feed-spec.md: the feed schema (1.12), how sources merge, the five lane classes, machine rest and strain, lane state (one word and one sentence per lane), goals (the goal each lane serves, with a count under it), allowance chips, black holes (no agent at the work, outside waits, queues, coming up, the shipping gap, freshness, burn rate), the library (one honest age and word per mirrored folder), the view at a glance (since you last looked, grouping by project), and what silence looks like.
-
CHANGELOG.md: what changed in each release, and what it was checked on; docs/device-checklist.md: what only a person can check on a real Mac, iPhone and TV.
-
docs/ADDINS.md: the card contract: one small JSON file per tool in a drop directory, shown as a tile with a stale mark. Nothing is run or imported.
-
docs/adapters.md: write a pusher for your tool: what to send, the sinks file, the honesty rules for adapters, and how to test one by recording and replaying the files it reads.
-
docs/hosting.md: the
weatherdeckcommand, binding and profiles, every config key, transports, pushing to several hosts. -
docs/runbook-windows.md and docs/runbook-macos.md: half a page each to run a host.
-
docs/runbook-feed-gap.md: a silent feed versus a machine that is down: the read-only checks in order (uptime, lingering, timers, the journal or cron log, the beat's age) for Linux, macOS and Windows, what each answer means, and whether
KillMode=processmatters for a pusher package. -
docs/beat.md: the machine beat (
bin/weatherdeck-beat): memory pressure, swap rate, run queue and disk per machine, its cost, and how it reaches the board. -
In the source repository:
scripts/build-packagebuilds the distributable zip (the product only; every entry carries the commit time of HEAD, orSOURCE_DATE_EPOCHwhen set, so the same commit built with the same Python and zlib on the same OS gives byte-identical zips andsha256sumis a real comparison there; across machines or OSes compare per-file content instead, in a scratch directory:unzip -q <zip> -d x && (cd x && find . -type f | LC_ALL=C sort | xargs shasum -a 256 | shasum -a 256), which works on Linux and macOS; file modes still differ on a Windows checkout; a build from a tree that is not a git checkout stamps 1980-01-01, so compare only builds of the same commit or of the same kind of tree),scripts/self-auditscans for secrets and names before a release,scripts/release-scanruns it and also scans the whole git history for names, e-mail addresses, home paths and tokens (see CONTRIBUTING.md). Packages that bundle an adapter for a specific tool are built from that adapter's own repository, not here. -
examples/: the synthetic demo feeds, a tiny generic adapter and an example host config (examples/host/).
Try it without installing
Open the static demo: a folder of plain files that shows the board with a recorded feed of invented sources, no server and no Python needed to look at it. It is built in the source repository, not from this package (which does not carry the build scripts): there, python3 scripts/build-static-demo writes dist/static-demo/; open dist/static-demo/index.html in a browser, or put that folder on any static host. A yellow bar, DEMO: recorded synthetic feed , stays on the screen and says nothing is live. The page replays three recorded frames in order, a slow step every 25 seconds, so the calls, lanes and weather change as they did in the recording (with reduced motion it holds one frame and offers a button for the next). To record the frames again, in the source repository, python3 scripts/record-demo-feed.
On a TV, a desk screen or a laptop (any window 700 CSS px or wider) the front door is the open sea (#/sea, or no route): the fleet on the water at full screen, one ship per machine with its name plate, the headline card for the calls on the left and the log along the bottom, on a 640 x 360 art-pixel stage. Each ship plate carries a quiet badge: how many asks wait on you from that machine, and how many of its lanes are off course or alerting. A ship opens its plan, a place opens its list. The Lists door beside the ? (and in a ship's plan bar) opens the page board (#/board, docs/theme-spec.md section 24): a header with the way back to the sea and the key, a three-state strip (needs you, needs attention, all fine), the lanes grouped under the goal they serve, else by project (a state word and icon, the job, one sentence, the worker's own notes behind a tap) and the sea with a caption for every picture. On a phone the page board is #/sea itself. The tv view never shows the page board: there the sea is the whole display. The list below describes the stage's parts (one column on a phone with the tv view).
-
Waiting on you (the one amber plate): decisions, approvals, capacity and machine problems, with where to act. A critical takes over the bar instead.
-
Trust: a lamp by the clock says how many sources are live and how old the newest report is; a silent source is named there, its machine reads SILENT and its work keeps its state with LAST KNOWN beside it.
-
Machines: a pip and a word each (OK, STRUGGLING judged against the machine's own norm, a low disk, ALERT, SILENT, LOST, or ASLEEP for a machine you list in
display.may_sleepthat went quiet during quiet hours), with vitals on the default board and the phone. A machine its owner declared RESERVED, under MAINTENANCE or DRAINING is shown calmly, with its reason and until when, and its silence is not an alarm. -
The log: off course first: work that needs action (failed, blocked, a call) and work running long, nothing else. Then the rest, calmer: under way, waiting (on a gate, a PR, a person, capacity or quiet hours, and until when, counted apart), no word, landed. Each row has a project chip, a plain title cut only at a whole word, one of six row words (Waiting on you, Stuck, Can't tell, Working, Waiting on someone else, Finished) and one sentence (never a raw status line or a task id; the full text is inside the opened row; see docs/theme-spec.md section 9.5) and an honest percent range , or its phase ("2 of 4") when the source knows the phase and not a percent; rows that do not fit fold into one "+N more" row. Its last row carries one chip per allowance account: provider, account, window, percent left and reset time, in a fixed order.
-
On the phone, below: waiting items, work under way, waiting, landed in the last 24 hours (or since your day start), up next, releases, allowance, machine vitals, sources and the last 12 hours.
-
Click in. Every plate is a door to its place, and every row in a place opens in full: the calls (each with the exact line to say in chat and a Copy button; the board never sends anything), the lanes with their steps and history, what is next, what landed, the machines with their stations and reporters, and the log of every push the host received. Each level is a URL (
#/ship/<machine>/deck/bridge), so Back, a shared link and a pinned TV work; a TV left on a deck or on the lists returns to the open sea after a minute. See docs/theme-spec.md section 16.
Quiet hours with nothing waiting show a dim resting screen on the TV; a lost host shows a plate that counts down to the next try.
Themes. The core is generic; each look is a folder under web/themes/ (theme.name in the config). default is plain slate with system faces. ship-deck draws the fleet as a ship at sea in hi-bit pixel art (machines are deck sections, work is the crew), with self-hosted OFL fonts. Each sailor stands at the station for its lane's stage, and a few creatures carry one piece of news each: a longboat for a landing, dolphins escorting the first one in ten minutes, gulls that leave a machine whose reporters go late, a whale for a release, slack sails for work gone quiet, and a lighthouse for the board's own host. Each is written to the Logbook. Opt-in sound (off by default) rings bells for a new call. See docs/theme-spec.md sections 16 and 17; weatherdeck run --demo --scenario sea-life plays every one in about three minutes.
Preview any state without touching data: add #controls=1 to the page URL and use the buttons (late, stale, lost, host down, empty, loading, night, anchor, sky, motion, theme). #night=1 forces the night palette, #theme=ship-deck previews a theme.
-
Binds only the addresses you list;
0.0.0.0and::are refused. Default: localhost only. -
No tokens: ingest from the local machine only. With tokens: per-source, and a token cannot speak for another source.
-
View profiles:
fullat/, atvview at/tv/for a screen the household can see (task titles, repo names and pull-request links, no free text about what a worker is doing), and a redactedpublicview at/public/(counts, group and machine names, percent only). Each has its own optional read token, and each listen address chooses which profiles it serves, so a TV on the LAN can be given thetvview only.weatherdeck privacy onturns thetvview into counts only untilweatherdeck privacy off. Redaction happens on the host, never only in the browser. -
Feed text is untrusted: the page sets it with
textContent, under a strict content security policy.bin/weatherdeck(.cmd) the command (launchers for src/) src/weatherdeck/ server, ingest, merge, history store, demo player web/ the page: index.html, theme.js, frontdoor.js, model.js, board.js, decks.js, page.js, sightings.js, livery.js, weather.js, world.js, app.js, style.css; themes/ examples/ demo feeds, a generic adapter, an example host config docs/ spec and hosting guide scripts/ self-audit, release-scan, merged-check, build-package, build-static-demo, record-demo-feed (source repo only)
Licence, contributing and support
MIT licensed, see LICENSE. The name is "Weatherdeck" (one word); the wire schema ids keep the earlier name (docs/feed-spec.md, "Schema ids").
- Contributing: CONTRIBUTING.md. Open an issue first for anything beyond a small fix.
- Questions and bugs: SUPPORT.md, through GitHub issues.
- Security reports: SECURITY.md, through GitHub's private vulnerability reporting, never a public issue.
- Conduct: CODE_OF_CONDUCT.md.



