Skip to content

Commit cb2e1d3

Browse files
authored
refactor(bridges): collapse chat bridges into auto-discovered bridges/*.sh files (#77)
* refactor(bridges): collapse chat bridges into auto-discovered bridges/*.sh files Closes #76. Per-bridge logic was scattered across 4 files in 11 case statements totaling ~2,500 LOC: lib/chat-bridge.sh (install dispatcher), lib/chat-bridges.sh (registry + templates), upgrade.sh (per-bridge sync/systemd/launchd update), lib/summary.sh (per-bridge restart/verify hints). Adding a new bridge meant editing 3+ files and threading a new arm through every case. The runtimes/ layer already solved this same shape via runtimes/<name>.sh auto-discovery; bridges now adopt the same pattern. New layout: bridges/ ├── _dispatch.sh — auto-discover, bridge_load, bridge_call, │ bridge_has_hook, install_chat_bridge, │ BRIDGE_DETECTION_ORDER + shared helpers │ (_resolve_node_bin_dir, _compose_path_value, │ _merge_systemd_env_lines, _smart_update_systemd_unit, │ _ensure_systemd_path_contains, _plist_string_after_key) ├── kimaki.sh — install + sync_config + render_systemd/launchd ├── kimaki/ — kimaki-private assets (plugins, post-upgrade.sh, │ skills-kill-list.txt) — moved from repo root ├── cc-connect.sh └── telegram.sh Hook contract every bridge implements (see bridges/_dispatch.sh docblock for the full list): bridge_install, bridge_systemd_units, bridge_launchd_labels, bridge_binaries, bridge_display_name, bridge_display_title, bridge_render_systemd, bridge_render_launchd, bridge_sync_config, bridge_update_systemd, bridge_restart_cmd, bridge_verify_cmd, bridge_logs_cmd, bridge_start_hint, bridge_stop_hint, bridge_is_ready. Optional: bridge_update_launchd, bridge_vps_setup_block, bridge_launchd_setup_block, bridge_vps_start_preamble, bridge_verify_extra. Optional hooks are gated through bridge_has_hook so a bridge omits any prose block it doesn't need (cc-connect has no setup blocks because it has no token). Dispatch model: * bridge_load <name> sources bridges/<name>.sh into the current shell. Used after CHAT_BRIDGE is decided so install/sync hooks can mutate parent globals (KIMAKI_BIN, RESOLVED_KIMAKI_PLUGINS_DIR, UPDATED_ITEMS) the same way the legacy code did. * bridge_call <n> <hook> sources <n> in a SUBSHELL and invokes hook. Used for registry walks (detection, multi-bridge metadata queries) where parent state must not be clobbered. Detection priority is preserved via BRIDGE_DETECTION_ORDER constant in _dispatch.sh (kimaki > cc-connect > telegram), then alphabetical filesystem order for any future bridges added without updating the constant. Hosts that somehow have multiple bridges installed see the same tie-break behaviour as before. Consumers all simplified: * setup.sh sources bridges/_dispatch.sh and calls install_chat_bridge. No more 'lib chat-bridge' source line. * upgrade.sh phase 2 / phase 5 / phase 5a became 4-line wrappers that call bridge_sync_config / bridge_update_systemd / bridge_update_launchd on the loaded bridge. The 215-LOC _sync_kimaki_config body and the three _update_*_systemd functions moved into bridges/<name>.sh as bridge_sync_config / bridge_update_systemd. _smart_update_systemd_unit and friends moved to bridges/_dispatch.sh as shared helpers. * lib/summary.sh _print_*_setup_block case statements became bridge_<setup_block> hook calls; _print_launchd_run_block no longer takes a bridge arg (uses the loaded bridge's metadata directly). * upgrade.sh's _print_verify_block kimaki special case became an optional bridge_verify_extra hook. * runtimes/opencode.sh kimaki plugin paths repointed to $SCRIPT_DIR/bridges/kimaki/plugins/. Tests: * tests/bridge-render.sh rewritten as a golden-file regression suite. Renders every (bridge × unit / launchd-label) combo through the new bridge_render_* hooks and diffs against committed fixtures under tests/__snapshots__/bridges/. Pre-refactor it diffed legacy install function output against the new generators in lib/chat-bridges.sh; both files are gone, so the test is now snapshot-based with a --update flag for refreshing fixtures intentionally. The committed snapshots were captured by running the legacy bridge_render_* generators with deterministic env values, so this PR is provably byte-equivalent to main. * tests/path-helpers.sh source path updated (lib/chat-bridges.sh → bridges/_dispatch.sh). 11/11 assertions pass. * tests/post-upgrade-restore.sh path updated for the moved kimaki/post-upgrade.sh. Live-verified on intelligence-chubes4: ./upgrade.sh --dry-run --local output is byte-identical to main modulo timestamps and script paths. The 8 rendered template snapshots are byte-identical to legacy output. Net delta: ~1594 LOC deleted across the four legacy files; ~1830 LOC added across the four new bridges/ files. Roughly LOC-neutral but the shape is dramatically different — adding a new bridge is now 'drop a file in bridges/' (the promise the README already made for runtimes, now actually delivered for bridges). The kimaki-only --kimaki-only upgrade flag and --no-chat setup flag are unchanged; the README and skills/upgrade-wp-coding-agents/SKILL.md references to file paths got updated for the move. ## AI assistance - **AI assistance:** Yes - **Tool(s):** Claude Code (Sonnet 4.5) - **Used for:** Drafted the bridges/_dispatch.sh dispatcher, mechanically moved per-bridge functions out of lib/chat-bridge.sh / lib/chat-bridges.sh / upgrade.sh / lib/summary.sh into bridges/<name>.sh, rewrote tests/bridge-render.sh as a snapshot harness, and live-verified the byte-equivalence diff against main on intelligence-chubes4. Chris reviewed the dispatch model + hook contract and ran the smoke tests. * docs(upgrade): repoint stale _sync_kimaki_config comment at bridge_sync_config * fix(tests): sanitize PATH + KIMAKI_BIN in bridge-render harness The committed kimaki-systemd / kimaki-launchd snapshots were generated on my dev machine, where `command -v node` and the kimaki shim at /Users/chubes/.kimaki/bin/kimaki are reachable. `_resolve_node_bin_dir` correctly followed both, baking /Users/chubes/.kimaki/bin into the rendered Environment=PATH= line. CI runners (clean Linux, no kimaki shim, no node on PATH) rendered without that segment and failed the diff. Two-part fix: 1. tests/bridge-render.sh now exports PATH=/usr/bin:/bin at the top of the env-mock block, so `command -v node` and the shim-parsing fallback both miss on every machine. Snapshots become reproducible. 2. The two kimaki snapshots refreshed to drop the dev-machine path segment. Diff is purely the removal of /Users/chubes/.kimaki/bin from the PATH= line — no template logic changed. CI red on PR #77, fixed here.
1 parent 9126474 commit cb2e1d3

27 files changed

Lines changed: 2210 additions & 1781 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,10 @@ Local installs run as your current user — no root, no service user, no chown.
256256

257257
The default chat bridge for OpenCode. On VPS, wp-coding-agents installs post-upgrade hooks that:
258258

259-
- **Remove unwanted bundled skills** — Kimaki ships with skills for frameworks and tools that aren't relevant to WordPress agent workflows. The kill list (`kimaki/skills-kill-list.txt`) controls which skills are removed after each upgrade.
259+
- **Remove unwanted bundled skills** — Kimaki ships with skills for frameworks and tools that aren't relevant to WordPress agent workflows. The kill list (`bridges/kimaki/skills-kill-list.txt`) controls which skills are removed after each upgrade.
260260
- **Filter redundant context** — A plugin strips Kimaki's built-in memory injection and scheduling instructions from the agent context, since DM handles those concerns. Saves ~2,400 tokens per session.
261261

262-
To customize the kill list, edit `kimaki/skills-kill-list.txt` before running setup, or edit `/opt/kimaki-config/skills-kill-list.txt` on the server after install.
262+
To customize the kill list, edit `bridges/kimaki/skills-kill-list.txt` before running setup, or edit `/opt/kimaki-config/skills-kill-list.txt` on the server after install.
263263

264264
On local installs, Kimaki installs globally via npm but without a systemd service. Run it manually:
265265

0 commit comments

Comments
 (0)