Towline
An open-source toolkit that lets AI coding agents (Claude Code, Cursor, Codex, etc.) deploy and operate Docker containers on Portainer-managed infrastructure. It consists of five parts:
- towline CLI — scaffolds a new project: creates a Portainer team, scoped API key, container stack, agent config, compose files, and git repo.
- towline-mcp — an MCP server (Go binary) that runs per-project, giving the agent 10 operational tools (health, logs, env vars, domains, scale, exec) plus upstream Portainer stack CRUD and Docker proxy, all scoped to a single stack.
- DevOps skill — a markdown file (
skills/towline-devops.md) installed into every project that teaches the agent how to use the tools: deployment workflows, debugging patterns, rollback procedures, and the tier/approval model. - Template packs — bundles of compose files, domain-specific agent skills, and additional MCP configs. The
ai-stackpack ships Ollama + Open WebUI with an AI operations skill; then8npack ships n8n + PostgreSQL with a workflow operations skill. Compose templates (api,web-app) are also available without pack-level skills. - Remote gateway — serves your projects as a connector to apps with no terminal (Claude on the web, desktop or phone, ChatGPT/Codex), on your own domain through a Cloudflare Tunnel, with every change waiting for your approval.
New in v0.5.0: the remote gateway. Release notes
$ curl -fsSL towline.dev/install | shWho this is for
You run Portainer (self-hosted or cloud) and want AI agents to deploy containers without giving them admin access to your entire infrastructure. Towline creates a per-project boundary: dedicated Portainer team, scoped API key, single-stack MCP server. Even if the agent misbehaves, Portainer rejects anything outside its assigned scope.
What a project looks like
~/projects/my-app/
├── .mcp.json # MCP config → launches towline-mcp (0600, gitignored)
├── .claude/settings.json # Claude Code permissions
├── .cursor/ .gemini/ # Same MCP config for Cursor and Gemini CLI
├── towline.json # Project config (stack, tier, compose policy)
├── CLAUDE.md # Agent instructions for this project
├── docker-compose.yml # From template or pack
├── .env.example
├── skills/
│ ├── towline-devops.md # Base operational skill
│ └── ai-ops.md # Pack skill (if using ai-stack)
└── .git/The skills are not documentation — they are agent training. The DevOps skill teaches deployment workflows, debugging procedures, and how to use the approval system. Pack skills add domain knowledge on top (e.g., the ai-stack skill teaches how to pull Ollama models and manage Open WebUI).
Dev and prod tiers
In dev tier, the agent has full autonomy — every tool call executes immediately. In prod tier, reads and operational actions (health, logs, start, scale) are instant, but mutations (deploy, env changes, domains, stop, delete, exec) need approval: from a human in Towline's built-in approval server (towline approvals serve, web UI and CLI), or, for autonomous setups, from the agent's own explicit confirmation. Either way the agent gets a single-use approval token bound to the specific tool and arguments — it can't be reused with different parameters.
In every tier, a compose security policy rejects stacks that could reach the host or other projects (privileged mode, host bind mounts, host networking, external volumes and networks, and more). You can allow specific bind mounts, networks and volumes per project in towline.json; the agent can't.
Use it from Claude or ChatGPT
The remote gateway lets apps that have no terminal work on your projects as a connector. It runs as one stack next to Portainer and is published on your own domain through a Cloudflare Tunnel, so it works behind NAT with no port forwarding.
export TUNNEL_TOKEN=<cloudflare tunnel token>
towline remote setup --url https://mcp.example.com --all- Open
https://mcp.example.com/uiand sign in with the owner token that setup printed. - Create a connection: pick the projects and Read only or Deploy access. Apps like Claude and ChatGPT sign in with OAuth; Claude Code and Cursor get a header token.
- Add
https://mcp.example.com/mcpas a connector in the app.
Every deploy, configuration change or exec made through the gateway waits for your approval on that page, on dev projects too (--approval prod limits it to prod). The gateway holds each project's own scoped key, never the admin key. Cloudflare Access can sit in front of /ui and /oauth/authorize; apps call the other paths from their servers. Remote gateway guide
Step by step
1. Install
$ curl -fsSL towline.dev/install | shInstalls two binaries: towline (CLI) and towline-mcp (MCP server) to /usr/local/bin. The installer verifies each archive's SHA-256 against the release checksums before extracting it. Run towline help to see all commands.
2. Connect to Portainer
$ towline setupInteractive wizard. Asks for your Portainer URL, admin API key, and default environment ID, verifies Portainer's TLS certificate unless you say it's self-signed, and asks how prod operations are approved (by a human or by the agent). Saves to ~/.towline/config.yaml. Only needed once per machine.
3. Create a project
$ towline init --template web-app my-appCreates a Portainer team, scoped API key, container stack, MCP server config, DevOps skill, compose file, and git repo. The project directory is ready for your agent. Flags (--template, --tier dev|prod) go before the project name. Run inside an existing codebase, it adds Towline there instead, merging into existing agent configs; it refuses if the directory already has a towline.json or git tracks a file that would hold the token.
4. Start your agent
$ cd ~/projects/my-app && claudeThe agent reads .claude/settings.json which launches towline-mcp automatically. It picks up the DevOps skill from CLAUDE.md, gets access to the MCP tools, and can deploy, debug, scale, and operate within the isolated stack. For non-Claude agents, the MCP config is also generated for Cursor, Gemini CLI, etc.
5. Manage projects
towline list # see all projects
towline refresh --all # upgrade existing projects after towline update
towline approvals serve # approval server for prod (web UI at /ui)
towline remote status # remote gateway health
towline destroy my-app # remove Portainer stack, user and teamtowline promote, rotate-keys and status are planned but not implemented yet.
Requirements
- Portainer v2.28+ with API access (self-hosted or Portainer Cloud)
- Docker on the container host
- An MCP-compatible agent (Claude Code, Cursor, Codex, Gemini CLI, Windsurf), or, through the remote gateway, an app that takes connectors (Claude, ChatGPT/Codex)
- For the remote gateway: a domain on Cloudflare (the free plan is enough)