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
26 changes: 18 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,24 @@ jobs:
- name: Check out repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup Hugo
uses: peaceiris/actions-hugo@2752ce1d29631191ea3f27c23495fa06139a5b78 # v3.2.1
- name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
hugo-version: "0.152.2"
extended: true
node-version: "22"
cache: npm
cache-dependency-path: website/package-lock.json

- name: Build documentation
run: hugo --minify
- name: Install dependencies
run: npm ci

- name: Check types
run: npm run check

- name: Check formatting
run: npm run format:check

- name: Build documentation and search index
run: npm run build

- name: Build search index
run: npx --yes pagefind@latest --site public
- name: Test website
run: npm test
25 changes: 16 additions & 9 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,29 @@ jobs:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup Hugo
uses: peaceiris/actions-hugo@2752ce1d29631191ea3f27c23495fa06139a5b78 # v3.2.1
- name: Set up Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
hugo-version: "0.152.2"
extended: true
node-version: "22"
cache: npm
cache-dependency-path: website/package-lock.json

- name: Build documentation
run: hugo --minify
- name: Install dependencies
run: npm ci

- name: Build search index
run: npx --yes pagefind@latest --site public
- name: Check types and formatting
run: npm run check && npm run format:check

- name: Build documentation and search index
run: npm run build

- name: Test website
run: npm test

- name: Upload artifact
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: website/public
path: website/dist

deploy:
permissions:
Expand Down
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ wheels/
# Virtual environments
.venv

# Hugo docs site (website/)
# Website build output and dependencies
website/public/
website/resources/
website/.hugo_build.lock
website/node_modules/
website/dist/
website/.astro/

