artifact-hub

Publish a file. Get a link that opens.

One command. artifact-hub keeps the bytes and serves them back inline, so the link you hand to someone renders in their browser instead of landing in their downloads folder.

Publish report.html
ah upload report.html
It prints one line — the URL, and nothing else
https://breezy-anchor-766lz23ojurv6gxdl6g7zns4vu.artifacthub.link/

That is not an illustration. It is a live artifact, and it is the page in the frame below.

Nothing was deployed to put this online.

https://breezy-anchor-766lz23ojurv6gxdl6g7zns4vu.artifacthub.link/
A rendered report page with its own typography, a data table and hairline rules, served at its own hostname.
One HTML file, pushed with the command above. It answers on a hostname of its own — a browser origin apart from every other artifact and from the dashboard — which is why it can carry its own styling without being able to reach anything else.

Two lines to install, one to sign in.

ah is a single file of plain JavaScript with no dependencies at all. You can read the whole thing before you run it, which is the only honest argument for downloading a program from a website.

Install
mkdir -p ~/.local/bin
curl -fsSL https://artifacthub.link/ah.mjs -o ~/.local/bin/ah
chmod +x ~/.local/bin/ah
Sign in
ah login

ah login opens a consent screen, mints a key and writes it to a 0600 file. The key is never printed, never passed as a flag, and never reaches your shell history. On a machine with no browser — a VPS, a container, an SSH session — ah login --device prints a URL and an eight-letter code you open on anything, a phone included. Nothing is ever pasted back into the terminal, which is the point: a credential typed into a session is a credential in that session's log. Needs Node 18 or newer, and nothing else.

It is one HTTP request underneath.

The same publish, without ah
curl -sS --fail-with-body -T report.html \
  -H "Authorization: Bearer $ARTIFACT_HUB_TOKEN" \
  https://api.artifacthub.link/v1/report.html

This needs a key in ARTIFACT_HUB_TOKEN that you issue from your keys page and then keep somewhere yourself — which is the step ah exists to delete. Everything below is reachable this way too, as query parameters; the machine-readable spec is the reference.

Three things a file host usually gets wrong.

It keeps the ones you already published.

Publishing is one command out of eight. ah also files, finds, moves and retires what is already there, and every command takes --json when something else is reading.

A working session
ah upload chart.png --path reports/2026 --expires 7d
ah ls reports/2026
ah list --q invoice --sort updated --starred
ah move 3k9m2xq7wp4v archive/2025
ah delete 3k9m2xq7wp4v

However you happen to be working.

A terminal

ah, above. One file, no dependencies, credentials it manages for you, and an exit code per failure so a script can tell a missing key from a refused one.

An agent

For Claude Code there is a skill: with it installed, “publish this and give me the link” is the whole instruction. It resolves the credential itself, runs ah login when there is none, and refuses to put a token anywhere a transcript can reach.

Anything else speaks plain HTTP on https://api.artifacthub.link. The behaviour summary and the spec are the documentation — there is no third thing to read.

A browser

Sign in to browse what you have published, drag things into folders, issue and revoke API keys, and delete an artifact when you are done with it.