registry  /  @fny/joy-tmux  /  1.10.0

@fny/joy-tmux@1.10.0

joy-tmux daemon + CLI — run Claude Code sessions in tmux, bridged to the joy/Happy relay.

AI Security Review

scanned 2h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. No confirmed malicious attack surface; the package is an explicit CLI/daemon for running Claude Code sessions in tmux with relay-controlled operations. It does expose powerful remote session operations when the user starts/authenticates the daemon.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
User runs joy start, joy install, or creates/controls sessions via the CLI/app.
Impact
User-approved remote agent control can execute shell commands and edit files inside session workspaces; no evidence of covert exfiltration or unconsented install-time mutation.
Mechanism
Authenticated local daemon plus encrypted relay RPCs for tmux/Claude session control
Rationale
Static inspection shows a powerful but package-aligned tmux/Claude daemon with explicit service installation and authenticated relay RPCs, not covert lifecycle execution or malicious credential/file exfiltration. The residual risk is dangerous user-invoked agent capability and first-party hook/service setup, so warn rather than block.
Evidence
package.jsonbin/joy.mjssrc/cli.tssrc/server.tssrc/relay/relay.tssrc/domain/operations.tssrc/domain/fileOps.tssrc/claude/hooks.tssrc/paths.ts~/.happy/access.key~/.happy/settings.json~/.happy/joy-tmux-state/daemon.json~/.happy/joy-tmux-state/daemon.log~/.config/systemd/user/joy-tmux.service~/Library/LaunchAgents/vip.voltai.joy-tmux.plist~/.happy/joy-tmux-state/joy-hook.mjs~/.happy/joy-tmux-state/claude-settings.json
Network endpoints3
api.cluster-fluster.comexp.host/--/api/v2/push/send127.0.0.1:4997

Decision evidence

public snapshot
AI called this Suspicious at 82.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • src/domain/fileOps.ts exposes relay/HTTP session bash and writeFile handlers within session cwd.
  • src/relay/relay.ts connects to https://api.cluster-fluster.com using ~/.happy access.key bearer credentials.
  • src/cli.ts has explicit joy install/update commands that write systemd/launchd user services and run pnpm add -g.
  • src/claude/hooks.ts writes a package-owned Claude settings file and hook script under joy state dir.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle hooks.
  • bin/joy.mjs only registers tsx and imports src/cli.ts; no hidden install-time behavior.
  • Service setup is only activated by explicit joy install, not npm installation or import.
  • Network traffic is package-aligned relay/push functionality and uses local daemon auth for localhost API.
  • File/shell RPCs are scoped to user-created sessions and path validation limits file ops to session cwd or per-session media dir.
  • No credential harvesting beyond reading the documented Happy/Joy credentials needed for relay auth.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNetworkShellWebSocket
Supply chain
HighEntropyStringsUrlStrings
Manifest
NoLicense
scanned 41 file(s), 580 KB of source, external domains: 0.0.0.0, 127.0.0.1, api.cluster-fluster.com, claude.com, console.anthropic.com, d-9267d2a99a.awsapps.com, example.com, exp.host, github.com, www.apple.com

Source & flagged code

7 flagged · loading source
src/cli.tsView file
10import { homedir, platform as osPlatform } from "os"; L11: import { spawn, spawnSync } from "child_process"; L12: import { moduleDir } from "./esm";
High
Child Process

Package source references child process execution.

src/cli.tsView on unpkg · L10
10import { homedir, platform as osPlatform } from "os"; L11: import { spawn, spawnSync } from "child_process"; L12: import { moduleDir } from "./esm"; ... L14: L15: const PORT = parseInt(process.env.PORT ?? "4997"); L16: const BASE = `http://127.0.0.1:${PORT}`; L17: const HAPPY_HOME = happyHomeDir();
High
Same 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
10import { homedir, platform as osPlatform } from "os"; L11: import { spawn, spawnSync } from "child_process"; L12: import { moduleDir } from "./esm"; ... L22: // store (…/.pnpm/@fny+joy-tmux@1.0.15_…/node_modules/@fny/joy-tmux). Baking THAT into a L23: // launchd/systemd service breaks on the next `pnpm add -g`: pnpm makes a fresh store dir L24: // for the new version and deletes the old one, so the service's server.ts path vanishes
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

src/cli.tsView on unpkg · L10
10import { homedir, platform as osPlatform } from "os"; L11: import { spawn, spawnSync } from "child_process"; L12: import { moduleDir } from "./esm"; ... L14: L15: const PORT = parseInt(process.env.PORT ?? "4997"); L16: const BASE = `http://127.0.0.1:${PORT}`; L17: const HAPPY_HOME = happyHomeDir(); L18: const STATE_DIR = joyStateDir(); ... L47: function readState(): DaemonState | null { L48: try { return JSON.parse(readFileSync(STATE_FILE, "utf8")) as DaemonState; } catch { return null; } L49: } ... L61: headers: authHeaders(),
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

src/cli.tsView on unpkg · L10
src/domain/operations.tsView file
48// like `--import tsx` + the script path) so the replacement runs the same way. L49: const argv = [process.execPath, ...process.execArgv, ...process.argv.slice(1)]; L50: const cmd = argv.map(a => `'${a.replace(/'/g, "'\\''")}'`).join(" ");
High
Shell

Package source references shell execution.

src/domain/operations.tsView on unpkg · L48
bin/joy.mjsView file
15L16: await import(new URL('../src/cli.ts', import.meta.url).href);
Medium
Dynamic Require

Package source references dynamic require/import behavior.

bin/joy.mjsView on unpkg · L15
src/relay/relay.tsView file
matchType = previous_version_dangerous_delta matchedPackage = @fny/joy-tmux@1.8.0 matchedIdentity = npm:QGZueS9qb3ktdG11eA:1.8.0 similarity = 0.927 summary = stored previous version shares package body but lacks this dangerous source file
Critical
Previous Version Dangerous Delta

This package version adds a dangerous source file absent from the previous stored version; route for source-aware review.

src/relay/relay.tsView on unpkg

Findings

1 Critical4 High5 Medium5 Low
CriticalPrevious Version Dangerous Deltasrc/relay/relay.ts
HighChild Processsrc/cli.ts
HighShellsrc/domain/operations.ts
HighSame File Env Network Executionsrc/cli.ts
HighRuntime Package Installsrc/cli.ts
MediumDynamic Requirebin/joy.mjs
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencesrc/cli.ts
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License