# Copyright 2026 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 EAPI=8 inherit systemd DESCRIPTION="Web/desktop UI front-end for the OpenCode AI coding agent" HOMEPAGE="https://github.com/openchamber/openchamber" # The dist tarball is a self-contained @openchamber/web runtime: the pre-built # web UI plus packages/web's pruned *production* node_modules closure. It is # generated by files/openchamber-mkdist.sh (see that script for the why). The # only thing built here is the better-sqlite3 native addon, rebuilt from its # bundled sources against the user's net-libs/nodejs for ABI safety. SRC_URI="https://files.hossie.de/gentoo/distfiles/${P}-dist.tar.xz" S="${WORKDIR}/${P}" LICENSE="MIT" SLOT="0" KEYWORDS="~amd64" # net-libs/nodejs[ssl] provides node, npm (which bundles node-gyp) and the # headers/python node-gyp needs; the C/C++ toolchain is pulled implicitly. BDEPEND=">=net-libs/nodejs-22[ssl]" # opencode is the coding agent OpenChamber drives; it must be on PATH at runtime. RDEPEND=" >=net-libs/nodejs-22 dev-util/opencode-bin " # The dist tarball is a custom-repackaged blob hosted off-tree; keep it off # the Gentoo mirrors. RESTRICT="mirror" QA_PREBUILT="usr/lib/openchamber/*" src_compile() { # Point node-gyp at Gentoo's node headers so it never reaches the network. export npm_config_nodedir="${EPREFIX}/usr" local node_gyp="$(npm root -g)/npm/node_modules/node-gyp/bin/node-gyp.js" [[ -f ${node_gyp} ]] || die "could not locate node-gyp (net-libs/nodejs)" local bsq=( node_modules/.bun/better-sqlite3@*/node_modules/better-sqlite3 ) [[ -d ${bsq[0]} ]] || die "vendored better-sqlite3 not found" einfo "Rebuilding better-sqlite3 against ${EPREFIX}/usr nodejs" ( cd "${bsq[0]}" || die node "${node_gyp}" rebuild || die "better-sqlite3 native build failed" [[ -f build/Release/better_sqlite3.node ]] || die "better_sqlite3.node missing" ) || die } src_install() { local dest="/usr/lib/${PN}" # We KEYWORD ~amd64: drop native binaries for other arches that the bun # store ships. node-pty keeps only its linux-x64 N-API prebuild; bun-pty's # Rust libs are only used under Bun (we run plain node) so they all go. local f for f in node_modules/.bun/node-pty@*/node_modules/node-pty/prebuilds/*; do [[ ${f} == *linux-x64 ]] || rm -rf "${f}" || die done rm -rf node_modules/.bun/bun-pty@*/node_modules/bun-pty/rust-pty/target || die # Pruning node_modules to the production closure leaves the bun hoist full # of symlinks to dev-only deps that were removed. They are never required # at runtime; drop the dangling ones so they don't trip QA or tooling. find node_modules packages -xtype l -delete || die # Preserve the bun symlink farm verbatim: relative symlinks under # packages/web/node_modules resolve up into node_modules/.bun, so the whole # tree must land together with its structure intact. dodir "${dest}" cp -a node_modules packages "${ED}${dest}/" || die "install tree failed" dosym -r "${dest}/packages/web/bin/cli.js" /usr/bin/openchamber fperms 0755 "${dest}/packages/web/bin/cli.js" # Per-user daemon: the agent works on the invoking user's projects and # credentials, so it runs in their session, not as a system service. systemd_douserunit "${FILESDIR}"/openchamber.service } pkg_postinst() { elog "OpenChamber is a UI for the OpenCode AI coding agent (the 'opencode'" elog "CLI, pulled in via dev-util/opencode-bin)." elog elog "Start the server with: openchamber serve" elog "By default it binds 127.0.0.1:3000 with no auth -- pass --ui-password" elog "or OPENCHAMBER_UI_PASSWORD before exposing it." elog elog "A systemd *user* unit is installed (run it in your own session, not" elog "as root -- the agent needs your projects, ssh keys and opencode auth):" elog " systemctl --user daemon-reload" elog " systemctl --user enable --now openchamber.service" elog "Put optional settings (OPENCHAMBER_UI_PASSWORD, OPENCODE_HOST, ...) in" elog " ~/.config/openchamber/env" elog elog "Optional features: the tunnel command needs net-misc/cloudflared" elog "(also not in Gentoo)." elog elog "Do NOT use 'openchamber update' -- this package is managed by Portage." elog "Upgrade via emerge instead." }