Skip to content

Commit 7fe7201

Browse files
authored
Add script to open Claude and submit prompt
1 parent c50cc84 commit 7fe7201

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed

commands/apps/claude/claude.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env node
2+
3+
// Dependency: This script requires `chrome-cli` installed: https://github.com/prasmussen/chrome-cli
4+
// Install via homebrew: `brew install chrome-cli`
5+
6+
// Required parameters:
7+
// @raycast.schemaVersion 1
8+
// @raycast.title Prompt Claude
9+
// @raycast.mode silent
10+
// @raycast.packageName Claude
11+
12+
// Optional parameters:
13+
// @raycast.icon 🧠
14+
// @raycast.argument1 { "type": "text", "placeholder": "prompt"}
15+
16+
// Documentation:
17+
// @raycast.description Open Claude in Chrome browser and submit a prompt
18+
// @raycast.author Nimo Beeren
19+
// @raycast.authorURL https://github.com/nimobeeren
20+
21+
const { execSync } = require("child_process");
22+
23+
const prompt = process.argv[2];
24+
25+
process.env.OUTPUT_FORMAT = "json";
26+
27+
/** Escape a string so that it can be used in JavaScript code when wrapped in double quotes. */
28+
function escapeJsString(str) {
29+
return str.replaceAll(`\\`, `\\\\`).replaceAll(`"`, `\\"`);
30+
}
31+
32+
/** Escape a string so that it can be used in a shell command when wrapped in single quotes. */
33+
function escapeShellString(str) {
34+
return str.replaceAll(`'`, `'"'"'`);
35+
}
36+
37+
try {
38+
execSync("which chrome-cli");
39+
} catch {
40+
console.error(
41+
"chrome-cli is required to run this script (https://github.com/prasmussen/chrome-cli)"
42+
);
43+
process.exit(1);
44+
}
45+
46+
// Find the Claude tab if one is already open
47+
let tabs = JSON.parse(execSync("chrome-cli list tabs")).tabs;
48+
let claudeTab = tabs.find((tab) => tab.url.startsWith("https://claude.ai/"));
49+
50+
// If there is a Claude tab open, get its info. Otherwise, open Claude in a new
51+
// window.
52+
let claudeTabInfo;
53+
if (claudeTab) {
54+
// Open a new Claude session in the existing tab and focus it
55+
execSync(`chrome-cli open 'https://claude.ai/new' -t ${claudeTab.id}`);
56+
// Get tab info
57+
claudeTabInfo = JSON.parse(execSync(`chrome-cli info -t ${claudeTab.id}`));
58+
} else {
59+
// Open a Claude session in a new window, focus it and return the tab info
60+
claudeTabInfo = JSON.parse(
61+
execSync("chrome-cli open 'https://claude.ai/new' -n")
62+
);
63+
}
64+
65+
// Wait for the tab to be loaded, then execute the script
66+
let interval = setInterval(() => {
67+
if (claudeTabInfo.loading) {
68+
claudeTabInfo = JSON.parse(
69+
execSync(`chrome-cli info -t ${claudeTabInfo.id}`)
70+
);
71+
} else {
72+
clearInterval(interval);
73+
executeScript();
74+
}
75+
}, 100);
76+
77+
function executeScript() {
78+
const script = async function (prompt) {
79+
// Wait for prompt element to be on the page
80+
let promptElement;
81+
await new Promise((resolve) => {
82+
let interval = setInterval(() => {
83+
promptElement = document.querySelector(
84+
'[aria-label="Write your prompt to Claude"] > div'
85+
);
86+
if (promptElement) {
87+
clearInterval(interval);
88+
resolve();
89+
}
90+
}, 100);
91+
});
92+
93+
// Set the prompt
94+
const p = document.createElement("p");
95+
p.textContent = prompt;
96+
promptElement.replaceChildren(p);
97+
98+
// Wait for submit button to be on the page
99+
let submitButton;
100+
await new Promise((resolve) => {
101+
let interval = setInterval(() => {
102+
submitButton = document.querySelector('[aria-label="Send Message"]');
103+
if (submitButton) {
104+
clearInterval(interval);
105+
resolve();
106+
}
107+
}, 100);
108+
});
109+
110+
// Submit the prompt
111+
submitButton.click();
112+
};
113+
114+
const functionString = escapeShellString(script.toString());
115+
const promptString = escapeShellString(escapeJsString(prompt));
116+
117+
execSync(
118+
`chrome-cli execute '(${functionString})("${promptString}")' -t ${claudeTabInfo.id}`
119+
);
120+
}

0 commit comments

Comments
 (0)