- provider: one late compaction
- gobstopper: every crossing, early
-
-
- );
-}
diff --git a/site/app/layout.tsx b/site/app/layout.tsx
index c0fc1de2..db55c018 100644
--- a/site/app/layout.tsx
+++ b/site/app/layout.tsx
@@ -143,7 +143,7 @@ export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
-
+
{/* eslint-disable-next-line @next/next/no-sync-scripts */}
diff --git a/site/app/page.tsx b/site/app/page.tsx
index 45c8fbeb..f5e3ac88 100644
--- a/site/app/page.tsx
+++ b/site/app/page.tsx
@@ -1,36 +1,20 @@
import {
- MarketingCallToAction,
- MarketingInstallPanel,
- MarketingInterfaceGrid,
- MarketingMaker,
+ MarketingFlow,
MarketingPage,
- MarketingPrimitives,
- MarketingProofFrame,
MarketingQuestionList,
- MarketingRelated,
MarketingSection,
- MarketingTrustBoundary,
ProductHero,
ProviderMarkChip,
} from "@hraness/design-kit/react/server";
import { product, type PortfolioProductId } from "@hraness/design-kit/portfolio";
import { SiteHeader, SiteFooter } from "./_components/site-chrome";
-import { HeroField } from "./hero-field";
-import { HeroGraphic } from "./hero-graphic";
import { publishedRelease } from "./publication";
-
-function TopicIcon({ slug }: Readonly<{ slug: string }>) {
- return (
-
- );
-}
-
-/** A related-product card from the portfolio snapshot: mark, name, and one-line role. */
+/** A related product from the portfolio snapshot: name, address, and one-line role. */
function related(id: PortfolioProductId, name: string) {
- const { canonicalUrl, mark, oneLiner } = product(id);
- return { href: canonicalUrl, mark, name, role: oneLiner };
+ const { canonicalUrl, oneLiner } = product(id);
+ return { href: canonicalUrl, name, role: oneLiner };
}
const releaseVersion = publishedRelease?.version;
@@ -38,44 +22,85 @@ const repository = "https://github.com/hraness/gobstopper";
const heading = "Context compaction you can undo.";
const summary =
- "A local proxy that keeps long sessions in Claude Code, Codex, opencode, Crush, Aider, Goose, and other agents under a context threshold. Past it, each request keeps the task and the newest turns word for word and drops old tool output the agent can read again, following CliffCompaction's rule. File commands preview the same kind of cut on saved sessions and write a smaller copy. Every original byte stays in a local vault you can search and restore from.";
-const footnote =
- "Free and open source (MIT or Apache-2.0). Installs with Cargo and needs Rust 1.85 or newer; the proxy also needs curl 8.3 or newer. Runs on your machine with no account.";
+ "Gobstopper is a free, open-source command-line tool that makes long coding sessions smaller. Its local proxy keeps each request from Claude Code, Codex, and other agents under a token threshold by summarizing older turns and sending the newest ones word for word. On saved sessions it writes a smaller copy, and every original byte stays in a local vault you can search and restore from.";
+const facts =
+ "MIT or Apache-2.0 · Installs with Cargo (Rust 1.85 or newer) · The proxy needs curl 8.3 or newer · Runs on your machine, no account";
+
+const agents = ["claudecode", "codex", "opencode", "crush", "aider", "goose"] as const;
-const primitives = [
+const steps = [
{
- icon: "session-detection",
- label: "Session detection",
- summary: "Finds sessions in the Codex and Claude Code stores. Reports measured context separately from estimates and missing usage. Recent file activity cannot tell you whether another process is using a session.",
+ label: "Start the proxy with your agent",
+ code: "gobstopper proxy run -- claude",
+ detail: "It starts on a free local port, points the agent's ANTHROPIC_BASE_URL and OPENAI_BASE_URL at itself, and stops when the agent exits. Use `gobstopper proxy serve` for a background proxy on 127.0.0.1:8260.",
},
{
- icon: "edit-ir",
- label: "A few kinds of edit",
- summary: "Strategies propose replacing stale tool output, inserting a digest, or having the provider compact. Gobstopper checks supported record links, order, and tool-call pairs before writing a copy. Those checks do not establish that a provider can resume it.",
+ label: "Small requests pass through",
+ detail: "Requests under the threshold, 128,000 estimated tokens by default, go to the provider unchanged.",
},
{
- icon: "strategies",
- label: "Strategies",
- summary: "The default, auto, picks a strategy from the transcript. Sawtooth recommends provider compaction, elide replaces eligible stale tool output, cliff keeps the newest assistant steps and drops older tool results over 500 bytes, and structured writes a state card from metadata. For running sessions in Claude Code, Codex, and OpenAI-compatible agents, gobstopper proxy applies CliffCompaction's rule to each outgoing request. Scored ranks candidates; optional on-device models can score or draft cards. Agentic accepts edits proposed by a program you trust.",
+ label: "Large requests keep the recent work",
+ detail: "Past the threshold, the system prompt, the first task, and at least the last three turns go out word for word. Older turns become one summary that keeps human and assistant text and tool results up to 500 characters. Longer tool results are dropped, because the agent can read the file or rerun the command.",
},
{
- icon: "presets-config",
- label: "Presets, plugins and config",
- summary: "Set defaults once, override them per provider or per session, and save named presets. Plugins are versioned bundles pinned to an exact executable, and Gobstopper checks every edit they return. The older command hook still works once you trust it explicitly.",
+ label: "Check what it did",
+ code: "gobstopper proxy status",
+ detail: "Shows the running proxy's settings, how many requests it compacted, and the estimated tokens saved. Session files stay unchanged.",
},
+] as const;
+
+const ways = [
{
- icon: "undo-vault",
- label: "Undo vault",
- summary: "Before writing a separate Claude Code or Codex copy, Gobstopper archives the original and prepared bytes. Search the snapshot for a missing record, read its saved text, or use undo to prepare a restored copy with a new session identity.",
+ label: "Proxy",
+ summary: "Point an agent's provider address at the proxy, or let `proxy run` start one for a single session. Replay a recorded session to see what the proxy would have sent, without calling a provider.",
+ code: `gobstopper proxy run -- claude
+ANTHROPIC_BASE_URL=http://127.0.0.1:8260 claude
+gobstopper proxy replay `,
},
{
- icon: "telemetry-eval",
- label: "Telemetry and eval",
- summary: "Events link snapshots with observed usage. Eval compares strategies on frozen input, checks supported structures, and counts which sampled details remain. It reports missing measurements and coverage; model judgments, billing, and successful task continuation need separate evidence.",
+ label: "Saved sessions",
+ summary: "Find Claude Code and Codex sessions, preview a plan, and prepare a separate smaller copy. Check it for problems that would break resume, and keep the original for recovery.",
+ code: `gobstopper plan --trigger 250000
+gobstopper apply --strategy elide
+gobstopper verify && gobstopper undo `,
+ },
+ {
+ label: "Watcher and hooks",
+ summary: "The watcher checks sessions every 30 seconds by default and can prepare separate copies. Dry-run mode previews its decisions. Hook setup writes a settings file for you to review and does not change provider settings.",
+ code: `gobstopper watch --dry-run --once
+gobstopper install-hooks --output ./hook-candidates.json`,
+ },
+ {
+ label: "Your program",
+ summary: "A preset command receives the transcript as normalized JSON and returns edits. It runs only after you mark it trusted. Package it as a versioned plugin bundle to pin the exact executable.",
+ code: `[presets.my-policy]
+strategy = "elide"
+keep_recent_tool_outputs = 4
+
+[presets.custom]
+command = "node my-editor.js"
+trusted_legacy_command = true`,
},
] as const;
-const agents = ["claudecode", "codex", "opencode", "crush", "aider", "goose"] as const;
+const inside = [
+ {
+ label: "Strategies",
+ detail: "The default, auto, picks a strategy from the transcript. Elide replaces eligible stale tool output, cliff keeps the newest assistant steps and drops older tool results over 500 bytes, structured writes a state card from metadata, and sawtooth recommends provider compaction. Scored ranks candidates; optional on-device models can score them or draft cards.",
+ },
+ {
+ label: "Undo vault",
+ detail: "Before writing a separate Claude Code or Codex copy, Gobstopper archives the original and prepared bytes. Search a snapshot for a missing record, read its saved text, or run `undo` to prepare a restored copy with a new session identity.",
+ },
+ {
+ label: "Presets and plugins",
+ detail: "Set defaults once, override them per provider or per session, and save named presets. Plugins are versioned bundles pinned to an exact executable, and Gobstopper checks every edit they return.",
+ },
+ {
+ label: "Eval and telemetry",
+ detail: "Eval compares strategies on frozen input, checks supported structures, and counts which sampled details remain. Events link snapshots with observed usage and report missing measurements as missing.",
+ },
+] as const;
const trust = [
{
@@ -84,7 +109,7 @@ const trust = [
},
{
label: "Source files stay unchanged",
- detail: "Claude Code and Codex compaction writes a separate copy and archives the original and prepared bytes. Snapshot readers coordinate with cleanup, and damaged recovery data stops cleanup. Keep backups of the vault: local snapshots depend on your storage.",
+ detail: "Claude Code and Codex compaction writes a separate copy and archives the original and prepared bytes. Damaged recovery data stops cleanup. Keep backups of the vault: local snapshots depend on your storage.",
},
{
label: "Automatic provider compaction is disabled",
@@ -94,6 +119,10 @@ const trust = [
label: "Unknown outcomes stay unknown",
detail: "If a provider operation has an uncertain result, Gobstopper does not retry it automatically after a restart or cooldown. Missing usage stays unmeasured. Hook observations do not establish that Gobstopper caused a compaction.",
},
+ {
+ label: "Smaller is not the same as better",
+ detail: "Copy checks cover record links, order, and tool-call pairs. They do not establish that a provider can resume the copy, that every task fact survives, or what you will be billed.",
+ },
] as const;
const questions = [
@@ -123,6 +152,14 @@ const questions = [
},
] as const;
+const relatedProducts = [
+ related("xcb", "xcb"),
+ related("wrench", "Ghostget"),
+ related("aicharts", "AI Charts"),
+ related("peopleblade", "PeopleBlade"),
+ related("kb", "Wordcell"),
+] as const;
+
function withCode(text: string) {
return text.split("`").map((part, index) => (index % 2 === 1 ? {part} : part));
}
@@ -139,7 +176,7 @@ const structuredData = {
export default function Home() {
return (
-