Skip to content
titah

Capabilities

Artifacts

Publishing a page to your dashboard from the terminal, what a published page can and cannot do, and why it is served from somewhere else entirely.

The terminal is good at text and bad at nearly everything else. A table with twelve columns, a chart, a side-by-side comparison, something you want to click — all of them get worse when flattened into ASCII rows.

The artifact tool gives the model somewhere else to put an answer. It publishes one self-contained HTML document to your account and hands back a URL you can open in a browser.

› Show me where the build time went this month, as a page I can send to Ana.

  artifact: publish "Weekly build times"
  Publish 34 KiB of HTML to https://titah.dev as "Weekly build times".

  This sends a document off your machine. It stays private to your account —
  nobody else can open it until you turn on a share link in the dashboard.

  [a]llow once  [A]lways  [d]eny

Approve it and the answer ends with a link. The page lives at /dashboard/artifacts/ alongside everything else you have published.

It needs an account, and it asks every time

Nothing is published when you are not signed in — run titah login first — and every publish goes through the network permission dialog naming the host, the title and the byte count.

That is why artifacts.enabled defaults to true, unlike tracking.sync. Sync uploads automatically, with nobody in the loop, so it has to be switched on deliberately. Publishing only ever happens because the model asked and you said yes.

{ "artifacts": { "enabled": false } }

titah doctor says which of the two switches is off, rather than just “off”:

Account
  signed in as [email protected]
  server: https://titah.dev
  artifacts: on — published pages go to https://titah.dev

One page, many versions

An agent iterating on a page calls the tool ten or thirty times in a session. Each call after the first passes back the slug from the previous one, so all of them land on the same page at the same URL:

Slug: kQ2v9x1aB7CdEfGhIjKlMn — pass slug="kQ2v9x1aB7CdEfGhIjKlMn" to this tool
to revise this page instead of publishing a second one.

That matters because the link is the point. A link you sent someone after the third iteration would otherwise show a half-finished page for ever.

Republishing identical bytes writes nothing and says so. This is what makes a retry after a timeout safe: if the tool never saw the response, sending the same document again cannot produce a duplicate.

The twenty most recent versions are kept; older ones are pruned. Version numbers keep climbing, so “version 24” still means something after 1 to 4 have gone.

Limits

One document512 KiB — the same cap the CLI puts on a transcript
Versions kept20 per artifact
Artifacts200 per account
Total32 MiB per account

An oversized document is refused before it leaves your machine, and the refusal names both numbers so the model can make the page smaller rather than send the same one again.

The CLI also keeps its own copy of everything it publishes, in ~/.local/share/titah/artifacts/<slug>.html. The server is never the only place your page exists.

Private by default, and the CLI cannot change that

A published page is visible to you and nobody else. Turning on a public link is done from the dashboard, by a person, in a browser — the API refuses to do it for a CLI token at all:

403  Publishing a share link has to be done from the dashboard.

This is deliberate and it is the single most important rule here. An agent can be steered by anything it reads — a web page, an issue comment, a dependency’s README. One that has been steered can publish a page, which is the feature working as intended. It cannot put that page in front of anyone else.

When you do turn a link on, it looks like https://titah.dev/s/<token>. Turning it off revokes it immediately, and turning sharing back on afterwards issues a different link — the old one never works again. “Issue a new link” does the same thing without going private in between.

What a published page can do

Everything a web page can do, which is the point: React, Tailwind, Chart.js and d3 all load from cdn.jsdelivr.net, unpkg.com and cdnjs.cloudflare.com, fonts load from Google Fonts, and the page’s own scripts run normally.

What it cannot do

Your page is served from a different origin — artifacts.titah.dev, not titah.dev — and embedded in an iframe sandboxed without allow-same-origin. That combination gives the document an opaque origin, and the consequences are worth reading rather than skimming:

  • it cannot read or write any cookie, so it can never see your session
  • localStorage, sessionStorage and IndexedDB all throw
  • the surrounding page is cross-origin to it; it cannot reach the dashboard, read your email address, or call the API as you
  • it cannot make a network request at all — fetch, XMLHttpRequest, WebSocket, EventSource and sendBeacon are refused, form submissions go nowhere, and images load only from a short allowlist of named hosts

That last one deserves its own sentence. A hostile page can render a convincing “paste your API key here” box. It cannot transmit what you type into it, anywhere, to anyone.

None of this is achieved by inspecting the HTML. Your document is stored and served byte for byte as it was written, never rewritten or filtered — filtering would break the feature while buying confidence it cannot deliver. The containment is the origin, the sandbox and the policy.

Still, treat a shared page as a stranger’s

The protections above stop a page reaching your account. They do not stop it saying things. A page can tell a reader to run a command, or ask for a password, and no security header can prevent that.

So a shared page is always framed with a badge saying who it came from, and a footer saying what it is. If you are the one opening somebody’s link: never type a password or an API key into it, and be as sceptical of what it tells you to do as you would be of anything else a stranger sent you.

Keep your own copy

A published page is the first thing Titah puts on a server that may exist nowhere else. A synced transcript is a copy of a session still sitting on your machine; a page the model wrote for you is not a copy of anything.

That is why the CLI writes every document it publishes to ~/.local/share/titah/artifacts/<slug>.html as well. It is the copy you control, it needs no account to read, and it is plain HTML — open it in a browser and it works.

Deleting an artifact removes every version of it and takes any shared link with it, immediately. There is no undo, which is why the dashboard asks twice. The local copy is untouched.