Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
95 changes: 88 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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](<https://agent-browser.dev/>) 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.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
2 changes: 1 addition & 1 deletion scripts/npm-publish-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
7 changes: 4 additions & 3 deletions skills/direct/references/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading