task: docs runbook + agents catalog (#301)

Closes #300.
This commit is contained in:
Ryan Eggleston authored and GitHub committed 2026-05-15 22:14:45 -06:00
1 parent 5951874e06
commit f8006f4825
25 files changed
+737 -119

No files matched your search

+8 -1
View File
@@ -9,8 +9,15 @@ Update policy and release automation live in [`.claude/rules/git.md`](.claude/ru
## [Unreleased]
### Added
- `docs/connecting.md` — new runbook documenting the VSCode Attach + port-forwarding workflow for remote dev servers. Covers the "machine unreachable" debugging pattern: VS Code Remote SSH's automatic port-forwarding, manual fallback for direct-terminal users, and the `localhost:` prefix convention for accessing services on the Docker host. Referenced from `intro.md`, `quickstart.md`, `harnesses/overview.md`, `harnesses/t3code.md`, and `integrations/slack.md`. ([#300](https://github.com/ryaneggz/open-harness/issues/300))
- **Agents catalog**: new `docs/agents/` section (renamed from `docs/agents/` → `docs/harnesses/` after initial creation to match sidebar label). Includes `_category_.json` organizing the section, `overview.md` as the hub page, and five per-branch playbook pages (`portfolio-mgr.md`, `blog-writer.md`, `linkedin-ghostwriter.md`, `dc-designer.md`, `uat-tester.md`), each documenting use-case, harness selection, auth flow, and tmux launch pattern. ([#300](https://github.com/ryaneggz/open-harness/issues/300))
- `.devcontainer/docker-compose.yml` publishes container port 1455 to the host loopback (`127.0.0.1:1455:1455`) for the **Pi harness** login flow, whose OAuth callback binds `http://localhost:1455`. With the port on the host loopback, VS Code Remote SSH's automatic port-forwarding carries the redirect back to the laptop and Pi login completes out of the box; direct-terminal (plain `ssh`) users still need to forward the port manually with `ssh -L 1455:localhost:1455 user@host`. The Codex CLI is unaffected — it has its own headless path via `codex login --device-auth`. ([#287](https://github.com/ryaneggz/open-harness/issues/287))
### Changed
- Renamed `docs/agents/` folder to `docs/harnesses/` so the folder name matches the sidebar label; added `@docusaurus/plugin-client-redirects` to `apps/docs/` with seven redirects from `/docs/agents/*` → `/docs/harnesses/*` preserving URLs from the initial agents-catalog PR. ([#300](https://github.com/ryaneggz/open-harness/issues/300))
- Cross-linked `docs/connecting.md` from `intro.md`, `quickstart.md`, `harnesses/overview.md`, `harnesses/t3code.md`, and `integrations/slack.md` so the VSCode attach pattern is discoverable from each major entry point. ([#300](https://github.com/ryaneggz/open-harness/issues/300))
- Fixed `apps/README.md` script-name drift: `pnpm --filter @openharness/docs dev` → `pnpm --filter @openharness/docs start` to match the actual `start` script in `apps/docs/package.json`. ([#300](https://github.com/ryaneggz/open-harness/issues/300))
### Removed
- In-tree docker-compose overlays under `.devcontainer/` except `docker-compose.postgres.yml`: the five host-auth overlays (`claude-host.yml`, `codex-host.yml`, `opencode-host.yml`, `pi-host.yml`, `deepagents-host.yml`), the three SSH overlays (`ssh.yml`, `ssh-generate.yml`, `sshd.yml`), `git.yml`, and `cloudflared.yml`. The host-auth overlays existed to share host agent credentials when the host UID matched the sandbox's UID 1000; `.devcontainer/entrypoint.sh` now syncs the sandbox user's UID/GID to the bind-mounted repo's owner on boot (replacing the host-group-membership workaround), so files written in either direction stay readable without per-agent overlays. Agent auth still persists in named volumes (`claude-auth`, `codex-auth`, `pi-auth`, `opencode-auth`, `deepagents-auth`, `cloudflared-auth`, `gh-config`); `gh auth login` covers git over HTTPS without per-overlay setup. Postgres remains opt-in via `docker-compose.postgres.yml`. Removed companion infrastructure: `install/cloudflared-tunnel.sh`, the `/cloudflared-tunnel` skill, the `*_HOST_BIND_MOUNT` / `SANDBOX_PASSWORD` / `INSTALL_BROWSER` / `INSTALL_CLOUDFLARED` / `GIT_COMMON_DIR` / `HOST_SSH_DIR` / `HOST_*_DIR` env plumbing in `.devcontainer/entrypoint.sh`, and the host-UID overlay-stripping block in `scripts/install.sh`. Deleted doc: `docs/integrations/cloudflare.md`. The `composeOverrides[]` mechanism in `config.json` is retained so downstream packs (Pi extensions, BYO harness packs) can still register their own overlays. ([#283](https://github.com/ryaneggz/open-harness/issues/283))
- Orphaned `.pi/onboard-steps/slack.ts` (and the empty `.pi/onboard-steps/` directory). The wizard logic lives in `apps/oh/src/config/slack.ts` now, with the bugs from the original mifune port fixed (correct tmux session name `agent-pi`, real `pi` launch path, token-prefix validation, allowlist-ID validation, atomic env-file merge). ([#281](https://github.com/ryaneggz/open-harness/issues/281))
@@ -18,7 +25,7 @@ Update policy and release automation live in [`.claude/rules/git.md`](.claude/ru
- `.pi/overlays/docker-compose.slack.yml` and all references to it. The in-tree Pi extension at `.pi/extensions/slack/` reads `SLACK_APP_TOKEN` / `SLACK_BOT_TOKEN` directly from `process.env` at `session_start`, so the compose-time wiring overlay is redundant. `docs/integrations/slack.md`, `README.md`, `docs/architecture/container-runtime.md`, `docs/guide/bring-your-own-harness.md`, `.devcontainer/docker-compose.yml`, and `.devcontainer/.example.env` no longer reference the overlay; `.pi/overlays/` directory removed. Source of truth for Slack env wiring is `.pi/extensions/slack/README.md`.
### Changed
- Docs frame the orchestrator-via-VS-Code-attach as the canonical workflow. `docs/quickstart.md` "Enter the sandbox" now leads with the VS Code Dev Containers attach flow (Command Palette → `Dev Containers: Attach to Running Container...` → `openharness`), since it works identically on localhost and over Remote-SSH; `make shell` is demoted to a terminal fallback. `docs/intro.md` "How it works" names the **orchestrator** (the agent session attached at the project root that owns git, lifecycle, and edits, drives other containers over the Docker socket, and only needs host-shell intervention for things the running container can't do for itself — typically a new bind-mounted volume), frames a second sandbox as opt-in for isolation only, and closes with a Mermaid architecture diagram (orchestrator at the center of the sandbox subgraph, tmux session row, `docker.sock` → optional second sandbox, external GitHub / LLM-provider edges, host bind-mount). `docs/agents/overview.md` replaces the redundant "Running an agent in tmux" section with "Default surfaces" (Pi+Slack, T3 Code, docs app on `:3000`), each as a named tmux session, with explicit guidance to open the two browser surfaces in VS Code's Simple Browser (`Ctrl+Shift+P` → `Simple Browser: Show`; `Cmd+Shift+P` on macOS) so the live UI sits next to the code being edited. Documented tmux sessions renamed `agent-pi` → `harness-pi` and `agent-t3code` → `harness-t3code` in `docs/agents/overview.md` only — the `oh config slack` wizard at `apps/oh/src/config/slack.ts` still creates `agent-pi`, and `context/rules/sandbox-processes.md` still defines the `agent-` prefix; full rename across wizard code, rule, and sibling docs (`docs/intro.md`, `docs/integrations/slack.md`, `docs/agents/t3code.md`, `.pi/extensions/slack/README.md`) will follow. ([#302](https://github.com/ryaneggz/open-harness/issues/302))
- Docs frame the orchestrator-via-VS-Code-attach as the canonical workflow. `docs/quickstart.md` "Enter the sandbox" now leads with the VS Code Dev Containers attach flow (Command Palette → `Dev Containers: Attach to Running Container...` → `openharness`), since it works identically on localhost and over Remote-SSH; `make shell` is demoted to a terminal fallback. `docs/intro.md` "How it works" names the **orchestrator** (the agent session attached at the project root that owns git, lifecycle, and edits, drives other containers over the Docker socket, and only needs host-shell intervention for things the running container can't do for itself — typically a new bind-mounted volume), frames a second sandbox as opt-in for isolation only, and closes with a Mermaid architecture diagram (orchestrator at the center of the sandbox subgraph, tmux session row, `docker.sock` → optional second sandbox, external GitHub / LLM-provider edges, host bind-mount). `docs/harnesses/overview.md` replaces the redundant "Running an agent in tmux" section with "Default surfaces" (Pi+Slack, T3 Code, docs app on `:3000`), each as a named tmux session, with explicit guidance to open the two browser surfaces in VS Code's Simple Browser (`Ctrl+Shift+P` → `Simple Browser: Show`; `Cmd+Shift+P` on macOS) so the live UI sits next to the code being edited. Documented tmux sessions renamed `agent-pi` → `harness-pi` and `agent-t3code` → `harness-t3code` in `docs/harnesses/overview.md` only — the `oh config slack` wizard at `apps/oh/src/config/slack.ts` still creates `agent-pi`, and `context/rules/sandbox-processes.md` still defines the `agent-` prefix; full rename across wizard code, rule, and sibling docs (`docs/intro.md`, `docs/integrations/slack.md`, `docs/harnesses/t3code.md`, `.pi/extensions/slack/README.md`) will follow. ([#302](https://github.com/ryaneggz/open-harness/issues/302))
- `.worktrees/README.md` now reserves `.worktrees/project/<owner>/<repo>/` for durable standalone repo clones and narrows `.worktrees/agent/` to harness agent branches / legacy agent-owned clones, using generic examples so the layout applies cleanly to new users. ([#295](https://github.com/ryaneggz/open-harness/issues/295), [#298](https://github.com/ryaneggz/open-harness/issues/298))
- `oh config slack` wizard UX overhaul. Token prompts now echo `●` per keystroke (was: silent — looked frozen) via a TTY-aware raw-mode `askSecret` that handles backspace, Ctrl-U, and Ctrl-C; piped/non-TTY stdin still uses the legacy readline fallback as `askSecretPiped` so `echo "" | oh config slack` keeps working. Flow is reframed into four numbered steps `[1/4] … [4/4]` with inline "Where:" hints and clickable URLs (OSC 8 hyperlinks; fall back to `label (url)` on legacy terminals). Each input shows `✓ valid prefix` / `✓ N user(s) accepted` after validation. A final summary screen lists the keys (tokens redacted, IDs visible) and gates the env-file write behind a `Proceed? [Y/n]` confirmation. New helpers exported from `apps/oh/src/lib/prompt.ts`: `step()`, `link()`, `bold()`. Zero new runtime dependencies. ([#290](https://github.com/ryaneggz/open-harness/issues/290))
- Migrate `.pi/extensions/slack/{index,tools}.ts` from the deprecated `@mariozechner/pi-coding-agent` (and `@mariozechner/pi-agent-core`) to the upstream-recommended successors `@earendil-works/pi-coding-agent` (and `@earendil-works/pi-agent-core`). Per `npm view @mariozechner/pi-coding-agent`'s deprecation notice, the old package is no longer maintained. The other two in-tree extensions (`path-guard.ts`, `plan-mode/index.ts`) had already migrated; slack was the laggard. `.devcontainer/Dockerfile`'s `[pi-coding-agent]` mapping in the `PKG` array, `docs/agents/pi.md`'s upstream link, `docs/installation.md`'s Pi row, and `.pi/UPSTREAM.md`'s lineage label all updated to match. ([#281](https://github.com/ryaneggz/open-harness/issues/281))
+1 -1
View File
@@ -21,7 +21,7 @@ root.
From the repo root:
```bash
pnpm --filter @openharness/docs dev # run a workspace package
pnpm --filter @openharness/docs start # run a workspace package
pnpm --filter @openharness/docs build # build it
```
+21
View File
@@ -74,6 +74,27 @@ const config: Config = {
],
],
plugins: [
[
"@docusaurus/plugin-client-redirects",
{
// Redirects for the renamed engine pages: docs/agents/ was renamed
// to docs/harnesses/. A new "Agents" section now lives at
// docs/agents/, so /docs/agents and /docs/agents/overview are real
// pages again and cannot be redirected. The 6 engine-name redirects
// below preserve old deep-links into the harness pages.
redirects: [
{ from: "/docs/agents/claude-code", to: "/docs/harnesses/claude-code" },
{ from: "/docs/agents/codex", to: "/docs/harnesses/codex" },
{ from: "/docs/agents/deepagents", to: "/docs/harnesses/deepagents" },
{ from: "/docs/agents/opencode", to: "/docs/harnesses/opencode" },
{ from: "/docs/agents/pi", to: "/docs/harnesses/pi" },
{ from: "/docs/agents/t3code", to: "/docs/harnesses/t3code" },
],
},
],
],
presets: [
[
"classic",
+1
View File
@@ -11,6 +11,7 @@
},
"dependencies": {
"@docusaurus/core": "3.7.0",
"@docusaurus/plugin-client-redirects": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@docusaurus/theme-mermaid": "3.7.0",
"@easyops-cn/docusaurus-search-local": "^0.55.1",
+6 -6
View File
@@ -22,31 +22,31 @@ const AGENTS: Array<{
{
name: "Claude Code",
description: "Anthropic's terminal coding agent.",
href: "/docs/agents/claude-code",
href: "/docs/harnesses/claude-code",
icon: <img src="/img/agents/claude-code.png" alt="" width={28} height={28} />,
},
{
name: "Codex",
description: "OpenAI's CLI coding agent.",
href: "/docs/agents/codex",
href: "/docs/harnesses/codex",
icon: <img src="/img/agents/codex.png" alt="" width={28} height={28} />,
},
{
name: "OpenCode",
description: "Terminal agent with OpenAI OAuth support.",
href: "/docs/agents/opencode",
href: "/docs/harnesses/opencode",
icon: <OpenCodeIcon />,
},
{
name: "Pi",
description: "A lightweight, customizable harness.",
href: "/docs/agents/pi",
href: "/docs/harnesses/pi",
icon: <PiIcon />,
},
{
name: "DeepAgents",
description: "LangChain's multi-provider terminal agent.",
href: "/docs/agents/deepagents",
href: "/docs/harnesses/deepagents",
icon: (
<img
src="https://avatars.githubusercontent.com/u/126733545?s=200&v=4"
@@ -59,7 +59,7 @@ const AGENTS: Array<{
{
name: "T3 Code",
description: "Browser UI over Claude/Codex/OpenCode (port 3773).",
href: "/docs/agents/t3code",
href: "/docs/harnesses/t3code",
icon: (
<img
src="https://github.com/pingdotgg.png"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"label": "Harnesses",
"position": 9,
"label": "Agents",
"position": 10,
"collapsible": true,
"collapsed": true,
"link": {
+57
View File
@@ -0,0 +1,57 @@
---
id: blog-writer
title: "Blog Writer"
sidebar_position: 2
---
# Blog Writer
The Blog Writer is a technical content agent that writes for [ruska.ai/blog](https://ruska.ai/blog) — a blog showcasing AI expertise and driving leads for Ruska AI's automation services. It runs on a weekly heartbeat, rotates through five content pillars (Service Spotlight, Technical How-To, Industry Trends, Behind the Build, Tool Reviews), and produces a fully-formatted blog post plus LinkedIn and X promotional drafts, then opens a PR against the `ruska-ai/website` repository for human review. As its `SOUL.md` states: "You write posts that a developer would bookmark and an SMB owner would forward to their team."
## Branch
[github.com/ryaneggz/open-harness@agent/blog-writer](https://github.com/ryaneggz/open-harness/tree/agent/blog-writer)
## Spin up
```bash
# Clone the harness and check out this agent's branch in a worktree:
git clone https://github.com/ryaneggz/open-harness.git ~/.openharness
cd ~/.openharness
mkdir -p .worktrees/agent
git worktree add .worktrees/agent/blog-writer origin/agent/blog-writer
cd .worktrees/agent/blog-writer
make sandbox
make shell
```
First files to read inside the sandbox:
- [`AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/AGENTS.md)
- [`workspace/AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/AGENTS.md)
## Workspace contents
- [`workspace/.claude/skills/blog-writing/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.claude/skills/blog-writing/SKILL.md) — primary skill: blog post creation, social media derivation, PR workflow, and exact frontmatter format
- [`workspace/.claude/agents/agent-builder.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.claude/agents/agent-builder.md) — sub-agent for scaffolding new agents
- [`workspace/.claude/agents/command-builder.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.claude/agents/command-builder.md) — sub-agent for building CLI commands
- [`workspace/.claude/agents/skill-builder.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.claude/agents/skill-builder.md) — sub-agent for building new skills
- [`workspace/.claude/posts/linkedin-template.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.claude/posts/linkedin-template.md) — LinkedIn post template
- [`workspace/.claude/posts/x-template.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.claude/posts/x-template.md) — X.com post template
- [`workspace/heartbeats/blog-writer.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/heartbeats/blog-writer.md) — weekly blog post heartbeat (Mondays 9am MT)
- [`workspace/heartbeats/memory-distill.md`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/heartbeats/memory-distill.md) — Sunday memory distillation heartbeat
- [`workspace/.pi/banner.json`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.pi/banner.json) — custom Pi agent banner
- [`workspace/.pi/extensions/custom-banner.ts`](https://github.com/ryaneggz/open-harness/blob/agent/blog-writer/workspace/.pi/extensions/custom-banner.ts) — Pi banner extension
## How to use it
Start the sandbox and enter the container with `make shell`. The agent runs Claude Code inside `workspace/`. The weekly heartbeat fires every Monday at 9am MT and runs the full blog-writing workflow automatically: it reads `MEMORY.md` for pillar rotation context, checks the published posts in `ruska-ai/website` to avoid duplicates, picks a topic, writes an 800–1500 word post with correct frontmatter, derives a LinkedIn post (50–200 words) and an X post (under 280 characters), creates a PR against `ruska-ai/website:master`, and logs the result. You can also invoke the `/blog-writing` skill interactively to trigger a post on demand or to draft content for a specific topic.
## Customization tips
The agent reads `heartbeats.conf` for its schedule. To change the posting day or time, edit `workspace/heartbeats.conf` and run `make heartbeat` from the host to sync. Content pillar rotation and topic avoidance are tracked in `workspace/MEMORY.md` and `workspace/memory/YYYY-MM-DD.md` — update `MEMORY.md` to seed a preferred pillar sequence. The blog's author fields (name, LinkedIn URL, avatar) are defined in the `/blog-writing` skill's frontmatter template; update them there if the author changes.
## Best practices observed
- Content pillar rotation is tracked in `MEMORY.md` to prevent clustering — the heartbeat reads recent memory entries before picking a topic.
- Blog post is always the primary artifact; LinkedIn and X posts are derived from it rather than written independently, keeping all three consistent.
- Weekly heartbeat fires via cron (`heartbeats.conf`) and writes structured memory logs so the next run can resume context without re-reading history.
+65
View File
@@ -0,0 +1,65 @@
---
id: dc-designer
title: "DC Designer"
sidebar_position: 3
---
# DC Designer
The DC Designer is a datacenter design engineering agent that autonomously develops a 50MW→200MW hyperscale AI datacenter facility. It works across 15 interconnected plan documents (power, cooling, network, compute, storage, layout, redundancy, security, sustainability, cost model, 3D visualization, phased rollout, and buildout requirements), a FreeCAD parametric 3D model (`model_datacenter.py`) that generates 10 STL layers, and an interactive Three.js viewer (`output/dc_viewer.html`) served via Cloudflare tunnel at `https://dc-designer.ruska.dev`. The agent runs on three heartbeats — an hourly autonomous enhancement pipeline, a weekly design review, and a weekly memory distillation — and enforces quality through a seven-gate pre-merge pipeline before any feature lands.
## Branch
[github.com/ryaneggz/open-harness@agent/dc-designer](https://github.com/ryaneggz/open-harness/tree/agent/dc-designer)
## Spin up
```bash
# Clone the harness and check out this agent's branch in a worktree:
git clone https://github.com/ryaneggz/open-harness.git ~/.openharness
cd ~/.openharness
mkdir -p .worktrees/agent
git worktree add .worktrees/agent/dc-designer origin/agent/dc-designer
cd .worktrees/agent/dc-designer
make sandbox
make shell
```
First files to read inside the sandbox:
- [`AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/AGENTS.md)
- [`workspace/AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/AGENTS.md)
## Workspace contents
**Skills (7 pipeline-specific + 2 templates + 1 utility):**
- [`workspace/.claude/skills/design-consistency/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/design-consistency/SKILL.md) — 7-gate cross-document validation (power budget, cooling match, space allocation, cost coherence, phase alignment, redundancy claims, PUE feasibility)
- [`workspace/.claude/skills/model-review/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/model-review/SKILL.md) — code quality and plan alignment audit for `model_datacenter.py`
- [`workspace/.claude/skills/enhancement-quality-tracker/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/enhancement-quality-tracker/SKILL.md) — quality scoring and trend analysis across features
- [`workspace/.claude/skills/implementation-drift-gate/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/implementation-drift-gate/SKILL.md) — 7-gate plan/model/viewer drift detection
- [`workspace/.claude/skills/pre-merge-gate/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/pre-merge-gate/SKILL.md) — hard gate checking artifact completeness before PR merge
- [`workspace/.claude/skills/iteration-closeout/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/iteration-closeout/SKILL.md) — post-merge workflow enforcer
- [`workspace/.claude/skills/pipeline-strategy-review/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/pipeline-strategy-review/SKILL.md) — strategy effectiveness tracker
- [`workspace/.claude/skills/tunnel-setup/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.claude/skills/tunnel-setup/SKILL.md) — Cloudflare tunnel management
**Heartbeats:**
- [`workspace/heartbeats/enhance-datacenter.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/heartbeats/enhance-datacenter.md) — hourly autonomous feature pipeline (24/7)
- [`workspace/heartbeats/design-review.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/heartbeats/design-review.md) — weekly design review (Wednesdays 10am MT)
- [`workspace/heartbeats/memory-distill.md`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/heartbeats/memory-distill.md) — weekly memory distillation (Sundays 8pm MT)
**Custom extension:**
- [`workspace/.openharness/banner.json`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.openharness/banner.json) — custom banner configuration
- [`workspace/.openharness/extensions/custom-banner.ts`](https://github.com/ryaneggz/open-harness/blob/agent/dc-designer/workspace/.openharness/extensions/custom-banner.ts) — custom banner extension
## How to use it
Run `/setup` from the host after provisioning the sandbox to complete end-to-end setup: it builds the Docker image, starts the container, installs tools, clones the `ai-datacenter-designer` target project into `workspace/ai-datacenter-designer/`, syncs heartbeats, starts the HTTP viewer on port 8200, and brings up the Cloudflare tunnel. Once running, the hourly heartbeat drives autonomous feature development: each pulse checks for a resumable pipeline state, picks the next feature from `enhancements/tracker.md`, creates a per-feature worktree, implements the feature across model/plans/viewer, runs the full pre-merge gate, and merges on pass. The weekly design review runs `/design-consistency` to validate cross-document figures. You can also interact with the agent directly inside the sandbox to request specific features or investigate drift.
## Customization tips
The tunnel hostname (`dc-designer.ruska.dev`) is managed by the `/tunnel-setup` skill and stored in `~/.cloudflared/config-dc-designer.yml` inside the container. To use a different tunnel or disable it, edit that config and restart cloudflared. Heartbeat intervals are set in `workspace/heartbeats.conf`; the hourly enhancement cadence can be slowed by changing the cron expression and running `make heartbeat` from the host. The feature backlog lives in `workspace/ai-datacenter-designer/enhancements/tracker.md` — add entries there to queue new work for the enhancement pipeline.
## Best practices observed
- Hourly enhancement heartbeat uses a persistent JSON pipeline-state file (`enhancements/.pipeline-state.json`) to resume mid-feature across container restarts without losing progress.
- Pre-merge gate (7 checks including plan/model/viewer drift) is a hard gate — the pipeline does not merge unless all gates pass, enforcing consistent quality across the 15-document design corpus.
- Feature work always happens in per-feature worktrees (`~/repo/.worktrees/feat/<N>-<slug>`), never directly on `main`, keeping the trunk stable while the hourly pipeline runs autonomously.
+67
View File
@@ -0,0 +1,67 @@
---
id: linkedin-ghostwriter
title: "LinkedIn Ghostwriter"
sidebar_position: 5
---
# LinkedIn Ghostwriter
The LinkedIn Ghostwriter is a content agent that drafts LinkedIn posts in Ryan Eggleston's voice to grow Open Harness adoption. Each heartbeat cycle it consults a style guide, reads reference posts for voice calibration, picks a topic from a rotating queue, and writes a 50–200 word post that must pass a five-item mandatory checklist: a link to the Open Harness repo, at least one concrete proof point (number, command, or file name), an engagement hook, a connection to a specific Open Harness feature, and a closer not used in any previous draft. Drafts are saved to timestamped files for human review — never published automatically. The funnel goal, as stated in the skill: "Followers → Stars → Contributors → Customers (SMB automation services in Southern Utah)."
## Branch
[github.com/ryaneggz/open-harness@agent/linkedin-ghostwriter](https://github.com/ryaneggz/open-harness/tree/agent/linkedin-ghostwriter)
## Spin up
```bash
# Clone the harness and check out this agent's branch in a worktree:
git clone https://github.com/ryaneggz/open-harness.git ~/.openharness
cd ~/.openharness
mkdir -p .worktrees/agent
git worktree add .worktrees/agent/linkedin-ghostwriter origin/agent/linkedin-ghostwriter
cd .worktrees/agent/linkedin-ghostwriter
make sandbox
make shell
```
First files to read inside the sandbox:
- [`AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/AGENTS.md)
- [`workspace/AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/AGENTS.md)
## Workspace contents
**Skills:**
- [`workspace/.claude/skills/linkedin-ghostwriter/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.claude/skills/linkedin-ghostwriter/SKILL.md) — primary skill: content pillar rotation, mandatory checklist, post structure, draft save workflow
- [`workspace/.claude/skills/post-bridge/SKILL.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.claude/skills/post-bridge/SKILL.md) — Post Bridge API integration for social publishing
**Reference library:**
- [`workspace/.claude/skills/linkedin-ghostwriter/references/style-guide.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.claude/skills/linkedin-ghostwriter/references/style-guide.md) — voice and content strategy guide
- [`workspace/.claude/skills/linkedin-ghostwriter/references/open-harness.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.claude/skills/linkedin-ghostwriter/references/open-harness.md) — repo context and business goals
- [`workspace/.claude/skills/linkedin-ghostwriter/references/posts/`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.claude/skills/linkedin-ghostwriter/references/posts/) — 9 reference posts with screenshots for voice calibration
- [`workspace/.claude/skills/linkedin-ghostwriter/assets/drafts/`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.claude/skills/linkedin-ghostwriter/assets/drafts/) — timestamped draft output (100+ drafts generated)
- [`workspace/.claude/skills/linkedin-ghostwriter/assets/drafts/queue.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.claude/skills/linkedin-ghostwriter/assets/drafts/queue.md) — pending/done topic queue
**Heartbeat:**
- [`workspace/HEARTBEAT.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/HEARTBEAT.md) — heartbeat instructions (LinkedIn Ghostwriter task runs each cycle)
**Custom banner:**
- [`workspace/.pi/banner.json`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.pi/banner.json) — Pi agent custom banner
- [`workspace/.pi/extensions/custom-banner.ts`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/.pi/extensions/custom-banner.ts) — Pi banner extension
**Memory:**
- [`workspace/memory/linkedin-ghostwriter-iterations.md`](https://github.com/ryaneggz/open-harness/blob/agent/linkedin-ghostwriter/workspace/memory/linkedin-ghostwriter-iterations.md) — per-cycle iteration log (pillar balance, checklist pass/fail, lessons)
## How to use it
Start the sandbox and enter with `make shell`. The agent runs Claude Code inside `workspace/`. Each heartbeat cycle it reads the iteration memory for past learnings, consults the style guide and two reference posts, checks the topic queue, drafts a post with a content-pillar label (Pain→Solution, Build Log, Steal My Workflow, or Honest Reflection), verifies the mandatory checklist, saves the draft to a timestamped file under `assets/drafts/`, updates the queue, and writes a cycle summary to `memory/linkedin-ghostwriter-iterations.md`. You can also invoke the `/linkedin-ghostwriter` skill interactively to draft a post for a specific topic or angle. To publish, copy a draft and use the `/post-bridge` skill or your own publishing workflow.
## Customization tips
Content pillar rotation, topic history, and the mandatory closer log are all tracked in `workspace/memory/linkedin-ghostwriter-iterations.md` and `assets/drafts/queue.md`. Seed the queue's `## Pending` section with specific topics or angles to steer future drafts. The style guide at `references/style-guide.md` defines anti-patterns and formatting conventions — edit it to adjust voice or structural rules. The heartbeat interval is controlled by the host-side `HEARTBEAT_INTERVAL` environment variable (default 1800 seconds). See `workspace/AGENTS.md` on the branch for env-var and channel customization.
## Best practices observed
- Mandatory five-item checklist enforced per draft (repo link, proof point, engagement hook, OH feature connection, unique closer) ensures consistent post quality without relying on the agent's discretion.
- Iteration memory (`linkedin-ghostwriter-iterations.md`) tracks pillar balance across cycles so the agent can self-correct if it clusters on one content type.
- Draft queue (`assets/drafts/queue.md`) maintains a Pending/Done topic ledger, letting the heartbeat pick up pre-seeded topics or generate fresh ones from a different pillar than the previous cycle.
+33 -72
View File
@@ -1,92 +1,53 @@
---
id: overview
title: "Agents Overview"
sidebar_position: 1
title: "Harnesses Overview"
---
# Harnesses Overview
# Agents Overview
Open Harness ships with five agent CLIs preinstalled in the sandbox image: **Claude Code** (default), **Codex**, **OpenCode**, **Pi**, and **DeepAgents**. A sixth harness, **T3 Code**, runs on demand via `npx t3` as a browser UI on port 3773. Inside the sandbox, launch whichever you prefer — switch between them at any time, or keep long-running sessions in tmux.
Open Harness ships a set of pre-built agent identities on public `agent/*` branches. Each branch contains a fully-scaffolded `workspace/` — identity files (`SOUL.md`, `AGENTS.md`), skills, heartbeats, and memory — that gives a harness a specific purpose. Check out the branch, run `make sandbox`, and the agent is live.
The sandbox is the product; the harness is your call. To go beyond the preinstalled options, install via `npm` / `pip` / `cargo` inside the sandbox, edit the Dockerfile, or layer in a harness pack such as [`@ryaneggz/mifune`](https://github.com/ryaneggz/mifune). For Pi+Slack specifically, the recommended path is the in-tree extension at [`.pi/extensions/slack/`](../integrations/slack.md). The product surface is one developer, one project, one harness — not racing or stacking multiple CLIs against each other.
## Agents vs. Harnesses
## Supported agents
| | Harnesses | Agents |
|---|---|---|
| **What** | The CLI engine you run (`claude`, `codex`, `pi`, …) | A configured workspace that gives an engine purpose |
| **Where** | Preinstalled in the sandbox image | `agent/*` branches; `workspace/` bind-mounted at runtime |
| **Analogy** | The interpreter | The program |
| Agent | Role | Start command | Source |
|---|---|---|---|
| [Claude Code](./claude-code.md) | Anthropic's terminal coding agent (default) | `claude` | preinstalled |
| [Codex](./codex.md) | OpenAI's CLI coding agent | `codex` | preinstalled |
| [OpenCode](./opencode.md) | Terminal coding agent with OpenAI OAuth support | `opencode` | preinstalled |
| [Pi](./pi.md) | Lightweight, customizable harness | `pi` | preinstalled |
| [DeepAgents](./deepagents.md) | LangChain's multi-provider terminal agent | `deepagents` | preinstalled |
| [T3 Code](./t3code.md) | Browser UI over Claude/Codex/OpenCode (port 3773) | `npx t3` | on-demand |
An agent identity is engine-agnostic: the same `workspace/` can drive Claude Code, Codex, or Pi — whichever harness is authenticated. See [Harnesses](../harnesses/overview.md) for the engine-level docs.
## Verifying installation
## Adopting an agent
**Option A — worktree (keeps your main checkout intact):**
```bash
claude --version
codex --version
opencode --version
pi --version
deepagents -v
npx t3 --version # T3 Code (not preinstalled — fetched on demand)
git fetch origin
git worktree add .worktrees/agent/<name> agent/<name>
cd .worktrees/agent/<name>
make sandbox
```
## Authentication
Open Harness ships Claude Code, Codex, OpenCode, Pi, and DeepAgents preinstalled. Authenticate at least one harness before use:
- **Claude Code**: run `claude` and follow the OAuth prompt (see [Claude Code](./claude-code.md)).
- **Codex**: run `codex login` (see [Codex](./codex.md)).
- **OpenCode**: run `opencode auth login` (see [OpenCode](./opencode.md)).
- **Pi**: configure provider keys via environment variables (see [Pi](./pi.md)).
- **DeepAgents**: write provider keys to `~/.deepagents/.env` (see [DeepAgents](./deepagents.md)).
- **T3 Code**: authenticate one of Claude / Codex / OpenCode first, then `npx t3` and open the printed pairing URL (see [T3 Code](./t3code.md)).
## Default surfaces
Three surfaces cover most day-to-day use:
- **Pi+Slack** — chat with the agent from Slack instead of the terminal.
- **T3 Code** — browser UI on port `3773` driving Claude / Codex / OpenCode.
- **Docs app** — the Docusaurus site you're reading now, on port `3000`.
Each runs in its own named tmux session per [`context/rules/sandbox-processes.md`](https://github.com/ryaneggz/open-harness/blob/development/context/rules/sandbox-processes.md). For the two browser surfaces, open them in **VS Code's Simple Browser** (`Ctrl+Shift+P` → `Simple Browser: Show`; `Cmd+Shift+P` on macOS) so the live UI sits in a tab next to the code you're editing.
### Pi+Slack
The Pi agent with the Slack bridge loaded. The wizard writes `.devcontainer/.env`, launches the `harness-pi` session, and waits for the Socket Mode connection to come up:
**Option B — fresh clone:**
```bash
oh config slack # interactive wizard
tmux attach -t harness-pi # watch the live log
git clone https://github.com/ryaneggz/open-harness.git
cd open-harness
git checkout agent/<name>
make sandbox
```
Talk to the agent from Slack (DM or `@mention` in an allow-listed channel). Full setup: [Slack integration](../integrations/slack.md).
Both paths land you at the standard `make sandbox` flow described in [Installation](/docs/installation).
### T3 Code
## Available agents
Web UI on `http://localhost:3773` over an already-authenticated provider:
| Agent | Description | Branch |
|---|---|---|
| [Blog Writer](./blog-writer) | Writes technical blog posts for ruska.ai in Ryan Eggleston's voice — developer-bookmark quality, SMB-forward | [agent/blog-writer](https://github.com/ryaneggz/open-harness/tree/agent/blog-writer) |
| [DC Designer](./dc-designer) | Provisions and maintains a sandbox for an AI-driven 50MW–200MW hyperscale datacenter facility design | [agent/dc-designer](https://github.com/ryaneggz/open-harness/tree/agent/dc-designer) |
| [LinkedIn Ghostwriter](./linkedin-ghostwriter) | General-purpose coding agent scaffolded for LinkedIn content drafting workflows | [agent/linkedin-ghostwriter](https://github.com/ryaneggz/open-harness/tree/agent/linkedin-ghostwriter) |
| [Portfolio Manager](./portfolio-mgr) | Runs a mock $100K portfolio informed by Bridgewater's 13F filing and Ray Dalio's All Weather strategy | [agent/portfolio-mgr](https://github.com/ryaneggz/open-harness/tree/agent/portfolio-mgr) |
| [UAT Tester](./uat-tester) | Visual acceptance testing agent — methodical, screenshot-driven, ranked by user impact | [agent/uat-tester](https://github.com/ryaneggz/open-harness/tree/agent/uat-tester) |
```bash
tmux new-session -d -s harness-t3code 'npx t3 2>&1 | tee /tmp/harness-t3code.log'
tmux capture-pane -t harness-t3code -p | grep -i pairingUrl
```
Open the printed pairing URL (`http://localhost:3773/pair#token=…`) in the Simple Browser tab. Full setup: [T3 Code](./t3code.md).
### Docs app
The site you're reading now, served locally:
```bash
tmux new-session -d -s app-docs 'pnpm --filter @openharness/docs dev 2>&1 | tee /tmp/app-docs.log'
```
Open `http://localhost:3000` in the Simple Browser tab for hot-reload feedback on doc edits without leaving the editor.
### Reattach to any session
```bash
tmux ls # list sessions
tmux attach -t <session-name> # reattach (Ctrl-b d to detach)
```
Each page documents the agent's purpose, workspace layout, and any setup steps beyond `make sandbox`.
+60
View File
@@ -0,0 +1,60 @@
---
id: portfolio-mgr
title: "Portfolio Manager"
sidebar_position: 7
---
# Portfolio Manager
Portfolio Manager is a quantitative portfolio-management agent that tracks and rebalances a mock $100K portfolio modeled on Ray Dalio's All Weather strategy and Bridgewater Associates' latest 13F filing. It pulls live prices via yfinance, scores market sentiment with WebSearch, computes risk metrics (Sharpe, Sortino, max drawdown, beta, volatility), and flags allocation drift before it exceeds the 5% rebalancing threshold. As the agent's own SOUL.md states: "You are data-driven: cite numbers, percentages, and Sharpe ratios, not vibes." This is an educational simulation — all trades are mock, and the agent never presents output as financial advice.
## Branch
[github.com/ryaneggz/open-harness@agent/portfolio-mgr](https://github.com/ryaneggz/open-harness/tree/agent/portfolio-mgr)
## Spin up
```bash
# Clone the harness and check out this agent's branch in a worktree:
git clone https://github.com/ryaneggz/open-harness.git ~/.openharness
cd ~/.openharness
mkdir -p .worktrees/agent
git worktree add .worktrees/agent/portfolio-mgr origin/agent/portfolio-mgr
cd .worktrees/agent/portfolio-mgr
make sandbox
make shell
```
First files to read inside the sandbox:
- [`AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/AGENTS.md)
- [`workspace/AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/AGENTS.md)
## Workspace contents
- **Skills**
- [`/allocation-check`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/.claude/skills/allocation-check/SKILL.md) — validate current weights against target allocation before any rebalance
- [`/risk-metrics`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/.claude/skills/risk-metrics/SKILL.md) — compute Sharpe, Sortino, max drawdown, beta, and volatility
- [`/sentiment-score`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/.claude/skills/sentiment-score/SKILL.md) — WebSearch-driven macro sentiment composite
- [`/strategy-review`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/.claude/skills/strategy-review/SKILL.md) — measure decision quality over rolling periods
- **Heartbeats** (defined in [`heartbeats.conf`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/heartbeats.conf))
- [`market-check.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/heartbeats/market-check.md) — daily at 4:30 PM ET after market close: fetch prices, compute P&L, run risk-metrics and sentiment-score, flag drift > 3%
- [`rebalance-review.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/heartbeats/rebalance-review.md) — Friday 5 PM MT: weekly rebalance decision
- [`monthly-retro.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/heartbeats/monthly-retro.md) — 1st of each month: rolling performance retrospective
- [`memory-distill.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/heartbeats/memory-distill.md) — Sunday 8 PM MT: distill daily logs into MEMORY.md
- **Portfolio data** — [`portfolio/state.json`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/portfolio/state.json) (current holdings), [`portfolio/ledger.json`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/portfolio/ledger.json) (strategy versions + forward performance), [`portfolio/scorecard.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/portfolio/scorecard.md) (rolling summary)
- **Pi banner** — [`workspace/.pi/banner.json`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/.pi/banner.json) with a custom extension at [`workspace/.pi/extensions/custom-banner.ts`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/.pi/extensions/custom-banner.ts)
- **Sub-agents** — agent-builder, command-builder, skill-builder under [`workspace/.claude/agents/`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/.claude/agents/)
## How to use it
Once the sandbox is running and Claude Code is started (`claude`), the agent enters an autonomous daily cycle driven by the `market-check` heartbeat. During interactive sessions you can ask the agent to run any skill directly — for example, ask it to run `/risk-metrics` or `/allocation-check` to get an on-demand snapshot. The portfolio state lives in `portfolio/state.json`; the agent reads it at every heartbeat and writes updates to the daily memory log. When allocation drift on any position exceeds 5%, the agent proposes a rebalance and runs the quality-gate chain (`/risk-metrics` then `/allocation-check`) before confirming the mock trade.
## Customization tips
The target tickers and allocation weights are stored in `MEMORY.md` and `portfolio/state.json` on the branch — update them to swap the underlying 13F or All Weather mix. The heartbeat schedule (market-close time, rebalance day) is in [`heartbeats.conf`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/heartbeats.conf); edit the cron expressions there and run `make heartbeat` to re-sync the daemon. See `workspace/AGENTS.md` on the branch for the full environment and tool reference.
## Best practices observed
- Dual-skill quality gate (`/risk-metrics` → `/allocation-check`) runs before every rebalance decision, preventing premature trades on noisy single-day moves.
- Market-check heartbeat scheduled via [`heartbeats/market-check.md`](https://github.com/ryaneggz/open-harness/blob/agent/portfolio-mgr/workspace/heartbeats/market-check.md) fires daily at 4:30 PM ET after market close, keeping the agent on a market-hours rhythm without manual triggers.
- `portfolio/ledger.json` tracks strategy versions alongside forward performance, enabling before/after comparison whenever the All Weather weights are changed.
+69
View File
@@ -0,0 +1,69 @@
---
id: uat-tester
title: "UAT Tester"
sidebar_position: 4
---
# UAT Tester
UAT Tester is a visual acceptance-testing agent that exercises deployed web applications as a real user would. Using headless Chromium via the `agent-browser` CLI, it navigates every user flow — authentication, CRUD operations, navigation, forms — across desktop, tablet, and mobile viewports. Its README describes its scope precisely: "A visual UAT agent that tests deployed web applications as a real user would. Identifies visual bugs, broken flows, accessibility violations, and UX issues. Produces a deduplicated, impact-ranked top-20 findings list per project as user stories." The agent supports multiple concurrent projects, each with its own scoped findings directory, and includes a recheck loop for verifying deployed fixes. It never writes application code, deploys changes, or merges PRs.
## Branch
[github.com/ryaneggz/open-harness@agent/uat-tester](https://github.com/ryaneggz/open-harness/tree/agent/uat-tester)
## Spin up
```bash
# Clone the harness and check out this agent's branch in a worktree:
git clone https://github.com/ryaneggz/open-harness.git ~/.openharness
cd ~/.openharness
mkdir -p .worktrees/agent
git worktree add .worktrees/agent/uat-tester origin/agent/uat-tester
cd .worktrees/agent/uat-tester
make sandbox
make shell
```
First files to read inside the sandbox:
- [`AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/AGENTS.md)
- [`workspace/AGENTS.md`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/AGENTS.md)
## Workspace contents
- **Core testing skills** (under [`workspace/.claude/skills/`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/))
- [`/visual-uat`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/visual-uat/SKILL.md) — full 6-phase UAT sweep of a registered project
- [`/recheck`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/recheck/SKILL.md) — re-verify specific findings after fixes are deployed
- [`/test-auth`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-auth/SKILL.md), [`/test-forms`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-forms/SKILL.md), [`/test-nav`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-nav/SKILL.md), [`/test-crud`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-crud/SKILL.md), [`/test-search`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-search/SKILL.md)
- [`/test-a11y`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-a11y/SKILL.md) — WCAG A/AA, keyboard nav, ARIA, alt text, focus checks
- [`/test-responsive`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-responsive/SKILL.md) — 3-viewport sweep (desktop, tablet, mobile)
- [`/test-visual-regression`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/test-visual-regression/SKILL.md) — before/after screenshot comparison
- [`/quality-gate`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/quality-gate/SKILL.md), [`/strategy-review`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/skills/strategy-review/SKILL.md)
- **Specialist sub-agents** (spawned in parallel, under [`workspace/.claude/agents/`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/agents/))
- [`a11y-auditor.md`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/agents/a11y-auditor.md) — WCAG compliance sweep
- [`responsive-tester.md`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/agents/responsive-tester.md) — 3-viewport coverage
- [`flow-walker.md`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/agents/flow-walker.md) — happy-path and edge-case user flows
- [`visual-diff.md`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/agents/visual-diff.md) — regression detection for rechecked items
- **Rules** (auto-loaded from [`workspace/.claude/rules/`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/rules/))
- `uat-testing.md` — core protocol: evidence required, dedup, top-20 cap, user story format, no app code
- `agent-browser.md` — browser hygiene: session isolation, wait-before-capture, naming conventions
- `findings-management.md` — JSON source of truth, severity criteria, dedup logic, archive protocol
- `multi-project.md` — project isolation: scoped to slug, registration required
- **Heartbeat**
- [`heartbeats/uat-report.md`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/heartbeats/uat-report.md) — every 4 hours, 9 AM–9 PM: status report across registered projects
- **Project registry** — [`uat/projects.json`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/uat/projects.json) — register each app under test with a slug, URL, and login instructions
- **Slack integration** — [`workspace/.claude/hooks/notify_slack.sh`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/.claude/hooks/notify_slack.sh); `.slack/skills` for shared skill access
## How to use it
Register the target application in `uat/projects.json` with a slug, URL, and login instructions. Then ask the agent to run `/visual-uat <slug>` — it spawns the four specialist sub-agents in parallel (a11y auditor, responsive tester, flow walker, visual diff), collects their findings, deduplicates them, and produces a top-20 impact-ranked list as user stories in both JSON and Markdown. When developers report fixes, run `/recheck <slug> [IDs]` and the agent re-plays the original reproduction steps, returning `PASS`, `FAIL`, or `CHANGED` for each item. The `uat-report` heartbeat fires every 4 hours during active hours (9 AM–9 PM) to surface any status changes without manual prompting.
## Customization tips
Each project is registered independently in `uat/projects.json` — add as many projects as needed, each with its own slug and findings directory. The active window for the heartbeat (currently 9–21) and frequency (every 4 hours) are set in [`heartbeats.conf`](https://github.com/ryaneggz/open-harness/blob/agent/uat-tester/workspace/heartbeats.conf). Severity thresholds and the top-20 cap are governed by `workspace/.claude/rules/findings-management.md`. See `workspace/AGENTS.md` on the branch for the full environment and tool reference, including the `INSTALL_BROWSER=true` requirement for the sandbox build.
## Best practices observed
- Four specialist sub-agents (a11y auditor, responsive tester, flow walker, visual diff) spawn in parallel during a `/visual-uat` run, giving simultaneous coverage across accessibility, responsiveness, flows, and regression without sequential bottlenecks.
- A hard top-20 cap per project with an archive-and-promote mechanism keeps the findings list actionable — overflow is preserved in `findings-archive.json` and promoted back when higher-priority items are resolved.
- The self-improving autoresearch loop (Karpathy pattern) runs after every skill execution: hypothesize a change, apply it, measure on the next run, keep or revert — skills and rules tighten automatically based on real finding data rather than speculation.
+165
View File
@@ -0,0 +1,165 @@
---
id: connecting
slug: /connecting
sidebar_position: 4
title: "Connecting to the Sandbox"
---
# Connecting to the Sandbox
The sandbox is a Docker container running on your host (or a remote server). Getting UI apps like the docs site and T3 Code onto your laptop browser depends on **how** you connect — not every connection method forwards ports. This page covers your options, explains which one to use, and walks an end-to-end recipe.
## Three ways to connect
| Option | Command / action | Port forwarding to laptop |
|--------|-----------------|--------------------------|
| **A — Terminal** | `make shell` from the host | None — plain shell only |
| **B — VSCode Attach (local)** | Dev Containers extension → "Attach to Running Container" → `openharness` | Automatic while attached |
| **C — VSCode Remote-SSH + Attach (remote host)** | SSH into your host in VSCode, then Attach to Container | Automatic while attached |
### Option A — Terminal
```bash
cd ~/.openharness
make shell
```
You land inside the container as the `sandbox` user. This is enough to run CLI agents and configure Slack. Container ports are **not** forwarded to your laptop — you cannot open `localhost:3000` in your browser via this method alone.
### Option B — VSCode Attach to Running Container (local host)
1. Install the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
2. Open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) → **Dev Containers: Attach to Running Container**.
3. Select **openharness**.
VSCode opens a remote window connected to the container and **automatically forwards container ports to `localhost`** on your laptop for the duration of the session.
### Option C — VSCode Remote-SSH + Attach (remote host)
If the sandbox runs on a remote server:
1. Connect to the server via **Remote-SSH** in VSCode.
2. From that SSH window, follow Option B to attach to the `openharness` container.
Port forwarding works identically — VSCode tunnels the container ports through the SSH connection to your laptop `localhost`. No manual `ssh -L` required.
## Why VSCode Attach is the recommended path
Attaching via VSCode is the easiest way to reach container UIs on your laptop browser. The auto-forwarding is session-scoped: ports appear under the **Ports** panel while attached and disappear when you close or detach from the VSCode window.
If you only need a terminal (no browser UI), Option A is fine.
## What happens when you close VSCode
When you close the VSCode remote window or detach from the container, the port forwards drop. Apps in tmux keep running inside the container — they are unaffected — but `localhost:<port>` on your laptop no longer resolves until you re-attach.
## Default exposure posture
The sandbox publishes **one port** by default:
```
127.0.0.1:1455:1455 # Pi harness OAuth login callback (host loopback only)
```
Nothing else is published to the host. The `127.0.0.1` binding ensures port 1455 is reachable from `localhost` on the host machine — which VSCode's Remote-SSH forwarding can carry back to your laptop — without exposing it on any public interface.
All other container ports (3000, 3773, etc.) are only reachable via VSCode's auto-forwarding or a manual `ssh -L` tunnel.
## Opt-in public exposure
If you need a port reachable beyond your laptop — for example, to share a preview with a teammate — there are two opt-in paths:
**1. Compose overlay binding `0.0.0.0`**
Add a custom compose file that binds the port on all interfaces and merge it in with `composeOverrides[]` in `config.json`:
```yaml
# docker-compose.my-expose.yml
services:
sandbox:
ports:
- "0.0.0.0:3000:3000"
```
This is NOT the default; you opt in explicitly. Be aware that binding to `0.0.0.0` exposes the port on the host's public interface.
**2. External tunnel**
The harness ships no built-in tunnel tool. For public access, bring your own: `cloudflared`, `ngrok`, `tailscale funnel`, or an nginx/Caddy reverse proxy. Start the tunnel inside the sandbox in a named tmux session (see [tmux conventions](#tmux-session-naming)).
## tmux session naming
All long-running processes inside the sandbox run in named tmux sessions. The naming convention is `<category>-<identifier>`:
| Category | Example | Purpose |
|----------|---------|---------|
| `agent-` | `agent-claude`, `agent-pi` | AI agent processes |
| `app-` | `app-docs`, `app-api` | Dev servers |
For the full convention see [`context/rules/sandbox-processes.md`](https://github.com/ryaneggz/open-harness/blob/development/context/rules/sandbox-processes.md).
## End-to-end recipe
This recipe assumes the sandbox is already running (`make ps` confirms the `openharness` container is up). Steps run inside the sandbox unless noted.
### Step 1 — Attach via VSCode
Follow Option B (or C for a remote host). The Ports panel in VSCode shows forwarded ports as you launch apps.
### Step 2 — Configure Slack
```bash
# Inside the sandbox (already attached via VSCode or make shell)
oh config slack
```
The interactive wizard collects your Slack tokens, validates them, writes `.devcontainer/.env`, and restarts the `agent-pi` tmux session in Socket Mode. For the full wizard walkthrough see [Integrations → Slack](/docs/integrations/slack).
After the wizard completes, verify the bridge is live:
```bash
tmux capture-pane -t agent-pi -p | grep -i 'connected\|listening'
```
### Step 3 — Launch T3 Code
T3 Code is not preinstalled; the first invocation downloads it via `npx`.
```bash
tmux new-session -d -s agent-t3code 'npx t3 2>&1 | tee /tmp/agent-t3code.log'
tmux attach -t agent-t3code
```
Watch the session output — T3 Code prints a pairing URL. Open that URL in your browser to complete the browser-based pairing step. After pairing, the UI is available at `localhost:3773` on your laptop (via VSCode auto-forwarding).
Detach from the tmux session without stopping it: `Ctrl-b d`.
For more on T3 Code setup see [Harnesses → T3 Code](/docs/harnesses/t3code).
### Step 4 — Launch the docs site
```bash
tmux new-session -d -s app-docs 'pnpm --filter @openharness/docs start 2>&1 | tee /tmp/app-docs.log'
```
The Docusaurus dev server binds port 3000 inside the container. Via VSCode auto-forwarding, open `localhost:3000` in your laptop browser.
### Step 5 — Confirm ports in VSCode
Open the **Ports** panel (bottom status bar → Ports, or `Ctrl+Shift+P` → "Focus on Ports"). You should see:
| Port | Forwarded to | App |
|------|-------------|-----|
| 1455 | localhost:1455 | Pi OAuth callback |
| 3000 | localhost:3000 | Docs site |
| 3773 | localhost:3773 | T3 Code UI |
If a port is missing, confirm the tmux session is running (`tmux ls`) and that you are still attached via VSCode.
## Quick-reference: reach `localhost` from your laptop
| App | Container port | Laptop URL (VSCode attached) |
|-----|---------------|------------------------------|
| Docs site | 3000 | `http://localhost:3000` |
| T3 Code UI | 3773 | `http://localhost:3773` |
| Pi OAuth callback | 1455 | `http://localhost:1455` |
+10
View File
@@ -0,0 +1,10 @@
{
"label": "Harnesses",
"position": 9,
"collapsible": true,
"collapsed": true,
"link": {
"type": "doc",
"id": "harnesses/overview"
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+94
View File
@@ -0,0 +1,94 @@
---
sidebar_position: 1
title: "Harnesses Overview"
---
# Harnesses Overview
Open Harness ships with five agent CLIs preinstalled in the sandbox image: **Claude Code** (default), **Codex**, **OpenCode**, **Pi**, and **DeepAgents**. A sixth harness, **T3 Code**, runs on demand via `npx t3` as a browser UI on port 3773. Inside the sandbox, launch whichever you prefer — switch between them at any time, or keep long-running sessions in tmux.
The sandbox is the product; the harness is your call. To go beyond the preinstalled options, install via `npm` / `pip` / `cargo` inside the sandbox, edit the Dockerfile, or layer in a harness pack such as [`@ryaneggz/mifune`](https://github.com/ryaneggz/mifune). For Pi+Slack specifically, the recommended path is the in-tree extension at [`.pi/extensions/slack/`](../integrations/slack.md). The product surface is one developer, one project, one harness — not racing or stacking multiple CLIs against each other.
## Supported agents
| Agent | Role | Start command | Source |
|---|---|---|---|
| [Claude Code](./claude-code.md) | Anthropic's terminal coding agent (default) | `claude` | preinstalled |
| [Codex](./codex.md) | OpenAI's CLI coding agent | `codex` | preinstalled |
| [OpenCode](./opencode.md) | Terminal coding agent with OpenAI OAuth support | `opencode` | preinstalled |
| [Pi](./pi.md) | Lightweight, customizable harness | `pi` | preinstalled |
| [DeepAgents](./deepagents.md) | LangChain's multi-provider terminal agent | `deepagents` | preinstalled |
| [T3 Code](./t3code.md) | Browser UI over Claude/Codex/OpenCode (port 3773) | `npx t3` | on-demand |
## Verifying installation
```bash
claude --version
codex --version
opencode --version
pi --version
deepagents -v
npx t3 --version # T3 Code (not preinstalled — fetched on demand)
```
## Authentication
Open Harness ships Claude Code, Codex, OpenCode, Pi, and DeepAgents preinstalled. Authenticate at least one harness before use:
- **Claude Code**: run `claude` and follow the OAuth prompt (see [Claude Code](./claude-code.md)).
- **Codex**: run `codex login` (see [Codex](./codex.md)).
- **OpenCode**: run `opencode auth login` (see [OpenCode](./opencode.md)).
- **Pi**: configure provider keys via environment variables (see [Pi](./pi.md)).
- **DeepAgents**: write provider keys to `~/.deepagents/.env` (see [DeepAgents](./deepagents.md)).
- **T3 Code**: authenticate one of Claude / Codex / OpenCode first, then `npx t3` and open the printed pairing URL (see [T3 Code](./t3code.md)).
## Default surfaces
Three surfaces cover most day-to-day use:
- **Pi+Slack** — chat with the agent from Slack instead of the terminal.
- **T3 Code** — browser UI on port `3773` driving Claude / Codex / OpenCode.
- **Docs app** — the Docusaurus site you're reading now, on port `3000`.
Each runs in its own named tmux session per [`context/rules/sandbox-processes.md`](https://github.com/ryaneggz/open-harness/blob/development/context/rules/sandbox-processes.md). For the two browser surfaces, open them in **VS Code's Simple Browser** (`Ctrl+Shift+P` → `Simple Browser: Show`; `Cmd+Shift+P` on macOS) so the live UI sits in a tab next to the code you're editing.
### Pi+Slack
The Pi agent with the Slack bridge loaded. The wizard writes `.devcontainer/.env`, launches the `harness-pi` session, and waits for the Socket Mode connection to come up:
```bash
oh config slack # interactive wizard
tmux attach -t harness-pi # watch the live log
```
Talk to the agent from Slack (DM or `@mention` in an allow-listed channel). Full setup: [Slack integration](../integrations/slack.md).
### T3 Code
Web UI on `http://localhost:3773` over an already-authenticated provider:
```bash
tmux new-session -d -s harness-t3code 'npx t3 2>&1 | tee /tmp/harness-t3code.log'
tmux capture-pane -t harness-t3code -p | grep -i pairingUrl
```
Open the printed pairing URL (`http://localhost:3773/pair#token=…`) in the Simple Browser tab. Full setup: [T3 Code](./t3code.md).
### Docs app
The site you're reading now, served locally:
```bash
tmux new-session -d -s app-docs 'pnpm --filter @openharness/docs dev 2>&1 | tee /tmp/app-docs.log'
```
Open `http://localhost:3000` in the Simple Browser tab for hot-reload feedback on doc edits without leaving the editor.
### Reattach to any session
```bash
tmux ls # list sessions
tmux attach -t <session-name> # reattach (Ctrl-b d to detach)
```
[Connecting to the Sandbox](/docs/connecting)
File renamed without changes.
@@ -67,3 +67,5 @@ If you can't reach `localhost:3773` from the host, expose port 3773 from the san
## Upstream documentation
- [`pingdotgg/t3code` on GitHub](https://github.com/pingdotgg/t3code)
[Connecting to the Sandbox](/docs/connecting)
+2
View File
@@ -182,3 +182,5 @@ file inventory, env var reference, and build/test instructions, see
For upstream lineage, sync model, and divergence history, see
[`.pi/UPSTREAM.md`](https://github.com/ryaneggz/open-harness/blob/development/.pi/UPSTREAM.md).
[Connecting to the Sandbox](/docs/connecting)
+2
View File
@@ -67,3 +67,5 @@ If you already have a sandbox running, jump directly to the page you need.
## Where to get help
- Source code and issues: [github.com/ryaneggz/open-harness](https://github.com/ryaneggz/open-harness)
[Connecting to the Sandbox](/docs/connecting)
+9 -7
View File
@@ -45,17 +45,19 @@ The sandbox ships with Claude Code, Codex, OpenCode, Pi, and DeepAgents
preinstalled, plus T3 Code on demand via `npx`. Authenticate at least one
before use:
- **[Claude Code](./agents/claude-code.md)**: run `claude` and follow the OAuth prompt
- **[Codex](./agents/codex.md)**: run `codex login`
- **[OpenCode](./agents/opencode.md)**: run `opencode auth login`
- **[Pi](./agents/pi.md)**: configure provider keys via environment variables
- **[DeepAgents](./agents/deepagents.md)**: write provider keys to `~/.deepagents/.env`
- **[T3 Code](./agents/t3code.md)**: authenticate one of Claude / Codex / OpenCode, then `npx t3` (browser UI on port 3773)
- **[Claude Code](./harnesses/claude-code.md)**: run `claude` and follow the OAuth prompt
- **[Codex](./harnesses/codex.md)**: run `codex login`
- **[OpenCode](./harnesses/opencode.md)**: run `opencode auth login`
- **[Pi](./harnesses/pi.md)**: configure provider keys via environment variables
- **[DeepAgents](./harnesses/deepagents.md)**: write provider keys to `~/.deepagents/.env`
- **[T3 Code](./harnesses/t3code.md)**: authenticate one of Claude / Codex / OpenCode, then `npx t3` (browser UI on port 3773)
Claude Code remains the documented default. See
[the harnesses overview](./agents/overview) for the full list and
[the harnesses overview](./harnesses/overview) for the full list and
per-harness setup.
[Connecting to the Sandbox](/docs/connecting)
If `GH_TOKEN` was set during install, the entrypoint already ran
`gh auth login` and `gh auth setup-git` for you. Otherwise run them once
inside the shell:
+63 -30
View File
@@ -42,6 +42,9 @@ importers:
'@docusaurus/core':
specifier: 3.7.0
version: 3.7.0(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(debug@4.4.3)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
'@docusaurus/plugin-client-redirects':
specifier: 3.7.0
version: 3.7.0(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
'@docusaurus/preset-classic':
specifier: 3.7.0
version: 3.7.0(@algolia/client-search@5.51.0)(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(@types/react@19.2.14)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.6.3)
@@ -1175,6 +1178,13 @@ packages:
react: '*'
react-dom: '*'
'@docusaurus/plugin-client-redirects@3.7.0':
resolution: {integrity: sha512-6B4XAtE5ZVKOyhPgpgMkb7LwCkN+Hgd4vOnlbwR8nCdTQhLjz8MHbGlwwvZ/cay2SPNRX5KssqKAlcHVZP2m8g==}
engines: {node: '>=18.0'}
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
'@docusaurus/plugin-content-blog@3.7.0':
resolution: {integrity: sha512-EFLgEz6tGHYWdPU0rK8tSscZwx+AsyuBW/r+tNig2kbccHYGUJmZtYN38GjAa3Fda4NU+6wqUO5kTXQSRBQD3g==}
engines: {node: '>=18.0'}
@@ -3698,15 +3708,6 @@ packages:
flatted@3.4.2:
resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==}
follow-redirects@1.15.11:
resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
follow-redirects@1.16.0:
resolution: {integrity: sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==}
engines: {node: '>=4.0'}
@@ -6398,6 +6399,7 @@ packages:
uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
value-equal@1.0.1:
@@ -8198,6 +8200,39 @@ snapshots:
- uglify-js
- webpack-cli
'@docusaurus/plugin-client-redirects@3.7.0(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)':
dependencies:
'@docusaurus/core': 3.7.0(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(debug@4.4.3)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
'@docusaurus/logger': 3.7.0
'@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@docusaurus/utils-common': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
eta: 2.2.0
fs-extra: 11.3.4
lodash: 4.18.1
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
tslib: 2.8.1
transitivePeerDependencies:
- '@docusaurus/faster'
- '@mdx-js/react'
- '@parcel/css'
- '@rspack/core'
- '@swc/core'
- '@swc/css'
- bufferutil
- csso
- debug
- esbuild
- eslint
- lightningcss
- supports-color
- typescript
- uglify-js
- utf-8-validate
- vue-template-compiler
- webpack-cli
'@docusaurus/plugin-content-blog@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)':
dependencies:
'@docusaurus/core': 3.7.0(@mdx-js/react@3.1.1(@types/react@19.2.14)(react@18.3.1))(debug@4.4.3)(eslint@9.39.4(jiti@2.6.1))(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
@@ -9049,7 +9084,7 @@ snapshots:
'@jest/schemas': 29.6.3
'@types/istanbul-lib-coverage': 2.0.6
'@types/istanbul-reports': 3.0.4
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/yargs': 17.0.35
chalk: 4.1.2
@@ -9489,11 +9524,11 @@ snapshots:
'@types/body-parser@1.19.6':
dependencies:
'@types/connect': 3.4.38
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/bonjour@3.5.13':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/chai@5.2.3':
dependencies:
@@ -9503,11 +9538,11 @@ snapshots:
'@types/connect-history-api-fallback@1.5.4':
dependencies:
'@types/express-serve-static-core': 4.19.8
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/connect@3.4.38':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/d3-array@3.2.2': {}
@@ -9650,7 +9685,7 @@ snapshots:
'@types/express-serve-static-core@4.19.8':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/qs': 6.15.0
'@types/range-parser': 1.2.7
'@types/send': 1.2.1
@@ -9680,7 +9715,7 @@ snapshots:
'@types/http-proxy@1.17.17':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/istanbul-lib-coverage@2.0.6': {}
@@ -9706,7 +9741,7 @@ snapshots:
'@types/node-forge@1.3.14':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/node@17.0.45': {}
@@ -9751,16 +9786,16 @@ snapshots:
'@types/sax@1.2.7':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/send@0.17.6':
dependencies:
'@types/mime': 1.3.5
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/send@1.2.1':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/serve-index@1.9.4':
dependencies:
@@ -9769,7 +9804,7 @@ snapshots:
'@types/serve-static@1.15.10':
dependencies:
'@types/http-errors': 2.0.5
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/send': 0.17.6
'@types/set-cookie-parser@2.4.10':
@@ -9779,7 +9814,7 @@ snapshots:
'@types/sockjs@0.3.36':
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
'@types/statuses@2.0.6':
optional: true
@@ -10058,7 +10093,7 @@ snapshots:
axios@1.16.0:
dependencies:
follow-redirects: 1.16.0
follow-redirects: 1.16.0(debug@4.4.3)
form-data: 4.0.5
proxy-from-env: 2.1.0
transitivePeerDependencies:
@@ -11426,12 +11461,10 @@ snapshots:
flatted@3.4.2:
optional: true
follow-redirects@1.15.11(debug@4.4.3):
follow-redirects@1.16.0(debug@4.4.3):
optionalDependencies:
debug: 4.4.3
follow-redirects@1.16.0: {}
fork-ts-checker-webpack-plugin@6.5.3(eslint@9.39.4(jiti@2.6.1))(typescript@5.6.3)(webpack@5.98.0):
dependencies:
'@babel/code-frame': 7.29.0
@@ -11861,7 +11894,7 @@ snapshots:
http-proxy@1.18.1(debug@4.4.3):
dependencies:
eventemitter3: 4.0.7
follow-redirects: 1.15.11(debug@4.4.3)
follow-redirects: 1.16.0(debug@4.4.3)
requires-port: 1.0.0
transitivePeerDependencies:
- debug
@@ -12028,7 +12061,7 @@ snapshots:
jest-util@29.7.0:
dependencies:
'@jest/types': 29.6.3
'@types/node': 24.12.2
'@types/node': 25.6.0
chalk: 4.1.2
ci-info: 3.9.0
graceful-fs: 4.2.11
@@ -12036,13 +12069,13 @@ snapshots:
jest-worker@27.5.1:
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
merge-stream: 2.0.0
supports-color: 8.1.1
jest-worker@29.7.0:
dependencies:
'@types/node': 24.12.2
'@types/node': 25.6.0
jest-util: 29.7.0
merge-stream: 2.0.0
supports-color: 8.1.1