Files
claude-remote/paste.mjs
2026-03-18 22:30:22 +00:00

50 lines
1.7 KiB
JavaScript

import { execFileSync, spawn } from 'child_process';
import { setTimeout as sleep } from 'timers/promises';
import { find_claude_window } from './find-window.mjs';
export async function copy_to_clipboard(text) {
await new Promise((resolve, reject) => {
const proc = spawn('xclip', ['-selection', 'clipboard'], { stdio: ['pipe', 'ignore', 'ignore'] });
proc.on('error', reject);
proc.on('close', code => code === 0 ? resolve() : reject(new Error(`xclip exited ${code}`)));
proc.stdin.write(text);
proc.stdin.end();
});
}
export function focus_window(window_id) {
execFileSync('xdotool', ['windowactivate', '--sync', window_id]);
}
export async function paste_to_window(window_id, { submit = true } = {}) {
execFileSync('xdotool', ['windowactivate', '--sync', window_id]);
execFileSync('xdotool', ['key', '--window', window_id, 'shift+Insert']);
if (submit) {
await sleep(200);
execFileSync('xdotool', ['key', '--window', window_id, 'Return']);
}
}
function normalise_window_id(raw) {
// Accept decimal (25165857) or hex (0x1800021) — always return 0x hex string
const n = raw.startsWith('0x') ? parseInt(raw, 16) : parseInt(raw, 10);
return '0x' + n.toString(16);
}
export async function send_to_claude(text, options = {}) {
const window_id = options.window_id
? normalise_window_id(String(options.window_id))
: find_claude_window({ debug: options.debug });
if (!window_id) {
throw new Error('Could not find Claude Code window');
}
console.error(`[send] using window ${window_id}`);
if (options.focus_only) {
focus_window(window_id);
return window_id;
}
await copy_to_clipboard(text);
await paste_to_window(window_id, options);
return window_id;
}