Deploy plugins
A plugin is one JSON file in .kiln/plugins/: a palette label and a shell command, run through the jobs layer like any project tool (see the plugins write-up). Deploy plugins are the same thing with one extra tag that says where in the UI the command belongs.
The idea
kiln already runs the project's own tooling rather than reimplementing it. Deploy is no different. Instead of teaching kiln how to talk to Vercel, you point it at the command you'd run anyway, and tell it that command is your prod deploy:
{
"type": "deploy.prod",
"provider": "vercel",
"name": "Deploy to Vercel",
"command": "vercel --prod"
}
type is the new part. Where on (save / job-fail) binds a plugin to an IDE event, type binds it to a surface slot. A deploy.prod plugin becomes a button in the title bar, next to lint, test, and build. The plugin stays one shell line you can read in five seconds; kiln just knows where to wire it.
Two slots to start, deploy.prod and deploy.preview, grown only on demand.
The fields
type— the surface slot. Unknown values decode to nothing, so a newer plugin file stays loadable in an older kiln, just palette-only.provider— a display hint, like"vercel". It shows in the button tooltip and groups related plugins. It never changes behavior: thecommandis what runs.run— where the command runs,joborterminal. Leave it out and the slot decides: deploy slots default to a terminal, everything else to a hidden job.
One file can hold an array, so a single vercel.json carries prod and preview together:
[
{
"type": "deploy.prod",
"provider": "vercel",
"name": "Prod",
"command": "vercel --prod"
},
{
"type": "deploy.preview",
"provider": "vercel",
"name": "Preview",
"command": "vercel"
}
]
If two plugins claim the same slot, the later one wins, matching the project → user → local layering of the rest of .kiln.
Why deploys open a terminal
A normal plugin runs in a hidden shell and reports through a toast and the run strip. A deploy is different: it's long, log-heavy, and often interactive. vercel asks you to log in, pick a scope, link a project, confirm prod. A hidden job can't answer a prompt, so it would just hang.
So a deploy opens a fresh terminal and types the command there. You watch the build stream and answer anything it asks, in a new shell that doesn't collide with whatever you were typing in your workspace terminal. The trade is that terminal output isn't parsed the way jobs are, so you don't get the toast counts or the structured report. For a deploy, watching it live is the better deal.
A note on safety
The plugin safety gate keeps grown plugins read-only: the squad can write a plugin from a wish, so it's never allowed to push, delete, or sudo. A deploy does exactly that mutating, production-touching thing, which is why a deploy plugin can't be squad-grown. It's hand-authored, it lives in a trusted workspace, and routing it to a terminal is the honest version of that: it's a labeled shortcut for a line you'd have typed into a shell yourself.