@prismer/claude-code-plugin
Advanced tools
| #!/usr/bin/env node | ||
| /** | ||
| * Prismer Setup — Browser auto-login flow for Claude Code plugin | ||
| * | ||
| * 1. Starts localhost callback server | ||
| * 2. Opens browser to prismer.cloud/setup with callback URL | ||
| * 3. User signs in → key auto-created → redirected back | ||
| * 4. Saves key to ~/.prismer/config.toml | ||
| */ | ||
| import { createServer } from 'http'; | ||
| import { randomBytes } from 'crypto'; | ||
| import { readFileSync, writeFileSync, mkdirSync, chmodSync } from 'fs'; | ||
| import { join } from 'path'; | ||
| import { homedir } from 'os'; | ||
| import { execFileSync } from 'child_process'; | ||
| const CONFIG_DIR = join(homedir(), '.prismer'); | ||
| const CONFIG_FILE = join(CONFIG_DIR, 'config.toml'); | ||
| const BASE_URL = process.env.PRISMER_BASE_URL || 'https://prismer.cloud'; | ||
| const TIMEOUT_MS = 5 * 60 * 1000; | ||
| const force = process.argv.includes('--force'); | ||
| function readExistingKey() { | ||
| try { | ||
| const raw = readFileSync(CONFIG_FILE, 'utf-8'); | ||
| const m = raw.match(/^api_key\s*=\s*['"]([^'"]+)['"]/m); | ||
| return m?.[1] || ''; | ||
| } catch { return ''; } | ||
| } | ||
| function saveConfig(apiKey) { | ||
| mkdirSync(CONFIG_DIR, { recursive: true }); | ||
| writeFileSync(CONFIG_FILE, [ | ||
| '# Prismer Cloud configuration', | ||
| `# Generated by /prismer:prismer-setup on ${new Date().toISOString().slice(0, 10)}`, | ||
| '', '[default]', | ||
| `api_key = "${apiKey}"`, | ||
| `base_url = "${BASE_URL}"`, '', | ||
| ].join('\n')); | ||
| try { chmodSync(CONFIG_FILE, 0o600); } catch {} | ||
| } | ||
| function openBrowser(url) { | ||
| const cmds = { darwin: ['open'], linux: ['xdg-open'], win32: ['cmd', '/c', 'start', '""'] }; | ||
| const args = cmds[process.platform] || cmds.linux; | ||
| try { execFileSync(args[0], [...args.slice(1), url], { stdio: 'ignore' }); } catch {} | ||
| } | ||
| // Check existing | ||
| const existing = readExistingKey(); | ||
| if (!force && existing.startsWith('sk-prismer-')) { | ||
| console.log(`Already configured: ${existing.slice(0, 12)}...${existing.slice(-4)}`); | ||
| console.log('Run with --force to reconfigure.'); | ||
| process.exit(0); | ||
| } | ||
| // Start callback server | ||
| const state = randomBytes(16).toString('hex'); | ||
| let resolved = false; | ||
| const server = createServer((req, res) => { | ||
| const url = new URL(req.url, 'http://localhost'); | ||
| if (url.pathname !== '/callback') { res.writeHead(404); res.end(); return; } | ||
| const key = url.searchParams.get('key'); | ||
| const s = url.searchParams.get('state'); | ||
| if (!key || s !== state || !key.startsWith('sk-prismer-')) { | ||
| res.writeHead(400, { 'Content-Type': 'text/html' }); | ||
| res.end('<html><body style="font-family:system-ui;text-align:center;padding:60px"><h2>Setup failed</h2><p>Invalid parameters.</p></body></html>'); | ||
| return; | ||
| } | ||
| res.writeHead(200, { 'Content-Type': 'text/html' }); | ||
| res.end('<html><body style="font-family:system-ui;text-align:center;padding:60px"><h2>Done!</h2><p>API key received. You can close this tab.</p></body></html>'); | ||
| resolved = true; | ||
| saveConfig(key); | ||
| console.log(`API key saved: ${key.slice(0, 12)}...${key.slice(-4)}`); | ||
| console.log(`Config: ${CONFIG_FILE}`); | ||
| server.close(); | ||
| process.exit(0); | ||
| }); | ||
| server.listen(0, '127.0.0.1', () => { | ||
| const port = server.address().port; | ||
| const cb = encodeURIComponent(`http://127.0.0.1:${port}/callback`); | ||
| const setupUrl = `${BASE_URL}/setup?callback=${cb}&state=${state}&utm_source=claude-code-plugin&utm_medium=auto`; | ||
| console.log('Opening browser to sign in...'); | ||
| openBrowser(setupUrl); | ||
| console.log('Waiting for authentication...'); | ||
| console.log(`If browser didn't open: ${setupUrl}`); | ||
| setTimeout(() => { | ||
| if (!resolved) { | ||
| console.error('Timed out (5 min). Try /prismer:prismer-setup again.'); | ||
| server.close(); | ||
| process.exit(1); | ||
| } | ||
| }, TIMEOUT_MS); | ||
| }); |
| { | ||
| "name": "prismer", | ||
| "description": "Prismer Evolution — cross-agent learning network. Turns every coding session into shared knowledge: errors become strategies, successful fixes become recommendations for all agents.", | ||
| "version": "1.7.5", | ||
| "version": "1.7.6", | ||
| "author": { | ||
@@ -18,19 +18,3 @@ "name": "Prismer", | ||
| "hooks" | ||
| ], | ||
| "userConfig": { | ||
| "api_key": { | ||
| "title": "API Key", | ||
| "description": "Prismer API key (get one at https://prismer.cloud/setup). Optional — plugin works in read-only mode without a key.", | ||
| "type": "string", | ||
| "sensitive": true, | ||
| "required": false | ||
| }, | ||
| "base_url": { | ||
| "title": "Base URL", | ||
| "description": "Prismer API base URL (default: https://prismer.cloud)", | ||
| "type": "string", | ||
| "sensitive": false, | ||
| "required": false | ||
| } | ||
| } | ||
| ] | ||
| } |
+1
-5
@@ -5,9 +5,5 @@ { | ||
| "command": "npx", | ||
| "args": ["-y", "@prismer/mcp-server@latest"], | ||
| "env": { | ||
| "PRISMER_API_KEY": "${user_config.api_key}", | ||
| "PRISMER_BASE_URL": "${user_config.base_url}" | ||
| } | ||
| "args": ["-y", "@prismer/mcp-server@latest"] | ||
| } | ||
| } | ||
| } |
+1
-1
| { | ||
| "name": "@prismer/claude-code-plugin", | ||
| "version": "1.7.5", | ||
| "version": "1.7.6", | ||
| "description": "Prismer Evolution plugin for Claude Code — auto-learning from every coding session", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
| --- | ||
| name: prismer-setup | ||
| description: Set up Prismer API key — registers or connects your account with one command | ||
| description: Set up Prismer API key — opens browser, auto-registers, zero copy-paste | ||
| user-invocable: true | ||
| allowed-tools: Bash, Read, Write, AskUserQuestion | ||
| allowed-tools: Bash, AskUserQuestion | ||
| --- | ||
@@ -10,135 +10,28 @@ | ||
| Set up your Prismer API key for CLI commands, MCP tools, Claude Code plugin, and all SDKs. | ||
| ## Step 1: Check existing config | ||
| This is the same flow as `prismer setup` in the CLI — browser auto-login, key auto-received, zero copy-paste needed. | ||
| ## Flow | ||
| ### Step 1: Check if already configured | ||
| ```bash | ||
| # Check existing config | ||
| if [ -f ~/.prismer/config.toml ]; then | ||
| echo "Found existing config at ~/.prismer/config.toml" | ||
| grep "api_key" ~/.prismer/config.toml 2>/dev/null | head -1 | ||
| fi | ||
| # Check env | ||
| if [ -n "$PRISMER_API_KEY" ]; then | ||
| echo "PRISMER_API_KEY is set in environment" | ||
| fi | ||
| cat ~/.prismer/config.toml 2>/dev/null | grep api_key | head -1 || echo "No config found" | ||
| ``` | ||
| If an API key is already configured and valid, tell the user: | ||
| - "You're already set up! Key: sk-prismer-...xxxx" | ||
| - Offer to verify connectivity: `curl -s -H "Authorization: Bearer $KEY" https://prismer.cloud/api/version | head -1` | ||
| - If they want to reconfigure, proceed to Step 2 | ||
| If already configured and user doesn't want to reconfigure, stop here. | ||
| ### Step 2: Attempt auto-setup via CLI (preferred) | ||
| ## Step 2: Run auto-setup | ||
| Try the automatic browser-based flow first — this is the **recommended path**: | ||
| IMPORTANT: This command opens the browser and waits for the user to sign in. Set Bash timeout to 300000 (5 minutes): | ||
| ```bash | ||
| npx -y @prismer/sdk setup | ||
| node "${CLAUDE_PLUGIN_ROOT}/scripts/setup.mjs" --force | ||
| ``` | ||
| This will: | ||
| 1. Start a local server on a random port | ||
| 2. Open the browser to `https://prismer.cloud/setup?callback=http://127.0.0.1:PORT/callback&state=xxx` | ||
| 3. The user signs in (or is already signed in) → key auto-created → redirected back → key saved | ||
| The script: | ||
| 1. Starts a local callback server | ||
| 2. Opens the browser to prismer.cloud/setup | ||
| 3. User signs in or registers → key auto-created → redirected back to localhost | ||
| 4. Key saved to `~/.prismer/config.toml` | ||
| **If the CLI is not available or the auto flow fails**, fall back to Step 2B. | ||
| **Wait for it to complete.** It will print "API key saved" when done. | ||
| ### Step 2B: Manual fallback | ||
| ## Step 3: After setup | ||
| Open the browser manually: | ||
| ```bash | ||
| open "https://prismer.cloud/setup?utm_source=claude-code-plugin&utm_medium=setup" 2>/dev/null || \ | ||
| xdg-open "https://prismer.cloud/setup?utm_source=claude-code-plugin&utm_medium=setup" 2>/dev/null || \ | ||
| echo "Please open: https://prismer.cloud/setup" | ||
| ``` | ||
| Tell the user: "After signing in, copy the API key from the page and paste it here." | ||
| Wait for the user to paste the key (AskUserQuestion). | ||
| Validate format: must start with `sk-prismer-`. If invalid, ask again. | ||
| Save to config: | ||
| ```bash | ||
| mkdir -p ~/.prismer | ||
| cat > ~/.prismer/config.toml << EOF | ||
| # Prismer Cloud configuration | ||
| # Generated by /prismer-setup on $(date +%Y-%m-%d) | ||
| [default] | ||
| api_key = "THE_KEY_HERE" | ||
| base_url = "https://prismer.cloud" | ||
| EOF | ||
| chmod 600 ~/.prismer/config.toml | ||
| ``` | ||
| ### Step 3: Configure MCP server (if not already) | ||
| Check if `~/.claude/mcp_servers.json` has a `prismer` entry. If not, add it: | ||
| ```bash | ||
| # Check if prismer MCP is configured | ||
| if [ -f ~/.claude/mcp_servers.json ]; then | ||
| python3 -c "import json; d=json.load(open('$HOME/.claude/mcp_servers.json')); exit(0 if 'prismer' in d else 1)" 2>/dev/null | ||
| if [ $? -eq 0 ]; then | ||
| echo "MCP server already configured" | ||
| else | ||
| echo "Adding Prismer MCP server..." | ||
| fi | ||
| fi | ||
| ``` | ||
| If the MCP entry needs to be added or updated with the new key: | ||
| ```json | ||
| { | ||
| "prismer": { | ||
| "command": "npx", | ||
| "args": ["-y", "@prismer/mcp-server@latest"], | ||
| "env": { | ||
| "PRISMER_API_KEY": "THE_KEY_HERE" | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| Use `python3` or `node` to merge this into the existing `mcp_servers.json` without overwriting other entries. | ||
| ### Step 4: Verify everything works | ||
| ```bash | ||
| echo "Verifying setup..." | ||
| # Test API connectivity | ||
| RESP=$(curl -s -H "Authorization: Bearer THE_KEY_HERE" https://prismer.cloud/api/version) | ||
| echo "API: $RESP" | ||
| # Show summary | ||
| echo "" | ||
| echo "Setup complete!" | ||
| echo " Config: ~/.prismer/config.toml" | ||
| echo " MCP: ~/.claude/mcp_servers.json" | ||
| echo "" | ||
| echo "You now have access to:" | ||
| echo " - CLI: prismer load, prismer search, prismer evolve, ..." | ||
| echo " - MCP: 29 tools (evolution, memory, context, parse, skills)" | ||
| echo " - Plugin: /evolve-analyze, /evolve-record, cross-agent learning" | ||
| echo " - SDKs: @prismer/sdk (TS), prismer (Py), prismer-sdk-go, prismer-sdk (Rust)" | ||
| echo "" | ||
| echo "Restart Claude Code to activate MCP tools." | ||
| ``` | ||
| ## Important Notes | ||
| - **Prefer auto-flow**: Always try `npx -y @prismer/sdk setup` first — zero copy-paste, best UX. | ||
| - **Never display the full API key** in output after initial save. Show only `sk-prismer-...xxxx` (last 4 chars). | ||
| - **File permissions**: `~/.prismer/config.toml` must be `chmod 600` (owner-only read/write). | ||
| - **Existing config**: If config already exists, ask before overwriting. | ||
| - **API key format**: Must match `sk-prismer-*` pattern. Reject anything else. | ||
| - **MCP merge**: Never overwrite the entire `mcp_servers.json` — only add/update the `prismer` key. | ||
| - **Equivalent CLI command**: `prismer setup` does the same thing. Tell the user they can also use the CLI directly. | ||
| Tell the user: "Setup complete! Run `/reload-plugins` to activate MCP tools." |
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 8 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 8 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
31
3.33%1716
4.13%96212
-0.62%38
5.56%19
11.76%