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
4 changes: 2 additions & 2 deletions apps/headless/docs/P2.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ confirm mutating calls according to their policy. These annotations are hints,
not a substitute for the host's socket, validation, and navigation boundaries.

```sh
ssh hermes-vm headless start
ssh hermes-vm headless-mcp
ssh your-host headless start
ssh your-host headless-mcp
```

The adapter exposes one `headless` tool whose `argv` input is the normal CLI
Expand Down
74 changes: 74 additions & 0 deletions apps/web/app/docs/changelog/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { DocsShell } from "@/components/docs-shell";
import { plainText } from "@/lib/markdown";
import { loadProductDocsContent } from "@/lib/repository-content.mjs";
import { docsMetadata } from "@/lib/site-metadata";

export const metadata = docsMetadata(
"Changelog",
"Current Headless product and protocol versions, with the latest release notes.",
"/docs/changelog",
);

export default function ChangelogPage() {
const { protocolVersion, release, releases } = loadProductDocsContent();
return (
<DocsShell
activePath="/docs/changelog"
kicker={`Released / ${release.date}`}
title={
<>
Headless <em>v{release.version}</em>
</>
}
lede={plainText(release.summary)}
>
<div className="docs-version-strip" aria-label="Current versions">
<div>
<span>Product</span>
<strong>v{release.version}</strong>
</div>
<div>
<span>Protocol</span>
<strong>{protocolVersion}</strong>
</div>
</div>
{release.changes.map((group, index) => (
<section key={group.title}>
<p className="docs-label">
{String(index + 1).padStart(2, "0")} / {group.title}
</p>
<h2>{group.title}</h2>
<ul className="docs-list">
{group.items.map((item) => (
<li key={item}>{plainText(item)}</li>
))}
</ul>
</section>
))}
<section>
<p className="docs-label">Release history</p>
<h2>Earlier versions.</h2>
<div className="docs-release-history">
{releases.slice(1).map((earlier) => (
<article key={earlier.version}>
<header>
<h3>v{earlier.version}</h3>
<time dateTime={earlier.date}>{earlier.date}</time>
</header>
{earlier.changes.map((group) => (
<div key={group.title}>
<h4>{group.title}</h4>
<ul className="docs-list docs-list-compact">
{group.items.map((item) => (
<li key={item}>{plainText(item)}</li>
))}
</ul>
</div>
))}
</article>
))}
</div>
</section>
</DocsShell>
);
}
37 changes: 37 additions & 0 deletions apps/web/app/docs/commands/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { CommandBlock } from "@/components/docs-copy-controls";
import { DocsShell } from "@/components/docs-shell";
import { plainText } from "@/lib/markdown";
import { loadProductDocsContent } from "@/lib/repository-content.mjs";
import { docsMetadata } from "@/lib/site-metadata";

export const metadata = docsMetadata(
"Command reference",
"The complete generated Headless CLI command reference, grouped by lifecycle, interaction, evidence, and diagnostics.",
"/docs/commands",
);

export default function CommandsPage() {
const { commands } = loadProductDocsContent();
return (
<DocsShell
activePath="/docs/commands"
kicker={`${commands.count} command forms`}
title={<>The complete agent surface.</>}
lede="These usage lines come from the generated command reference, which protocol tests keep in sync with the CLI help output. Unknown parameters fail closed."
>
{commands.groups.map((group, index) => (
<section
id={group.title.toLowerCase().replaceAll(" ", "-")}
key={group.title}
>
<p className="docs-label">
{String(index + 1).padStart(2, "0")} / {group.title}
</p>
<h2>{group.title}</h2>
<p>{plainText(group.description)}</p>
<CommandBlock>{group.usage}</CommandBlock>
</section>
))}
</DocsShell>
);
}
41 changes: 41 additions & 0 deletions apps/web/app/docs/install/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { CommandBlock } from "@/components/docs-copy-controls";
import { DocsShell } from "@/components/docs-shell";
import { plainText } from "@/lib/markdown";
import { loadProductDocsContent } from "@/lib/repository-content.mjs";
import { docsMetadata } from "@/lib/site-metadata";

export const metadata = docsMetadata(
"Install",
"Install Headless on macOS, Linux, WSL2, or through the verified npm launcher.",
"/docs/install",
);

export default function InstallPage() {
const { install, version } = loadProductDocsContent();
return (
<DocsShell
activePath="/docs/install"
kicker={`Current release / v${version}`}
title={<>Choose your runtime.</>}
lede="Use a signed native package, the checksum-verified Linux bootstrap, WSL2, or the npm launcher. Every path keeps browser control on a private local socket."
>
{install.map((method, index) => (
<section
id={method.title.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-")}
key={method.title}
>
<p className="docs-label">
{String(index + 1).padStart(2, "0")} / {method.title}
</p>
<h2>{method.title}</h2>
{method.copy.slice(0, 2).map((paragraph) => (
<p key={paragraph}>{plainText(paragraph)}</p>
))}
{method.commands.map((commands) => (
<CommandBlock key={commands}>{commands}</CommandBlock>
))}
</section>
))}
</DocsShell>
);
}
7 changes: 7 additions & 0 deletions apps/web/app/docs/markdown/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { loadDocumentationContent } from "@/lib/repository-content.mjs";
import { docsMetadata } from "@/lib/site-metadata";

export const metadata = docsMetadata(
"Documentation as Markdown",
"Plain-text Headless documentation for agents and copyable workflows.",
"/docs/markdown",
);

export default function DocsMarkdownPage() {
const documentation = loadDocumentationContent();
Expand Down
49 changes: 49 additions & 0 deletions apps/web/app/docs/mcp/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { CommandBlock } from "@/components/docs-copy-controls";
import { DocsShell } from "@/components/docs-shell";
import { plainText } from "@/lib/markdown";
import { loadProductDocsContent } from "@/lib/repository-content.mjs";
import { docsMetadata } from "@/lib/site-metadata";

export const metadata = docsMetadata(
"MCP setup",
"Connect an MCP client to Headless over stdio without exposing a browser-control port.",
"/docs/mcp",
);

export default function McpPage() {
const { mcp } = loadProductDocsContent();
return (
<DocsShell
activePath="/docs/mcp"
kicker="One stdio tool"
title={<>Connect without a control port.</>}
lede={plainText(mcp.copy[0])}
>
<section>
<p className="docs-label">01 / Project configuration</p>
<h2>Use the checked-in launcher.</h2>
<p>
Add this configuration at the project root. The launcher selects the
repository runtime and exposes the normal CLI argument list as one MCP
tool.
</p>
<CommandBlock>{mcp.config}</CommandBlock>
</section>
<section>
<p className="docs-label">02 / Remote agent</p>
<h2>Tunnel stdio, not DevTools.</h2>
<p>{plainText(mcp.copy[1])}</p>
{mcp.commands.map((commands) => (
<CommandBlock key={commands}>{commands}</CommandBlock>
))}
</section>
<section className="docs-note">
<p>
The tool can stop the host and close sessions. MCP annotations mark it
mutating, destructive, non-idempotent, and open-world so clients can
apply their own confirmation policy.
</p>
</section>
</DocsShell>
);
}
Loading