npm package: @securecode/sdk
Description: SecureCodeHQ SDK - Access your secrets programmatically
Latest version: 0.10.2

# @securecode/sdk

The official Node.js SDK for [SecureCodeHQ](https://securecodehq.com) — the secrets vault for developers who build with Claude Code.

## Install

```bash
npm install @securecode/sdk
```

## Quick Start

The fastest way to get started is through the **MCP onboarding** — just tell Claude Code:

```
You: "Set up SecureCode for this project"
```

This creates your account, imports your `.env` files, and configures everything automatically. After onboarding, a `.securecoderc` file is created in your project root — the SDK reads it automatically.

### Manual setup

Set your API key and start using secrets:

```bash
export SECURECODE_API_KEY=sc_your_key_here
```

```typescript
import { getSecret } from '@securecode/sdk';

const stripeKey = await getSecret('STRIPE_SECRET_KEY');
const dbUrl = await getSecret('DATABASE_URL');
```

## Load All Secrets at Once

Inject all your secrets into `process.env` with a single API call:

```typescript
import { loadEnv } from '@securecode/sdk';

await loadEnv();
// Now use process.env.STRIPE_SECRET_KEY, process.env.DATABASE_URL, etc.
```

Options:

```typescript
await loadEnv({
  tags: { env: 'production', project: 'acme' }, // filter by tags
  override: false, // don't overwrite existing env vars
});
```

> **Note:** `override` defaults to `true` — secrets from the vault overwrite existing `process.env` values. Set `override: false` to preserve local values.

## Framework Integration

### Next.js (App Router)

Use `instrumentation.ts` to load secrets at startup. **Important:** Next.js compiles this file for both Node.js and Edge runtimes. Use the `NEXT_RUNTIME` guard to avoid Edge bundling issues:

```typescript
// src/instrumentation.ts
export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { loadEnv } = await import("@securecode/sdk");
    await loadEnv();
  }
}
```

> For Next.js 14, add `experimental: { instrumentationHook: true }` to `next.config.mjs`.

### Express / Plain Node.js

Call `loadEnv()` before your app starts:

```typescript
import { loadEnv } from '@securecode/sdk';

await loadEnv();
// Now start your server — all secrets are in process.env
```

### Granular Access (getSecret)

For fine-grained audit trails, use `getSecret()` instead of `loadEnv()`:

```typescript
import { getSecret } from '@securecode/sdk';

// Each call = 1 HTTP request + 1 audit log entry
const stripe = await getSecret('STRIPE_KEY');
const db = await getSecret('DATABASE_URL');
```

**When to use which:**
- `loadEnv()` — 1 API call, all secrets in `process.env`, ideal for app startup
- `getSecret()` — 1 call per secret, individual audit trail per secret, ideal for on-demand access

## CLI Tools

### Migrate from .env files

Scan and import your `.env` files into SecureCodeHQ:

```bash
npx securecode migrate                        # scan all .env* files
npx securecode migrate .env.production        # import specific file
npx securecode migrate --tags "project:acme"  # apply tags
npx securecode migrate --ttl 720 -y           # 30-day TTL, skip confirm
```

### Run with secrets injected

Load secrets into `process.env` and run your command:

```bash
npx securecode-run node server.js
npx securecode-run -- npm start
npx securecode-run --tags "env:production" node app.js
```

## Configuration

The SDK resolves the API key from these sources (in order):

1. `SECURECODE_API_KEY` environment variable
2. `.securecoderc` file in the project root (created during onboarding)
3. `.mcp.json` file (MCP server configuration)

The `.securecoderc` file can also set project and environment filters:

```ini
SECURECODE_API_KEY=sc_your_key_here
SECURECODE_PROJECT=acme
SECURECODE_ENV=staging
```

When `SECURECODE_PROJECT` and/or `SECURECODE_ENV` are set, `loadEnv()` and `listSecrets()` automatically filter by those tags.

## Full Client

For more control, create a client instance:

```typescript
import { SecureCodeClient } from '@securecode/sdk';

const client = new SecureCodeClient({
  apiKey: 'sc_your_key_here',
});

// Get a secret value
const value = await client.getSecret('OPENAI_API_KEY');

// Get a secret with tags to disambiguate
const prodKey = await client.getSecret('DB_URL', { env: 'production' });

// Reveal mode — value returned to caller (audited as conscious action)
const revealed = await client.getSecret('DB_URL', undefined, undefined, { reveal: true });

// List all secrets (metadata only, no values)
const secrets = await client.listSecrets();

// Filter by tags
const prodSecrets = await client.listSecrets({
  tags: { env: 'production', project: 'acme' },
});

// Create a secret with tags and TTL
await client.createSecret({
  name: 'NEW_API_KEY',
  value: 'sk-...',
  description: 'OpenAI production key',
  tags: { env: 'production', project: 'acme' },
  ttlHours: 720, // expires in 30 days
});

// Update a secret
await client.updateSecret('NEW_API_KEY', {
  value: 'sk-new-value...',
  tags: { env: 'production', rotated: 'true' },
});

// Renew an expired secret
await client.renewSecret('EXPIRED_KEY', 48); // 48 hours

// Delete a secret
await client.deleteSecret('OLD_KEY');

// Export all secrets as .env format
const envContent = await client.exportEnv({ format: 'env' });
```

## MCP Access Rules

When an MCP rule blocks access, the SDK throws `McpRuleBlockedError`:

```typescript
import { SecureCodeClient, McpRuleBlockedError } from '@securecode/sdk';

const client = new SecureCodeClient({ apiKey: 'sc_...' });

try {
  const value = await client.getSecret('STRIPE_LIVE_KEY');
} catch (err) {
  if (err instanceof McpRuleBlockedError) {
    console.log(err.ruleAction);  // 'block_always' | 'require_confirmation' | ...
    console.log(err.ruleName);    // 'Block production secrets'

    // For require_confirmation rules, acknowledge and retry:
    if (err.ruleAction === 'require_confirmation') {
      const value = await client.getSecret('STRIPE_LIVE_KEY', undefined, err.ruleId);
    }
  }
}

// List active rules (read-only)
const rules = await client.getActiveRules();
```

## Session Lock

Control when Claude Code can access your secrets:

```typescript
// Wake session with scoped access
await client.wakeSession({
  scope: [{ project: 'acme', env: 'staging' }],
  autoSleepMinutes: 60,
});

// Check session status
const status = await client.getSessionStatus();
console.log(status.status); // 'active' | 'sleeping'

// Lock session when done
await client.sleepSession();
```

## API Key Retry on Rotation

The SDK automatically handles API key rotation. If a request returns 401, the SDK re-reads the API key from its source (env var, `.securecoderc`, or `.mcp.json`) and retries once. This means you can rotate keys without restarting your application.

## Requirements

- Node.js >= 18

## License

MIT