Lines 1-30typescript
1#!/usr/bin/env -S node --import tsx
2// joy — CLI for the joy-tmux daemon. Mirrors happy-cli's surface (start/stop/
3// restart/status/list/doctor/install/auth/notify) but drives the joy-tmux
4// daemon over its localhost HTTP API. The daemon writes ~/.happy/joy-tmux-state/
5// daemon.json (token+pid+port) on startup, which is how this CLI finds and
8import { existsSync, readFileSync, writeFileSync, mkdirSync, openSync, rmSync } from "fs";
9import { join, dirname, resolve, basename, sep } from "path";
10import { homedir, platform as osPlatform } from "os";
11import { spawn, spawnSync } from "child_process";
12import { moduleDir } from "./esm";
13import { happyHomeDir, joyStateDir } from "./paths";
15const PORT = parseInt(process.env.PORT ?? "4997");
16const BASE = `http://127.0.0.1:${PORT}`;
17const HAPPY_HOME = happyHomeDir();
HighSame File Env Network Execution
A single source file combines environment access, network access, and code or shell execution; review context before blocking.
src/cli.tsView on unpkg · L10 18const STATE_DIR = joyStateDir();
MediumInstall Persistence
Source writes installer persistence such as shell profile or service configuration.
src/cli.tsView on unpkg · L10 19const STATE_FILE = join(STATE_DIR, "daemon.json");
20const LOG_FILE = join(STATE_DIR, "daemon.log");
21// pnpm global installs resolve import.meta.url into pnpm's versioned content-addressed
22// store (…/.pnpm/@fny+joy-tmux@1.0.15_…/node_modules/@fny/joy-tmux). Baking THAT into a
23// launchd/systemd service breaks on the next `pnpm add -g`: pnpm makes a fresh store dir
24// for the new version and deletes the old one, so the service's server.ts path vanishes
HighRuntime Package Install
Package source invokes a package manager install command at runtime.
src/cli.tsView on unpkg · L10 25// and the daemon crash-loops. Collapse it to pnpm's stable top-level node_modules symlink
26// (always repointed at the current version). No-op for source checkouts / npm-global,
27// which have no .pnpm segment. (NODE = process.execPath is already a stable, canonical
28// version-install path — verified — so it needs no such treatment.)
29const PKG_DIR = moduleDir(import.meta.url).replace(/\/\.pnpm\/[^/]+\/node_modules\//, "/node_modules/");
30const SERVER_TS = join(PKG_DIR, "server.ts");