Skip to content

Add ai setup command to configure openrouter key#126

Merged
Fermionic-Lyu merged 3 commits into
mainfrom
add-ai-setup-command
May 13, 2026
Merged

Add ai setup command to configure openrouter key#126
Fermionic-Lyu merged 3 commits into
mainfrom
add-ai-setup-command

Conversation

@Fermionic-Lyu
Copy link
Copy Markdown
Contributor

@Fermionic-Lyu Fermionic-Lyu commented May 13, 2026


Summary by cubic

Adds ai setup to @insforge/cli to configure the InsForge Model Gateway by fetching the project’s OpenRouter key and writing OPENROUTER_API_KEY to an env file with safe defaults. Bumps the CLI to 0.1.78.

  • New Features

    • npx @insforge/cli ai setup writes OPENROUTER_API_KEY (defaults to .env.local).
    • Supports --env-file <path> and --json.
    • Adds .env*.local to .gitignore only for local env files inside the project.
    • Does not overwrite a different existing key; reports mismatches.
    • JSON output returns only maskedKey; the raw key is never returned.
  • Bug Fixes

    • Clear, AI-specific 404 when the backend lacks Model Gateway support.
    • Clear error if the backend returns a missing or whitespace-only key.

Written for commit 922d7ef. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added ai command with setup subcommand to fetch and store an OpenRouter API key (supports custom env file and JSON output)
  • Documentation

    • README updated with AI command usage, setup workflow, env-file options, and secure deployment guidance
  • Behavior

    • Improved error messaging when AI-related backend routes are unavailable
  • Tests

    • Added tests covering setup flow, key retrieval, env-file handling, and ignore-file updates
  • Chores

    • Version bumped to 0.1.78

Review Change Stack

Note

Add ai setup command to fetch and write OpenRouter API key to an env file

  • Adds a new ai setup CLI subcommand that fetches the project's OPENROUTER_API_KEY from the backend via getOpenRouterApiKey and writes it to an env file (default .env.local) using upsertEnvFile.
  • Skips overwriting if an existing key differs, and reports mismatched keys without exposing the raw value.
  • Automatically appends .env*.local to .gitignore when the target file is a local env file inside the project and no equivalent ignore rule exists.
  • Supports --env-file to target a custom env file and --json for machine-readable output; the JSON result includes a maskedKey but never the raw key.

Changes since #126 opened

  • Added ai setup command to configure openrouter API key [922d7ef]
  • Bumped package version from 0.1.77 to 0.1.78 [922d7ef]
  • Modified .gitignore update logic for non-default local environment files [e3e580e]
  • Added whitespace trimming and validation for OpenRouter API keys [e3e580e]
  • Added AI-specific error messaging for route-level 404 responses [e3e580e]
  • Added interactive progress spinner during OpenRouter API key fetching [e3e580e]
  • Removed description setting for top-level AI command [e3e580e]

Macroscope summarized 3c0fa38.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Walkthrough

Adds insforge ai setup: fetches a linked project's OpenRouter API key, upserts it into a target env file (default .env.local), optionally appends local env ignore entries to .gitignore, records analytics, and includes tests and README documentation.

Changes

AI Setup Feature

Layer / File(s) Summary
OpenRouter API Key Retrieval
src/lib/api/ai.ts, src/lib/api/ai.test.ts
Adds OpenRouterKeyResponse and getOpenRouterApiKey() to fetch and validate OpenRouter keys from /api/ai/openrouter/api-key, trimming and erroring with CLIError on invalid responses.
ossFetch AI 404 handling & tests
src/lib/api/oss.ts, src/lib/api/oss.test.ts
Special-cases 404s for /api/ai* in ossFetch with an upgrade guidance message and adds test coverage asserting the message when Model Gateway routes are missing.
AI Setup Subcommand Implementation
src/commands/ai/setup.ts, src/commands/ai/setup.test.ts
Registers ai setup with --env-file/--json; implements runAiSetup to validate linkage, fetch the OpenRouter key, upsert OPENROUTER_API_KEY into the chosen env file, update .gitignore for local env filenames, emit analytics, and return AiSetupResult. Tests cover env writing, masking, non-overwrite/mismatch handling, and .gitignore logic.
CLI Command Registration
src/commands/ai/index.ts, src/index.ts
Adds registerAiCommands and registers the top-level ai command in the main CLI program.
User Documentation & Version
README.md, package.json
Documents npx @insforge/cli ai setup, usage examples (--env-file, --json), deployment guidance for server-side env variables, and bumps package version to 0.1.78.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • jwfing