# System files
.DS_Store
Expand Down
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,17 @@ uv run tau
uv run tau -p "explain this repo"
```

Run the Hugo documentation site:
Run the Astro documentation site (Node 22.12+):

```bash
cd website
hugo server -D
npm ci
npm run dev
```

Open <http://localhost:1313/>. Build with `hugo --minify`.
Open <http://localhost:4321/>. Build with `npm run build`, then
`npm run preview` to test Pagefind search. Run `npm run check`,
`npm run format:check`, and `npm test` (after building) for website checks.

## Documentation

Expand Down
50 changes: 50 additions & 0 deletions dev-notes/astro-website.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Moving the website from Hugo to Astro

## What and why

The website is now a static Astro site. This replaces Hugo templates with typed
Astro components without changing Tau's Python packages or its frontend adapter
boundaries. Like Pi's separation of brain, environment, and frontend, the website
remains an independent presentation layer: neither Astro nor Node is a runtime
dependency of the agent.

Markdown stays in `website/content/`. A content collection validates metadata;
the catch-all route maps `_index.md` to its section URL and all other pages to
their existing trailing-slash URLs. Hugo `relref` links became ordinary Markdown
links, and callouts became portable `[!NOTE]`, `[!TIP]`, and `[!CAUTION]`
blockquotes with an optional title. A small remark plugin retains their styling.

Shared layouts retain the CSS, mobile navigation, search modal, clipboard
buttons, metadata, analytics, and MathJax. Home and Why Tau retain the canvas
animations. Roadmap/sidebar YAML, `pyproject.toml`'s version, and Tau's existing
release JSON remain the source of truth; no copied release catalog is maintained.

## Hosting and checks

GitHub Pages and `twotimespi.dev` are unchanged. Astro copies `website/static/`
(including CNAME and the installers) into `dist/`. Pagefind indexes that output.
RSS remains at `/index.xml`; Astro generates a sitemap index referenced by
`robots.txt`. CI builds and tests the site, and the deployment workflow uploads
`dist/` rather than Hugo's `public/`.

Use Node 22.12+ and run from `website/`:

```bash
npm ci
npm run check
npm run format:check
npm run build
npm test
npm run preview
```

The preview server runs at http://localhost:4321/. Check the home animation,
Why Tau equations, roadmap, releases, mobile menu, search (also Ctrl/Cmd+K),
sidebar navigation, code-copy controls, and a nonexistent URL. `npm run dev`
is convenient for editing, but search needs the production build's index.

Built-site tests check every Markdown route, local asset/link targets, canonical
URLs, domain/installer/search artifacts, resolved templates, and key docs features.
Existing clipboard accessibility tests also run. Python CI checks remain unchanged.
Historical build journals referring to Hugo describe the commands used at their
time; the current contributor guide documents the Astro equivalents.
10 changes: 10 additions & 0 deletions website/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules/
dist/
.astro/
public/
resources/
content/
assets/
static/
data/
package-lock.json
4 changes: 4 additions & 0 deletions website/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"plugins": ["prettier-plugin-astro"],
"overrides": [{ "files": "*.astro", "options": { "parser": "astro" } }]
}
2 changes: 1 addition & 1 deletion website/assets/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ section{ padding:88px 0; }
margin:0 0 8px; font-family:var(--grotesk); font-weight:600; font-size:13px;
letter-spacing:.06em; text-transform:uppercase; color:var(--accent);
}
.admonition-body > *:last-child{ margin-bottom:0; }
.admonition > *:last-child{ margin-bottom:0; }
.admonition-tip{ border-left-color:var(--green); background:rgba(31,138,95,.07); }
.admonition-tip .admonition-title{ color:var(--green); }
.admonition-caution{ border-left-color:var(--red); background:rgba(214,67,91,.06); }
Expand Down
2 changes: 1 addition & 1 deletion website/assets/js/nav-toggle.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ document.addEventListener("DOMContentLoaded", function () {
// in local dev. Run `hugo --minify && npx pagefind@latest --site public
// && npx serve public` to test search for real.
searchBox.innerHTML =
'<p class="search-unavailable">Search index not built. Run <code>hugo --minify &amp;&amp; npx pagefind@latest --site public</code>, then serve <code>public/</code>, to test search locally.</p>';
'<p class="search-unavailable">Search index not built. Run <code>npm run build &amp;&amp; npm run preview</code>, serve <code>dist/</code>, to test search locally.</p>';
unavailableNoticeShown = true;
} else if (initialized) {
requestAnimationFrame(focusInput);
Expand Down
15 changes: 15 additions & 0 deletions website/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { defineConfig } from "astro/config";
import sitemap from "@astrojs/sitemap";
import { unified } from "@astrojs/markdown-remark";
import { admonitions } from "./src/admonitions.mjs";

export default defineConfig({
site: "https://twotimespi.dev",
trailingSlash: "always",
publicDir: "./static",
integrations: [sitemap()],
markdown: {
shikiConfig: { theme: "monokai" },
processor: unified({ remarkPlugins: [admonitions] }),
},
});
18 changes: 9 additions & 9 deletions website/content/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,63 +13,63 @@ When you send a prompt, Tau runs an **agent loop**: it asks the model to respond
streams that response, and when the model asks to use a **tool**, Tau runs the
tool, feeds the result back, and asks the model to continue — repeating until the
model has nothing left to do. That loop is the heart of every coding agent.
→ [How Tau works: the agent loop]({{< relref "./internals/agent-loop.md" >}})
→ [How Tau works: the agent loop](/internals/agent-loop/)

## Providers and models

A **provider** is the service that hosts AI models (OpenAI, Anthropic, OpenAI
Codex, OpenRouter, Hugging Face, or any OpenAI-compatible endpoint). A **model**
is the specific brain you're talking to (e.g. `gpt-5.5`, `claude-sonnet-4-6`).
You pick a provider + model; you can switch either mid-session.
→ [Providers & models]({{< relref "./guides/providers-and-models.md" >}})
→ [Providers & models](/guides/providers-and-models/)

## Tools

**Tools** are the actions the agent can take in your project. Tau ships four:
`read`, `write`, `edit`, and `bash`. The model decides when to call them; Tau
executes them in your working directory and streams the results.
→ [Tools reference]({{< relref "./reference/tools.md" >}})
→ [Tools reference](/reference/tools/)

## Sessions

A **session** is one ongoing conversation plus everything the agent did in it.
Sessions are saved to disk as append-only files, so you can **resume** them
later. Because the history is a tree, you can also **branch** from any earlier
point to try a different direction, and **export** a session to HTML or JSONL.
→ [Sessions]({{< relref "./guides/sessions.md" >}})
→ [Sessions](/guides/sessions/)

## Project instructions (`AGENTS.md`)

An **`AGENTS.md`** file gives the agent standing instructions about *your*
project — conventions, gotchas, how to run tests. Tau discovers these files
automatically and folds them into the system prompt.
→ [Project instructions]({{< relref "./guides/project-instructions.md" >}})
→ [Project instructions](/guides/project-instructions/)

## Skills and prompt templates

**Skills** are Markdown files describing how to do a specific task; you invoke
one with `/skill:<name>`. **Prompt templates** are reusable prompts you trigger
by name (with optional variables) instead of retyping. Both can live at the user
level (all projects) or per-project.
→ [Skills & prompt templates]({{< relref "./guides/skills-and-prompts.md" >}})
→ [Skills & prompt templates](/guides/skills-and-prompts/)

## Context and compaction

The model can only "see" a limited amount of text at once — its **context
window**. Long sessions fill it up. Tau estimates usage and **compacts**
automatically: it summarizes older messages so the conversation can keep going.
You can also compact on demand with `/compact`.
→ [Managing context]({{< relref "./guides/context.md" >}})
→ [Managing context](/guides/context/)

## Thinking modes

Some models can spend extra effort "thinking" before they answer. Tau exposes a
**thinking mode** (off → minimal → low → medium → high → xhigh → max) you can cycle
when the active model supports it, and optionally show the streamed reasoning.
→ [Managing context]({{< relref "./guides/context.md#thinking-modes" >}})
→ [Managing context](/guides/context/#thinking-modes)

## Two interfaces

Tau runs as an **interactive TUI** (the default) or in **print mode** (`-p`) for
a single non-interactive prompt. Both share the same session environment.
→ [The interactive session]({{< relref "./guides/tui.md" >}}) · [Print mode]({{< relref "./guides/print-mode.md" >}})
→ [The interactive session](/guides/tui/) · [Print mode](/guides/print-mode/)
25 changes: 19 additions & 6 deletions website/content/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ decision records live **in the repository**, under `dev-notes/`:

These are intentionally **not** published on this site — they're contributor
material. The published docs distill the result; see
[How Tau works]({{< relref "./internals/architecture.md" >}}).
[How Tau works](/internals/architecture/).

## Roadmap

The published, phase-by-phase roadmap and status lives on the
[roadmap page]({{< relref "./roadmap.md" >}}). The underlying checklist is
[roadmap page](/roadmap/). The underlying checklist is
tracked in [GitHub issue #1](https://github.com/huggingface/tau/issues/1).

## Running the project locally
Expand All @@ -47,17 +47,30 @@ uv run mypy

## The docs site

The site (this site) is a [Hugo](https://gohugo.io/) project under `website/`:
The site (this site) is an [Astro](https://astro.build/) project under `website/`.
Use Node 22.12 or newer:

```bash
cd website
hugo server -D # http://localhost:1313/
hugo --minify # static output in website/public/
npm ci
npm run dev # http://localhost:4321/
npm run check # Astro and TypeScript diagnostics
npm run format:check
npm run build # static output and Pagefind index in website/dist/
npm test # built-site and clipboard regression tests
npm run preview # preview the built site, including search
```

Search requires the built Pagefind index: use `build` followed by `preview`,
not the development server, to validate search.

User-facing docs live in `website/content/`; the landing and "Why Tau?" pages
are `website/content/_index.md` and `website/content/why-tau.md`, rendered by
templates in `website/layouts/`. Code blocks on documentation pages include a
Astro components in `website/src/components/`. Content collections validate page
metadata and preserve the existing trailing-slash URLs. Internal links use normal
Markdown paths; callouts use blockquotes beginning with `[!NOTE]`, `[!TIP]`, or
`[!CAUTION]`, optionally followed by a title. GitHub Pages still hosts the site
at the same custom domain. Code blocks on documentation pages include a
keyboard-focusable **Copy** button. Copy success or clipboard failures are also
announced to assistive technology.

Expand Down
2 changes: 1 addition & 1 deletion website/content/guides/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Thinking is model-aware: Tau enables it only when the active provider declares
supported levels for the active model. When it's unavailable, `/session` shows
the reason (e.g. the provider doesn't declare `thinking_levels`, or the model
isn't listed). Custom providers can opt in via `thinking_levels` in their config
— see [Configuration]({{< relref "../reference/configuration.md#providers" >}}).
— see [Configuration](/reference/configuration/#providers).

At startup Tau picks a valid level for the selected model automatically: a
remembered per-model choice wins, then `medium`, then the provider's own
Expand Down
4 changes: 2 additions & 2 deletions website/content/guides/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ The backend and provider must be registered by the same source and generation.
If another source shadows the provider, the backend can remain inspectable but
cannot use, reset, or manage models through the shadowed layer. Retired or
reloaded generations cancel their backend work and ignore late results. See the
[local backends guide]({{< relref "./local-inference.md" >}}).
[local backends guide](/guides/local-inference/).

### Dynamic providers

Expand Down Expand Up @@ -362,7 +362,7 @@ small test-only Ollama adapter. The trusted built-in `llama.cpp` provider uses
the same seams; no production Ollama backend is shipped. Provider discovery and
backend status may use different protocol endpoints, and `NoAuth` is a first-
class option. Its connection, cache, and troubleshooting behavior are covered
in the [local inference guide]({{< relref "./local-inference.md" >}}). Router
in the [local inference guide](/guides/local-inference/). Router
management and Hugging Face model mutations remain outside this phase.

### Tools
Expand Down
6 changes: 2 additions & 4 deletions website/content/guides/local-inference.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ Use the optional key in one of these ways:

A stored key wins over `LLAMA_API_KEY`. Without a key Tau sends no
`Authorization` header. Keys never enter the llama.cpp state file, sessions,
exports, or diagnostics. See [Project trust and security]({{< relref
"./project-trust.md#security-boundary" >}}).
exports, or diagnostics. See [Project trust and security](/guides/project-trust/#security-boundary).

## Choose a model

Expand Down Expand Up @@ -262,8 +261,7 @@ are not shipped Tau backends.
Tau never copies old fake keys, fake model IDs, catalog definitions, project
settings, or environment endpoints into built-in state. Reset removes only
built-in settings and safe snapshots; it never stops a server or deletes model
files. For other OpenAI-compatible endpoints, keep using [`/login custom`]({{<
relref "../guides/providers-and-models.md#adding-a-custom--local-provider" >}})
files. For other OpenAI-compatible endpoints, keep using [`/login custom`](/guides/providers-and-models/#adding-a-custom--local-provider)
or `tau setup`.

Router management never changes the safety boundary: all mutations are explicit,
Expand Down
7 changes: 3 additions & 4 deletions website/content/guides/print-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ if tau --mode text -p "do the tests pass? answer yes or no" | grep -qi yes; then
fi
```

{{% tip %}}
For interactive work, start the [TUI]({{< relref "./tui.md" >}}) instead — you get streaming,
steering, pickers, and session branching.
{{% /tip %}}
> [!TIP]
> For interactive work, start the [TUI](/guides/tui/) instead — you get streaming,
> steering, pickers, and session branching.
Loading
Loading