Skip to content

Commit 334883e

Browse files
committed
feat(claude-code): install/update plugin + prompt for Hindsight connection
1 parent 4bed49f commit 334883e

31 files changed

Lines changed: 174 additions & 10434 deletions

src/cli.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,88 @@ async function main() {
908908
bankId = claudeConfig.bankId;
909909
apiToken = claudeConfig.apiToken;
910910
} else if (harness === "claude-code") {
911-
// Claude Code: just save content locally, Claude handles the rest via skill
911+
// Step 1: Ensure Claude Code CLI is available
912+
try {
913+
execSync("which claude", { stdio: "pipe" });
914+
} catch {
915+
p.cancel(
916+
"Claude Code CLI not found. Install it:\n npm install -g @anthropic-ai/claude-code"
917+
);
918+
process.exit(1);
919+
}
920+
921+
// Step 2: Ensure marketplace + plugin installed
922+
const MARKETPLACE_REPO = "vectorize-io/hindsight";
923+
const MARKETPLACE_NAME = "vectorize-io-hindsight";
924+
const PLUGIN_NAME = "hindsight-memory";
925+
926+
let hasMarketplace = false;
927+
try {
928+
const out = execSync("claude plugin marketplace list", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
929+
hasMarketplace = out.includes(MARKETPLACE_NAME) || out.includes(MARKETPLACE_REPO);
930+
} catch { /* ignore */ }
931+
932+
if (!hasMarketplace) {
933+
p.log.info("Adding Hindsight marketplace...");
934+
try {
935+
execSync(`claude plugin marketplace add ${MARKETPLACE_REPO}`, { stdio: "inherit" });
936+
p.log.success("Marketplace added");
937+
} catch (err: any) {
938+
const msg = err?.stderr?.toString?.()?.trim() || err?.message || String(err);
939+
if (!msg.includes("already")) {
940+
p.log.warn(`Failed to add marketplace: ${msg}`);
941+
}
942+
}
943+
}
944+
945+
let pluginInstalled = false;
946+
try {
947+
const out = execSync("claude plugin list", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
948+
pluginInstalled = out.includes(PLUGIN_NAME);
949+
} catch { /* ignore */ }
950+
951+
if (!pluginInstalled) {
952+
p.log.info("Installing hindsight-memory plugin...");
953+
try {
954+
execSync(`claude plugin install ${PLUGIN_NAME}@${MARKETPLACE_NAME}`, { stdio: "inherit" });
955+
p.log.success("Plugin installed");
956+
} catch (err: any) {
957+
const msg = err?.stderr?.toString?.()?.trim() || err?.message || String(err);
958+
p.log.warn(`Failed to install plugin: ${msg}`);
959+
}
960+
} else {
961+
// Update to latest
962+
p.log.info("Updating hindsight-memory plugin...");
963+
try {
964+
execSync(`claude plugin update ${PLUGIN_NAME}@${MARKETPLACE_NAME}`, { stdio: "pipe" });
965+
p.log.success("Plugin up to date");
966+
} catch { /* ignore */ }
967+
}
968+
969+
// Step 3: Configure Hindsight connection in ~/.hindsight/claude-code.json
970+
const ccConfigDir = join(homedir(), ".hindsight");
971+
const ccConfigPath = join(ccConfigDir, "claude-code.json");
972+
let ccConfig: Record<string, any> = {};
973+
if (existsSync(ccConfigPath)) {
974+
try { ccConfig = JSON.parse(readFileSync(ccConfigPath, "utf-8")); } catch { /* ignore */ }
975+
}
976+
977+
const hasConnection = ccConfig.hindsightApiUrl || ccConfig.llmProvider;
978+
if (!hasConnection && process.stdin.isTTY) {
979+
const claudeConfig = await promptClaudeConfig(agentId);
980+
ccConfig.hindsightApiUrl = claudeConfig.apiUrl;
981+
ccConfig.hindsightApiToken = claudeConfig.apiToken;
982+
ccConfig.enableKnowledgeTools = true;
983+
mkdirSync(ccConfigDir, { recursive: true });
984+
writeFileSync(ccConfigPath, JSON.stringify(ccConfig, null, 2) + "\n");
985+
p.log.success(`Hindsight connection saved to ${color.dim(ccConfigPath)}`);
986+
} else if (!ccConfig.enableKnowledgeTools) {
987+
ccConfig.enableKnowledgeTools = true;
988+
mkdirSync(ccConfigDir, { recursive: true });
989+
writeFileSync(ccConfigPath, JSON.stringify(ccConfig, null, 2) + "\n");
990+
}
991+
992+
// Step 4: Save content locally for the agent
912993
const contentDir = join(homedir(), ".self-driving-agents", "claude-code", agentId);
913994
mkdirSync(contentDir, { recursive: true });
914995
// Copy content files to the local dir

website/.gitignore

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
node_modules/
2-
dist/
3-
.astro/
2+
.next/
3+
out/
44
.env
55
.env.*
66
!.env.example
7+
*.tsbuildinfo
8+
next-env.d.ts

website/README.md

Lines changed: 0 additions & 56 deletions
This file was deleted.

website/astro.config.mjs

Lines changed: 0 additions & 15 deletions
This file was deleted.

website/next.config.mjs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/** @type {import('next').NextConfig} */
2+
3+
// Static export so the site can deploy to GitHub Pages, S3, Vercel, anywhere.
4+
// basePath is empty by default for `npm run dev` and Vercel; set
5+
// SITE_BASE=/self-driving-agents in CI for GitHub Pages.
6+
const SITE_BASE = process.env.SITE_BASE || '';
7+
8+
const nextConfig = {
9+
output: 'export',
10+
basePath: SITE_BASE || undefined,
11+
trailingSlash: true,
12+
images: {
13+
unoptimized: true,
14+
},
15+
env: {
16+
NEXT_PUBLIC_BASE_PATH: SITE_BASE,
17+
},
18+
};
19+
20+
export default nextConfig;

0 commit comments

Comments
 (0)