Rename .js to .mjs and update import paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-18 22:30:22 +00:00
parent 835e446f7d
commit 1b66e499ad
5 changed files with 3 additions and 3 deletions

161
find-window.mjs Normal file
View File

@@ -0,0 +1,161 @@
import { readFileSync, readdirSync, readlinkSync } from 'fs';
import { execFileSync } from 'child_process';
function read_file(path) {
try {
return readFileSync(path, 'utf8');
} catch {
return null;
}
}
function get_exe(pid) {
try {
return readlinkSync(`/proc/${pid}/exe`);
} catch {
return null;
}
}
function get_cmdline(pid) {
const raw = read_file(`/proc/${pid}/cmdline`);
if (!raw) {
return null;
}
return raw.replace(/\0/g, ' ').trim();
}
function get_ppid(pid) {
const status = read_file(`/proc/${pid}/status`);
if (!status) {
return null;
}
const match = status.match(/^PPid:\s+(\d+)/m);
return match ? parseInt(match[1]) : null;
}
//const DOCKER_COMM_PATTERN = /^docker-compose$/;
const CLAUDE_CMDLINE_SIGNATURE = 'claude --dangerously-skip-permissions';
const DOCKER_COMM_PATTERN = /^docker-compose$/;
function get_comm(pid) {
return read_file(`/proc/${pid}/comm`)?.trim() ?? null;
}
export function list_docker_pids() {
const results = [];
for (const entry of readdirSync('/proc')) {
if (!/^\d+$/.test(entry)) {
continue;
}
const comm = get_comm(entry);
if (!comm || !DOCKER_COMM_PATTERN.test(comm)) {
continue;
}
const cmdline = get_cmdline(entry);
if (cmdline && cmdline.includes(CLAUDE_CMDLINE_SIGNATURE)) {
results.push({ pid: entry, comm, cmdline });
}
}
return results;
}
export function walk_to_konsole(pid) {
let current = String(pid);
const visited = new Set();
const chain = [];
while (current && current !== '0' && !visited.has(current)) {
visited.add(current);
const exe = get_exe(current);
chain.push({ pid: current, exe });
if (exe === '/usr/bin/konsole') {
return { konsole_pid: current, chain };
}
current = String(get_ppid(current));
}
return { konsole_pid: null, chain };
}
function get_net_client_list() {
try {
const out = execFileSync('xprop', ['-root', '_NET_CLIENT_LIST'], { encoding: 'utf8' });
// Format: _NET_CLIENT_LIST(WINDOW): window id # 0x..., 0x..., ...
const match = out.match(/window id # (.+)/);
if (!match) {
return [];
}
return match[1].split(',').map(s => parseInt(s.trim(), 16)).filter(Boolean);
} catch {
return [];
}
}
function get_window_pid(window_id) {
try {
const hex = '0x' + window_id.toString(16);
const out = execFileSync('xprop', ['-id', hex, '_NET_WM_PID'], { encoding: 'utf8' });
const match = out.match(/= (\d+)/);
return match ? parseInt(match[1]) : null;
} catch {
return null;
}
}
export function window_id_for_pid(pid) {
const target_pid = parseInt(pid);
for (const wid of get_net_client_list()) {
if (get_window_pid(wid) === target_pid) {
return '0x' + wid.toString(16);
}
}
return null;
}
export function find_claude_window_by_process_tree({ debug = false } = {}) {
const docker_pids = list_docker_pids();
if (debug) {
console.error(`[find-window] docker pids (${docker_pids.length}):`);
for (const { pid, comm, cmdline } of docker_pids) {
console.error(` pid=${pid} comm=${comm} cmdline=${cmdline}`);
}
}
for (const { pid } of docker_pids) {
const { konsole_pid, chain } = walk_to_konsole(pid);
if (debug) {
const chain_str = chain.map(e => `${e.pid}(${e.exe?.split('/').pop() ?? '?'})`).join(' → ');
console.error(`[find-window] pid=${pid} chain: ${chain_str}`);
}
if (!konsole_pid) {
continue;
}
if (debug) {
console.error(`[find-window] found konsole pid=${konsole_pid}, looking up window...`);
}
const window_id = window_id_for_pid(konsole_pid);
if (debug) {
console.error(`[find-window] window id: ${window_id ?? 'not found'}`);
}
if (window_id) {
return window_id;
}
}
return null;
}
export function find_claude_window_by_title(title = 'claude-docker') {
try {
const result = execFileSync(
'xdotool', ['search', '--name', title],
{ encoding: 'utf8' }
);
const ids = result.trim().split('\n').filter(Boolean);
return ids[0] ?? null;
} catch {
return null;
}
}
export function find_claude_window({ debug = false } = {}) {
return find_claude_window_by_process_tree({ debug }) ?? find_claude_window_by_title();
}