Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,11 @@ Scope taxonomy: every action requires `cortex:read` except the six **admin** act

## Plugin Skills

Twelve skills ship with the Claude Code plugin — one directory each under `plugins/cortex/skills/<skill>/SKILL.md`:
Thirteen skills ship with the Claude Code plugin — one directory each under `plugins/cortex/skills/<skill>/SKILL.md`:

| Skill | Purpose |
|-------|---------|
| `install-cortex` | Install, secure, deploy, connect, and verify Cortex |
| `cortex` | Primary log-intelligence skill |
| `frustration-assessment` | Analyze `abuse_investigate` evidence bundles |
| `hook-friction-assessment` | Analyze `hook_investigate` evidence bundles |
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ Cortex began as a syslog receiver. It now covers network logs, Docker, managed f

### Install the CLI

The npm launcher is the fastest path for local CLI and stdio MCP use:
The first-class guided path is:

```sh
npx skills add dinglebear-ai/cortex --skill install-cortex
```

Start a fresh agent task and invoke `$install-cortex`. It chooses server or client-only role, delegates to the canonical installer/setup engine, configures auth/network/storage, and verifies the live client connection.

The npm launcher remains the fastest manual path for local CLI and stdio MCP use:

```bash
npx -y @dinglebear/cortex --help
Expand Down
31 changes: 31 additions & 0 deletions docs/adr/002-first-class-install-cortex-skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
title: "ADR 002: First-Class Cortex Installer Skill"
created: 2026-09-18
updated: 2026-09-18
---

# ADR 002: First-Class Cortex Installer Skill

**Status:** Accepted
**Date:** 2026-09-18

## Context

Cortex already has a canonical native installer, idempotent setup repair, server/client plugin configuration, Google OAuth, separate MCP/REST credentials, Compose lifecycle, storage guardrails, and Codex app-server assessments. What is missing is one first-run workflow that makes the fleet topology and security choices explicit before configuration.

A Cortex fleet has one authoritative ingest/storage server. Other machines usually act as MCP clients or host-local forwarders. Syslog itself is unauthenticated, while HTTP services have distinct credentials and scopes. OAuth also defaults to disabling the static MCP bearer unless the operator deliberately retains it.

## Decision

Add `install-cortex` to the existing Cortex plugin. The skill downloads the canonical `install.sh` as a reviewable file, delegates setup to `cortex setup repair`, and asks the user to choose server or client-only role before any listener/storage work.

Server setup configures syslog sender network controls, HTTP/MCP/REST credentials, storage policy, optional Google OAuth, and Compose persistence. Client-only setup never starts another receiver/database. OAuth plus static bearer is an explicit break-glass choice, not an implicit default.

Remote exposure uses current proxy/Tailscale documentation and a backup/diff/approval gate. Optional local assessment uses Cortex's existing `CORTEX_LLM=codex` Codex app-server backend.

## Consequences

- First-run setup reflects Cortex's actual fleet topology instead of treating every machine as a server.
- The skill remains thin over executable setup/Compose contracts.
- Syslog network trust and HTTP authentication cannot be accidentally conflated.
- Native installer/setup changes remain testable independently from agent guidance.
10 changes: 9 additions & 1 deletion packages/cortex-rmcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ Cortex began as a syslog receiver. It now covers network logs, Docker, managed f

### Install the CLI

The npm launcher is the fastest path for local CLI and stdio MCP use:
The first-class guided path is:

```sh
npx skills add dinglebear-ai/cortex --skill install-cortex
```

Start a fresh agent task and invoke `$install-cortex`. It chooses server or client-only role, delegates to the canonical installer/setup engine, configures auth/network/storage, and verifies the live client connection.

The npm launcher remains the fastest manual path for local CLI and stdio MCP use:

```bash
npx -y @dinglebear/cortex --help
Expand Down
11 changes: 11 additions & 0 deletions plugins/cortex/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Cortex plugin contributor instructions

This package is a client/onboarding surface over Cortex. The binary, setup engine, Compose lifecycle, auth model, storage policy, and collectors remain owned by repository source and docs.