Poem

A rabbit hops through env files with care,
I fetch the key and hide it where it's fair,
.gitignore hums, "Keep secrets out of sight,"
Setup runs smooth beneath the moonlight,
🐰🔐✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title accurately summarizes the main change: adding a new ai setup command to configure the OpenRouter key.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-ai-setup-command

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/api/ai.ts`:
- Around line 13-21: Trim the incoming API key before validating and returning
it: in the API parsing logic for data.apiKey (and similarly for data.maskedKey
if you want consistency), call .trim() on the string, then check typeof ===
'string' and trimmed.length > 0; if invalid, throw the existing CLIError,
otherwise return the trimmed apiKey (and trimmed maskedKey when present) in the
returned object so whitespace-only or whitespace-padded keys are rejected and
stored normalized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3f66d55e-cd19-4770-b3f2-527d59835588

📥 Commits

Reviewing files that changed from the base of the PR and between 007bbb1 and 3c0fa38.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • README.md
  • src/commands/ai/index.ts
  • src/commands/ai/setup.test.ts
  • src/commands/ai/setup.ts
  • src/index.ts
  • src/lib/api/ai.test.ts
  • src/lib/api/ai.ts

Comment thread src/lib/api/ai.ts Outdated
Copy link
Copy Markdown
Member

@jwfing jwfing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — ai setup command

Summary: Adds npx @insforge/cli ai setup to fetch the linked project's OpenRouter key and write it to a local env file. The implementation is well-scoped, follows project conventions, handles the security-sensitive raw-key exposure correctly, and ships with meaningful test coverage.

Requirements context: No /docs/superpowers/ directory found in this repo — review is assessed against the PR description alone.


Findings

Critical

(none)


Suggestion

[Software Engineering] Missing test for the skipped case in runAiSetup
src/commands/ai/setup.test.ts

There is no test covering the path where OPENROUTER_API_KEY already exists in the env file with the same value (the skipped case). The upsertEnvFile logic itself is tested in env-writer.test.ts, but runAiSetup's behavior when the result has skipped: ['OPENROUTER_API_KEY'] (including the log output in non-JSON mode and the returned skipped array) is unverified. Low blast radius, but the existing key match is a common real-world scenario worth covering.


[Software Engineering] No loading indicator during the API fetch in interactive mode
src/commands/ai/setup.ts:51

const key = await getOpenRouterApiKey();

When !opts.json, the command shows clack.intro then immediately awaits the API call with no spinner. If the backend is slow, users see nothing for several seconds. The posthog setup command uses a clack.spinner() around its polling loop. A spinner around getOpenRouterApiKey() would give consistent UX and avoid the "is it frozen?" feeling.


[Functionality] No friendly 404 error message for the AI endpoint
src/lib/api/oss.ts / src/lib/api/ai.ts

ossFetch has custom 404 handling for /api/compute, /api/payments, and /api/database/migrations. The /api/ai/openrouter/api-key path is absent from that list. If a self-hosted instance doesn't have Model Gateway enabled, users get the generic "OSS request failed: 404". A specific message in getOpenRouterApiKey() (or an extra branch in ossFetch) — e.g. "AI gateway is not configured on this backend. See the InsForge dashboard AI page to enable Model Gateway." — would match the pattern used elsewhere and reduce friction for self-hosters.


Information

[Software Engineering] Duplicate description call for the ai command
src/commands/ai/index.ts:4 and src/index.ts:212

// src/index.ts
const aiCmd = program.command('ai').description('Manage AI model gateway setup');
// src/commands/ai/index.ts
aiCmd.description('Manage AI model gateway setup');

The description is set twice with the same string. The second call (in registerAiCommands) silently overwrites the first. Harmless, but one of them is redundant — the registration function already sets it, so the call-site in src/index.ts can drop .description(...).


[Security] Positive note — raw key never leaks into result or analytics

AiSetupResult only exposes maskedKey; the raw apiKey is never serialised into the command output, JSON result, or analytics event. The explicit test 'does not return the raw key in the setup result' (setup.test.ts:44–47) correctly guards this. The README and CLI output warnings about NEXT_PUBLIC_ / VITE_ / PUBLIC_ prefixes are a nice touch.


Verdict

approved (informational — explicit GitHub approval is a separate human action)

Zero critical findings. The PR is clean, well-tested for the key paths, follows the existing command/test conventions closely, and handles the security-sensitive key exposure correctly. The suggestions above are worth a follow-up but are not blocking.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 13, 2026

Greptile Summary

Adds a new ai setup subcommand to the CLI that fetches a project's OpenRouter API key from the InsForge backend and writes it to a local env file, with safe defaults (.env.local), optional --env-file and --json flags, gitignore auto-update, and mismatch protection.

  • src/commands/ai/setup.ts: New command implementation; fetches key via getOpenRouterApiKey, calls upsertEnvFile and ensureLocalEnvIgnored, never exposes the raw key in JSON output.
  • src/lib/api/ai.ts: New API helper that calls /api/ai/openrouter/api-key, trims and validates the returned key, and throws a clear error when the key is absent or whitespace-only.
  • src/lib/api/oss.ts: Adds an AI-specific 404 message (alongside existing compute/payments/db equivalents) when the backend route doesn't exist.

Confidence Score: 5/5

Safe to merge — the new command writes a local env file and updates gitignore; no existing behavior is modified.

The change is self-contained: a new CLI subcommand backed by a new API helper and a small additive patch to the 404 handler in ossFetch. The raw key never surfaces in JSON output or analytics events. The gitignore-update logic is correct and fully covered by tests, including the edge case of non-default local env file names. No existing command paths are touched.

No files require special attention.

Important Files Changed

Filename Overview
src/commands/ai/setup.ts New command; fetches key, writes env file, updates gitignore, never exposes raw key in output. Logic is correct and well-tested.
src/lib/api/ai.ts New API helper; validates key presence/whitespace, returns trimmed apiKey and optional maskedKey. Clean and well-guarded.
src/lib/api/oss.ts Adds AI-specific 404 message matching the pattern used by compute/payments/db handlers. No conflicts with existing checks.
src/commands/ai/setup.test.ts Good coverage: write, no-overwrite, skip-match, custom env file, and gitignore edge cases; raw-key-leak assertion is a valuable security check.
src/lib/api/ai.test.ts Tests happy path, missing key, and whitespace-only key. All three scenarios correctly validated.
src/lib/api/oss.test.ts Adds a test for the AI 404 path using a spy on fetch; correctly verifies the upgrade message is shown.
src/commands/ai/index.ts Thin registration shim, no logic.
src/index.ts Wires up the new ai command consistently with other command registrations.

Sequence Diagram

sequenceDiagram
    actor User
    participant CLI as npx @insforge/cli
    participant Config as getProjectConfig
    participant Backend as InsForge Backend
    participant FS as File System

    User->>CLI: ai setup [--env-file .env.local] [--json]
    CLI->>Config: getProjectConfig()
    Config-->>CLI: "{ project_id, api_key, oss_host, ... }"

    CLI->>Backend: GET /api/ai/openrouter/api-key
    alt Backend lacks Model Gateway
        Backend-->>CLI: 404 NOT_FOUND
        CLI-->>User: CLIError: Upgrade InsForge project
    else Key missing or whitespace
        Backend-->>CLI: "200 { apiKey: "" }"
        CLI-->>User: CLIError: AI gateway returned no key
    else Success
        Backend-->>CLI: "200 { apiKey, maskedKey }"
    end

    CLI->>FS: "upsertEnvFile(envPath, { OPENROUTER_API_KEY: apiKey })"
    FS-->>CLI: "{ added, skipped, mismatched }"

    CLI->>FS: ensureLocalEnvIgnored(cwd, envFile)
    FS-->>CLI: gitignoreUpdated (bool)

    CLI->>CLI: captureEvent(analytics)

    alt --json flag
        CLI-->>User: "{ success, envFile, added, skipped, mismatched, maskedKey }"
    else interactive
        CLI-->>User: clack output (Wrote .env.local, gitignore updated, ...)
    end
Loading

Reviews (2): Last reviewed commit: "bump CLI version" | Re-trigger Greptile

Comment thread src/commands/ai/setup.ts
Comment thread src/commands/ai/index.ts
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 8 files

Tip: cubic could auto-approve low-risk PRs like this, if it thinks it's safe to merge. Learn more

@Fermionic-Lyu Fermionic-Lyu enabled auto-merge May 13, 2026 20:36
Copy link
Copy Markdown
Member

@jwfing jwfing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, approved.

@Fermionic-Lyu Fermionic-Lyu merged commit 601f8d6 into main May 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants