From daily-carry
Manage Portainer deployments - create stacks from Git repos, check deployment status, redeploy, view logs. Use when user asks about deploying to Portainer, checking stack status, or managing Docker deployments.
npx claudepluginhub jayteealao/agent-skills --plugin daily-carryThis skill is limited to using the following tools:
Manage Docker stack deployments via Portainer API.
Verifies tests pass on completed feature branch, presents options to merge locally, create GitHub PR, keep as-is or discard; executes choice and cleans up worktree.
Guides root cause investigation for bugs, test failures, unexpected behavior, performance issues, and build failures before proposing fixes.
Writes implementation plans from specs for multi-step tasks, mapping files and breaking into TDD bite-sized steps before coding.
Manage Docker stack deployments via Portainer API.
Before using, ensure these are available:
https://portainer.example.com)Store sensitive config in environment or prompt user when needed.
curl -s -X GET "$PORTAINER_URL/api/stacks" \
-H "X-API-Key: $PORTAINER_TOKEN" | jq '.[] | {Id, Name, Status, CreationDate}'
Status codes: 1 = active, 2 = inactive
# Get specific stack by name
STACK_NAME="my-stack"
curl -s -X GET "$PORTAINER_URL/api/stacks" \
-H "X-API-Key: $PORTAINER_TOKEN" | jq ".[] | select(.Name==\"$STACK_NAME\")"
STACK_ID=24
ENDPOINT_ID=1
curl -s -X GET "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/json?all=true" \
-H "X-API-Key: $PORTAINER_TOKEN" | jq '.[] | select(.Labels["com.docker.compose.project"]=="STACK_NAME") | {Id: .Id[:12], Name: .Names[0], State, Status}'
Required parameters:
name: Stack name (lowercase, hyphens allowed)repositoryURL: Git repo URLrepositoryReferenceName: Branch (e.g., refs/heads/main)composeFile: Path to compose file in repoenv: Array of environment variablesENDPOINT_ID=$(curl -s "$PORTAINER_URL/api/endpoints" -H "X-API-Key: $PORTAINER_TOKEN" | jq '.[0].Id')
curl -X POST "$PORTAINER_URL/api/stacks/create/standalone/repository?endpointId=$ENDPOINT_ID" \
-H "X-API-Key: $PORTAINER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-stack",
"repositoryURL": "https://github.com/user/repo.git",
"repositoryReferenceName": "refs/heads/main",
"composeFile": "docker-compose.yml",
"repositoryAuthentication": true,
"repositoryUsername": "USERNAME",
"repositoryPassword": "GITHUB_TOKEN",
"env": [
{"name": "VAR_NAME", "value": "value"}
],
"autoUpdate": {
"interval": "5m"
}
}'
For private repos, set repositoryAuthentication: true and provide credentials.
Get GitHub token via: gh auth token
STACK_ID=24
ENDPOINT_ID=1
curl -X PUT "$PORTAINER_URL/api/stacks/$STACK_ID/git/redeploy?endpointId=$ENDPOINT_ID" \
-H "X-API-Key: $PORTAINER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"pullImage": true, "prune": false}'
STACK_ID=24
ENDPOINT_ID=1
curl -X DELETE "$PORTAINER_URL/api/stacks/$STACK_ID?endpointId=$ENDPOINT_ID" \
-H "X-API-Key: $PORTAINER_TOKEN"
CONTAINER_ID="abc123"
ENDPOINT_ID=1
curl -s "$PORTAINER_URL/api/endpoints/$ENDPOINT_ID/docker/containers/$CONTAINER_ID/logs?stdout=true&stderr=true&tail=100" \
-H "X-API-Key: $PORTAINER_TOKEN"
Gather requirements:
Check if repo is private:
curl -s -o /dev/null -w "%{http_code}" https://github.com/USER/REPO
If 404, need GitHub credentials.
Get endpoint ID:
curl -s "$PORTAINER_URL/api/endpoints" -H "X-API-Key: $TOKEN" | jq '.[0].Id'
Check for existing stack:
curl -s "$PORTAINER_URL/api/stacks" -H "X-API-Key: $TOKEN" | jq -r '.[] | select(.Name=="STACK_NAME") | .Id'
Create or update based on whether stack exists.
Verify deployment by checking stack status after creation.
Present status in a clear format:
| Stack | Status | Containers | Last Updated |
|-------|--------|------------|--------------|
| my-app | Active | 3/3 running | 2 hours ago |
Common errors and solutions:
| Error | Cause | Solution |
|---|---|---|
authentication failed | Private repo without credentials | Add repositoryAuthentication, username, password |
Invalid request payload | Malformed JSON | Check JSON syntax, especially nested objects |
stack already exists | Duplicate name | Use update/redeploy instead of create |
endpoint not found | Wrong endpoint ID | Query /api/endpoints first |
gh auth token for GitHub credentials (auto-refreshes)See scripts/deploy-portainer.sh in this repository for a complete example.