From 061e03ff65ff312acf730901fa1fc8f9f27f50a7 Mon Sep 17 00:00:00 2001 From: Jake Magar Date: Fri, 18 Sep 2026 16:42:43 -0400 Subject: [PATCH 1/2] feat: add first-class install-cortex skill --- CLAUDE.md | 3 +- README.md | 10 ++++- .../002-first-class-install-cortex-skill.md | 31 ++++++++++++++ plugins/cortex/AGENTS.md | 11 +++++ plugins/cortex/CHANGELOG.md | 7 ++++ plugins/cortex/README.md | 13 ++++++ plugins/cortex/scripts/plugin-setup.sh | 2 +- plugins/cortex/skills/install-cortex/SKILL.md | 23 +++++++++++ .../skills/install-cortex/agents/openai.yaml | 6 +++ .../skills/install-cortex/references/setup.md | 39 ++++++++++++++++++ .../tests/test_install_skill_contract.py | 41 +++++++++++++++++++ scripts/plugin-setup.sh | 2 +- 12 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 docs/adr/002-first-class-install-cortex-skill.md create mode 100644 plugins/cortex/AGENTS.md create mode 100644 plugins/cortex/CHANGELOG.md create mode 100644 plugins/cortex/README.md create mode 100644 plugins/cortex/skills/install-cortex/SKILL.md create mode 100644 plugins/cortex/skills/install-cortex/agents/openai.yaml create mode 100644 plugins/cortex/skills/install-cortex/references/setup.md create mode 100644 plugins/cortex/tests/test_install_skill_contract.py diff --git a/CLAUDE.md b/CLAUDE.md index de2ccd42d..d1c7c43ee 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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.md`: +Thirteen skills ship with the Claude Code plugin — one directory each under `plugins/cortex/skills//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 | diff --git a/README.md b/README.md index f8d666343..3be18e671 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/adr/002-first-class-install-cortex-skill.md b/docs/adr/002-first-class-install-cortex-skill.md new file mode 100644 index 000000000..9724bff27 --- /dev/null +++ b/docs/adr/002-first-class-install-cortex-skill.md @@ -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. diff --git a/plugins/cortex/AGENTS.md b/plugins/cortex/AGENTS.md new file mode 100644 index 000000000..5355f7f83 --- /dev/null +++ b/plugins/cortex/AGENTS.md @@ -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. diff --git a/plugins/cortex/CHANGELOG.md b/plugins/cortex/CHANGELOG.md new file mode 100644 index 000000000..1d7aabfa4 --- /dev/null +++ b/plugins/cortex/CHANGELOG.md @@ -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. diff --git a/plugins/cortex/README.md b/plugins/cortex/README.md new file mode 100644 index 000000000..9da83faa8 --- /dev/null +++ b/plugins/cortex/README.md @@ -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. diff --git a/plugins/cortex/scripts/plugin-setup.sh b/plugins/cortex/scripts/plugin-setup.sh index 1974ffeaf..e50103410 100755 --- a/plugins/cortex/scripts/plugin-setup.sh +++ b/plugins/cortex/scripts/plugin-setup.sh @@ -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() { diff --git a/plugins/cortex/skills/install-cortex/SKILL.md b/plugins/cortex/skills/install-cortex/SKILL.md new file mode 100644 index 000000000..992068882 --- /dev/null +++ b/plugins/cortex/skills/install-cortex/SKILL.md @@ -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. diff --git a/plugins/cortex/skills/install-cortex/agents/openai.yaml b/plugins/cortex/skills/install-cortex/agents/openai.yaml new file mode 100644 index 000000000..c6dbb66dd --- /dev/null +++ b/plugins/cortex/skills/install-cortex/agents/openai.yaml @@ -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 diff --git a/plugins/cortex/skills/install-cortex/references/setup.md b/plugins/cortex/skills/install-cortex/references/setup.md new file mode 100644 index 000000000..d3e9c08a1 --- /dev/null +++ b/plugins/cortex/skills/install-cortex/references/setup.md @@ -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. diff --git a/plugins/cortex/tests/test_install_skill_contract.py b/plugins/cortex/tests/test_install_skill_contract.py new file mode 100644 index 000000000..93f225b39 --- /dev/null +++ b/plugins/cortex/tests/test_install_skill_contract.py @@ -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() diff --git a/scripts/plugin-setup.sh b/scripts/plugin-setup.sh index 1974ffeaf..e50103410 100755 --- a/scripts/plugin-setup.sh +++ b/scripts/plugin-setup.sh @@ -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() { From 434ab50b0cff820d3c11d8242e218b9437ccf4f7 Mon Sep 17 00:00:00 2001 From: Jake Magar Date: Fri, 18 Sep 2026 16:56:22 -0400 Subject: [PATCH 2/2] fix: sync Cortex npm package README --- packages/cortex-rmcp/README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/cortex-rmcp/README.md b/packages/cortex-rmcp/README.md index f8d666343..3be18e671 100644 --- a/packages/cortex-rmcp/README.md +++ b/packages/cortex-rmcp/README.md @@ -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