For a while I had a ritual. Every time I opened a new chat with my coding agent, I pasted in the same paragraph: here's my server's address, here's how you deploy, the build field is called this and not that, don't do the other thing. If I forgot, the agent did what any smart newcomer does. It guessed. It guessed field names that sounded right and weren't. It called endpoints that should exist and don't.
The agent wasn't the problem. It had never seen my server. Nobody had given it the manual.
That paragraph is now a file. It sits in a folder on my laptop, the agent reads it when the conversation turns to my server, and I haven't pasted anything in months. I think this is one of the most underrated tricks in working with agents right now, and it takes about an hour to do for your own setup.
This post explains how those files work, using agentic-hosting as the example. It's an open-source tool I built that turns a Linux server into a place where AI agents can deploy apps and databases on their own. By the end you'll know how to install its agent instructions, use its six shortcut commands, and write the same kind of file for your own infrastructure.
⭐ If this is useful, a star on GitHub helps other people find it.
🤖 Give this to your agent: point it at https://raw.githubusercontent.com/dennisonbertram/agentic-hosting/main/llms.txt and it can sign up and set things up from that one link.
A few words first
I use Claude Code, Anthropic's coding agent that runs in your terminal, so the examples here are for it. Two terms:
- A skill is a folder with a file called
SKILL.mdin it. The file has a short header saying what the skill is for, then plain instructions. Claude reads the instructions when your request matches the header. - A slash command is a shortcut you type, like
/ah-deploy. It's also just a markdown file. When you type the command, Claude Code drops that file's text into the conversation as instructions.
Skills follow an open format called Agent Skills, so other agent tools can read the same files. Slash commands are a Claude Code feature.
agentic-hosting itself is one program, ah, running on your server. Agents talk to it over an HTTP API. $AH_URL below is your server's address and $AH_KEY is the agent's API key.
What a skill file looks like
Here's the top of the skill I ship, trimmed and wrapped:
---
name: agentic-hosting
description: This skill should be used when
the user asks to install, set up, or operate
agentic-hosting... Trigger on "deploy a
service", "provision a database", "register
a tenant", "view logs", ...
---
# agentic-hosting
Fetch this file from a raw GitHub URL and
follow it end to end. You do not need a GUI.
Every action is curl against `/v1/`.
The part between the --- lines is the header. The part I didn't expect to matter so much is description. Claude Code keeps every installed skill's description in view all the time, but it only loads the full body when your request looks like a match. So the description isn't a summary for people. It's a list of the things you'd actually say when you want this skill. "Deploy a service." "View logs." If I'd written "a self-hosted PaaS control plane", Claude would rarely connect that to "put my app online."
That loading rule also means a long skill is cheap until it's used. You can put a lot of detail in the body without paying for it in every conversation.
Two copies, two jobs
agentic-hosting ships its instructions in two shapes, because people use agents in two ways.
One file you can hand to any agent. The standalone skill lives at skills/agentic-hosting/SKILL.md. It's about 300 lines and covers everything: installing the server, creating an account, deploying from git, adding Postgres or Redis, reading logs, and the full API map. Any agent that can read a URL can follow it. llms.txt (the link in the callout above) is the index that points to it and to the rest of the docs.
A Claude Code bundle. The repo's .claude/ folder has a fuller skill, four reference files it can open when it needs detail, and six slash commands. One line installs all of it:
curl -fsSL https://agentic.hosting/install-skill.sh | bash
That puts the skill and its reference files in ~/.claude/skills/agentic-hosting/ and the commands in ~/.claude/commands/. Files in your home folder work in every project on that machine. Then tell it where your server is, in your shell profile:
export AH_URL=https://your-server
export AH_KEY=keyid.secret
If you only want the single file:
R=https://raw.githubusercontent.com
P=dennisonbertram/agentic-hosting/main
D=~/.claude/skills/agentic-hosting
mkdir -p "$D"
curl -fsSL -o "$D/SKILL.md" \
"$R/$P/skills/agentic-hosting/SKILL.md"
Using it
The easiest way is to just talk. Once the skill is installed, these all work without any special syntax:
deploy https://github.com/me/blog as "blog-web"
on port 3000, then show me the build output
add a postgres database to blog-web
what's the status of my services?
Claude matches the request to the skill, reads the instructions, and runs the curl calls. You can also call the skill by name with /agentic-hosting, since the folder name doubles as a command.
The six slash commands are shortcuts for the jobs I do most:
| Command | What it does |
|---|---|
/ah-deploy |
Deploy from a git URL or Docker image |
/ah-status |
Disk, services, databases, builds |
/ah-db |
Add Postgres or Redis to an app |
/ah-logs |
Stream app logs, or a build's logs |
/ah-register |
Create an account, get an API key |
/ah-snapshot |
Snapshot an app before a risky change |
/ah-status is the one I use daily. It reads disk use, lists every app with its status and crash count, flags anything not running, and checks for builds in progress. It's my morning "is anything on fire" check, and when something is, the same skill tells the agent how to handle it: what a tripped crash breaker looks like, how to reset it and redeploy, what to do when the disk is nearly full. The agent works the incident instead of handing me an error.
One note on /ah-register: it reads the server's setup secret over SSH, so it's for whoever runs the server, not for an agent that's just been handed a key.
What's inside a slash command
Here's the top of /ah-deploy, trimmed and wrapped:
---
description: Deploy a service to
agentic-hosting from a git URL or Docker
image.
argument-hint: <git-url-or-image>
<service-name> [port]
allowed-tools: Bash
---
You are an agentic-hosting operator. Use
`$AH_URL` and `$AH_KEY` from the environment
(ask the user if not set).
Below that is a numbered list: check the server is up, stop if the disk is over 90% full, create the app, start the build, stream the log, wait up to 10 minutes for it to be running, report the URL.
Two lines in the header deserve attention.
argument-hint is what you see while typing the command. It's documentation for you, nothing more.
allowed-tools: Bash lets Claude run shell commands without asking you first, for the turn where you invoked the command. That's why /ah-deploy runs without a stack of permission prompts. It's also something to decide on purpose. For a deploy command, I want it. For a command that deletes things, I'd leave it off and approve each step. Claude Code also has a disable-model-invocation: true setting for commands Claude shouldn't start on its own, which is worth using for anything with side effects.
The bug I found while writing this
To write this post I checked every command file against the current Claude Code docs, and found a real problem in mine.
Slash commands can pull in what you typed after the command. My command files were written when $1 meant the first argument. In current Claude Code, numbering starts at zero: $0 is the first argument and $1 is the second. So when you type this:
/ah-deploy https://github.com/me/blog blog-web 3000
the instructions Claude gets say to deploy 3000 using blog-web, and the git URL never appears in the instructions at all. Nothing errors. The agent just starts from a scrambled brief.
Until the files are fixed, plain English (the examples above) is the reliable way to deploy. If you write your own commands, two habits avoid this. Use $ARGUMENTS, which is everything you typed, and let Claude sort it out. Or name your arguments in the header (arguments: [source, service, port]) and write $source and $service in the body, so the numbering can't shift under you.
The bigger lesson is that these files are code that nothing compiles. They drift from your API, and from the agent tool, and nobody gets an error when they do.
How to write one for your own infrastructure
This is the part I'd steal if I were you. You don't need a platform like mine. Any internal API, deploy script, or runbook works. Here's what I've learned makes these files good.
1. Write the description in your own words. List the phrases you'd actually type. Claude truncates long descriptions in its listing (about 1,500 characters), so lead with the common ones.
2. Show the exact request, and name the wrong one. The most useful line in my skill is a negative: "There is no git_url / branch field." Agents kept inventing those names because they sound right. Writing down the plausible mistake fixed it in a way that just showing the right shape didn't.
3. Say what done looks like. My skill doesn't say "wait for the deploy." It gives a loop that checks every 5 seconds for up to 10 minutes and stops on one of three things: running, failed, or the crash breaker open. Agents are great at following a loop and bad at deciding when to give up.
4. Keep the main file short and link out. Anthropic's docs suggest keeping SKILL.md under 500 lines. Mine is about 400, and the full API listing, operations notes, domain setup, and server install live in four separate files the skill points to. Claude opens them only when it needs them.
5. Put the habits in writing. My database command says never print the full connection string, only host and port. That's an instruction, not a lock. The string still passes through the commands Claude runs. Write the habit down anyway. It works most of the time, and the real protection belongs on the server.
6. Test it like code, against the real thing. Open a fresh session, ask for the task in plain words, and compare what the agent does with what the server accepts. Every time I've done this I've found something. Earlier checks caught my skill reading the build's ID from a field called id when the server returns build_id, and waiting for a status string the server never sends. Both are fixed now. This round turned up the argument numbering above, plus a line in both skill files that says "redeploy" rebuilds from git. It doesn't. It restarts the app with the image it already has and the current settings.
Here's a skeleton to start from. Swap in your own endpoints:
---
name: my-deploys
description: Use when the user asks to deploy,
roll back, check deploy status, or read
logs for our apps on deploy.internal.
---
# Deploying our apps
Base URL: $DEPLOY_URL. Auth header:
`Authorization: Bearer $DEPLOY_TOKEN`.
## Deploy
POST /deploys {"app":"<name>","ref":"<sha>"}
- `ref` must be a full commit SHA. There is
no `branch` field.
- Poll GET /deploys/<id> every 5s, up to
10 min. Stop on "live" or "failed".
## Never
- Print tokens or connection strings.
- Deploy to prod without saying so first.
## More detail
- references/api.md for every endpoint.
Save it as ~/.claude/skills/my-deploys/SKILL.md, start a new session, and ask it to deploy something. Then read what it did.
The skill isn't the permission
One last thing I'd tell anyone doing this. The skill file teaches the agent how. It shouldn't decide what the agent is allowed to do. That belongs in the API key.
In agentic-hosting, the key you get when you create an account is an owner key. Extra keys you create for agents are member keys by default. A member key can deploy, add databases, and read logs, but it can't revoke keys or suspend the account. So my agents run with member keys, and the skill can be as capable as I like without any one agent being able to lock me out.
Wrapping up
A skill is the paragraph you keep pasting, saved as a file with a header that tells the agent when to read it. agentic-hosting ships one file any agent can follow, plus a Claude Code bundle with six shortcut commands, and the same recipe works for your own infrastructure: real phrases in the description, exact requests with the wrong ones named, a clear stopping point, and regular testing against the real API.
- Star agentic-hosting on GitHub so more people find it.
- Give it to your agent: llms.txt to sign up and set up, or the agent skill for daily use.
- Try the quickstart, or start at the docs site.
- Open an issue if you've written a skill for your own infra and found a pattern that works. I'd like to collect them.
Cover photo: members of an outdoor-orientation workshop learning to read maps and use compasses in Warrensburg, New York. Anne LaBastille, October 1973, for the EPA's Documerica project. U.S. National Archives, public domain.
Top comments (0)