- `skills/install-cortex` orchestrates root `install.sh`, `cortex setup repair`, Compose, and plugin/client configuration. Do not duplicate setup logic in the skill.
- Keep server and client-only roles distinct. One authoritative server owns ingestion/storage; client-only hosts must not start a second receiver/database accidentally.
- Preserve separate MCP and REST credentials. Syslog itself is unauthenticated and must rely on sender CIDR/network controls.
- OAuth is Google/lab-auth. Static MCP bearer is disabled by default in OAuth runtime config; retaining it is an explicit break-glass choice via `CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH=false`.
- Remote exposure, Tailscale, or existing proxy changes require current official docs, verified config backups/checksums, exact proposed changes, and explicit approval.
- Cortex `CORTEX_LLM=codex` is Codex app-server backed. Do not replace it with shell prompt hacks.
- Every new cross-provider skill should carry `agents/openai.yaml`. Validate skill/package contracts and disposable Skills CLI installation before publication.
7 changes: 7 additions & 0 deletions plugins/cortex/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Changelog

## 0.1.0 - 2026-09-18

- Add `install-cortex` as the first-class server/client installation and repair workflow.
- Cover canonical installer/setup repair, Compose persistence, syslog network controls, separate MCP/REST credentials, Google OAuth with optional static bearer break-glass, reverse-proxy/Tailscale approval gates, Codex app-server LLM support, and live client verification.
- Add package-level README and contributor instructions for the existing Cortex plugin.
13 changes: 13 additions & 0 deletions plugins/cortex/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Cortex plugin

This package connects agent clients to Cortex and ships log-intelligence skills plus the first-run `install-cortex` workflow.

## First-class install

```sh
npx skills add dinglebear-ai/cortex --skill install-cortex
```

Then invoke `$install-cortex`. It can provision the one Cortex server in a fleet or configure a client-only machine against an existing server. The workflow delegates runtime setup to the canonical Cortex installer and `cortex setup repair`.

The complete Claude plugin remains described by the repository's root `.claude-plugin/plugin.json`. Plugin configuration supports server/client mode, bearer or Google OAuth, separate service credentials, syslog listener settings, storage policy, and remote server URLs.
2 changes: 1 addition & 1 deletion plugins/cortex/scripts/plugin-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ prepare_oauth_env() {
redirects="$(append_csv_unique "${redirects}" "${codex_callback}")"
fi
export CORTEX_AUTH_ALLOWED_REDIRECT_URIS="${redirects}"
export CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH="${CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH:-false}"
export CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH="${CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH:-true}"
}

main() {
Expand Down
23 changes: 23 additions & 0 deletions plugins/cortex/skills/install-cortex/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: install-cortex
description: Install or repair Cortex. Use when provisioning its server, configuring a client-only host, choosing syslog/MCP/REST auth or Google OAuth, enabling durable Compose, selecting Codex app-server LLM support, or verifying agent connectivity.
---

# Install Cortex

Configure one server or a client-only connection; let Cortex own setup.

## Rules

- Inspect role, Cortex/data, ports, Docker, disk/retention, sender networks, clients, and public URL.
- Server asks syslog bind/CIDRs, HTTP bind, separate MCP/REST credentials, OAuth, storage, LLM, and persistence. Syslog has no token auth. Client-only hosts start no receiver/database.
- OAuth requires public URL/Google credentials/admin email. Ask explicitly before retaining `CORTEX_TOKEN` with `CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH=false`.
- Existing proxy/Tailscale/Compose edits require current official docs, verified backup/checksum, exact changes, and explicit approval.

## Flow

1. Follow [setup](references/setup.md): acquire/run canonical `install.sh` and let `cortex setup repair` own config.
2. Server: configure tokens/storage; keep HTTP loopback unless needed; restrict syslog with `CORTEX_ALLOWED_SOURCE_CIDRS` and network controls.
3. Start managed Compose and prove `restart: unless-stopped` persistence. Remote HTTPS keeps Cortex auth behind the proxy.
4. Optional `CORTEX_LLM=codex[/MODEL]` uses Codex app-server; verify Codex auth first.
5. Configure selected agent MCP clients, reload them, and prove read-only `status` from a fresh session. Run setup check/doctor/health and report paths/URLs/service state/evidence without secrets.
6 changes: 6 additions & 0 deletions plugins/cortex/skills/install-cortex/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface:
display_name: "Install Cortex"
short_description: "Install, secure, and connect Cortex"
default_prompt: "Use $install-cortex to install or repair Cortex and connect my agent safely."
policy:
allow_implicit_invocation: false
39 changes: 39 additions & 0 deletions plugins/cortex/skills/install-cortex/references/setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Cortex setup

## Install

```sh
curl -fsSLo /tmp/cortex-install.sh https://raw.githubusercontent.com/dinglebear-ai/cortex/main/install.sh
sh /tmp/cortex-install.sh
```

The canonical installer checksum-verifies native releases (or supports `CORTEX_INSTALL_METHOD=build`) and calls `cortex setup repair` without replacing existing tokens.

## Server + auth

Defaults: syslog `0.0.0.0:1514` UDP/TCP, HTTP `127.0.0.1:3100`, MCP `/mcp`, REST `/api/*`. Syslog requires CIDR/network controls.

Keep `CORTEX_TOKEN` separate from `CORTEX_API_TOKEN` and optional `CORTEX_API_ADMIN_TOKEN`. Non-loopback unauthenticated HTTP fails closed unless a trusted-gateway boundary is explicit.

OAuth callback: `https://YOUR_PUBLIC_URL/auth/google/callback`. Required: `CORTEX_AUTH_MODE=oauth`, public URL, Google client ID/secret, admin email. OAuth normally disables static MCP bearer; set `CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH=false` only for intentional dual mode. OTLP may still need `CORTEX_TOKEN`.

```sh
cortex setup check
cortex setup repair
cortex compose up
cortex compose status
```

Compose uses `restart: unless-stopped`; verify Docker starts at boot and health survives restart.

## Client, LLM, proof

Client-only machines use the server `/mcp` URL/auth and run no database/receiver. `CORTEX_LLM=codex` is Codex app-server; `gemini[/MODEL]` is the alternative.

```sh
cortex status
cortex doctor
curl -fsS http://127.0.0.1:3100/health
```

Create a test syslog record only with approval. Debug setup, listener/network, auth, storage, Compose, proxy, client, and LLM layers independently.
41 changes: 41 additions & 0 deletions plugins/cortex/tests/test_install_skill_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from pathlib import Path
import unittest

PLUGIN = Path(__file__).resolve().parents[1]
ROOT = PLUGIN.parents[1]
SKILL = PLUGIN / "skills" / "install-cortex" / "SKILL.md"
REF = PLUGIN / "skills" / "install-cortex" / "references" / "setup.md"
OPENAI = PLUGIN / "skills" / "install-cortex" / "agents" / "openai.yaml"

class InstallCortexContractTest(unittest.TestCase):
def test_install_and_security_contract(self):
text = SKILL.read_text() + REF.read_text()
required = [
"cortex setup repair", "CORTEX_ALLOWED_SOURCE_CIDRS",
"CORTEX_TOKEN", "CORTEX_API_TOKEN", "auth/google/callback",
"CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH=false",
"CORTEX_LLM=codex", "Codex app-server", "restart: unless-stopped",
"explicit approval",
]
for value in required:
self.assertIn(value, text)

def test_skill_requires_explicit_invocation(self):
self.assertIn("allow_implicit_invocation: false", OPENAI.read_text())

def test_oauth_setup_preserves_secure_static_token_default(self):
expected = 'CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH="${CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH:-true}"'
insecure = 'CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH="${CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH:-false}"'
for script in [ROOT / "scripts" / "plugin-setup.sh", PLUGIN / "scripts" / "plugin-setup.sh"]:
text = script.read_text()
self.assertIn(expected, text)
self.assertNotIn(insecure, text)

def test_canonical_installer_delegates_to_setup_repair(self):
text = (ROOT / "install.sh").read_text()
self.assertIn("dinglebear-ai/cortex", text)
self.assertIn("setup repair", text)
self.assertIn("checksum mismatch", text)

if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion scripts/plugin-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ prepare_oauth_env() {
redirects="$(append_csv_unique "${redirects}" "${codex_callback}")"
fi
export CORTEX_AUTH_ALLOWED_REDIRECT_URIS="${redirects}"
export CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH="${CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH:-false}"
export CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH="${CORTEX_AUTH_DISABLE_STATIC_TOKEN_WITH_OAUTH:-true}"
}

main() {
Expand Down
Loading