| name | juju |
| description | Operate a Juju controller — deploy, configure, integrate, scale, debug, and manage charms on Kubernetes and machine models. Use when asked to "deploy a charm", "add a model", "check status", "debug a unit", "integrate applications", "scale up/down", "manage secrets", "configure an app", "run an action", "destroy a model", or any Juju CLI operation. Keywords include juju, deploy, integrate, relate, model, controller, status, debug-log, config, action, expose, storage, secrets, ssh, scale. |
| allowed-tools | Bash(juju:*), Bash(charmcraft pack:*), Bash(charmcraft analyse:*), Read, Grep, Glob |
Juju Operations Assistant
Operate a live Juju environment: deploy charms, manage models, configure applications, integrate services, debug issues, and manage the full lifecycle.
Live Environment
Current controller: !juju whoami --format=json 2>/dev/null || echo '{"error": "not connected"}'
Controllers: !juju controllers --format=tabular 2>/dev/null | head -15 || echo "No controllers found"
Active model status: !juju status --format=short 2>/dev/null | head -20 || echo "No active model"
Session Setup
When starting work that requires a Juju model, always:
- Choose the right controller for the substrate:
juju switch concierge-lxd
juju switch concierge-k8s
If the controllers were not set up by Concierge, they will have different names, and you will need to refer to the "cloud" field in juju status.
-
Create a dedicated model with a recognisable, unique name:
juju add-model claude-<descriptive-id>
-
Immediately tell the user how to observe the model — print this right after model creation, and again at the end of the session:
Model created: <controller>:<model>
To watch status:
juju status -m <controller>:<model> --watch 2s
To stream logs:
juju debug-log -m <controller>:<model> --tail
Core Workflows
Deploy a Charm
juju deploy postgresql-k8s --channel 14/stable --trust
juju deploy ubuntu --base ubuntu@24.04 -n 3
charmcraft pack
charmcraft analyse ./*.charm
juju deploy ./<name>.charm --resource <name>=<image>
juju deploy mysql-k8s --channel 8.0/stable --config profile=testing
juju deploy app-k8s --constraints "mem=4G cores=2"
juju deploy postgresql-k8s --storage pgdata=kubernetes,10G
Key flags:
--trust — grant the charm access to cloud credentials (required by many charms)
--channel — specify the risk channel (e.g., 14/stable, latest/edge)
--base — target OS for machine charms (e.g., ubuntu@22.04)
-n — number of units to deploy
--config — pass key=value or a YAML config file
--constraints — resource requirements (mem, cores, root-disk, virt-type, arch)
--resource — attach OCI images or files
--storage — attach storage (format: <store>=<pool>,<size>)
Configure Applications
juju config <app>
juju config <app> key1=value1 key2=value2
juju config <app> --file config.yaml
juju config <app> --reset key1,key2
juju config <app> key1
Integrate (Relate) Applications
juju integrate <app1> <app2>
juju integrate <app1>:endpoint1 <app2>:endpoint2
juju remove-relation <app1> <app2>
juju status --relations
Common integration patterns:
- Database:
juju integrate myapp postgresql-k8s
- Ingress:
juju integrate myapp traefik-k8s
- TLS:
juju integrate myapp self-signed-certificates
- Logging:
juju integrate myapp grafana-agent-k8s
Scale Applications
juju scale-application <app> <count>
juju add-unit <app> -n <count>
juju remove-unit <app>/<unit-number>
Run Actions
juju actions <app>
juju run <app>/<unit> <action-name>
juju run <app>/<unit> <action-name> param1=value1 param2=value2
juju run <app>/<unit> <action-name> --wait=5m
juju operations --actions
Expose / Network Access
juju expose <app>
juju expose <app> --to-cidrs 10.0.0.0/24
juju expose <app> --to-spaces public
juju unexpose <app>
Status and Monitoring
Reading Status
juju status
juju status --relations
juju status --watch 2s
juju status --format json
juju show-application <app>
juju show-unit <app>/<unit>
Status interpretation:
- active — charm is healthy (the text part of the status may indicate degraded performance)
- waiting/idle — charm is waiting for something (often a relation)
- blocked/idle — charm needs user intervention (read the status message!)
- maintenance — charm is performing an operation
- error — a hook failed; check logs and use
juju resolved
Streaming Logs
juju debug-log --tail
juju debug-log --tail --include unit-<app>-<n>
juju debug-log --tail --level ERROR
juju debug-log --tail --include <app>
juju model-config logging-config="<root>=WARNING;unit=DEBUG"
SSH and Exec
juju ssh <app>/<unit>
juju ssh <app>/<unit> -- <command>
juju ssh --container <container-name> <app>/<unit>
juju scp <local-path> <app>/<unit>:<remote-path>
juju scp <app>/<unit>:<remote-path> <local-path>
juju exec --all -- <command>
juju exec --application <app> -- <command>
Model Management
juju models
juju add-model <name>
juju add-model <name> --config logging-config="<root>=INFO"
juju switch <controller>
juju switch <controller>:<model>
juju model-config
juju model-config <key>
juju model-config <key>=<value>
juju set-model-constraints cores=2 mem=4G
Secrets Management
juju add-secret <name> key1=value1 key2=value2
juju grant-secret <name> <app>
juju revoke-secret <name> <app>
juju secrets
juju show-secret <name>
juju show-secret <name> --reveal
juju update-secret <name> key1=newvalue
juju remove-secret <name>
Debugging Workflows
When a unit is in error state:
-
Read the status message — it often tells you what is wrong:
juju status --format json | python3 -c "
import sys, json
s = json.load(sys.stdin)
for app, info in s.get('applications', {}).items():
for unit, u in info.get('units', {}).items():
ws = u.get('workload-status', {})
if ws.get('current') in ('error', 'blocked'):
print(f'{unit}: {ws[\"current\"]} — {ws.get(\"message\", \"\")}')
"
-
Check the logs for the failing unit:
juju debug-log --tail --level ERROR --include unit-<app>-<n>
-
Retry the failed hook once the issue is understood:
juju resolved <app>/<unit>
-
For deeper inspection, SSH in:
juju ssh <app>/<unit>
juju ssh --container <container> <app>/<unit>
-
Interactive hook debugging (drops you into a tmux session when hook fires):
juju debug-hooks <app>/<unit>
For comprehensive troubleshooting, see references/troubleshooting.md
Cleanup and Teardown
Always clean up models when done. Follow this order:
juju remove-application <app> --destroy-storage
juju destroy-model <controller>:<model> --destroy-storage -y
juju destroy-model <controller>:<model> --destroy-storage --force --no-wait -y
Safety rules:
- Never destroy a controller unless the user explicitly asks
- Never destroy a model that you did not create unless the user explicitly asks
- Never remove packages installed by Concierge unless explicitly asked
- Always use
--destroy-storage to avoid orphaned volumes
- Always use
-m <controller>:<model> for destructive commands to avoid accidents
Working with Both Substrates
The environment may have one or both of Kubernetes and LXD controllers. Choose based on the charm type. If the environment was set up by Concierge, then the controllers will be named concierge-k8s and concierge-lxd, and the model in both cases will be named testing.
| Kubernetes | Machine/LXD |
|---|
| Charm type | K8s charms (sidecar pattern) | Machine charms |
| Workload | OCI images via Pebble | Debs, snaps, binaries |
| Scale | juju scale-application | juju add-unit / juju remove-unit |
| SSH to workload | juju ssh --container <c> <u> | juju ssh <u> (needs a key configured in Juju 4 and above) |
| Storage | kubernetes pool | lxd pool |
Best Practices
- Always use
-m controller:model for commands that modify state — avoids acting on the wrong model
- Use
--format json when parsing output programmatically — human-readable format changes between versions
- Check
juju status after deploy/integrate/config changes — don't assume success
- Use
--trust when deploying charms that need cloud API access
- Set
logging-config early: juju model-config logging-config="<root>=WARNING;unit=DEBUG"
- Wait for operations — use
watch -n2 juju status or poll with juju status --format json rather than guessing timing
- Read charm documentation before deploying:
juju info <charm> shows metadata, channels, and supported bases
Additional References
When you need detailed information: