Agents
self-host is built to be driven by an agent through plain commands. Paste this one sentence into Claude Code, Codex, OpenCode, OpenClaw or any coding agent:
Install the self-host skill from github.com/ajnart/self-host and help me run my own movie server.Or let the binary write the skill for every agent on the machine: ~/.agents/skills, plus Claude Code, Codex, OpenCode, Pi, Gemini and Hermes when they are installed (Omarchy’s agents read the same folders). self-host skill remove deletes only what it wrote.
self-host skill installOr use the skills CLI (needs Bun or Node.js):
bunx --bun skills@latest add ajnart/self-host --skill self-host# or: npx --yes skills add ajnart/self-host --skill self-hostThe one public skill only routes to the guide built into the binary; installing it deploys nothing. Invoke it with /self-host in Claude Code and OpenClaw, $self-host in Codex. Agents can also start from llms.txt.
self-host skill
Section titled “self-host skill”self-host skillprints the agent guide that matches the installed binary: every command it registers, the JSON events, exit codes, Access procedures and the rules below. Run it again after self-host self-update.
Inspect, plan, approval, apply, verify
Section titled “Inspect, plan, approval, apply, verify”Loading the skill conveys intent, never approval. Every change follows the same order:
- Inspect with
self-host doctor --json,self-host apps info <app> --jsonandself-host status --json. - Plan: show the person the one
self-host installline and what it will do. - Approval: wait for an explicit yes. Anything reachable from the internet needs its own yes that names the risk.
- Apply with
--yes, which authorizes; it is never a preview flag. - Verify with
self-host status --json. A running container or an HTTP 200 is not acceptance: check that the App does its job.
Every conversation
Section titled “Every conversation”- Run
self-host status --jsonfirst. It answers “where is X?”: each App’sdescription,addressesandstate, plushome,dashboardandprofile. With no Project yet it exits 1 with “no Project yet”; runself-host profile --jsoninstead. - If the Profile’s
experienceis empty, ask once: “Have you run your own server or used Docker before, or is this all new to you?” Save the answer withself-host profile set experience neworself-host profile set experience advanced. A skipped question means new. - New: one question at a time, plain words, a sentence before and after every change, and no talk of Docker, ports or Compose unless Docker must be installed. Advanced: terse, with the exact flags.
- At the end of every setup, give the Recap from
self-host status --json: each App in plain words with its Address, where the Home folder is, and how to sign in withself-host credentials, never quoting a secret. Then offerself-host share, which prints a postable install line and site link for the Catalog Apps only.
The –json commands
Section titled “The –json commands”self-host doctor --jsonself-host apps list --jsonself-host apps info ntfy --json# only after approval:self-host install ntfy --exposure local --yes --jsonself-host status --jsoninstall,setup,start,stop,restart,update,remove,config set,backup,restoreanddoctorprint one JSON event per line:run.start,step.start,step.ok,step.skip,step.warn,step.fail,step.manual,command,info,pull.progressandrun.end.status,profile,debug,credentials,apps list,apps info,logsandhost reportprint one JSON document.- Existing keys are stable; new fields are additive.
A step.fail event carries what the agent needs to finish the step by hand:
{ "event": "step.fail", "app": "sonarr", "step": "download-client", "error": "qBittorrent refused login", "url": "http://192.168.1.20:8989", "credential": "admin", "hint": "Add qBittorrent under Settings › Download Clients."}Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 |
Success. |
1 |
Error. Read the error field of the last run.end or step.fail. |
2 |
Setup incomplete: everything is installed, but at least one Setup step failed. |
3 |
Only Manual steps remain: finish them in the browser, then retry Setup. |
After a failure, read self-host debug <app> --json, do what the hint says, then rerun self-host setup <app>. Finished steps are skipped, so reruns are safe.
Inputs and secrets
Section titled “Inputs and secrets”--set app.key=value(repeatable) answers non-secret inputs;--set jellyfin.port=8097picks a port.--set-file app.key=/pathreads a private input from an owner-only file, and=-reads stdin. Never put a secret in a command line, a reply or a file you write. Values land only in the Project’ssecrets.env.self-host credentialsreveals the shared Admin login and per-App API keys. Use it privately and keep its output out of chat, logs and screenshots.
An isolated Project
Section titled “An isolated Project”Set SELF_HOST_HOME to an absolute directory and SELF_HOST_COMPOSE_PROJECT to a unique lowercase name, and keep both the same for every later command.
Apps the Catalog lacks
Section titled “Apps the Catalog lacks”When the person wants an App that self-host apps list does not have, offer the closest Catalog Apps, then tell the maintainers once:
self-host apps request "<name>" --url <homepage>For software they want to run anyway, add an Unmanaged app: a Compose file under ~/.self-host/extra/<name>/compose.yml. The CLI lists it with its Address, starts, stops, updates and backs it up, but runs no Setup for it.
self-host · Apache-2.0 · home · apps · docs · github · discord · llms.txt · telemetry