mirror of
https://github.com/KeygraphHQ/shannon.git
synced 2026-10-03 14:56:50 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6108de3cfc | ||
|
|
7e0464bf79 | ||
|
|
dc2a4fe4e8 | ||
|
|
ed5659e2e2 |
No files matched your search
@@ -53,3 +53,8 @@ SHANNON_AI_MODEL=anthropic:claude-sonnet-4-6
|
|||||||
# https://github.com/KeygraphHQ/shannon/blob/main/docs/ai-providers.md#openai-codex-chatgpt-pluspro-subscription
|
# https://github.com/KeygraphHQ/shannon/blob/main/docs/ai-providers.md#openai-codex-chatgpt-pluspro-subscription
|
||||||
# SHANNON_USE_PI_AUTH=1
|
# SHANNON_USE_PI_AUTH=1
|
||||||
# SHANNON_AI_MODEL=openai-codex:gpt-5.5
|
# SHANNON_AI_MODEL=openai-codex:gpt-5.5
|
||||||
|
|
||||||
|
# Or the guide below to use an xAI subscription
|
||||||
|
# https://github.com/KeygraphHQ/shannon/blob/main/docs/ai-providers.md#xai-grok-subscription
|
||||||
|
# SHANNON_USE_PI_AUTH=1
|
||||||
|
# SHANNON_AI_MODEL=xai:grok-4.6
|
||||||
@@ -152,10 +152,10 @@ Durable workflow orchestration with crash recovery, queryable progress, intellig
|
|||||||
5. **Reporting** (`report`) — Executive-level security report
|
5. **Reporting** (`report`) — Executive-level security report
|
||||||
|
|
||||||
### Supporting Systems
|
### Supporting Systems
|
||||||
- **Configuration** — YAML configs in `apps/worker/configs/` with JSON Schema validation (`config-schema.json`). Supports auth settings (MFA/TOTP), URL/code rule scoping (`rules.avoid`/`rules.focus`), run-scope steering (`vuln_classes`, `exploit`), free-form `rules_of_engagement`, and post-hoc `report` options (`min_severity`, `min_confidence`, `guidance`, and `sarif` to emit a SARIF 2.1.0 log via `apps/worker/src/services/sarif-renderer.ts`; exploit-only). `code_path` avoid rules are enforced via the `@gotgenes/pi-permission-system` extension: `apps/worker/src/temporal/activities.ts:syncCodePathDenyRules` writes a global `path` deny config once per workflow (`apps/worker/src/ai/pi/permission-system.ts:syncPermissionSystemConfig`), and the executor loads the extension when that config is present (`apps/worker/src/ai/pi/pi-executor.ts`), so denies fire across every tool and child `task` session. `vuln_classes`/`exploit` scope is locked into `session.json` on first run; resumes with a different scope fail fast (`persistOrValidateRunScope`). Credential resolution — local mode: env vars → `./.env`; npx mode: env vars → `~/.shannon/config.toml` (via `npx @keygraph/shannon setup`)
|
- **Configuration** — YAML configs in `apps/worker/configs/` with JSON Schema validation (`config-schema.json`). Supports auth settings (MFA/TOTP), URL/code rule scoping (`rules.avoid`/`rules.focus`), run-scope steering (`vuln_classes`, `exploit`), free-form `rules_of_engagement`, and post-hoc `report` options (`min_severity`, `min_confidence`, `guidance`, and `sarif` for a SARIF 2.1.0 log via `apps/worker/src/services/sarif-renderer.ts`, on by default for exploit runs and opt out with `report.sarif: false`). `code_path` avoid rules are enforced via the `@gotgenes/pi-permission-system` extension: `apps/worker/src/temporal/activities.ts:syncCodePathDenyRules` writes a global `path` deny config once per workflow (`apps/worker/src/ai/pi/permission-system.ts:syncPermissionSystemConfig`), and the executor loads the extension when that config is present (`apps/worker/src/ai/pi/pi-executor.ts`), so denies fire across every tool and child `task` session. `vuln_classes`/`exploit` scope is locked into `session.json` on first run; resumes with a different scope fail fast (`persistOrValidateRunScope`). Credential resolution — local mode: env vars → `./.env`; npx mode: env vars → `~/.shannon/config.toml` (via `npx @keygraph/shannon setup`)
|
||||||
- **Prompts** — Per-phase templates in `apps/worker/prompts/` with variable substitution (`{{TARGET_URL}}`, `{{CONFIG_CONTEXT}}`). Shared partials in `apps/worker/prompts/shared/` via `apps/worker/src/services/prompt-manager.ts`, including `_code-path-rules.txt` (focus/avoid `[FILE]`/`[GLOB]` routing) and `_rules-of-engagement.txt` (free-text engagement rules). When `exploit: false`, `apps/worker/src/services/findings-renderer.ts` deterministically converts each `*_exploitation_queue.json` into a `*_findings.md` for report assembly — no LLM in the loop
|
- **Prompts** — Per-phase templates in `apps/worker/prompts/` with variable substitution (`{{TARGET_URL}}`, `{{CONFIG_CONTEXT}}`). Shared partials in `apps/worker/prompts/shared/` via `apps/worker/src/services/prompt-manager.ts`, including `_code-path-rules.txt` (focus/avoid `[FILE]`/`[GLOB]` routing) and `_rules-of-engagement.txt` (free-text engagement rules). When `exploit: false`, `apps/worker/src/services/findings-renderer.ts` deterministically converts each `*_exploitation_queue.json` into a `*_findings.md` for report assembly — no LLM in the loop
|
||||||
- **Agent Harness (pi)** — Uses the **pi harness** (`@earendil-works/pi-coding-agent`, requires Node ≥ 22.19) via `apps/worker/src/ai/pi/pi-executor.ts` (`runPiPrompt` → `createAgentSession`). Retry is split in `apps/worker/src/ai/pi/retry-settings.ts`: pi's agent-level loop is off so Temporal owns agent restarts, while `provider.maxRetries` stays on — pi reads the `provider` block independently of the `enabled` flag — so transport faults are absorbed in-session rather than costing a full agent re-run. `maxRetryDelayMs` is left at pi's 60s default. One model runs every phase, named by `SHANNON_AI_MODEL=<provider>:<model-id>` (default `anthropic:claude-sonnet-4-6`). `apps/worker/src/ai/models.ts` parses the spec — splitting on the **first** colon only, so Bedrock IDs keep theirs — and resolves it through pi's `ModelRuntime`. pi ships the `CredentialStore` interface but no in-memory implementation (its own reads `auth.json` from disk), so `RuntimeCredentialStore` in that file supplies one: credentials arrive as env vars in an ephemeral container and must never touch disk. `createModelRuntime(providerId, apiKey)` builds the runtime; `allowModelNetwork` stays at its default `false` so a scan never blocks on a catalog refresh. `resolveModelSelection()` is **async** because `ModelRuntime.create()` is. Any pi-ai provider id is accepted — `parseModelSpec` no longer rejects against a hardcoded list, so pi's registry is the authority (an unknown provider/model surfaces as a clear "not found in pi registry" error at preflight, which points to the browsable catalogue at `pi.dev/models` — `PI_CATALOG_URL` in `apps/worker/src/ai/models.ts`, appended to the not-found errors and shown in the setup wizard's "Other provider" hint). Four providers are **curated** (`CURATED_PROVIDERS`: `anthropic`, `openai`, `xai`, `amazon-bedrock`) with their own credential variables, config sections, and setup flows; each provider's API key env var is declared once in `PROVIDER_API_KEY_ENV` — Shannon uses each vendor's own variable name (`OPENAI_API_KEY`, `XAI_API_KEY`, …), never an invented one; Bedrock's entry is `AWS_BEARER_TOKEN_BEDROCK`, paired with `AWS_REGION`, which preflight requires separately as provider config rather than a credential. Any other provider uses the **generic** credential path: `SHANNON_AI_API_KEY` (`GENERIC_API_KEY_ENV`) supplies the key for any provider whose credential is a plain API key. Curated providers' own variables take precedence over it, and it also works as a fallback for them — Bedrock is the sole exception (it authenticates through its AWS_ variables, so the generic key never stands in for it). The CLI forwards `SHANNON_AI_API_KEY` in `COMMON_FORWARD_VARS` (it is provider-neutral, binding to whatever `SHANNON_AI_MODEL` names, so the "only one provider configured" guard counts only named credentials), and stores it under a generic `[provider]` config.toml section (`provider.api_key`). `npx @keygraph/shannon setup` exposes this as the "Other provider" option: free-text provider id + model id + key (a curated provider id is rejected there, since it has its own option). `SHANNON_AI_BASE_URL` overrides the endpoint for any provider (proxies/gateways); the credential is unchanged. `pointAtGateway` (`apps/worker/src/ai/models.ts`) applies the one dialect change: behind a base URL, `openai` follows `SHANNON_AI_OPENAI_FORMAT` (`chat-completions` default, or `responses`). On `chat-completions` it switches the API to `openai-completions` and drops the catalogue's Responses-shaped `compat` block so pi's `detectCompat` derives completions settings; on `responses` the descriptor is unchanged but for the endpoint. `resolveGatewayFormat` rejects the variable when the provider is not `openai` or no base URL is set, since it cannot take effect there. All other providers keep their API. The CLI mirrors the accepted values in `apps/cli/src/model-spec.ts`, forwards the variable in `COMMON_FORWARD_VARS`, and maps it to `openai.format` in config.toml. `buildEnvFlags` forwards only the selected provider's credential into the worker container. The CLI mirrors the parse rule and the provider/credential tables in `apps/cli/src/model-spec.ts` (it cannot import from the worker package); the two must stay in sync. pi ships no JSON-schema output or `Task`/`TodoWrite` built-ins, so structured queues are captured via a `submit_exploitation_queue` custom tool (`apps/worker/src/ai/queue-schemas.ts`), and `task` (child sessions scoped to `read`, `grep`, `find`, `ls`, `write`, and `bash` — no nested `task` or collector tools; `CHILD_TOOLS` in `apps/worker/src/ai/pi/task-tool.ts`) + `todo_write` (`apps/worker/src/ai/pi/session-tools.ts`) are provided as custom tools; the per-phase collectors are pi custom tools (TypeBox `defineTool` in `apps/worker/src/collectors/`). Shannon sets no thinking configuration at all — no `thinkingLevel` is passed to any `createAgentSession` call, so pi's own default applies. There Line truncated
|
- **Agent Harness (pi)** — Uses the **pi harness** (`@earendil-works/pi-coding-agent`, requires Node ≥ 22.19) via `apps/worker/src/ai/pi/pi-executor.ts` (`runPiPrompt` → `createAgentSession`). Retry is split in `apps/worker/src/ai/pi/retry-settings.ts`: pi's agent-level loop is off so Temporal owns agent restarts, while `provider.maxRetries` stays on — pi reads the `provider` block independently of the `enabled` flag — so transport faults are absorbed in-session rather than costing a full agent re-run. `maxRetryDelayMs` is left at pi's 60s default. One model runs every phase, named by `SHANNON_AI_MODEL=<provider>:<model-id>` (default `anthropic:claude-sonnet-4-6`). `apps/worker/src/ai/models.ts` parses the spec — splitting on the **first** colon only, so Bedrock IDs keep theirs — and resolves it through pi's `ModelRuntime`. pi ships the `CredentialStore` interface but no in-memory implementation (its own reads `auth.json` from disk), so `RuntimeCredentialStore` in that file supplies one: credentials arrive as env vars in an ephemeral container and must never touch disk. `createModelRuntime(providerId, apiKey)` builds the runtime; `allowModelNetwork` stays at its default `false` so a scan never blocks on a catalog refresh. `resolveModelSelection()` is **async** because `ModelRuntime.create()` is. Any pi-ai provider id is accepted — `parseModelSpec` no longer rejects against a hardcoded list, so pi's registry is the authority (an unknown provider/model surfaces as a clear "not found in pi registry" error at preflight, which points to the browsable catalogue at `pi.dev/models` — `PI_CATALOG_URL` in `apps/worker/src/ai/models.ts`, appended to the not-found errors and shown in the setup wizard's "Other provider" hint). Four providers are **curated** (`CURATED_PROVIDERS`: `anthropic`, `openai`, `xai`, `amazon-bedrock`) with their own credential variables, config sections, and setup flows; each provider's API key env var is declared once in `PROVIDER_API_KEY_ENV` — Shannon uses each vendor's own variable name (`OPENAI_API_KEY`, `XAI_API_KEY`, …), never an invented one; Bedrock's entry is `AWS_BEARER_TOKEN_BEDROCK`, paired with `AWS_REGION`, which preflight requires separately as provider config rather than a credential. Any other provider uses the **generic** credential path: `SHANNON_AI_API_KEY` (`GENERIC_API_KEY_ENV`) supplies the key for any provider whose credential is a plain API key. Curated providers' own variables take precedence over it, and it also works as a fallback for them — Bedrock is the sole exception (it authenticates through its AWS_ variables, so the generic key never stands in for it). The CLI forwards `SHANNON_AI_API_KEY` in `COMMON_FORWARD_VARS` (it is provider-neutral, binding to whatever `SHANNON_AI_MODEL` names, so the "only one provider configured" guard counts only named credentials), and stores it under a generic `[provider]` config.toml section (`provider.api_key`). `npx @keygraph/shannon setup` exposes this as the "Other provider" option: free-text provider id + model id + key (a curated provider id is rejected there, since it has its own option). `SHANNON_AI_BASE_URL` overrides the endpoint for any provider (proxies/gateways); the credential is unchanged. `pointAtGateway` (`apps/worker/src/ai/models.ts`) applies the one dialect change: behind a base URL, `openai` follows `SHANNON_AI_OPENAI_FORMAT` (`chat-completions` default, or `responses`). On `chat-completions` it switches the API to `openai-completions` and drops the catalogue's Responses-shaped `compat` block so pi's `detectCompat` derives completions settings; on `responses` the descriptor is unchanged but for the endpoint. `resolveGatewayFormat` rejects the variable when the provider is not `openai` or no base URL is set, since it cannot take effect there. All other providers keep their API. The CLI mirrors the accepted values in `apps/cli/src/model-spec.ts`, forwards the variable in `COMMON_FORWARD_VARS`, and maps it to `openai.format` in config.toml. `buildEnvFlags` forwards only the selected provider's credential into the worker container. The CLI mirrors the parse rule and the provider/credential tables in `apps/cli/src/model-spec.ts` (it cannot import from the worker package); the two must stay in sync. pi ships no JSON-schema output or `Task`/`TodoWrite` built-ins, so structured queues are captured via a `submit_exploitation_queue` custom tool (`apps/worker/src/ai/queue-schemas.ts`), and `task` (child sessions scoped to `read`, `grep`, `find`, `ls`, `write`, and `bash` — no nested `task` or collector tools; `CHILD_TOOLS` in `apps/worker/src/ai/pi/task-tool.ts`) + `todo_write` (`apps/worker/src/ai/pi/session-tools.ts`) are provided as custom tools; the per-phase collectors are pi custom tools (TypeBox `defineTool` in `apps/worker/src/collectors/`). Shannon sets no thinking configuration at all — no `thinkingLevel` is passed to any `createAgentSession` call, so pi's own default applies. There Line truncated
|
||||||
- **Pi Credential Reuse** — `SHANNON_USE_PI_AUTH=1` opts into reusing the host's Pi login, including an `openai-codex` ChatGPT Plus/Pro subscription selected with `SHANNON_AI_MODEL=openai-codex:<model-id>`. `apps/cli/src/env.ts` requires `~/.pi/agent/auth.json`; `start.ts` passes its path to `spawnWorker`, which mounts only that file read-write at `/tmp/.pi/agent/auth.json`. The flag itself is not forwarded: the worker detects the file with `piAuthPresent()` and passes its path to `ModelRuntime.create`. CLI and worker API-key presence checks are skipped on this path, but the normal preflight model probe still validates the credential. The image and UID-remapping entrypoint keep `/tmp/.pi/agent` owned by `pentest` so adjacent Pi/Shannon configuration remains writable. Refreshed OAuth state is persisted to the host for subsequent scans.
|
- **Pi Credential Reuse** — `SHANNON_USE_PI_AUTH=1` opts into reusing the host's Pi login, including an `openai-codex` ChatGPT Plus/Pro subscription (`SHANNON_AI_MODEL=openai-codex:<model-id>`) or an `xai` Grok subscription (`SHANNON_AI_MODEL=xai:<model-id>`); the mechanism is provider-agnostic and works for any Pi login. `apps/cli/src/env.ts` requires `~/.pi/agent/auth.json`; `start.ts` passes its path to `spawnWorker`, which mounts only that file read-write at `/tmp/.pi/agent/auth.json`. The flag itself is not forwarded: the worker detects the file with `piAuthPresent()` and passes its path to `ModelRuntime.create`. CLI and worker API-key presence checks are skipped on this path, but the normal preflight model probe still validates the credential. The image and UID-remapping entrypoint keep `/tmp/.pi/agent` owned by `pentest` so adjacent Pi/Shannon configuration remains writable. Refreshed OAuth state is persisted to the host for subsequent scans.
|
||||||
- **Audit System** — Crash-safe append-only logging in `workspaces/{hostname}_{sessionId}/`. The run directory's top level holds the human-facing report in both formats (`Security-Assessment-Report.pdf` and `Security-Assessment-Report.md`, `FINAL_REPORT_PDF_FILENAME`/`FINAL_REPORT_MD_FILENAME` in `apps/worker/src/paths.ts`); everything else — deliverables, per-agent logs, prompts, `session.json`, `workflow.log`, and browser artifacts — is nested under a hidden `.shannon/` internals dir (`INTERNAL_DIR`) so a customer sees only the report. Audit path helpers route through `generateInternalPath` (`apps/worker/src/audit/utils.ts`); the CLI nests the overlay backing dirs under the same `.shannon/` (`apps/cli/src/docker.ts`, `start.ts`). `session.json`/`workflow.log` reads use dual-read resolvers (`resolveSessionJsonPath`, `resolveRunFile`) that prefer `.shannon/` and fall back to the legacy run-root layout, so pre-restructure workspaces stay listable (`workspaces`/`logs`) without migration. Resuming a pre-restructure workspace upgrades it in place first: `migrateLegacyWorkspaceLayout` (`apps/cli/src/commands/start.ts`) renames the flat deliverables/logs/session entries into `.shannon/` (carrying the deliverables `.git` along) before the overlay dirs are mounted, so resume finds the old checkpoints instead of re-running every agent. The report agent writes structured findings to `report.json`, from which `report-renderer.ts` renders the assembled markdown and `report-json-adapter.ts` produces the Typst-shaped JSON that `pdf-renderer.ts` compiles into `comprehensive_security_assessment_report.pdf` using the bundled `apps/worker/templates/typst/report.typ` template (the `typst` binary is installed in the worker image). `copyReportToRunRoot` (`apps/worker/src/services/reporting.ts`) surfaces both the PDF and the markdown to the run root as `Security-Assessment-Report.pdf` and `Security-Assessment-Report.md`; the deliverables-dir copies remain as the git-checkpointed sources. PDF compilation is best-effort — a failure is logged and the run still completes. WorkflowLogger (`apps/worker/src/audit/workflow-logger.ts`) provides unified human-readable per-workflow logs, backed by LogStream (`apps/worker/src/audit/log-stream.ts`) shared stream primitive
|
- **Audit System** — Crash-safe append-only logging in `workspaces/{hostname}_{sessionId}/`. The run directory's top level holds the human-facing report in both formats (`Security-Assessment-Report.pdf` and `Security-Assessment-Report.md`, `FINAL_REPORT_PDF_FILENAME`/`FINAL_REPORT_MD_FILENAME` in `apps/worker/src/paths.ts`); everything else — deliverables, per-agent logs, prompts, `session.json`, `workflow.log`, and browser artifacts — is nested under a hidden `.shannon/` internals dir (`INTERNAL_DIR`) so a customer sees only the report. Audit path helpers route through `generateInternalPath` (`apps/worker/src/audit/utils.ts`); the CLI nests the overlay backing dirs under the same `.shannon/` (`apps/cli/src/docker.ts`, `start.ts`). `session.json`/`workflow.log` reads use dual-read resolvers (`resolveSessionJsonPath`, `resolveRunFile`) that prefer `.shannon/` and fall back to the legacy run-root layout, so pre-restructure workspaces stay listable (`workspaces`/`logs`) without migration. Resuming a pre-restructure workspace upgrades it in place first: `migrateLegacyWorkspaceLayout` (`apps/cli/src/commands/start.ts`) renames the flat deliverables/logs/session entries into `.shannon/` (carrying the deliverables `.git` along) before the overlay dirs are mounted, so resume finds the old checkpoints instead of re-running every agent. The report agent writes structured findings to `report.json`, from which `report-renderer.ts` renders the assembled markdown and `report-json-adapter.ts` produces the Typst-shaped JSON that `pdf-renderer.ts` compiles into `comprehensive_security_assessment_report.pdf` using the bundled `apps/worker/templates/typst/report.typ` template (the `typst` binary is installed in the worker image). `copyReportToRunRoot` (`apps/worker/src/services/reporting.ts`) surfaces both the PDF and the markdown to the run root as `Security-Assessment-Report.pdf` and `Security-Assessment-Report.md`; the deliverables-dir copies remain as the git-checkpointed sources. PDF compilation is best-effort — a failure is logged and the run still completes. WorkflowLogger (`apps/worker/src/audit/workflow-logger.ts`) provides unified human-readable per-workflow logs, backed by LogStream (`apps/worker/src/audit/log-stream.ts`) shared stream primitive
|
||||||
- **Deliverables** — Saved to `.shannon/deliverables/` in the target repo via the `save-deliverable` CLI script (`apps/worker/src/scripts/save-deliverable.ts`)
|
- **Deliverables** — Saved to `.shannon/deliverables/` in the target repo via the `save-deliverable` CLI script (`apps/worker/src/scripts/save-deliverable.ts`)
|
||||||
- **Workspaces & Resume** — Named workspaces via `-w <name>` or auto-named from URL+timestamp. Resume detects completed agents via `session.json`. `loadResumeState()` in `apps/worker/src/temporal/activities.ts` validates deliverable existence, restores git checkpoints, and cleans up incomplete deliverables
|
- **Workspaces & Resume** — Named workspaces via `-w <name>` or auto-named from URL+timestamp. Resume detects completed agents via `session.json`. `loadResumeState()` in `apps/worker/src/temporal/activities.ts` validates deliverable existence, restores git checkpoints, and cleans up incomplete deliverables
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<picture>
|
<picture>
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./assets/github-banner-dark.png">
|
<source media="(prefers-color-scheme: dark)" srcset="./assets/github-banner-dark.png">
|
||||||
<source media="(prefers-color-scheme: light)" srcset="./assets/github-banner-light.png">
|
<source media="(prefers-color-scheme: light)" srcset="./assets/github-banner-light.png">
|
||||||
<img src="./assets/github-banner.png" alt="Shannon - AI Pentester by Keygraph" width="100%">
|
<img src="./assets/github-banner-light.png" alt="Shannon, AI Pentester for Web Apps and APIs, by Keygraph" width="100%">
|
||||||
</picture>
|
</picture>
|
||||||
|
|
||||||
<a href="https://trendshift.io/repositories/15604" target="_blank"><img src="https://trendshift.io/api/badge/repositories/15604" alt="KeygraphHQ%2Fshannon | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
<a href="https://trendshift.io/repositories/15604" target="_blank"><img src="https://trendshift.io/api/badge/repositories/15604" alt="KeygraphHQ%2Fshannon | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||||
@@ -101,6 +101,7 @@ For source builds, authenticated scans, provider-specific setup, and platform no
|
|||||||
> **Prefer to use a subscription instead of API credits?**
|
> **Prefer to use a subscription instead of API credits?**
|
||||||
>
|
>
|
||||||
> - **OpenAI Codex:** The latest version of Shannon supports ChatGPT Plus and Pro subscriptions. Follow the [OpenAI Codex subscription setup guide](docs/ai-providers.md#openai-codex-chatgpt-pluspro-subscription) to get started.
|
> - **OpenAI Codex:** The latest version of Shannon supports ChatGPT Plus and Pro subscriptions. Follow the [OpenAI Codex subscription setup guide](docs/ai-providers.md#openai-codex-chatgpt-pluspro-subscription) to get started.
|
||||||
|
> - **xAI (Grok):** The latest version of Shannon supports xAI subscriptions. Follow the [xAI subscription setup guide](docs/ai-providers.md#xai-grok-subscription) to get started.
|
||||||
> - **Claude Code:** The latest version of Shannon does not support Claude Code subscriptions. Follow the [Claude Code subscription setup guide](docs/ai-providers.md#claude-code-subscription) to use version `1.9.0`, which is the final release built on the Claude Agent SDK.
|
> - **Claude Code:** The latest version of Shannon does not support Claude Code subscriptions. Follow the [Claude Code subscription setup guide](docs/ai-providers.md#claude-code-subscription) to use version `1.9.0`, which is the final release built on the Claude Agent SDK.
|
||||||
|
|
||||||
## Key Capabilities
|
## Key Capabilities
|
||||||
@@ -111,7 +112,7 @@ For source builds, authenticated scans, provider-specific setup, and platform no
|
|||||||
- **Authenticated testing**: configuration files can describe login flows, test credentials, TOTP, email-based login flows, focus areas, and rules of engagement.
|
- **Authenticated testing**: configuration files can describe login flows, test credentials, TOTP, email-based login flows, focus areas, and rules of engagement.
|
||||||
- **OWASP-focused coverage**: Shannon targets exploitable Injection, XSS, SSRF, Broken Authentication, and Broken Authorization issues.
|
- **OWASP-focused coverage**: Shannon targets exploitable Injection, XSS, SSRF, Broken Authentication, and Broken Authorization issues.
|
||||||
- **Resumable workspaces**: Shannon can resume interrupted runs without re-running completed agents.
|
- **Resumable workspaces**: Shannon can resume interrupted runs without re-running completed agents.
|
||||||
- **Machine-readable output**: Shannon emits findings as structured JSON, and as SARIF 2.1.0 when you enable it in configuration. SARIF is the OASIS standard for static analysis results, so findings flow into any code scanning service, vulnerability management platform, security dashboard, or CI/CD pipeline that reads it.
|
- **Machine-readable output**: Shannon emits findings as structured JSON, and as SARIF 2.1.0 by default on exploit-mode scans (opt out with `report.sarif: "false"`). SARIF is the OASIS standard for static analysis results, so findings flow into any code scanning service, vulnerability management platform, security dashboard, or CI/CD pipeline that reads it.
|
||||||
- **Bring your own key, provider-agnostic**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any endpoint speaking the Anthropic Messages API or the OpenAI Chat Completions or Responses API, including self-hosted models served through Ollama, vLLM, or LM Studio and gateways such as OpenRouter and LiteLLM. You supply the credentials, so source code and model traffic stay inside your infrastructure. Local and self-hosted models are technically supported but not recommended: they may not follow Shannon's instructions or tool-use constraints as reliably as frontier models, so take that path only if you know how your chosen model behaves.
|
- **Bring your own key, provider-agnostic**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any endpoint speaking the Anthropic Messages API or the OpenAI Chat Completions or Responses API, including self-hosted models served through Ollama, vLLM, or LM Studio and gateways such as OpenRouter and LiteLLM. You supply the credentials, so source code and model traffic stay inside your infrastructure. Local and self-hosted models are technically supported but not recommended: they may not follow Shannon's instructions or tool-use constraints as reliably as frontier models, so take that path only if you know how your chosen model behaves.
|
||||||
|
|
||||||
## Editions
|
## Editions
|
||||||
@@ -267,7 +268,7 @@ Yes, always. You provide the LLM credentials Shannon uses to run a pentest, in e
|
|||||||
|
|
||||||
### Does Shannon output SARIF?
|
### Does Shannon output SARIF?
|
||||||
|
|
||||||
Yes. Shannon emits SARIF 2.1.0, the OASIS standard format for static analysis results, alongside structured JSON. Any SARIF consumer reads it: code scanning services, vulnerability management platforms, security dashboards, and CI/CD pipelines. Set `report.sarif` to `"true"` in your configuration file to enable the SARIF log.
|
Yes. Shannon emits SARIF 2.1.0, the OASIS standard format for static analysis results, alongside structured JSON. Any SARIF consumer reads it: code scanning services, vulnerability management platforms, security dashboards, and CI/CD pipelines. It is written by default on exploit-mode scans; set `report.sarif` to `"false"` in your configuration file to opt out.
|
||||||
|
|
||||||
### Which AI providers does Shannon support?
|
### Which AI providers does Shannon support?
|
||||||
|
|
||||||
|
|||||||
+49
-11
@@ -1,22 +1,60 @@
|
|||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/github-banner.png" alt="Shannon — AI Pentester for Web Applications and APIs" width="100%">
|
<img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/github-banner-light.png" alt="Shannon, AI Pentester for Web Apps and APIs, by Keygraph" width="100%">
|
||||||
|
|
||||||
# Shannon — AI Pentester by Keygraph
|
### Shannon is an autonomous, AI pentester for web applications and APIs.
|
||||||
|
|
||||||
Shannon is an autonomous, white-box AI pentester for web applications and APIs. <br />
|
It analyzes your source code, identifies attack paths, and executes real exploits to prove vulnerabilities before they reach production.
|
||||||
It analyzes your source code, identifies attack vectors, and executes real exploits to prove vulnerabilities before they reach production.
|
|
||||||
|
**This package is Shannon Open Source: the full agent, run locally from your command line.**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<a href="https://github.com/KeygraphHQ/shannon/discussions/categories/announcements"><img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/announcements.png" height="40" alt="Announcements"></a>
|
<a href="https://discord.gg/9ZqQPuhJB7"><img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/discord_button_light.png" height="40" alt="Join Discord"></a> <a href="https://keygraph.io/"><img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/keygraph_button_light.png" height="40" alt="Visit Keygraph.io"></a>
|
||||||
<a href="https://discord.gg/9ZqQPuhJB7"><img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/discord.png" height="40" alt="Join Discord"></a>
|
|
||||||
<a href="https://keygraph.io/"><img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/Keygraph_Button.png" height="40" alt="Visit Keygraph.io"></a>
|
|
||||||
<a href="https://www.linkedin.com/company/keygraph/"><img src="https://raw.githubusercontent.com/KeygraphHQ/shannon/main/assets/linkedin.png" height="40" alt="Follow Us on Linkedin"></a>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Full README and usage guide**
|
|
||||||
[https://github.com/KeygraphHQ/shannon#readme](https://github.com/KeygraphHQ/shannon#readme)
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- **Docker**: required for the worker container.
|
||||||
|
- **Node.js 18+**: required for the recommended `npx` workflow.
|
||||||
|
- **AI provider credentials**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, any other provider in the harness catalogue, and any endpoint that speaks the Anthropic Messages API or the OpenAI Chat Completions or Responses API through a custom base URL. You bring your own key, and Keygraph never proxies your model traffic. Shannon is provider-agnostic.
|
||||||
|
- **Cyber safeguards cleared with your provider**: Anthropic and OpenAI apply real-time safeguards to cyber-security workloads, which can interrupt a scan mid-run. Complete their guidance for legitimate security testers before your first run.
|
||||||
|
|
||||||
|
### Run Shannon
|
||||||
|
|
||||||
|
> **Warning:** Shannon actively executes exploits. Run it only against applications and environments you own or have explicit written authorization to test. Do not run Shannon against production systems.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Configure credentials with the interactive wizard.
|
||||||
|
npx @keygraph/shannon setup
|
||||||
|
|
||||||
|
# Run a pentest against a source-available target.
|
||||||
|
npx @keygraph/shannon start -u https://your-app.com -r /path/to/your-repo
|
||||||
|
```
|
||||||
|
|
||||||
|
Shannon pulls the worker image from Docker Hub, starts the required local infrastructure, mounts the target repository read-only inside an ephemeral worker container, and writes results to a local workspace.
|
||||||
|
|
||||||
|
## Editions
|
||||||
|
|
||||||
|
Shannon ships in two ways. **Shannon Open Source** is this package: the standalone pentester you run yourself, on demand, and complete in that lane. The **Keygraph platform** is the commercial product that runs an enhanced build of Shannon continuously and closes the full AppSec lifecycle around it - code analysis, finding management, automated remediation, verification, and enterprise deployment.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
**Full README, guides, and usage documentation:** [github.com/KeygraphHQ/shannon](https://github.com/KeygraphHQ/shannon#readme)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Shannon Open Source is licensed under the [GNU Affero General Public License v3.0](https://github.com/KeygraphHQ/shannon/blob/main/LICENSE).
|
||||||
|
|
||||||
|
Commercial and enterprise licensing is available for organizations that need different license terms, commercial support, private redistribution, managed-service use, or broader deployment options, including the Keygraph platform.
|
||||||
|
|
||||||
|
For commercial licensing, contact [shannon@keygraph.io](mailto:shannon@keygraph.io).
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<b>Built by <a href="https://keygraph.io">Keygraph</a></b>
|
||||||
|
</p>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@keygraph/shannon",
|
"name": "@keygraph/shannon",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"description": "Shannon - Autonomous white-box AI pentester for web applications and APIs by Keygraph",
|
"description": "Shannon is an autonomous white-box AI pentester for web applications and APIs, by Keygraph.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.mjs",
|
"main": "dist/index.mjs",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -35,8 +35,12 @@
|
|||||||
"appsec",
|
"appsec",
|
||||||
"keygraph"
|
"keygraph"
|
||||||
],
|
],
|
||||||
"author": "",
|
"author": "Keygraph, Inc.",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/KeygraphHQ/shannon/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/KeygraphHQ/shannon#readme",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/KeygraphHQ/shannon.git",
|
"url": "git+https://github.com/KeygraphHQ/shannon.git",
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import {
|
|||||||
} from '../paths.js';
|
} from '../paths.js';
|
||||||
import { indentFailureSegments } from '../scan/failure.js';
|
import { indentFailureSegments } from '../scan/failure.js';
|
||||||
import { resolveWorkflowId } from '../session.js';
|
import { resolveWorkflowId } from '../session.js';
|
||||||
import { displaySplash } from '../splash.js';
|
import { displayPlainBanner, displaySplash } from '../splash.js';
|
||||||
import { getTerminalOutcome } from '../temporal-client.js';
|
import { getTerminalOutcome } from '../temporal-client.js';
|
||||||
import { stdoutIsTerminal } from '../tty.js';
|
import { stdoutIsTerminal } from '../tty.js';
|
||||||
import { tailUntilComplete } from './logs.js';
|
import { tailUntilComplete } from './logs.js';
|
||||||
@@ -81,10 +81,12 @@ export async function start(args: StartArgs): Promise<void> {
|
|||||||
const repo = resolveRepo(args.repo);
|
const repo = resolveRepo(args.repo);
|
||||||
const config = args.config ? resolveConfig(args.config) : undefined;
|
const config = args.config ? resolveConfig(args.config) : undefined;
|
||||||
|
|
||||||
// Inputs are valid — show the splash before the Docker/Temporal setup work.
|
// Inputs are valid — identify the run before the Docker/Temporal setup work.
|
||||||
// Skip it off a real terminal (e.g. CI) so piped/logged output stays clean.
|
const bannerVersion = isLocal() ? undefined : args.version;
|
||||||
if (stdoutIsTerminal()) {
|
if (stdoutIsTerminal()) {
|
||||||
displaySplash(isLocal() ? undefined : args.version);
|
displaySplash(bannerVersion);
|
||||||
|
} else {
|
||||||
|
displayPlainBanner(bannerVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Ensure workspaces dir is writable by container user (UID 1001)
|
// 4. Ensure workspaces dir is writable by container user (UID 1001)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Shannon CLI — AI Penetration Testing Framework
|
* Shannon CLI — AI Pentester for Web Apps and APIs
|
||||||
*
|
*
|
||||||
* Unified CLI supporting two modes:
|
* Unified CLI supporting two modes:
|
||||||
* Local mode: Run from cloned repo — builds locally, mounts prompts, uses ./workspaces/
|
* Local mode: Run from cloned repo — builds locally, mounts prompts, uses ./workspaces/
|
||||||
@@ -79,7 +79,7 @@ function showHelp(withSplash: boolean): void {
|
|||||||
const mode = getMode();
|
const mode = getMode();
|
||||||
const prefix = commandPrefix();
|
const prefix = commandPrefix();
|
||||||
|
|
||||||
const header = withSplash ? '' : '\nShannon - AI Penetration Testing Framework\n';
|
const header = withSplash ? '' : '\nShannon — AI Pentester by Keygraph\n';
|
||||||
|
|
||||||
console.log(`${header}
|
console.log(`${header}
|
||||||
Usage:
|
Usage:
|
||||||
|
|||||||
@@ -75,3 +75,20 @@ export function displaySplash(version?: string): void {
|
|||||||
|
|
||||||
console.log(lines.join('\n'));
|
console.log(lines.join('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Matches the divider width the CI wrappers and the scan renderer already use. */
|
||||||
|
const RULE_WIDTH = 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plain-text banner for non-terminal output (CI logs, pipes, redirects).
|
||||||
|
* Drops the wordmark but keeps the authorized-use notice, which a reader of
|
||||||
|
* someone else's pipeline log still needs to see.
|
||||||
|
*/
|
||||||
|
export function displayPlainBanner(version?: string): void {
|
||||||
|
const rule = '─'.repeat(RULE_WIDTH);
|
||||||
|
console.log(rule);
|
||||||
|
console.log(version ? ` Shannon v${version}` : ' Shannon');
|
||||||
|
console.log(' AI Pentester for Web Apps and APIs, by Keygraph');
|
||||||
|
console.log(' Authorized security testing only.');
|
||||||
|
console.log(rule);
|
||||||
|
}
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
"sarif": {
|
"sarif": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["true", "false"],
|
"enum": ["true", "false"],
|
||||||
"description": "Emit a SARIF 2.1.0 log (report.sarif) beside the report. Requires exploit=true; ignored otherwise."
|
"description": "Emit a SARIF 2.1.0 log (report.sarif) beside the report. On by default for exploit runs; set \"false\" to opt out. Ignored when exploit=false."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
|||||||
@@ -96,8 +96,9 @@ rules:
|
|||||||
# Report filters applied by the report agent when assembling the final report (optional).
|
# Report filters applied by the report agent when assembling the final report (optional).
|
||||||
# Example below is illustrative; edit, remove, or add sections as needed.
|
# Example below is illustrative; edit, remove, or add sections as needed.
|
||||||
# report:
|
# report:
|
||||||
# # Emit a SARIF 2.1.0 log (report.sarif) beside the report. Requires exploit: "true".
|
# # SARIF 2.1.0 log (report.sarif) beside the report. On by default for exploit runs;
|
||||||
# sarif: "true"
|
# # set "false" to opt out. Ignored when exploit is "false".
|
||||||
|
# sarif: "false"
|
||||||
# min_severity: low
|
# min_severity: low
|
||||||
# min_confidence: low
|
# min_confidence: low
|
||||||
# guidance: |
|
# guidance: |
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
"clean": "rm -rf dist"
|
"clean": "rm -rf dist"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@earendil-works/pi-agent-core": "^0.82.1",
|
"@earendil-works/pi-agent-core": "^0.84.2",
|
||||||
"@earendil-works/pi-ai": "^0.82.1",
|
"@earendil-works/pi-ai": "^0.84.2",
|
||||||
"@earendil-works/pi-coding-agent": "^0.82.1",
|
"@earendil-works/pi-coding-agent": "^0.84.2",
|
||||||
"@gotgenes/pi-permission-system": "^10.9.0",
|
"@gotgenes/pi-permission-system": "^10.9.0",
|
||||||
"@temporalio/activity": "^1.11.0",
|
"@temporalio/activity": "^1.11.0",
|
||||||
"@temporalio/client": "^1.11.0",
|
"@temporalio/client": "^1.11.0",
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (C) 2025 Keygraph, Inc.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Centralized brand strings for report deliverables.
|
||||||
|
*
|
||||||
|
* Kept in two parts because the two renderers join them differently: the Typst
|
||||||
|
* template splits its `brand` input on a pipe to set the cover's two lines
|
||||||
|
* (`report.typ:212`), while a human-read line takes an em dash.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const PRODUCT_NAME = 'Shannon';
|
||||||
|
export const PRODUCT_DESCRIPTOR = 'AI Pentester by Keygraph';
|
||||||
|
|
||||||
|
/** Cover wordmark for the Typst template, which parses the pipe. */
|
||||||
|
export const TYPST_BRAND = `${PRODUCT_NAME} | ${PRODUCT_DESCRIPTOR}`;
|
||||||
|
|
||||||
|
/** Attribution line for prose surfaces. */
|
||||||
|
export const BRAND_LOCKUP = `${PRODUCT_NAME} — ${PRODUCT_DESCRIPTOR}`;
|
||||||
@@ -679,7 +679,8 @@ export const distributeConfig = (config: Config | null): DistributedConfig => {
|
|||||||
const exploit = config?.exploit !== undefined ? config.exploit === 'true' : true;
|
const exploit = config?.exploit !== undefined ? config.exploit === 'true' : true;
|
||||||
|
|
||||||
const report = {
|
const report = {
|
||||||
sarif: config?.report?.sarif === 'true',
|
// Default on; only an explicit "false" opts out.
|
||||||
|
sarif: config?.report?.sarif !== 'false',
|
||||||
...(config?.report?.min_severity && { min_severity: config.report.min_severity }),
|
...(config?.report?.min_severity && { min_severity: config.report.min_severity }),
|
||||||
...(config?.report?.min_confidence && { min_confidence: config.report.min_confidence }),
|
...(config?.report?.min_confidence && { min_confidence: config.report.min_confidence }),
|
||||||
...(config?.report?.guidance && { guidance: config.report.guidance.trim() }),
|
...(config?.report?.guidance && { guidance: config.report.guidance.trim() }),
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export const FINAL_REPORT_MD_FILENAME = 'Security-Assessment-Report.md';
|
|||||||
/** Structured findings the report agent emits; the markdown report is rendered from it. */
|
/** Structured findings the report agent emits; the markdown report is rendered from it. */
|
||||||
export const REPORT_JSON_FILENAME = 'report.json';
|
export const REPORT_JSON_FILENAME = 'report.json';
|
||||||
|
|
||||||
/** SARIF 2.1.0 log, written only for exploit=true runs when report.sarif is enabled. */
|
/** SARIF 2.1.0 log, written for exploit=true runs unless report.sarif is set to false. */
|
||||||
export const SARIF_FILENAME = 'report.sarif';
|
export const SARIF_FILENAME = 'report.sarif';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function getAgentGitPaths(agentName: AgentName): string[] {
|
|||||||
paths.push(queueFilename);
|
paths.push(queueFilename);
|
||||||
}
|
}
|
||||||
// The report agent also emits the structured findings the markdown is rendered from, and the
|
// The report agent also emits the structured findings the markdown is rendered from, and the
|
||||||
// SARIF log when enabled. Listing the log unconditionally is harmless when it was not written,
|
// SARIF log when produced. Listing the log unconditionally is harmless when it was not written,
|
||||||
// and keeps a stale one from surviving the rollback of a failed attempt.
|
// and keeps a stale one from surviving the rollback of a failed attempt.
|
||||||
if (agentName === 'report') {
|
if (agentName === 'report') {
|
||||||
paths.push(REPORT_JSON_FILENAME);
|
paths.push(REPORT_JSON_FILENAME);
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ import { copyFile, cp, mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|||||||
import { tmpdir } from 'node:os';
|
import { tmpdir } from 'node:os';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { promisify } from 'node:util';
|
import { promisify } from 'node:util';
|
||||||
|
import { TYPST_BRAND } from '../branding.js';
|
||||||
import { adaptReportToTypst } from './report-json-adapter.js';
|
import { adaptReportToTypst } from './report-json-adapter.js';
|
||||||
import type { ReportData } from './report-renderer.js';
|
import type { ReportData } from './report-renderer.js';
|
||||||
|
|
||||||
const execFileAsync = promisify(execFile);
|
const execFileAsync = promisify(execFile);
|
||||||
|
|
||||||
const DEFAULT_TESTER = 'Shannon';
|
const DEFAULT_TESTER = 'Shannon';
|
||||||
const DEFAULT_BRAND = 'Shannon | AI Pentester by Keygraph';
|
const DEFAULT_BRAND = TYPST_BRAND;
|
||||||
|
|
||||||
const DATA_FILENAME = 'data.json';
|
const DATA_FILENAME = 'data.json';
|
||||||
const TEMPLATE_FILENAME = 'report.typ';
|
const TEMPLATE_FILENAME = 'report.typ';
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
* report agent previously wrote by hand. No LLM in the loop.
|
* report agent previously wrote by hand. No LLM in the loop.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { BRAND_LOCKUP } from '../branding.js';
|
||||||
import type { AddFindingInput, AdditionalSection, StepItem, StructuredStep } from '../collectors/finding-collector.js';
|
import type { AddFindingInput, AdditionalSection, StepItem, StructuredStep } from '../collectors/finding-collector.js';
|
||||||
import type { VulnClass } from '../types/config.js';
|
import type { VulnClass } from '../types/config.js';
|
||||||
|
|
||||||
@@ -212,6 +213,8 @@ export function renderReport(data: ReportData): string {
|
|||||||
// 1. Executive Summary
|
// 1. Executive Summary
|
||||||
sections.push('# Security Assessment Report');
|
sections.push('# Security Assessment Report');
|
||||||
sections.push('');
|
sections.push('');
|
||||||
|
sections.push(`*${BRAND_LOCKUP}*`);
|
||||||
|
sections.push('');
|
||||||
sections.push('## Executive Summary');
|
sections.push('## Executive Summary');
|
||||||
sections.push(`- Target: ${report_meta.target}`);
|
sections.push(`- Target: ${report_meta.target}`);
|
||||||
sections.push(`- Assessment Date: ${report_meta.assessment_date}`);
|
sections.push(`- Assessment Date: ${report_meta.assessment_date}`);
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ export async function injectModelIntoReport(
|
|||||||
*
|
*
|
||||||
* The SARIF log is surfaced beside it when present, since a CI step consuming it needs a stable
|
* The SARIF log is surfaced beside it when present, since a CI step consuming it needs a stable
|
||||||
* path and cannot be expected to reach into the internals directory. It is absent whenever the
|
* path and cannot be expected to reach into the internals directory. It is absent whenever the
|
||||||
* run was analysis-only or `report.sarif` was not enabled.
|
* run was analysis-only or `report.sarif` was set to false.
|
||||||
*/
|
*/
|
||||||
export async function copyReportToRunRoot(
|
export async function copyReportToRunRoot(
|
||||||
repoPath: string,
|
repoPath: string,
|
||||||
|
|||||||
@@ -450,13 +450,14 @@ export async function runAuthzExploitAgent(input: ActivityInput): Promise<AgentM
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write report.sarif when the run is exploitative and the operator asked for it.
|
* Write report.sarif for exploitative runs unless the operator opted out with report.sarif: false.
|
||||||
*
|
*
|
||||||
* Skipped entirely for analysis-only runs. The original reason was that those findings carried
|
* On by default so a CI step consuming the log always finds one. Skipped for analysis-only runs.
|
||||||
* no severity, so every `result.level` would have been invented; since severity is recorded in
|
* The original reason was that those findings carried no severity, so every `result.level` would
|
||||||
* both modes an analysis run could now populate `level`, but it would report an assessed
|
* have been invented; since severity is recorded in both modes an analysis run could now populate
|
||||||
* severity as a measured one, so the gate stays. Failures are logged and swallowed — the SARIF
|
* `level`, but it would report an assessed severity as a measured one, so the gate stays. Failures
|
||||||
* log is a secondary artifact and must not fail a run whose report is already written.
|
* are logged and swallowed — the SARIF log is a secondary artifact and must not fail a run whose
|
||||||
|
* report is already written.
|
||||||
*/
|
*/
|
||||||
async function writeSarifIfEnabled(
|
async function writeSarifIfEnabled(
|
||||||
input: ActivityInput,
|
input: ActivityInput,
|
||||||
@@ -469,7 +470,8 @@ async function writeSarifIfEnabled(
|
|||||||
|
|
||||||
const container = getOrCreateContainer(input.workflowId, buildSessionMetadata(input), buildContainerConfig(input));
|
const container = getOrCreateContainer(input.workflowId, buildSessionMetadata(input), buildContainerConfig(input));
|
||||||
const configResult = await container.configLoader.loadOptional(input.configPath, undefined, input.configYAML);
|
const configResult = await container.configLoader.loadOptional(input.configPath, undefined, input.configYAML);
|
||||||
if (isErr(configResult) || configResult.value?.report?.sarif !== true) return;
|
// Only an explicit false opts out; a missing config keeps the default on.
|
||||||
|
if (isErr(configResult) || configResult.value?.report?.sarif === false) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { renderSarif } = await import('../services/sarif-renderer.js');
|
const { renderSarif } = await import('../services/sarif-renderer.js');
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ export interface ReportConfig {
|
|||||||
min_severity?: Severity;
|
min_severity?: Severity;
|
||||||
min_confidence?: Confidence;
|
min_confidence?: Confidence;
|
||||||
guidance?: string;
|
guidance?: string;
|
||||||
/** Emit report.sarif alongside the markdown report. Ignored when exploit is false. */
|
/**
|
||||||
|
* Emit report.sarif alongside the markdown report. On by default for exploit runs; set 'false'
|
||||||
|
* to opt out. Ignored when exploit is false.
|
||||||
|
*/
|
||||||
sarif?: 'true' | 'false';
|
sarif?: 'true' | 'false';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-1
@@ -58,7 +58,7 @@ These are the models `npx @keygraph/shannon setup` offers, best-first. They are
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `anthropic` | `claude-sonnet-4-6`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-haiku-4-5-20251001` |
|
| `anthropic` | `claude-sonnet-4-6`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-haiku-4-5-20251001` |
|
||||||
| `openai` | `gpt-5.6-sol`, `gpt-5.5`, `gpt-5.4` |
|
| `openai` | `gpt-5.6-sol`, `gpt-5.5`, `gpt-5.4` |
|
||||||
| `xai` | `grok-4.5` |
|
| `xai` | `grok-4.6`, `grok-4.5` |
|
||||||
| `amazon-bedrock` | `us.anthropic.claude-sonnet-4-6`, `us.anthropic.claude-opus-4-8`, `us.anthropic.claude-opus-4-7` |
|
| `amazon-bedrock` | `us.anthropic.claude-sonnet-4-6`, `us.anthropic.claude-opus-4-8`, `us.anthropic.claude-opus-4-7` |
|
||||||
|
|
||||||
Bedrock IDs are region-prefixed and must be enabled in your account, so the ID that works for you may differ from the one listed here.
|
Bedrock IDs are region-prefixed and must be enabled in your account, so the ID that works for you may differ from the one listed here.
|
||||||
@@ -164,6 +164,24 @@ Before running a pentest, review the [cyber safeguards requirements](#cyber-safe
|
|||||||
|
|
||||||
Supported Codex models are `gpt-5.6-sol`, `gpt-5.5`, and `gpt-5.4`.
|
Supported Codex models are `gpt-5.6-sol`, `gpt-5.5`, and `gpt-5.4`.
|
||||||
|
|
||||||
|
## xAI (Grok subscription)
|
||||||
|
|
||||||
|
An xAI subscription can run Shannon. Shannon reuses a login created by Pi.
|
||||||
|
|
||||||
|
1. Install Pi by following the instructions at [pi.dev](https://pi.dev).
|
||||||
|
2. Log in with your subscription using Pi's [subscription authentication guide](https://pi.dev/docs/latest/providers#subscriptions). This creates `~/.pi/agent/auth.json` with an `xai` entry.
|
||||||
|
|
||||||
|
3. Select an xAI model and enable Pi authentication:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export SHANNON_USE_PI_AUTH=1
|
||||||
|
export SHANNON_AI_MODEL=xai:grok-4.6
|
||||||
|
```
|
||||||
|
|
||||||
|
4. In npx mode, run `npx @keygraph/shannon start ...` from the same shell. In source-build mode, add the two variables to `.env` and run `./shannon start ...`.
|
||||||
|
|
||||||
|
Suggested Grok models are `grok-4.6` and `grok-4.5`.
|
||||||
|
|
||||||
## Claude Code subscription
|
## Claude Code subscription
|
||||||
|
|
||||||
The latest version of Shannon does not support Claude Code subscriptions. The [`shannon-v1`](https://github.com/KeygraphHQ/shannon/tree/shannon-v1) branch is the final release built on the Claude Agent SDK and supports Claude Code OAuth.
|
The latest version of Shannon does not support Claude Code subscriptions. The [`shannon-v1`](https://github.com/KeygraphHQ/shannon/tree/shannon-v1) branch is the final release built on the Claude Agent SDK and supports Claude Code OAuth.
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ rules:
|
|||||||
# min_confidence: low
|
# min_confidence: low
|
||||||
# guidance: |
|
# guidance: |
|
||||||
# Drop findings about missing security headers and rate-limit gaps.
|
# Drop findings about missing security headers and rate-limit gaps.
|
||||||
# sarif: "true"
|
# sarif: "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Report Options
|
## Report Options
|
||||||
@@ -109,18 +109,17 @@ rules:
|
|||||||
| `min_severity` | Drops findings rated below this severity. Applies in both exploitative and analysis-only runs. |
|
| `min_severity` | Drops findings rated below this severity. Applies in both exploitative and analysis-only runs. |
|
||||||
| `min_confidence` | Drops findings rated below this confidence. Applies only when `exploit` is `"false"`. |
|
| `min_confidence` | Drops findings rated below this confidence. Applies only when `exploit` is `"false"`. |
|
||||||
| `guidance` | Free-text instruction to the report agent, such as which topics to exclude. |
|
| `guidance` | Free-text instruction to the report agent, such as which topics to exclude. |
|
||||||
| `sarif` | Emits a SARIF 2.1.0 log alongside the Markdown report. Requires `exploit: "true"`. |
|
| `sarif` | SARIF 2.1.0 log alongside the Markdown report. On by default for exploit runs; set `"false"` to opt out. Ignored when `exploit` is `"false"`. |
|
||||||
|
|
||||||
Every finding carries a severity, but it does not mean the same thing in each mode: an exploitative run measures severity from what the exploit demonstrated, while an analysis-only run assesses it from the class of flaw and the impact it would have. An analysis-only finding carries a confidence rating alongside its severity, since nothing was proven. Setting `min_confidence` on an exploitative run is ignored, and Shannon logs a warning naming the threshold to use instead.
|
Every finding carries a severity, but it does not mean the same thing in each mode: an exploitative run measures severity from what the exploit demonstrated, while an analysis-only run assesses it from the class of flaw and the impact it would have. An analysis-only finding carries a confidence rating alongside its severity, since nothing was proven. Setting `min_confidence` on an exploitative run is ignored, and Shannon logs a warning naming the threshold to use instead.
|
||||||
|
|
||||||
### SARIF Output
|
### SARIF Output
|
||||||
|
|
||||||
Set `sarif: "true"` to write `report.sarif` next to `Security-Assessment-Report.pdf` at the workspace root, for upload to GitHub code scanning or any other SARIF consumer.
|
On exploit-mode runs Shannon writes `report.sarif` next to `Security-Assessment-Report.pdf` at the workspace root by default, for upload to GitHub code scanning or any other SARIF consumer. No configuration is needed; set `sarif: "false"` to opt out.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
exploit: "true"
|
|
||||||
report:
|
report:
|
||||||
sarif: "true"
|
sarif: "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
Each finding becomes one SARIF result, filed under a rule per vulnerability class (`shannon/injection`, `shannon/xss`, `shannon/auth`, `shannon/authz`, `shannon/ssrf`) and tagged with its OWASP Top Ten 2025 category. Results are anchored to the code location the analysis phase recorded, falling back to the HTTP entry point when the finding names no file. Severity maps onto SARIF's three levels: `critical` and `high` become `error`, `medium` becomes `warning`, everything else becomes `note`.
|
Each finding becomes one SARIF result, filed under a rule per vulnerability class (`shannon/injection`, `shannon/xss`, `shannon/auth`, `shannon/authz`, `shannon/ssrf`) and tagged with its OWASP Top Ten 2025 category. Results are anchored to the code location the analysis phase recorded, falling back to the HTTP entry point when the finding names no file. Severity maps onto SARIF's three levels: `critical` and `high` become `error`, `medium` becomes `warning`, everything else becomes `note`.
|
||||||
|
|||||||
+27
-9
@@ -15,7 +15,7 @@
|
|||||||
<picture>
|
<picture>
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./assets/github-banner-dark.png">
|
<source media="(prefers-color-scheme: dark)" srcset="./assets/github-banner-dark.png">
|
||||||
<source media="(prefers-color-scheme: light)" srcset="./assets/github-banner-light.png">
|
<source media="(prefers-color-scheme: light)" srcset="./assets/github-banner-light.png">
|
||||||
<img src="./assets/github-banner.png" alt="Shannon - AI Pentester by Keygraph" width="100%">
|
<img src="./assets/github-banner-light.png" alt="Shannon, AI Pentester for Web Apps and APIs, by Keygraph" width="100%">
|
||||||
</picture>
|
</picture>
|
||||||
|
|
||||||
<a href="https://trendshift.io/repositories/15604" target="_blank"><img src="https://trendshift.io/api/badge/repositories/15604" alt="KeygraphHQ%2Fshannon | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
<a href="https://trendshift.io/repositories/15604" target="_blank"><img src="https://trendshift.io/api/badge/repositories/15604" alt="KeygraphHQ%2Fshannon | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||||
@@ -110,6 +110,7 @@ For source builds, authenticated scans, provider-specific setup, and platform no
|
|||||||
> **Prefer to use a subscription instead of API credits?**
|
> **Prefer to use a subscription instead of API credits?**
|
||||||
>
|
>
|
||||||
> - **OpenAI Codex:** The latest version of Shannon supports ChatGPT Plus and Pro subscriptions. Follow the [OpenAI Codex subscription setup guide](docs/ai-providers.md#openai-codex-chatgpt-pluspro-subscription) to get started.
|
> - **OpenAI Codex:** The latest version of Shannon supports ChatGPT Plus and Pro subscriptions. Follow the [OpenAI Codex subscription setup guide](docs/ai-providers.md#openai-codex-chatgpt-pluspro-subscription) to get started.
|
||||||
|
> - **xAI (Grok):** The latest version of Shannon supports xAI subscriptions. Follow the [xAI subscription setup guide](docs/ai-providers.md#xai-grok-subscription) to get started.
|
||||||
> - **Claude Code:** The latest version of Shannon does not support Claude Code subscriptions. Follow the [Claude Code subscription setup guide](docs/ai-providers.md#claude-code-subscription) to use version `1.9.0`, which is the final release built on the Claude Agent SDK.
|
> - **Claude Code:** The latest version of Shannon does not support Claude Code subscriptions. Follow the [Claude Code subscription setup guide](docs/ai-providers.md#claude-code-subscription) to use version `1.9.0`, which is the final release built on the Claude Agent SDK.
|
||||||
|
|
||||||
## Key Capabilities
|
## Key Capabilities
|
||||||
@@ -120,7 +121,7 @@ For source builds, authenticated scans, provider-specific setup, and platform no
|
|||||||
- **Authenticated testing**: configuration files can describe login flows, test credentials, TOTP, email-based login flows, focus areas, and rules of engagement.
|
- **Authenticated testing**: configuration files can describe login flows, test credentials, TOTP, email-based login flows, focus areas, and rules of engagement.
|
||||||
- **OWASP-focused coverage**: Shannon targets exploitable Injection, XSS, SSRF, Broken Authentication, and Broken Authorization issues.
|
- **OWASP-focused coverage**: Shannon targets exploitable Injection, XSS, SSRF, Broken Authentication, and Broken Authorization issues.
|
||||||
- **Resumable workspaces**: Shannon can resume interrupted runs without re-running completed agents.
|
- **Resumable workspaces**: Shannon can resume interrupted runs without re-running completed agents.
|
||||||
- **Machine-readable output**: Shannon emits findings as structured JSON, and as SARIF 2.1.0 when you enable it in configuration. SARIF is the OASIS standard for static analysis results, so findings flow into any code scanning service, vulnerability management platform, security dashboard, or CI/CD pipeline that reads it.
|
- **Machine-readable output**: Shannon emits findings as structured JSON, and as SARIF 2.1.0 by default on exploit-mode scans (opt out with `report.sarif: "false"`). SARIF is the OASIS standard for static analysis results, so findings flow into any code scanning service, vulnerability management platform, security dashboard, or CI/CD pipeline that reads it.
|
||||||
- **Bring your own key, provider-agnostic**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any endpoint speaking the Anthropic Messages API or the OpenAI Chat Completions or Responses API, including self-hosted models served through Ollama, vLLM, or LM Studio and gateways such as OpenRouter and LiteLLM. You supply the credentials, so source code and model traffic stay inside your infrastructure. Local and self-hosted models are technically supported but not recommended: they may not follow Shannon's instructions or tool-use constraints as reliably as frontier models, so take that path only if you know how your chosen model behaves.
|
- **Bring your own key, provider-agnostic**: Shannon runs on Anthropic, OpenAI, xAI, AWS Bedrock, and any endpoint speaking the Anthropic Messages API or the OpenAI Chat Completions or Responses API, including self-hosted models served through Ollama, vLLM, or LM Studio and gateways such as OpenRouter and LiteLLM. You supply the credentials, so source code and model traffic stay inside your infrastructure. Local and self-hosted models are technically supported but not recommended: they may not follow Shannon's instructions or tool-use constraints as reliably as frontier models, so take that path only if you know how your chosen model behaves.
|
||||||
|
|
||||||
## Editions
|
## Editions
|
||||||
@@ -280,7 +281,7 @@ Yes, always. You provide the LLM credentials Shannon uses to run a pentest, in e
|
|||||||
|
|
||||||
### Does Shannon output SARIF?
|
### Does Shannon output SARIF?
|
||||||
|
|
||||||
Yes. Shannon emits SARIF 2.1.0, the OASIS standard format for static analysis results, alongside structured JSON. Any SARIF consumer reads it: code scanning services, vulnerability management platforms, security dashboards, and CI/CD pipelines. Set `report.sarif` to `"true"` in your configuration file to enable the SARIF log.
|
Yes. Shannon emits SARIF 2.1.0, the OASIS standard format for static analysis results, alongside structured JSON. Any SARIF consumer reads it: code scanning services, vulnerability management platforms, security dashboards, and CI/CD pipelines. It is written by default on exploit-mode scans; set `report.sarif` to `"false"` in your configuration file to opt out.
|
||||||
|
|
||||||
### Which AI providers does Shannon support?
|
### Which AI providers does Shannon support?
|
||||||
|
|
||||||
@@ -567,7 +568,7 @@ rules:
|
|||||||
# min_confidence: low
|
# min_confidence: low
|
||||||
# guidance: |
|
# guidance: |
|
||||||
# Drop findings about missing security headers and rate-limit gaps.
|
# Drop findings about missing security headers and rate-limit gaps.
|
||||||
# sarif: "true"
|
# sarif: "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Report Options
|
## Report Options
|
||||||
@@ -577,18 +578,17 @@ rules:
|
|||||||
| `min_severity` | Drops findings rated below this severity. Applies in both exploitative and analysis-only runs. |
|
| `min_severity` | Drops findings rated below this severity. Applies in both exploitative and analysis-only runs. |
|
||||||
| `min_confidence` | Drops findings rated below this confidence. Applies only when `exploit` is `"false"`. |
|
| `min_confidence` | Drops findings rated below this confidence. Applies only when `exploit` is `"false"`. |
|
||||||
| `guidance` | Free-text instruction to the report agent, such as which topics to exclude. |
|
| `guidance` | Free-text instruction to the report agent, such as which topics to exclude. |
|
||||||
| `sarif` | Emits a SARIF 2.1.0 log alongside the Markdown report. Requires `exploit: "true"`. |
|
| `sarif` | SARIF 2.1.0 log alongside the Markdown report. On by default for exploit runs; set `"false"` to opt out. Ignored when `exploit` is `"false"`. |
|
||||||
|
|
||||||
Every finding carries a severity, but it does not mean the same thing in each mode: an exploitative run measures severity from what the exploit demonstrated, while an analysis-only run assesses it from the class of flaw and the impact it would have. An analysis-only finding carries a confidence rating alongside its severity, since nothing was proven. Setting `min_confidence` on an exploitative run is ignored, and Shannon logs a warning naming the threshold to use instead.
|
Every finding carries a severity, but it does not mean the same thing in each mode: an exploitative run measures severity from what the exploit demonstrated, while an analysis-only run assesses it from the class of flaw and the impact it would have. An analysis-only finding carries a confidence rating alongside its severity, since nothing was proven. Setting `min_confidence` on an exploitative run is ignored, and Shannon logs a warning naming the threshold to use instead.
|
||||||
|
|
||||||
### SARIF Output
|
### SARIF Output
|
||||||
|
|
||||||
Set `sarif: "true"` to write `report.sarif` next to `Security-Assessment-Report.pdf` at the workspace root, for upload to GitHub code scanning or any other SARIF consumer.
|
On exploit-mode runs Shannon writes `report.sarif` next to `Security-Assessment-Report.pdf` at the workspace root by default, for upload to GitHub code scanning or any other SARIF consumer. No configuration is needed; set `sarif: "false"` to opt out.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
exploit: "true"
|
|
||||||
report:
|
report:
|
||||||
sarif: "true"
|
sarif: "false"
|
||||||
```
|
```
|
||||||
|
|
||||||
Each finding becomes one SARIF result, filed under a rule per vulnerability class (`shannon/injection`, `shannon/xss`, `shannon/auth`, `shannon/authz`, `shannon/ssrf`) and tagged with its OWASP Top Ten 2025 category. Results are anchored to the code location the analysis phase recorded, falling back to the HTTP entry point when the finding names no file. Severity maps onto SARIF's three levels: `critical` and `high` become `error`, `medium` becomes `warning`, everything else becomes `note`.
|
Each finding becomes one SARIF result, filed under a rule per vulnerability class (`shannon/injection`, `shannon/xss`, `shannon/auth`, `shannon/authz`, `shannon/ssrf`) and tagged with its OWASP Top Ten 2025 category. Results are anchored to the code location the analysis phase recorded, falling back to the HTTP entry point when the finding names no file. Severity maps onto SARIF's three levels: `critical` and `high` become `error`, `medium` becomes `warning`, everything else becomes `note`.
|
||||||
@@ -689,7 +689,7 @@ These are the models `npx @keygraph/shannon setup` offers, best-first. They are
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `anthropic` | `claude-sonnet-4-6`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-haiku-4-5-20251001` |
|
| `anthropic` | `claude-sonnet-4-6`, `claude-opus-4-8`, `claude-opus-4-7`, `claude-haiku-4-5-20251001` |
|
||||||
| `openai` | `gpt-5.6-sol`, `gpt-5.5`, `gpt-5.4` |
|
| `openai` | `gpt-5.6-sol`, `gpt-5.5`, `gpt-5.4` |
|
||||||
| `xai` | `grok-4.5` |
|
| `xai` | `grok-4.6`, `grok-4.5` |
|
||||||
| `amazon-bedrock` | `us.anthropic.claude-sonnet-4-6`, `us.anthropic.claude-opus-4-8`, `us.anthropic.claude-opus-4-7` |
|
| `amazon-bedrock` | `us.anthropic.claude-sonnet-4-6`, `us.anthropic.claude-opus-4-8`, `us.anthropic.claude-opus-4-7` |
|
||||||
|
|
||||||
Bedrock IDs are region-prefixed and must be enabled in your account, so the ID that works for you may differ from the one listed here.
|
Bedrock IDs are region-prefixed and must be enabled in your account, so the ID that works for you may differ from the one listed here.
|
||||||
@@ -795,6 +795,24 @@ Before running a pentest, review the [cyber safeguards requirements](#cyber-safe
|
|||||||
|
|
||||||
Supported Codex models are `gpt-5.6-sol`, `gpt-5.5`, and `gpt-5.4`.
|
Supported Codex models are `gpt-5.6-sol`, `gpt-5.5`, and `gpt-5.4`.
|
||||||
|
|
||||||
|
## xAI (Grok subscription)
|
||||||
|
|
||||||
|
An xAI subscription can run Shannon. Shannon reuses a login created by Pi.
|
||||||
|
|
||||||
|
1. Install Pi by following the instructions at [pi.dev](https://pi.dev).
|
||||||
|
2. Log in with your subscription using Pi's [subscription authentication guide](https://pi.dev/docs/latest/providers#subscriptions). This creates `~/.pi/agent/auth.json` with an `xai` entry.
|
||||||
|
|
||||||
|
3. Select an xAI model and enable Pi authentication:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export SHANNON_USE_PI_AUTH=1
|
||||||
|
export SHANNON_AI_MODEL=xai:grok-4.6
|
||||||
|
```
|
||||||
|
|
||||||
|
4. In npx mode, run `npx @keygraph/shannon start ...` from the same shell. In source-build mode, add the two variables to `.env` and run `./shannon start ...`.
|
||||||
|
|
||||||
|
Suggested Grok models are `grok-4.6` and `grok-4.5`.
|
||||||
|
|
||||||
## Claude Code subscription
|
## Claude Code subscription
|
||||||
|
|
||||||
The latest version of Shannon does not support Claude Code subscriptions. The [`shannon-v1`](https://github.com/KeygraphHQ/shannon/tree/shannon-v1) branch is the final release built on the Claude Agent SDK and supports Claude Code OAuth.
|
The latest version of Shannon does not support Claude Code subscriptions. The [`shannon-v1`](https://github.com/KeygraphHQ/shannon/tree/shannon-v1) branch is the final release built on the Claude Agent SDK and supports Claude Code OAuth.
|
||||||
|
|||||||
Generated
+78
-66
@@ -46,17 +46,17 @@ importers:
|
|||||||
apps/worker:
|
apps/worker:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@earendil-works/pi-agent-core':
|
'@earendil-works/pi-agent-core':
|
||||||
specifier: ^0.82.1
|
specifier: ^0.84.2
|
||||||
version: 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
version: 0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
||||||
'@earendil-works/pi-ai':
|
'@earendil-works/pi-ai':
|
||||||
specifier: ^0.82.1
|
specifier: ^0.84.2
|
||||||
version: 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
version: 0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
||||||
'@earendil-works/pi-coding-agent':
|
'@earendil-works/pi-coding-agent':
|
||||||
specifier: ^0.82.1
|
specifier: ^0.84.2
|
||||||
version: 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
version: 0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
||||||
'@gotgenes/pi-permission-system':
|
'@gotgenes/pi-permission-system':
|
||||||
specifier: ^10.9.0
|
specifier: ^10.9.0
|
||||||
version: 10.9.0(@earendil-works/pi-coding-agent@0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6))(@earendil-works/pi-tui@0.82.1)
|
version: 10.9.0(@earendil-works/pi-coding-agent@0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6))(@earendil-works/pi-tui@0.84.2)
|
||||||
'@temporalio/activity':
|
'@temporalio/activity':
|
||||||
specifier: ^1.11.0
|
specifier: ^1.11.0
|
||||||
version: 1.15.0
|
version: 1.15.0
|
||||||
@@ -292,22 +292,34 @@ packages:
|
|||||||
'@clack/prompts@1.1.0':
|
'@clack/prompts@1.1.0':
|
||||||
resolution: {integrity: sha512-pkqbPGtohJAvm4Dphs2M8xE29ggupihHdy1x84HNojZuMtFsHiUlRvqD24tM2+XmI+61LlfNceM3Wr7U5QES5g==}
|
resolution: {integrity: sha512-pkqbPGtohJAvm4Dphs2M8xE29ggupihHdy1x84HNojZuMtFsHiUlRvqD24tM2+XmI+61LlfNceM3Wr7U5QES5g==}
|
||||||
|
|
||||||
'@earendil-works/pi-agent-core@0.82.1':
|
'@earendil-works/pi-agent-core@0.84.2':
|
||||||
resolution: {integrity: sha512-Z3kloziJIE2dmrisRckZX8zDca/gIv9/YdFAzeoqpHiLV2wsni6bL4hInNSjVKLbqT+4kqLIkph2JQLKvSepjg==}
|
resolution: {integrity: sha512-8Pn3wSCxj0cfo5I6jxQYVB/3uuQRmHhAlEclyjqpOuMEdQMIODHizRogv56FLdbU+dTiGnybeHQ2N+sV1/L2YA==}
|
||||||
engines: {node: '>=22.19.0'}
|
engines: {node: '>=22.19.0'}
|
||||||
|
|
||||||
'@earendil-works/pi-ai@0.82.1':
|
'@earendil-works/pi-ai@0.84.2':
|
||||||
resolution: {integrity: sha512-3WFYRhEp3lQB3444EhPMBcM7zSaEUE3eJgHOR7s4081NLqbw/FsWilIKWXSua0Gv3sRr7m9xMidR3pPDE7jI/A==}
|
resolution: {integrity: sha512-6MzsrYIYNVlE7SfpbL2yYb67Qo58p/7Q+xWG1RZvoX1P80aRCHSod2/13aFpxkow1lPO2LEh3c495J0Gwmyjig==}
|
||||||
engines: {node: '>=22.19.0'}
|
engines: {node: '>=22.19.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@earendil-works/pi-coding-agent@0.82.1':
|
'@earendil-works/pi-client@0.84.2':
|
||||||
resolution: {integrity: sha512-zbkAhoIuDPMF3pKuja0ajZabrMWU29FUMV9A/XMXT/XC1yXs5xt6t6t13GogQFsDrDqbFP4DkZQO1w8rWRAzYA==}
|
resolution: {integrity: sha512-/RFSPhD/bZbpOp1oJj+UneSUFSgZhWxzcSENUY+8+8xhoBrWXMYI2t77XNx4Yf+c8YK2qTHquForhNcelYpXvg==}
|
||||||
|
engines: {node: '>=22.19.0'}
|
||||||
|
|
||||||
|
'@earendil-works/pi-coding-agent@0.84.2':
|
||||||
|
resolution: {integrity: sha512-l4E+B7hgXKWddRo8bC/eSue2aWZjEgJ9xIpf5p0Og+lq8a2TArCwJ0HCoCPCgaBP/tN4zbYH/wOwvx9pJpeLCA==}
|
||||||
engines: {node: '>=22.19.0'}
|
engines: {node: '>=22.19.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@earendil-works/pi-tui@0.82.1':
|
'@earendil-works/pi-protocol@0.84.2':
|
||||||
resolution: {integrity: sha512-9yN8hALfKaxZq7n54EMxqhFCWnMi6LHkraMJ/1YjHiATq75XrI6XDMVppn9EDtiK7Fks8hUe1SDXUTrIvwRWfQ==}
|
resolution: {integrity: sha512-jbBh03fkeckWEroHpcZBr4w5/Ibat8WwdXFlXHivYQImrQNFtLpDeL0t1cku4hmK0q3pceIRQHkw4fwbM4YILQ==}
|
||||||
|
engines: {node: '>=22.19.0'}
|
||||||
|
|
||||||
|
'@earendil-works/pi-telemetry@0.84.2':
|
||||||
|
resolution: {integrity: sha512-wg5caea7uIv1BHRBm2Y116RvFG4oSAiP5qk9tA2463PDGIr4K8M1Ceyyg5DOpF/shUUl0gk826yQJAeAcHYB9g==}
|
||||||
|
engines: {node: '>=22.19.0'}
|
||||||
|
|
||||||
|
'@earendil-works/pi-tui@0.84.2':
|
||||||
|
resolution: {integrity: sha512-ds2TLihOnM5sLJB3VpXV6y0uR5efVuHf4MN7yDpsty6hA2DUO/EDVzjp/0od0G2JslzVLMjT8T8zavtxVb+qbg==}
|
||||||
engines: {node: '>=22.19.0'}
|
engines: {node: '>=22.19.0'}
|
||||||
|
|
||||||
'@emnapi/core@1.9.1':
|
'@emnapi/core@1.9.1':
|
||||||
@@ -557,14 +569,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==}
|
resolution: {integrity: sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
|
|
||||||
'@mistralai/mistralai@2.2.6':
|
|
||||||
resolution: {integrity: sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==}
|
|
||||||
peerDependencies:
|
|
||||||
'@opentelemetry/api': ^1.9.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@opentelemetry/api':
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.29.0':
|
'@modelcontextprotocol/sdk@1.29.0':
|
||||||
resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==}
|
resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -585,10 +589,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
|
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
|
||||||
engines: {node: '>=8.0.0'}
|
engines: {node: '>=8.0.0'}
|
||||||
|
|
||||||
'@opentelemetry/semantic-conventions@1.43.0':
|
|
||||||
resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==}
|
|
||||||
engines: {node: '>=14'}
|
|
||||||
|
|
||||||
'@oxc-project/types@0.122.0':
|
'@oxc-project/types@0.122.0':
|
||||||
resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==}
|
resolution: {integrity: sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==}
|
||||||
|
|
||||||
@@ -1376,6 +1376,10 @@ packages:
|
|||||||
graceful-fs@4.2.11:
|
graceful-fs@4.2.11:
|
||||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||||
|
|
||||||
|
grok-mermaid@0.2.2:
|
||||||
|
resolution: {integrity: sha512-XcJEP5dDC8liHBh52mlLjU18fNvu1ckFsu0QpIG3+APZ270fsj9wxpiA6cOURmbUEuoMVgjbC2+UYgTdCqqgzA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
has-flag@4.0.0:
|
has-flag@4.0.0:
|
||||||
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1620,9 +1624,8 @@ packages:
|
|||||||
once@1.4.0:
|
once@1.4.0:
|
||||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||||
|
|
||||||
openai@6.26.0:
|
openai@6.40.0:
|
||||||
resolution: {integrity: sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==}
|
resolution: {integrity: sha512-MWtTjd/gQt4jpbji61NTgFWJLoY/PdRJ6wG9/ZDRMYNMlBKrCrSlkLI+KgHP1vR1qT6LKSAyAqIxno6lcK9JiA==}
|
||||||
hasBin: true
|
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
ws: ^8.18.0
|
ws: ^8.18.0
|
||||||
zod: ^3.25 || ^4.0
|
zod: ^3.25 || ^4.0
|
||||||
@@ -2003,6 +2006,9 @@ packages:
|
|||||||
typebox@1.1.38:
|
typebox@1.1.38:
|
||||||
resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==}
|
resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==}
|
||||||
|
|
||||||
|
typebox@1.3.7:
|
||||||
|
resolution: {integrity: sha512-meKuifc33Pccx0O6PdIzYMq3Og8zvP4TIi/a+Bw3AEMZMxOD0+RHGQvpglEe6Zdy3wZ8nqn/j95h8LUZLk/6Hg==}
|
||||||
|
|
||||||
typescript@5.9.3:
|
typescript@5.9.3:
|
||||||
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
@@ -2014,8 +2020,8 @@ packages:
|
|||||||
undici-types@7.18.2:
|
undici-types@7.18.2:
|
||||||
resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
|
resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
|
||||||
|
|
||||||
undici@8.5.0:
|
undici@8.9.0:
|
||||||
resolution: {integrity: sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==}
|
resolution: {integrity: sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==}
|
||||||
engines: {node: '>=22.19.0'}
|
engines: {node: '>=22.19.0'}
|
||||||
|
|
||||||
unionfs@4.6.0:
|
unionfs@4.6.0:
|
||||||
@@ -2431,12 +2437,13 @@ snapshots:
|
|||||||
'@clack/core': 1.1.0
|
'@clack/core': 1.1.0
|
||||||
sisteransi: 1.0.5
|
sisteransi: 1.0.5
|
||||||
|
|
||||||
'@earendil-works/pi-agent-core@0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)':
|
'@earendil-works/pi-agent-core@0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@earendil-works/pi-ai': 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
'@earendil-works/pi-ai': 0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
||||||
|
'@earendil-works/pi-telemetry': 0.84.2
|
||||||
diff: 8.0.4
|
diff: 8.0.4
|
||||||
ignore: 7.0.5
|
ignore: 7.0.5
|
||||||
typebox: 1.1.38
|
typebox: 1.3.7
|
||||||
yaml: 2.9.0
|
yaml: 2.9.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@modelcontextprotocol/sdk'
|
- '@modelcontextprotocol/sdk'
|
||||||
@@ -2446,19 +2453,19 @@ snapshots:
|
|||||||
- ws
|
- ws
|
||||||
- zod
|
- zod
|
||||||
|
|
||||||
'@earendil-works/pi-ai@0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)':
|
'@earendil-works/pi-ai@0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@anthropic-ai/sdk': 0.91.1(zod@4.3.6)
|
'@anthropic-ai/sdk': 0.91.1(zod@4.3.6)
|
||||||
'@aws-sdk/client-bedrock-runtime': 3.1048.0
|
'@aws-sdk/client-bedrock-runtime': 3.1048.0
|
||||||
|
'@earendil-works/pi-telemetry': 0.84.2
|
||||||
'@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))
|
'@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))
|
||||||
'@mistralai/mistralai': 2.2.6(@opentelemetry/api@1.9.0)
|
|
||||||
'@opentelemetry/api': 1.9.0
|
'@opentelemetry/api': 1.9.0
|
||||||
'@smithy/node-http-handler': 4.7.3
|
'@smithy/node-http-handler': 4.7.3
|
||||||
http-proxy-agent: 7.0.2
|
http-proxy-agent: 7.0.2
|
||||||
https-proxy-agent: 7.0.6
|
https-proxy-agent: 7.0.6
|
||||||
openai: 6.26.0(ws@8.21.0)(zod@4.3.6)
|
openai: 6.40.0(ws@8.21.0)(zod@4.3.6)
|
||||||
partial-json: 0.1.7
|
partial-json: 0.1.7
|
||||||
typebox: 1.1.38
|
typebox: 1.3.7
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@modelcontextprotocol/sdk'
|
- '@modelcontextprotocol/sdk'
|
||||||
- bufferutil
|
- bufferutil
|
||||||
@@ -2467,16 +2474,23 @@ snapshots:
|
|||||||
- ws
|
- ws
|
||||||
- zod
|
- zod
|
||||||
|
|
||||||
'@earendil-works/pi-coding-agent@0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)':
|
'@earendil-works/pi-client@0.84.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@earendil-works/pi-agent-core': 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
'@earendil-works/pi-protocol': 0.84.2
|
||||||
'@earendil-works/pi-ai': 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
|
||||||
'@earendil-works/pi-tui': 0.82.1
|
'@earendil-works/pi-coding-agent@0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)':
|
||||||
|
dependencies:
|
||||||
|
'@earendil-works/pi-agent-core': 0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
||||||
|
'@earendil-works/pi-ai': 0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
||||||
|
'@earendil-works/pi-client': 0.84.2
|
||||||
|
'@earendil-works/pi-protocol': 0.84.2
|
||||||
|
'@earendil-works/pi-tui': 0.84.2
|
||||||
'@silvia-odwyer/photon-node': 0.3.4
|
'@silvia-odwyer/photon-node': 0.3.4
|
||||||
chalk: 5.6.2
|
chalk: 5.6.2
|
||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
diff: 8.0.4
|
diff: 8.0.4
|
||||||
glob: 13.0.6
|
glob: 13.0.6
|
||||||
|
grok-mermaid: 0.2.2
|
||||||
highlight.js: 10.7.3
|
highlight.js: 10.7.3
|
||||||
hosted-git-info: 9.0.3
|
hosted-git-info: 9.0.3
|
||||||
ignore: 7.0.5
|
ignore: 7.0.5
|
||||||
@@ -2484,8 +2498,8 @@ snapshots:
|
|||||||
minimatch: 10.2.5
|
minimatch: 10.2.5
|
||||||
proper-lockfile: 4.1.2
|
proper-lockfile: 4.1.2
|
||||||
semver: 7.8.0
|
semver: 7.8.0
|
||||||
typebox: 1.1.38
|
typebox: 1.3.7
|
||||||
undici: 8.5.0
|
undici: 8.9.0
|
||||||
yaml: 2.9.0
|
yaml: 2.9.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@mariozechner/clipboard': 0.3.9
|
'@mariozechner/clipboard': 0.3.9
|
||||||
@@ -2497,7 +2511,13 @@ snapshots:
|
|||||||
- ws
|
- ws
|
||||||
- zod
|
- zod
|
||||||
|
|
||||||
'@earendil-works/pi-tui@0.82.1':
|
'@earendil-works/pi-protocol@0.84.2':
|
||||||
|
dependencies:
|
||||||
|
typebox: 1.3.7
|
||||||
|
|
||||||
|
'@earendil-works/pi-telemetry@0.84.2': {}
|
||||||
|
|
||||||
|
'@earendil-works/pi-tui@0.84.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
get-east-asian-width: 1.6.0
|
get-east-asian-width: 1.6.0
|
||||||
marked: 18.0.5
|
marked: 18.0.5
|
||||||
@@ -2531,10 +2551,10 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
'@gotgenes/pi-permission-system@10.9.0(@earendil-works/pi-coding-agent@0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6))(@earendil-works/pi-tui@0.82.1)':
|
'@gotgenes/pi-permission-system@10.9.0(@earendil-works/pi-coding-agent@0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6))(@earendil-works/pi-tui@0.84.2)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@earendil-works/pi-coding-agent': 0.82.1(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
'@earendil-works/pi-coding-agent': 0.84.2(@modelcontextprotocol/sdk@1.29.0(zod@4.3.6))(ws@8.21.0)(zod@4.3.6)
|
||||||
'@earendil-works/pi-tui': 0.82.1
|
'@earendil-works/pi-tui': 0.84.2
|
||||||
tree-sitter-bash: 0.25.1
|
tree-sitter-bash: 0.25.1
|
||||||
web-tree-sitter: 0.26.9
|
web-tree-sitter: 0.26.9
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -2749,18 +2769,6 @@ snapshots:
|
|||||||
'@mariozechner/clipboard-win32-x64-msvc': 0.3.9
|
'@mariozechner/clipboard-win32-x64-msvc': 0.3.9
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@mistralai/mistralai@2.2.6(@opentelemetry/api@1.9.0)':
|
|
||||||
dependencies:
|
|
||||||
'@opentelemetry/semantic-conventions': 1.43.0
|
|
||||||
ws: 8.21.0
|
|
||||||
zod: 4.3.6
|
|
||||||
zod-to-json-schema: 3.25.2(zod@4.3.6)
|
|
||||||
optionalDependencies:
|
|
||||||
'@opentelemetry/api': 1.9.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- bufferutil
|
|
||||||
- utf-8-validate
|
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.29.0(zod@4.3.6)':
|
'@modelcontextprotocol/sdk@1.29.0(zod@4.3.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@hono/node-server': 1.19.14(hono@4.12.14)
|
'@hono/node-server': 1.19.14(hono@4.12.14)
|
||||||
@@ -2795,8 +2803,6 @@ snapshots:
|
|||||||
|
|
||||||
'@opentelemetry/api@1.9.0': {}
|
'@opentelemetry/api@1.9.0': {}
|
||||||
|
|
||||||
'@opentelemetry/semantic-conventions@1.43.0': {}
|
|
||||||
|
|
||||||
'@oxc-project/types@0.122.0': {}
|
'@oxc-project/types@0.122.0': {}
|
||||||
|
|
||||||
'@protobufjs/aspromise@1.1.2': {}
|
'@protobufjs/aspromise@1.1.2': {}
|
||||||
@@ -3598,6 +3604,8 @@ snapshots:
|
|||||||
|
|
||||||
graceful-fs@4.2.11: {}
|
graceful-fs@4.2.11: {}
|
||||||
|
|
||||||
|
grok-mermaid@0.2.2: {}
|
||||||
|
|
||||||
has-flag@4.0.0: {}
|
has-flag@4.0.0: {}
|
||||||
|
|
||||||
has-symbols@1.1.0:
|
has-symbols@1.1.0:
|
||||||
@@ -3820,7 +3828,7 @@ snapshots:
|
|||||||
wrappy: 1.0.2
|
wrappy: 1.0.2
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
openai@6.26.0(ws@8.21.0)(zod@4.3.6):
|
openai@6.40.0(ws@8.21.0)(zod@4.3.6):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
ws: 8.21.0
|
ws: 8.21.0
|
||||||
zod: 4.3.6
|
zod: 4.3.6
|
||||||
@@ -4212,6 +4220,8 @@ snapshots:
|
|||||||
|
|
||||||
typebox@1.1.38: {}
|
typebox@1.1.38: {}
|
||||||
|
|
||||||
|
typebox@1.3.7: {}
|
||||||
|
|
||||||
typescript@5.9.3: {}
|
typescript@5.9.3: {}
|
||||||
|
|
||||||
unconfig-core@7.5.0:
|
unconfig-core@7.5.0:
|
||||||
@@ -4221,7 +4231,7 @@ snapshots:
|
|||||||
|
|
||||||
undici-types@7.18.2: {}
|
undici-types@7.18.2: {}
|
||||||
|
|
||||||
undici@8.5.0: {}
|
undici@8.9.0: {}
|
||||||
|
|
||||||
unionfs@4.6.0:
|
unionfs@4.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4324,7 +4334,9 @@ snapshots:
|
|||||||
zod-to-json-schema@3.25.2(zod@4.3.6):
|
zod-to-json-schema@3.25.2(zod@4.3.6):
|
||||||
dependencies:
|
dependencies:
|
||||||
zod: 4.3.6
|
zod: 4.3.6
|
||||||
|
optional: true
|
||||||
|
|
||||||
zod@4.3.6: {}
|
zod@4.3.6:
|
||||||
|
optional: true
|
||||||
|
|
||||||
zx@8.8.5: {}
|
zx@8.8.5: {}
|
||||||
Reference in new issue
Block a user