Upload, update, or delete an HTML or Markdown document on outpost.offsprint.xyz via the `outpost` CLI and return a shareable URL. Use when the user asks to "share", "publish", "upload", "post", "update", "replace", "edit", "delete", "remove", or "unshare" a local .html / .md file, or when they ask for a link to a document they already have. Do NOT generate new documents to upload — only share what the user already has on disk or in the conversation.
Scanned 5/27/2026
Install via CLI
openskills install sah1l/outpost---
name: outpost
description: Upload, update, or delete an HTML or Markdown document on outpost.offsprint.xyz via the `outpost` CLI and return a shareable URL. Use when the user asks to "share", "publish", "upload", "post", "update", "replace", "edit", "delete", "remove", or "unshare" a local .html / .md file, or when they ask for a link to a document they already have. Do NOT generate new documents to upload — only share what the user already has on disk or in the conversation.
license: MIT
compatibility: Requires Node.js 18+ and network access. The `outpost` CLI is published on npm as `@offsprint/outpost`; if not installed globally, invoke via `npx @offsprint/outpost`.
metadata:
homepage: https://outpost.offsprint.xyz
repository: https://github.com/sah1l/outpost
package: "@offsprint/outpost"
allowed-tools: Bash
---
# outpost
Upload an existing HTML or Markdown document to outpost.offsprint.xyz via the
`outpost` CLI. The CLI handles auth and file transfer; your job is to pick the
right invocation and surface the resulting URL.
## When to use this skill
Use it when the user says things like:
- "share this file"
- "give me a public link to this report"
- "upload my notes"
- "publish this HTML"
- "update the doc I just shared"
- "replace the contents of <outpost URL>"
- "edit my published notes"
- "delete that share" / "unshare this" / "remove my notes from outpost"
**Do not** invoke this skill to publish content you generated in the
conversation. If the user asks you to first write a document and then share it,
save the document locally with their confirmation first, then use this skill.
For **updates**, you may use a slug from one of three sources:
1. The user supplied it on this turn (a slug or share URL).
2. You read it from a `<!-- outpost-slug: ... -->` marker in the file (see
[Tracking the slug for later updates](#tracking-the-slug-for-later-updates)).
3. You produced it yourself earlier in this session via `outpost upload` or
`outpost update --json` and the user is plainly referring to that doc
(e.g. "update what we just shared", "fix the typo in the upload").
Never invent a slug from passing mentions in chat or from documents the user
hasn't committed to — only the three sources above are authoritative.
## Prerequisites
The `outpost` CLI must be available. Two ways to invoke it:
- Globally installed: `outpost ...`
- One-off via npx: `npx @offsprint/outpost ...`
Prefer the global form if it's on PATH. If `outpost` is missing, fall back to
`npx @offsprint/outpost` — it pulls into the npm cache on first use, so later
invocations are fast.
If a command fails with "Not authenticated", tell the user to run:
```
outpost login
```
Do not attempt to authenticate on the user's behalf — `login` opens a browser
for device-code approval and requires the user.
## Invocation patterns
### Uploading an existing file
```bash
outpost upload <path> [--title "..."] [--public]
```
Format (`html` / `md`) is inferred from the extension. Use `--public` only when
the user explicitly asks for a public link.
### Uploading inline text
`--format` must come **before** `--text` because of how the CLI's arg parser
consumes the next token after `--text`:
```bash
outpost upload --format md --text "# Notes" --title "Notes"
outpost upload --format html --text "<h1>Hello</h1>" --title "Greeting"
```
### Uploading from a multi-line block
For anything longer than a one-liner, write the content to a tempfile and
upload that file — shell quoting becomes unreliable for long inputs.
### Stdin
```bash
cat note.md | outpost upload - --format md
```
`--format` is required because there's no filename to infer from.
### Updating an existing document
Use `update` when the user wants to replace the contents of a doc they already
shared. The slug stays the same — the URL doesn't change, so don't re-publish
it as if it's new.
```bash
# From a file
outpost update <slug-or-url> <path>
# Inline text — --format must come before --text
outpost update <slug-or-url> --format md --text "# Updated"
# Stdin
cat note.md | outpost update <slug-or-url> - --format md
# Metadata only — no body change
outpost update <slug-or-url> --title "New title"
outpost update <slug-or-url> --public # make public
outpost update <slug-or-url> --no-public # make private
```
The user may pass either a bare slug (`sprint-notes`) or the full share URL
(`https://outpost.offsprint.xyz/s/sprint-notes`); both work.
The doc's type is fixed: an `md` doc must be updated with `md` content, and
`html` with `html`. To change formats, ask the user to delete and re-upload.
Visibility is **tri-state**: omit both flags to leave it as-is. Only pass
`--public` or `--no-public` if the user explicitly asks to change it.
Common update failures: `403` (the user doesn't own that doc), `404` (slug
doesn't exist — suggest `outpost upload` to create a new one), `400 format
mismatch` (file extension doesn't match the existing doc's type).
### Deleting a document
Use `delete` only when the user explicitly asks to delete, remove, or
unshare a document. Do **not** infer delete from edit-shaped requests like
"remove this paragraph" — that's an `update`.
```bash
outpost delete <slug-or-url> --yes # skip the y/N confirmation
outpost delete <slug-or-url> -y --json # short flag + machine output
```
Always pass `--yes` (or `-y`) when invoking from a skill — agents have no
TTY, and the CLI refuses non-interactive deletes without explicit
confirmation. Without the flag and without a TTY the command exits 2 with a
hint.
Delete is permanent and the slug becomes available for reuse. Once you've
run a successful `outpost delete` for a slug, drop that slug from your
in-session memory — a follow-up `update` against it will 404, and a future
`upload` from another user could land on the same slug with different
content.
If the file had an `<!-- outpost-slug: ... -->` marker, offer to remove it
after a successful delete so a stale marker doesn't mislead a future
update.
Common delete failures: `403` (the user doesn't own that doc) — surface
the error verbatim. A missing slug returns success (the operation is
idempotent), so don't treat that as an error.
### Machine-readable output
Append `--json` to get `{slug, url, title, type}` (upload/update) or
`{slug, ok}` (delete) so results can be parsed out of stdout reliably.
## Tracking the slug for later updates
You have two ways to remember a slug across turns: an **on-disk marker** for
files (durable across sessions) and **in-session memory** for inline uploads
or until you write the marker.
### In-session memory of slugs you produced
Any slug returned by your own `outpost upload` or `outpost update --json`
call in this conversation is authoritative — reuse it for later turns in
the same session without re-asking the user. This is not "guessing from
conversational context"; it's a result you just received from the CLI.
This is especially important for **inline-text uploads** (`--text` /
stdin), where there is no local file to attach a marker to. If the user
says "tweak that and re-share it" after an inline upload, run
`outpost update <slug-you-just-got> ...` directly.
When you do an inline upload that the user is likely to revisit, mention
the trade-off once: *"Since this isn't backed by a local file, the slug
will only stick around for this session — save the URL if you'll need it
later."* That gives them a chance to capture it for future sessions.
If the user says something like "update that doc" or "the previous one"
and there are multiple candidate slugs from earlier in the session, ask
which one rather than guessing.
### On-disk marker (for files)
To make later `update` calls painless across sessions, record the slug in
the source file itself as an HTML comment. HTML comments render invisibly
in both `.html` and `.md` (Markdown passes them through), so this is safe
for both formats.
**Marker format** — must be on its own line, ideally at the top of the file:
```html
<!-- outpost-slug: <slug> -->
```
#### When to write the marker
Write or update the marker any time you have authoritative slug information
for a local file:
1. **After a successful `outpost upload`** — ask the user once if you may
record the slug in the file (e.g. *"I can add `<!-- outpost-slug:
sprint-notes -->` to the top of `./notes.md` so future updates know which
doc to replace. OK?"*). On a yes, insert the marker as the first line.
If the file already has a marker, replace it.
2. **Whenever the user gives you a slug or URL for a local file** — even if
they're not asking you to update it right now. Example: *"this notes.md
is at outpost.offsprint.xyz/s/sprint-notes"* — offer to add the marker
so it's there next time.
3. **After a successful `outpost update`** — only if the file is missing
the marker or has a stale one. Don't rewrite it on every update.
Always confirm before editing the user's file. Don't add the marker silently.
#### When to read the marker
When the user asks to update *this file* without giving a slug, look at the
top of the file for the marker. If you find one, use that slug — but
**confirm with the user first** before running `outpost update`, e.g.
*"Found `outpost-slug: sprint-notes` in the file — update that one?"*.
The marker is a hint, not a contract: it can be wrong if the file was copied
from someone else, restored from a backup, or if the doc was deleted on the
server. If `outpost update` returns 403 or 404, the marker is stale —
remove or correct it after talking to the user.
#### When NOT to use the marker
- If the user explicitly passes a slug/URL on this turn, prefer what they
said over the marker.
- If the file has no marker, don't guess. Ask the user.
- Never invent a marker for a file you didn't just upload — only record
slugs the user authorized or that came from a real upload.
## Reporting results to the user
After a successful upload, surface the URL plainly. Do not paraphrase the title
or summarize the document — the user already knows what they shared.
Example response:
> Uploaded "Sprint notes" → https://outpost.offsprint.xyz/s/sprint-notes
If the upload fails, show the CLI's stderr verbatim. Common causes: not signed
in, file too large (10 MB user limit), unsupported file type (only `.html` and
`.md` are accepted via this CLI).
## Boundaries
- Never generate document content just to upload it.
- Never use `--public` unless the user asked for a public link.
- Never run `outpost login` on the user's behalf — it requires browser
interaction.
- Never store, log, or echo the auth token from `~/.outpost/config.json`.
No comments yet. Be the first to comment!