Compare commits

...
3 Commits
Author SHA1 Message Date
ezl-keygraph 6108de3cfc feat: bump pi harness to 0.84.2 to enable xAI subscription auth (#435) 2026-08-28 21:20:13 +05:30
ezl-keygraph 7e0464bf79 feat: support pentests with xAI (Grok) subscription auth (#434) 2026-08-28 21:11:24 +05:30
ezl-keygraph dc2a4fe4e8 feat: brand the npm page, CLI output, and reports (#432)
* docs: rebuild the npm package README on the main README's identity

* docs: point the README banner fallback at an asset that exists

* docs: declare the npm package author, homepage, and issue tracker

* docs(cli): retire "Framework" and settle on the canonical product line

* docs: describe the banner image in alt text instead of repeating the lockup

* feat(cli): print a plain-text banner when stdout is not a terminal

* feat(report): attribute the markdown report from a shared brand constant

* feat(cli): frame the plain-text banner with rules and split the version line

* docs: drop the URL from the npm author field
2026-08-27 18:53:56 +05:30
15 changed files with 232 additions and 94 deletions

No files matched your search

+5
View File
@@ -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
+1 -1
View File
@@ -155,7 +155,7 @@ Durable workflow orchestration with crash recovery, queryable progress, intellig
- **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`) - **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
+2 -1
View File
@@ -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
+49 -11
View File
@@ -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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<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>
+6 -2
View File
@@ -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",
+6 -4
View File
@@ -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)
+2 -2
View File
@@ -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:
+17
View File
@@ -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);
}
+3 -3
View File
@@ -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",
+18
View File
@@ -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}`;
+2 -1
View File
@@ -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}`);
+19 -1
View File
@@ -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.
+21 -2
View File
@@ -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
@@ -688,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.
@@ -794,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.
+78 -66
View File
@@ -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: {}