diff --git a/CHANGELOG.md b/CHANGELOG.md index bdf554b..eae6a14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ Each section below is the release page text for one Direct version: a summary, then the changes. The release workflow copies the section whose heading matches the tagged version and adds the install and verification steps itself. +## 0.7.30 + +This release updates Direct's README and Agent Skill install guide. The library's exports and browser tooling are unchanged. + +- The README shows how to open a signed-in state without real credentials: put sign-in behind a port, name signed-in and signed-out scenarios, and keep the real identity provider as a separate `direct` coverage claim. +- "Install the Agent Skill" lists the folders Claude Code, Codex, Cursor, and Devin CLI read and how to invoke the skill in each: `/direct`, `$direct`, or the `/` menu. +- Install examples in the README, guides, and the skill's install reference use v0.7.29. + ## 0.7.29 - 2026-10-04 The semantic browser proxy now chooses outgoing network destinations only from the approved origins configured by its owner. diff --git a/README.md b/README.md index 33e4389..908cde9 100644 --- a/README.md +++ b/README.md @@ -156,16 +156,37 @@ npx skills add hraness/direct#v0.7.29 bunx skills add hraness/direct#v0.7.29 ``` -Invoke the skill as `/direct` in [Claude Code](https://code.claude.com/docs/en/skills) -or `$direct` in Codex. It guides installation, adoption, and -verification, including a check that production builds exclude Direct. Restart -or reload an agent runner that does not discover newly installed skills during -the current session. +To pick the agents in the command, name them with `--agent`. Add `--global` to +install for every project: + +```sh +npx skills add hraness/direct#v0.7.29 --global --agent claude-code codex cursor devin +``` + +With `--global`, the skill goes in each agent's global folder; without it, in +the project folder: + +| Agent | Global folder | Project folder | Invoke it with | +| --- | --- | --- | --- | +| [Claude Code](https://code.claude.com/docs/en/skills) | `~/.claude/skills/direct` | `.claude/skills/direct` | `/direct` | +| [Codex](https://learn.chatgpt.com/docs/build-skills) | `~/.agents/skills/direct` | `.agents/skills/direct` | `$direct`, or pick it from `/skills` | +| [Cursor](https://cursor.com/docs/skills) | `~/.agents/skills/direct` | `.agents/skills/direct` | Type `/` in Agent chat and choose `direct` | +| [Devin CLI](https://docs.devin.ai/cli/extensibility/skills/overview) | `~/.config/devin/skills/direct` | `.devin/skills/direct` | `/direct` | + +Cursor also reads the Claude Code folders, and Devin CLI also reads +`~/.agents/skills`. The skill guides installation, adoption, and verification, +including a check that production builds exclude Direct. Start a new session, +or reload the agent, if it doesn't list the skill right after you install it. + +On October 4, 2026, skills 1.7.0 wrote these folders, with the Claude Code and +Devin CLI folders linked to the `.agents` copy, and Codex 0.160.0 listed the +installed skill from both of its folders. Claude Code, Cursor, and Devin CLI +were not run with the skill. ### Tell your coding agent to install it -Copy this prompt into Codex or another coding agent. In Claude Code, replace -`$direct` with `/direct`: +Copy this prompt into Codex. In Claude Code or Devin CLI, start with `/direct` +instead of `$direct`; in Cursor, choose `direct` from the `/` menu first: ```text Use $direct to install hraness/direct from the immutable v0.7.29 GitHub release @@ -656,6 +677,66 @@ In the Todo example, each step of the check above is something you can inspect: You can read the same results through the TypeScript package, or from the page itself with any browser driver that can run a script there. +### Open a signed-in state without real credentials + +A browser agent that has to sign in before each check needs a real password, a stored session, or a person at the keyboard, and it can stall at the sign-in page. Put sign-in behind a port instead. The production entry asks your identity provider who is signed in; the Direct entry answers from the world, so a check opens a signed-in page by URL. + +**A sign-in port with signed-in and signed-out states** + +```typescript +// src/account-port.ts (both entries) +export interface AccountPort { + readonly currentAccount: () => + Promise<{ readonly name: string } | null>; +} + +// direct/definition.ts (Direct entry only) +export const accountDirectDefinition = defineDirect({ + parseWorld: parseAccountWorld, + defaultScenario: "account.signed-in", + scenarios: [ + { + id: "account.signed-in", + title: "Signed in", + description: "The settings page renders for a fixture account.", + route: "/settings", + world: createAccountWorld({ account: { name: "Sam" } }), + }, + { + id: "account.signed-out", + title: "Signed out", + description: "The settings page shows its sign-in prompt.", + route: "/settings", + world: createAccountWorld({ account: null }), + }, + ], + coverage: [ + { + key: "settings.signed-in", + mode: "fixture", + claim: "The real settings page renders for a signed-in fixture account.", + scenarios: ["account.signed-in"], + }, + { + key: "settings.signed-out", + mode: "fixture", + claim: "The real settings page shows its sign-in prompt without an account.", + scenarios: ["account.signed-out"], + }, + { + key: "sign-in.provider", + mode: "direct", + claim: "Sign-in, cookies, token refresh, and expiry need the real identity provider.", + scenarios: [], + }, + ], +}); +``` + +`AccountPort`, `parseAccountWorld`, and `createAccountWorld` are your app's code, written like the Todo example's port and world. The check opens `/direct/?__direct_scenario=account.signed-in`, confirms from `window.__direct` that the page opened that scenario on `/settings`, waits for a quiet probe, and then checks the page. No password, session cookie, or token is involved, and `account.signed-out` gives the same check the sign-in prompt. If code in the page still calls your identity provider with `fetch`, the default block stops that request, so the gap shows up as a failed request instead of a real sign-in attempt. + +The `fixture` label limits what that run shows: your interface handles a signed-in account. It doesn't test your identity provider, its cookies, token refresh, or session expiry, which is why the definition keeps that claim as `direct`. Keep a live check for the real sign-in flow, such as Playwright's [saved auth state](https://playwright.dev/docs/auth) with a test account. + ### When to use Direct [agent-browser]() gives coding agents a compact command-line interface for opening pages, reading accessibility snapshots, and interacting with elements. Playwright and other browser drivers do the same job with different APIs. Direct doesn't drive the browser; it hands the browser tool a known page state to start from. diff --git a/package.json b/package.json index 1128d31..bbd2cf0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hraness/direct", - "version": "0.7.29", + "version": "0.7.30", "description": "Direct gives browser agents repeatable app states that open by URL, with your real interface running on fixture data.", "license": "MIT", "type": "module", diff --git a/scripts/npm-publish-workflow.test.ts b/scripts/npm-publish-workflow.test.ts index 78e66b7..d096e27 100644 --- a/scripts/npm-publish-workflow.test.ts +++ b/scripts/npm-publish-workflow.test.ts @@ -377,7 +377,7 @@ import { isUtf8ByteLengthAtMost } from "./utf8-byte-boundary.js"; readonly version?: unknown; }; expect(manifest).toEqual(expect.objectContaining({ - version: "0.7.29", + version: "0.7.30", description: "Direct gives browser agents repeatable app states that open by URL, with your real interface running on fixture data.", keywords: [ "frontend-development", diff --git a/skills/direct/references/install.md b/skills/direct/references/install.md index fc45b4f..df531e3 100644 --- a/skills/direct/references/install.md +++ b/skills/direct/references/install.md @@ -18,9 +18,10 @@ global `direct` CLI. ## Add the library -For the new semantic browser factory in `@hraness/direct@0.7.29`, first verify -that version's immutable archive is available. Source alone does not establish -publication; otherwise keep the last verified install below. +This skill ships with `@hraness/direct@0.7.30`. Use that version only after its +immutable archive is published; source alone does not establish publication. +Until then, keep the last verified install below, which already includes +`createVerificationBrowser`. For a new installation, verify that the immutable v0.7.29 GitHub release and its archive are published before using this version. Source candidates do not