> For the complete documentation index, see [llms.txt](https://skyforgeai.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://skyforgeai.gitbook.io/docs/configuration.md).

# Configuration

***

## Config File

`skyforge.jsonc` is picked up automatically when you run `skyforge`. SkyForge searches in this order:

| Location                                              | When to use                                     |
| ----------------------------------------------------- | ----------------------------------------------- |
| `./skyforge.jsonc`                                    | Current directory — per-project (all platforms) |
| `~/skyforge.jsonc`                                    | Home directory — personal global (macOS/Linux)  |
| `~/.config/skyforge/skyforge.jsonc`                   | XDG config dir — global (macOS/Linux)           |
| `C:\Users\<username>\.config\skyforge\skyforge.jsonc` | Global config (Windows)                         |

**Tip:** Start with `~/skyforge.jsonc` so it works from any directory, then override per-project as needed.

***

## AI Providers

### Anthropic (Claude)

```jsonc
{
  "provider": {
    "anthropic": {
      "apiKey": "sk-ant-..."
    }
  },
  "model": "anthropic/claude-sonnet-4-6"
}
```

Models: `claude-opus-4-6`, `claude-sonnet-4-6`, `claude-haiku-4-5`

### OpenAI

```jsonc
{
  "provider": {
    "openai": {
      "apiKey": "sk-..."
    }
  },
  "model": "openai/gpt-4o"
}
```

### Google Gemini

```jsonc
{
  "provider": {
    "google": {
      "apiKey": "AIza..."
    }
  },
  "model": "google/gemini-2.5-pro"
}
```

### Azure OpenAI

```jsonc
{
  "provider": {
    "azure": {
      "apiKey": "your-azure-key",
      "resourceName": "your-resource-name"
    }
  },
  "model": "azure/gpt-4o"
}
```

### AWS Bedrock

```jsonc
{
  "provider": {
    "amazon-bedrock": {
      "region": "us-east-1"
    }
  }
}
```

Uses your local AWS credentials (`~/.aws/credentials` on macOS/Linux, `C:\Users\<username>\.aws\credentials` on Windows).

### Groq

```jsonc
{
  "provider": {
    "groq": {
      "apiKey": "gsk_..."
    }
  }
}
```

### OpenRouter

```jsonc
{
  "provider": {
    "openrouter": {
      "apiKey": "sk-or-..."
    }
  }
}
```

### Custom / OpenAI-Compatible Provider

Any OpenAI-compatible endpoint works — self-hosted vLLM, LiteLLM, Ollama, or a hosted gateway.

**TUI:** `Ctrl+P → Connect a provider → Custom (OpenAI-compatible)`

Walks you through: Provider ID → Display name → Base URL → Model ID → Model name → API key. Config is written to `~/.config/skyforge/skyforge.jsonc` automatically.

**Web UI:** Settings icon → **Connect provider** → scroll to **Other** → **Custom**

For advanced options, edit `~/.config/skyforge/skyforge.jsonc` after setup:

**LiteLLM / vLLM gateway:**

```jsonc
{
  "provider": {
    "litellm": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "LiteLLM",
      "options": {
        "baseURL": "https://your-litellm-gateway.com/v1",
        "apiKey": "sk-your-key",
        "litellmProxy": true
      },
      "models": {
        "gpt-4o": {
          "name": "GPT-4o via LiteLLM",
          "attachment": true,
          "reasoning": true,
          "modalities": {
            "input": ["text", "image"],
            "output": ["text"]
          }
        }
      }
    }
  }
}
```

> **`litellmProxy: true`** is required for LiteLLM/vLLM — fixes tool call formatting and enables image passthrough.

**Hosted gateway (company API):**

```jsonc
{
  "provider": {
    "mygateway": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "My Gateway",
      "options": {
        "baseURL": "https://your-gateway.example.com/v1",
        "apiKey": "sk-..."
      },
      "models": {
        "your-model-name": {
          "name": "My Model"
        }
      }
    }
  }
}
```

**Ollama (local):**

```jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ollama": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama",
      "options": {
        "baseURL": "http://localhost:11434/v1"
      },
      "models": {
        "llama3.2": {
          "name": "Llama 3.2"
        }
      }
    }
  }
}
```

### Multiple Providers

```jsonc
{
  "provider": {
    "anthropic": { "apiKey": "sk-ant-..." },
    "openai": { "apiKey": "sk-..." }
  },
  "model": "anthropic/claude-sonnet-4-6"
}
```

Switch models mid-session with **Ctrl+P** → `model`.

***

## ServiceNow Connection

SkyForge supports three authentication methods. All are configured via the TUI (`Ctrl+P → ServiceNow Auth`) or Web UI (Settings icon → ServiceNow Auth) — no manual config file editing required.

### OAuth 2.0 (Recommended)

Best for production instances. Requires setting up an OAuth app in ServiceNow first.

#### Setting up OAuth in ServiceNow

1. Go to **System OAuth → Application Registry**
2. Click **New → Create an OAuth API endpoint for external clients**
3. Fill in the fields exactly:

   | Field                      | Value                            | Why                                                           |
   | -------------------------- | -------------------------------- | ------------------------------------------------------------- |
   | **Name**                   | `SkyForge`                       | Cosmetic                                                      |
   | **Redirect URL**           | `http://localhost:3005/callback` | Must match byte-for-byte. No trailing slash.                  |
   | **Active**                 | ✅ checked                        | Inactive apps silently reject every request                   |
   | **Accessible from**        | `All application scopes`         | Required for global scope                                     |
   | **Scope Restriction**      | `Broadly scoped`                 | **Critical.** `Securely scoped` blocks all `/api/now/*` calls |
   | **Access Token Lifespan**  | `1800` or `18000`                | Either works                                                  |
   | **Refresh Token Lifespan** | `8640000` (100 days)             | **Critical.** If `0`, every refresh token is dead on arrival  |
4. Submit, open the record, reveal and copy **Client ID** and **Client Secret**

#### Authenticate

**TUI:** `Ctrl+P → ServiceNow Auth → OAuth`

**Web UI:** Settings icon → ServiceNow Auth → OAuth 2.0

A browser opens to the consent page — click **Allow**.

***

### Basic Auth (Development only)

**TUI:** `Ctrl+P → ServiceNow Auth → Basic Auth`

**Web UI:** Settings icon → ServiceNow Auth → Basic Auth

> ⚠️ Basic auth is for development only. Use OAuth for production.

> ⚠️ **Australia release and later:** The service account must have the `snc_basic_auth_api_access` role or all REST API calls will return 401. Assign via **User Administration → Users → \[user] → Roles → Edit → add `snc_basic_auth_api_access`**.

***

### Browser Session / SSO

Use when your instance requires SSO (SAML, Okta, Azure AD) and you have no local password or OAuth app.

**TUI:** `Ctrl+P → ServiceNow Auth → Browser Session (SSO)`

1. Enter instance URL → Enter (browser opens)
2. DevTools → Network → filter `api/now` → right-click any request → Copy as cURL
3. Paste into textarea → **Ctrl+S**

**Web UI:** Settings icon → ServiceNow Auth → Browser Session (SSO)

1. Follow the on-screen instructions
2. Paste cURL → **Connect**

> Sessions last \~8 hours. Re-paste a fresh cURL when expired.\
> Restart SkyForge after connecting to activate MCP tools.

### Multiple Instances

```jsonc
{
  "mcp": {
    "servicenow-dev": {
      "type": "local",
      "command": ["skyforge", "mcp", "start"],
      "environment": {
        "SERVICENOW_INSTANCE_URL": "https://dev12345.service-now.com",
        "SERVICENOW_CLIENT_ID": "dev-client-id",
        "SERVICENOW_CLIENT_SECRET": "dev-secret"
      }
    },
    "servicenow-prod": {
      "type": "local",
      "command": ["skyforge", "mcp", "start"],
      "environment": {
        "SERVICENOW_INSTANCE_URL": "https://prod.service-now.com",
        "SERVICENOW_CLIENT_ID": "prod-client-id",
        "SERVICENOW_CLIENT_SECRET": "prod-secret"
      }
    }
  }
}
```

***

## External MCP Servers

SkyForge supports any MCP-compatible server:

### Remote MCP (SSE/HTTP)

```jsonc
{
  "mcp": {
    "context7": {
      "type": "remote",
      "url": "https://mcp.context7.com/mcp"
    }
  }
}
```

### Local MCP (stdio)

```jsonc
{
  "mcp": {
    "my-custom-server": {
      "type": "local",
      "command": ["node", "./my-mcp-server.js"],
      "environment": {
        "API_KEY": "..."
      }
    }
  }
}
```

***

## Permissions

Control what SkyForge can do:

```jsonc
{
  "permission": {
    "bash": "ask",           // ask before running shell commands
    "write": "allow",        // allow file writes
    "read": "allow",         // allow file reads
    "external_directory": "deny"  // deny access outside project
  }
}
```

Options: `"allow"`, `"ask"`, `"deny"`

***

## Custom Agents

Define your own agents:

```jsonc
{
  "agent": {
    "servicenow-readonly": {
      "model": "anthropic/claude-haiku-4-5",
      "description": "Read-only ServiceNow queries",
      "permission": {
        "bash": "deny",
        "write": "deny"
      },
      "system": "You are a ServiceNow read-only assistant. Only query data, never create or modify anything."
    }
  }
}
```

***

## Disabling/Enabling Tools

```jsonc
{
  "tools": {
    "Bash": false,        // disable bash tool
    "WebSearch": false    // disable web search
  }
}
```

***

## Time Saved & Session Analytics

The dashboard estimates how much developer time each session saved. Classification has **two tiers**:

* **Tier 1 — rule-based (always on, free).** Maps the tools used in a session to ServiceNow deliverables (workspaces, dashboards, integrations, business rules, flows, etc.) and estimates the manual build time. Instant, no AI, zero tokens. Works in **every** setup — direct SkyForge use, local MCP, and Claude Desktop / Claude.ai over MCP. This is what you get out of the box.
* **Tier 2 — AI classification (opt-in).** A smarter second pass that reasons about the work instead of pattern-matching. Off by default. When enabled, SkyForge uses **your own configured provider** to refine the estimate — including for HTTP/MCP (Claude Desktop) sessions.

> You don't need to do anything for Tier 1 — Time Saved already works. Tier 2 is an optional upgrade.

### Enabling AI classification (Tier 2)

Two keys under `analytics` in `skyforge.jsonc`:

```jsonc
{
  "analytics": {
    "aiClassification": true,                          // master switch (default: false)
    "classifierModel": "openai/gpt-4o-mini"            // optional — which provider/model
    // examples: "openai/gpt-4o-mini", "anthropic/claude-haiku-4-5",
    //           "google/gemini-2.5-flash", "groq/llama-3.3-70b"
  }
}
```

| Key                          | Default       | Purpose                                                                    |
| ---------------------------- | ------------- | -------------------------------------------------------------------------- |
| `analytics.aiClassification` | `false`       | Turns Tier 2 on. Nothing happens unless `true`.                            |
| `analytics.classifierModel`  | default model | `"providerID/modelID"` — which configured provider/model to classify with. |

Minimum to enable (uses your default model):

```jsonc
{ "analytics": { "aiClassification": true } }
```

### Where the API key goes

`classifierModel` is **only a pointer** to a provider you've already set up under `provider` (see [AI Providers](#ai-providers)) — there is **no API-key field here**. The key for that provider is read from your normal provider config / `auth.json` / environment variable. So the `providerID` in `classifierModel` must match a provider you've configured. If it has no key, Tier 2 silently falls back to Tier 1.

> **Keys → provider config / `auth.json`. Which model to use → `analytics.classifierModel`. The analytics block never holds a secret.**

### Notes

* **Non-breaking.** The `analytics` block is optional and defaults off. Existing installs need no changes — they keep getting Tier 1.
* **Uses SkyForge's own LLM, not the MCP client's.** When Claude Desktop drives SkyForge over MCP, Claude executes tools but never provides the classifier's model. Tier 2 needs **the SkyForge install** (the one running the dashboard) to have a provider configured. If you only use SkyForge as an MCP relay and never configured a provider, you'll stay on Tier 1.
* **Same key/budget as your dev work.** Classification calls bill to the same provider account. Point `classifierModel` at a cheap model to keep it inexpensive.

***

## Ports & Server

By default SkyForge runs on:

* **Main server** (web UI + API): `:4096`
* **HTTP MCP server** (VS Code / Claude Code / Claude Desktop): `:3006`

### Connecting to the MCP server

**VS Code / Claude Code** — native HTTP transport:

```json
{ "type": "http", "url": "http://localhost:3006/mcp" }
```

**Claude Desktop** (`claude_desktop_config.json`) — Claude Desktop does not support `type: http` natively. Use `mcp-remote` as a stdio→HTTP bridge:

**Basic auth:**

```json
{
  "mcpServers": {
    "skyforge-nexus": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:3006/mcp",
        "--header", "X-SN-Instance:<your-instance>.service-now.com",
        "--header", "X-SN-Username:<username>",
        "--header", "X-SN-Password:<password>"
      ]
    }
  }
}
```

**OAuth 2.0:**

```json
{
  "mcpServers": {
    "skyforge-nexus": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:3006/mcp",
        "--header", "X-SN-Instance:<your-instance>.service-now.com",
        "--header", "X-SN-Client-Id:<client-id>",
        "--header", "X-SN-Client-Secret:<client-secret>"
      ]
    }
  }
}
```

> If you've already run `skyforge auth login` on the same machine, you can omit the `--header` args — the server will fall back to your local `auth.json` automatically.

### Custom ports via CLI flags

```bash
skyforge --port 8080                    # custom main server port
skyforge --mcp-port 9000                # custom HTTP MCP port
skyforge --port 8080 --mcp-port 9000    # both at once

skyforge serve --port 8080 --mcp-port 9000
```

### Custom ports via environment variables

```bash
OPENCODE_SERVER_PORT=8080 SN_MCP_HTTP_PORT=9000 skyforge
```

### Custom hostname

```bash
skyforge --hostname 0.0.0.0   # listen on all interfaces (LAN access)
```

> When running on a custom MCP port, update your client config accordingly:
>
> ```json
> // VS Code / Claude Code
> { "type": "http", "url": "http://localhost:9000/mcp" }
>
> // Claude Desktop — update the mcp-remote URL arg
> "args": ["mcp-remote", "http://localhost:9000/mcp", ...]
> ```

***

## Environment Variables

Instead of `skyforge.jsonc`, you can use environment variables:

```bash
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
export SERVICENOW_INSTANCE_URL="https://dev12345.service-now.com"
export SERVICENOW_CLIENT_ID="abc123"
export SERVICENOW_CLIENT_SECRET="secret"

skyforge
```

***

## Full Config Reference

```jsonc
{
  // AI provider configurations
  "provider": {
    "anthropic": { "apiKey": "..." },
    "openai": { "apiKey": "..." }
  },

  // Default model (provider/model format)
  "model": "anthropic/claude-sonnet-4-6",

  // Small model for lightweight tasks (title generation etc.)
  "model.mini": "anthropic/claude-haiku-4-5",

  // MCP server configurations
  "mcp": {
    "servicenow": { ... }
  },

  // Tool enable/disable
  "tools": {
    "Bash": true,
    "WebSearch": true
  },

  // Permissions
  "permission": {
    "bash": "ask",
    "write": "allow",
    "read": "allow"
  },

  // Disable specific providers
  "disabled_providers": ["openrouter"],

  // Only enable specific providers
  "enabled_providers": ["anthropic", "openai"],

  // Session analytics / Time Saved (Tier 2 AI classification — opt-in)
  "analytics": {
    "aiClassification": false,                      // default off — Tier 1 (rule-based) always on
    "classifierModel": "openai/gpt-4o-mini"         // optional — "provider/model" of a configured provider
    // e.g. "anthropic/claude-haiku-4-5", "google/gemini-2.5-flash"
  },

  // Custom agents
  "agent": { ... },

  // Plugins (npm packages)
  "plugin": ["my-skyforge-plugin"]
}
```

***

## Support

Have a bug or feature request? Submit it at [**GitHub Issues**](https://github.com/tryskyforge/skyforgeissues).

## License

SkyForge is licensed under the [Elastic License 2.0](/docs/license.md). Free for personal and internal use. Commercial redistribution requires a license.

***

## Running SkyForge

### Web interface (default)

```bash
skyforge
# or explicitly:
skyforge web
```

Opens `http://127.0.0.1:4096` in your browser.

### TUI (terminal interface)

```bash
skyforge tui
```

### Headless server (API only)

```bash
skyforge serve
skyforge serve --port 8080 --mcp-port 9000
```

### Run with a prompt directly

```bash
skyforge run "query the last 5 critical incidents"
```

### Attach TUI to a running server

```bash
skyforge attach http://host:4096
```

### Update

```bash
skyforge update          # updates to latest via npm
skyforge update 3.9.0    # updates to a specific version
```

Runs `npm install -g @skyforgeai/skyforge@<target>` under the hood.

### Export skills for Claude Desktop / Claude Code

Package SkyForge's agent instructions as a Claude Skill, so you can use SkyForge's ServiceNow expertise inside Claude Desktop or Claude Code (paired with the SkyForge MCP server for tool access).

```bash
skyforge export-skills              # orchestrator skill only → ~/skyforge-skills/_zips/skyforge.zip
skyforge export-skills --all        # orchestrator + reviewer + all 71 domain skills (one zip each)
skyforge export-skills ./my-skills  # custom output dir
```

By default this exports only the **`skyforge` orchestrator skill** (always zipped). That's all you need to upload — the orchestrator loads domain skills (servicenow-dev, business-rule-patterns, reviewer, etc.) on demand through the `sn_load_skill` MCP tool, so you don't upload all 73 individually.

**Claude Desktop (upload):**

```bash
skyforge export-skills
# then in Claude: Customize → Skills → "+" → upload ~/skyforge-skills/_zips/skyforge.zip
```

**Claude Code (local folder):**

```bash
skyforge export-skills --all
cp -r ~/skyforge-skills/*/ ~/.claude/skills/
```

Pair with `skyforge mcp serve` so the MCP tools (and `sn_load_skill`) are available alongside the skill.

**How it works:** the uploaded `skyforge` skill auto-triggers on any ServiceNow task and tells Claude how to work — load `servicenow-dev` first, confirm application scope, create an Update Set, load the matching domain skill, then build, loading the reviewer protocol before emitting code. ServiceNow tools aren't called directly; Claude uses `tool_search` to find them and `tool_execute({ tool, args })` to run them, with `sn_load_skill` delivering skill content on demand. Restart Claude Desktop after re-uploading the skill or restarting the server so it reconnects.

***

## Logs

| Log                 | macOS / Linux                         | Windows                                           |
| ------------------- | ------------------------------------- | ------------------------------------------------- |
| Session (dev build) | `~/.local/share/skyforge/log/dev.log` | `%USERPROFILE%\.local\share\skyforge\log\dev.log` |
| Session (installed) | `~/.local/share/skyforge/log/*.log`   | `%USERPROFILE%\.local\share\skyforge\log\`        |
| MCP calls           | `~/.skyforge/skyforge-mcp.log`        | `%USERPROFILE%\.skyforge\skyforge-mcp.log`        |
| MCP metrics         | `~/.skyforge/skyforge-metrics.log`    | `%USERPROFILE%\.skyforge\skyforge-metrics.log`    |

```bash
# Tail active log (dev build)
tail -f ~/.local/share/skyforge/log/dev.log

# Tail latest session log (installed binary)
ls -t ~/.local/share/skyforge/log/*.log | head -1 | xargs tail -f

# Watch MCP tool calls
tail -f ~/.skyforge/skyforge-mcp.log

# Full debug output
skyforge --log-level DEBUG --print-logs
```

***

## Keyboard Shortcuts (TUI)

SkyForge uses a **leader key** pattern — press and **release** `Ctrl+X` first, then press the second key.

| Key               | Action                             |
| ----------------- | ---------------------------------- |
| `Ctrl+X` then `A` | Open agent picker                  |
| `Shift+Tab`       | Cycle to next agent                |
| `Ctrl+Shift+Tab`  | Cycle to previous agent            |
| `Escape`          | Interrupt / stop current operation |
| `Ctrl+X` then `↑` | Go to parent session               |
| `Ctrl+X` then `→` | Next child session                 |
| `Ctrl+X` then `←` | Previous child session             |
| `Ctrl+P`          | Command palette                    |
| `/connect`        | Add AI provider                    |
| `/models`         | Switch model                       |
| `/themes`         | Change theme                       |
| `Ctrl+Shift+A`    | Toggle auto-accept permissions     |
| `Ctrl+C`          | Exit SkyForge                      |

***

## Agents

| Agent       | Trigger     | Description                                                 |
| ----------- | ----------- | ----------------------------------------------------------- |
| **Build**   | Default     | Full tool access — creates and deploys ServiceNow artifacts |
| **Plan**    | `Shift+Tab` | Read-only — analysis and exploration                        |
| **Review**  | `Shift+Tab` | Code review — writes report to `.skyforge/reviews/`         |
| **General** | `@general`  | Multi-step subagent for complex parallel tasks              |

Switch between Build / Plan / Review with `Shift+Tab`. Invoke General with `@general`.

Custom agents can be defined in `skyforge.jsonc` — see [Custom Agents](#custom-agents) above.

***

## Troubleshooting

### Reset to clean state

**macOS / Linux:**

```bash
rm -rf ~/.config/skyforge
rm -rf ~/.local/share/skyforge
rm -rf ~/.local/share/opentui
rm -rf ~/.cache/skyforge
rm -rf ~/.skyforge
```

**Windows (PowerShell):**

```powershell
Remove-Item -Recurse -Force "$env:USERPROFILE\.config\skyforge"
Remove-Item -Recurse -Force "$env:USERPROFILE\.local\share\skyforge"
Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\skyforge"
Remove-Item -Recurse -Force "$env:USERPROFILE\.skyforge"
```

Then reinstall:

```bash
npm i -g @skyforgeai/skyforge@latest
skyforge
```

### OAuth errors

| Error                                         | Fix                                                                 |
| --------------------------------------------- | ------------------------------------------------------------------- |
| `OAuth refresh token flow failed: 401`        | Refresh Token Lifespan is `0` — set to `8640000`, re-auth           |
| `Access to unscoped api is not allowed` (403) | Scope Restriction is `Securely scoped` — change to `Broadly scoped` |
| `Invalid redirect_uri`                        | Redirect URL must be exactly `http://localhost:3005/callback`       |

### SSO / Browser Session errors

| Error                                    | Fix                                                         |
| ---------------------------------------- | ----------------------------------------------------------- |
| `Session verification failed: HTTP 401`  | Session expired — copy fresh cURL from DevTools and re-auth |
| `No cookies in cURL`                     | Wrong request — filter DevTools by `api/now/table/`         |
| MCP tools not available after connecting | Restart SkyForge                                            |

### Other

| Problem                        | Fix                                                                    |
| ------------------------------ | ---------------------------------------------------------------------- |
| `Tool not found`               | Tools are lazy-loaded — type `search for X tools` first                |
| MCP not connecting             | `tail -f ~/.skyforge/skyforge-mcp.log` or `SN_MCP_DEBUG=true skyforge` |
| Web UI file attach not working | Must be on `localhost` or HTTPS                                        |
