feat: add spawn feedback subcommand (#2585)

* feat: add `spawn feedback` subcommand

Sends anonymous feedback to the Spawn team via PostHog survey API.
Usage: spawn feedback "your message here"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: update feedback survey ID and response key

Use the correct PostHog survey ID and $survey_response property.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use asyncTryCatch instead of try/catch in feedback command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
A 2026-03-13 10:19:37 -07:00 committed by GitHub
parent d1bbd6cac9
commit 8f02646b4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 61 additions and 1 deletions

View file

@ -1,6 +1,6 @@
{
"name": "@openrouter/spawn",
"version": "0.17.9",
"version": "0.17.10",
"type": "module",
"bin": {
"spawn": "cli.js"

View file

@ -0,0 +1,50 @@
import pc from "picocolors";
import { asyncTryCatch } from "../shared/result.js";
const POSTHOG_TOKEN = "phc_7ToS2jDeWBlMu4n2JoNzoA1FnArdKwFMFoHVnAqQ6O1";
const POSTHOG_URL = "https://us.i.posthog.com/i/v0/e/";
const SURVEY_ID = "019ce7ef-c3e7-0000-415b-729f190e09bc";
export async function cmdFeedback(args: string[]): Promise<void> {
const message = args.join(" ").trim();
if (!message) {
console.error(pc.red("Error: Please provide your feedback message."));
console.error(`\nUsage: ${pc.cyan('spawn feedback "your feedback here"')}`);
process.exit(1);
}
const body = {
token: POSTHOG_TOKEN,
distinct_id: "anon",
event: "survey sent",
properties: {
$survey_id: SURVEY_ID,
$survey_response: message,
$survey_completed: true,
source: "cli",
},
};
const result = await asyncTryCatch(async () => {
const res = await fetch(POSTHOG_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(10_000),
});
if (!res.ok) {
throw new Error(`PostHog returned ${String(res.status)}`);
}
});
if (!result.ok) {
console.error(pc.red("Failed to send feedback. Please try again later."));
process.exit(1);
}
console.log(pc.green("Thanks for your feedback!"));
}

View file

@ -39,6 +39,7 @@ function getHelpUsageSection(): string {
spawn matrix Full availability matrix (alias: m)
spawn agents List all agents with descriptions
spawn clouds List all cloud providers
spawn feedback "message" Send feedback to the Spawn team
spawn update Check for CLI updates
spawn version Show version (or --version, -v)
spawn help Show this help message (or --help, -h)`;

View file

@ -2,6 +2,8 @@
// delete.ts — cmdDelete
export { cmdDelete } from "./delete.js";
// feedback.ts — cmdFeedback
export { cmdFeedback } from "./feedback.js";
// help.ts — cmdHelp
export { cmdHelp } from "./help.js";
// info.ts — cmdMatrix, cmdAgents, cmdClouds, cmdAgentInfo, cmdCloudInfo

View file

@ -9,6 +9,7 @@ import {
cmdCloudInfo,
cmdClouds,
cmdDelete,
cmdFeedback,
cmdHelp,
cmdInteractive,
cmdLast,
@ -737,6 +738,12 @@ async function main(): Promise<void> {
return;
}
// ── `spawn feedback` — bypass flag parsing; rest of args are the message ───
if (rawArgs[0] === "feedback") {
await cmdFeedback(rawArgs.slice(1));
return;
}
const args = expandEqualsFlags(rawArgs);
await checkForUpdates();