50 lines
1.7 KiB
JavaScript
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.js';
|
|
|
|
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;
|
|
}
|