# gist.pub Publish a markdown file, an HTML file, or a folder of static assets to a secret URL. No account, no API key, no configuration. ## MCP server Agents with an MCP client: read https://gist.pub/docs/mcp for connection setup, authentication, tools, and examples. The hosted Streamable HTTP endpoint is https://app.gist.pub/api/mcp. Connect with OAuth using your gist.pub account; no local server or CLI installation is needed. Send file contents, not local paths. The commands below describe the separate `gpub` CLI. ## Install curl -fsSL https://gist.pub/install | bash `gpub --skill` prints this document with skill frontmatter on the front, for agent runtimes that load skills from a directory: gpub --skill > ~/.claude/skills/gpub/SKILL.md ## Publish gpub publish README.md # markdown, rendered to a styled HTML page gpub publish data.csv # CSV/TSV, rendered to a sortable table gpub publish config.json # JSON, rendered to a browsable tree gpub publish page.html # a single HTML file gpub publish photo.png # an image; the printed URL is the image itself gpub publish ./site/ # a folder of static assets gpub publish build.tar.gz # .tar.gz, .tgz, .tar or .zip of a folder `publish` writes the URL to stdout and nothing else, so it composes directly: URL=$(gpub publish README.md) Everything else — progress, warnings, the unpublish hint — goes to stderr. ## Update an existing gist gpub publish README.md --update https://gist.pub/k3f9x2mqp7ad4nrt Replaces the content at that URL and keeps the URL. Files the new version does not contain are removed. Requires the edit token, which is already on this machine if it published the gist; otherwise pass `--token`. The kind may change — a site can become markdown. To change part of a CSV or JSON gist rather than all of it, see Editing in place below; `--update` is for replacing the whole thing. Without `--update`, every publish creates a NEW url. ## What to know before publishing - The URL contains an unguessable secret and is the ONLY access control. Anyone who has it can read the gist. Never publish credentials or private data on the assumption that the URL stays private. - Hidden files are skipped by default, so a stray `.env` or `.git` is not published by accident. `--all` includes them; check what you are sending. - `.gitignore` is respected when publishing a folder. - Limits: 4 MB per file, 100 MB and 2000 files per gist. - A folder wants an `index.html` at its root. Without one, gist.pub generates a file listing as the landing page. - A published spreadsheet or JSON file stays editable in place — see Editing in place below. The table is sortable and the JSON tree is collapsible. Sheets over 5000 rows and JSON over 5000 nodes render that much and link to the full file. - Invalid JSON is rejected at publish time with the parser's message. - Inside a published site, RELATIVE links work (`./style.css`, `img/logo.png`). Root-absolute links (`/style.css`) do NOT — a gist lives under a path, not at the domain root. - Use `--dry-run` to see exactly what would be uploaded before sending anything. - An updated gist can serve the previous version from cache for up to a minute. ## Get the raw file Add an extension to the address and you get the original, not the rendered page: https://gist.pub/fg65842wfcy4za79.json the JSON itself https://gist.pub/fg65842wfcy4za79.md the markdown source https://gist.pub/fg65842wfcy4za79.csv the spreadsheet as CSV https://gist.pub/fg65842wfcy4za79.tsv the same, tab-separated https://gist.pub/@ada/roster.csv under a name, the same way This is the form to fetch when a program is reading the gist rather than a person. It reflects every edit — it is generated from the current content, not the file that was uploaded — and `.csv` and `.tsv` convert, so either works whatever the sheet was published as. The longer `/source.json` form still works and means the same thing. An extension that does not match the gist's kind is a 404, and a gist may be NAMED with a dot (`@ada/notes.md`), in which case the name wins. ## Manage gpub list # every gist you own gpub remove # unpublish (cached copies clear within a minute) gpub whoami # who this machine publishes as gpub login # sign in; claims what this machine published gpub logout # forget this machine's token Publishing is anonymous and needs no account. The first publish registers an identity and stores one edit token at `~/.config/gpub/identity.json`; that token authorizes every later edit and delete. `gpub token roll` replaces it if it leaks. To act as a different identity, pass `--token `. `gpub login` prints a code and a URL, and signs in once the code is approved in a browser. Everything this machine published anonymously becomes the account's, and afterwards any signed-in machine can edit any of it. ## Editing in place A published CSV or JSON gist is not a snapshot. `set` and `del` change one place in it; the URL never changes and there is nothing to republish. gpub set gpub del The target says what to change, and its shape says which kind of gist is meant: B2 a cell A1 notation; row 1 is the header 2 a row the same row B2 is in — takes one value per column B a column takes the header first, then one value per row + a new row appended to the end .port a JSON path jq-style; the leading dot is required Examples: gpub set B2 42 # one cell gpub set 3 Ada 12 # replace row 3 gpub set C role eng ops # replace column C, header first gpub set + Kate 5 # append a row gpub set .port 8080 # a number gpub set .name staging # a string gpub set .ver 1.20 --string # a string that looks like a number gpub set .servers[0].host b # into a list gpub del .debug # remove a key gpub del 3 # remove a row, closing the gap gpub del B # remove a column gpub del B2 # CLEAR a cell, not remove it `del` changes something INSIDE a gist. To unpublish the whole gist, that is `gpub remove ` — a different word on purpose, because two commands two letters apart with that difference in reach would be a trap. Things worth knowing: - Setting is the same act whether or not the place exists. A cell past the edge of the sheet grows it; a JSON path that is not there is created, building whatever objects and lists the path implies. - A JSON value is parsed as JSON when it can be, so `8080` is a number and `staging` is a string. `--string` forces the literal reading. - `del` on a cell CLEARS it. Removing a single cell would shift its neighbours, which is never what was meant; use `del ` or `del ` for that. - Row 1 is the header and cannot be deleted — set it instead. - Deleting something that is not there reports `nothing at ` and succeeds: the document ends up in the state you asked for either way. - Editing needs the edit token, so only the identity that published the gist — or, once signed in, any machine of that account — can do it. The exception is a JSON gist published with `--editable`, where knowing the URL is enough. The same operations over HTTP, if you are not using the CLI: PUT /api/gists//cells/B2 {"value": "42"} PUT /api/gists//rows/3 {"values": ["Ada", "12"]} POST /api/gists//rows {"values": ["Kate", "5"]} DELETE /api/gists//rows/3 PUT /api/gists//columns/B {"values": ["size", "12", "8"]} DELETE /api/gists//columns/B PUT /api/gists//doc/.port {"value": 8080} DELETE /api/gists//doc/.debug against `https://app.gist.pub`, with `Authorization: Bearer `. ## Editable JSON — a URL anyone can write to gpub publish config.json --editable Publishes the JSON so that ANYONE with the URL can edit it — `gpub set`/`del` and the `/doc/` API above work with no token at all. Useful as a tiny shared data store for scripts and agents. JSON gists only. Only the content is open: replacing, renaming, or removing the gist still requires the owner's token. Republishing with `--update` and without `--editable` closes it again. Treat the URL as the write credential it is. ## Readable addresses gpub name # move it to gist.pub/@you/ gpub name --clear # take the name away again A name requires being signed in, since it lives under your handle. IMPORTANT: the 16-character address is unguessable and a name is not — naming a gist is what makes it findable by anyone who guesses `@you/`. Only name what you would not mind being found. The secret address keeps working either way, and clearing the name puts the gist back behind it alone. ## Exit codes 0 published 1 bad usage, or the service rejected the input 2 network or server error — worth retrying 3 over a size or file-count limit