| name | jhack |
| description | Expert assistant for Juju charm development using jhack utilities. Use when debugging charms, inspecting relations, syncing code, replaying events, testing scenarios, or performing rapid development iterations. Keywords include jhack, Juju debugging, charm testing, relation inspection, event replay, sync, tail, fire, show-relation, show-stored. |
| license | Apache-2.0 |
| compatibility | Requires jhack and juju installed locally. Network access needed for model operations. |
| allowed-tools | Bash(jhack:*) Bash(juju:*) Read |
Jhack Development Assistant
Expert guidance for using jhack utilities to streamline Juju charm development, debugging, and testing.
What is Jhack?
Jhack is a collection of developer utilities that make charm development faster and easier by:
- Providing shortcuts for common operations
- Enabling rapid code iteration without redeployment
- Visualising charm state and relations
- Capturing and replaying real events
- Simplifying debugging workflows
Core Workflows
Inspecting Charm State
jhack show-relation myapp postgresql
jhack show-relation myapp:database postgresql:database
jhack show-stored myapp/0
jhack show-stored myapp/leader
jhack list-endpoints myapp
jhack charm-info myapp/0
show-relation displays what data charms are sharing in a relation as a formatted table, making debugging integration issues much easier.
show-stored shows the persistent state stored by the charm (via StoredState in Ops framework).
Live Development with Sync
jhack sync src/ myapp/0
jhack sync --src=./src --src=./lib myapp/0
jhack sync --no-watch src/ myapp/0
Use case: Edit code locally, jhack automatically pushes changes to the running unit. Combined with jhack utils fire, you can test changes in seconds without repacking and redeploying.
For packed charm sync: Use jhack charm sync-packed
Monitoring Events
jhack tail
jhack tail myapp/0
jhack tail -d myapp/0
jhack tail --filter=config-changed
tail provides a colour-coded, hierarchical view of charm events as they fire, showing:
- Event names
- Handler execution
- Nested events (e.g., relation-changed triggering config-changed)
- Timing information
Firing Events Manually
jhack utils fire myapp/0 config-changed
jhack utils fire myapp/0 database-relation-changed
jhack fire myapp/0 upgrade-charm
jhack ffwd myapp --interval=10s
jhack ffwd myapp --stop
Use case: Test specific event handlers without waiting for natural triggers or performing manual operations.
Event Replay (Advanced)
jhack replay install myapp/0
jhack replay list myapp/0
jhack replay emit myapp/0 5
jhack replay dump myapp/0 5
jhack replay purge myapp/0
Use case: Capture real production events (with all their context and data) and replay them for debugging or testing.
Scenario Testing
jhack scenario snapshot myapp/0 > state.json
jhack scenario state-apply myapp/0 state.json
Integration with ops-scenario: Use snapshot to capture real charm state, then use it in unit tests with the Ops state-transition (unit) testing framework.
Charm Manipulation
jhack charm update myapp.charm src/
jhack charm sync-packed --src=./src --charm=myapp.charm
jhack charm lobotomy myapp/0
jhack charm lobotomy myapp/0 --undo
jhack utils elect myapp/1
lobotomy is useful for freezing a charm's behavior during debugging - it prevents the charm from processing any events.
Pebble Commands (K8s Charms)
jhack pebble -c mycontainer myapp/0 plan
jhack pebble -c mycontainer myapp/0 services
jhack pebble -c mycontainer myapp/0 logs myservice
jhack pebble -c mycontainer myapp/0 exec "ls -la /"
Shortcut for: juju ssh --container=mycontainer myapp/0 -- pebble <command>
Debugging and Logs
jhack debug-log myapp/0
jhack script myapp/0 myscript.py
jhack eval myapp/0 "self.unit.status"
script and eval let you run arbitrary Python code in the context of a live charm, with access to the charm instance.
Destructive Operations
jhack nuke myapp
jhack nuke "test-*"
jhack nuke --model=mymodel --all
jhack kill myapp/0
jhack utils this-is-fine
Safety: All destructive commands require confirmation unless you enable devmode: jhack conf set devmode=true
Chaos Testing
jhack chaos mancioppi myapp --duration=300
jhack chaos flicker myapp
Use case: Identify race conditions and state management issues by rapidly scaling, relating, and modifying charms.
Common Workflows
Rapid Development Iteration
- Deploy charm:
juju deploy ./myapp.charm
- Start sync:
jhack sync src/ myapp/0
- Edit code locally
- Fire event to test:
jhack utils fire myapp/0 config-changed
- Watch events:
jhack tail myapp/0 -d
- Inspect state:
jhack show-stored myapp/0
Result: Test changes in seconds instead of minutes.
Debugging Integration Issues
- Check relation data:
jhack show-relation myapp postgresql
- Fire relation event:
jhack utils fire myapp/0 database-relation-changed
- Watch handler execution:
jhack tail myapp/0 -d
- Inspect stored state:
jhack show-stored myapp/0
Capturing Production Issues
- Install recorder:
jhack replay install myapp/0
- Wait for issue to occur
- List events:
jhack replay list myapp/0
- Dump problematic event:
jhack replay dump myapp/0 <id>
- Replay locally:
jhack replay emit myapp/0 <id>
Testing Leadership Changes
- Check current leader:
juju status
- Force different unit to lead:
jhack utils elect myapp/1
- Test leader-specific behavior
- Watch events:
jhack tail myapp
Command Quick Reference
jhack show-relation <app> <app>
jhack show-stored <unit>
jhack tail [unit]
jhack charm-info <unit>
jhack sync <src> <unit>
jhack utils fire <unit> <event>
jhack ffwd <app> --interval=10s
jhack replay install <unit>
jhack replay list <unit>
jhack replay emit <unit> <id>
jhack scenario snapshot <unit>
jhack scenario state-apply <unit> <file>
jhack pebble -c <container> <unit> <command>
jhack debug-log <unit>
jhack eval <unit> <expression>
jhack script <unit> <script>
jhack charm lobotomy <unit>
jhack utils elect <unit>
jhack kill <unit>
jhack nuke <pattern>
jhack utils this-is-fine
jhack chaos mancioppi <app>
Integration with Development Tools
With Tox
vim src/charm.py
tox -e format
tox -e lint
jhack sync src/ myapp/0
jhack utils fire myapp/0 config-changed
With Ops-Scenario
import json
from ops import testing
with open('tests/state.json') as f:
state = testing.State.from_dict(json.load(f))
ctx = testing.Context(MyCharm)
ctx.run(event, state)
With Charmcraft
charmcraft pack
jhack charm update myapp.charm src/
jhack charm sync-packed --charm=myapp.charm --src=./src
Best Practices
Development
- Use sync for rapid iteration - Don't repack/redeploy for every change
- Watch events with tail -d - Understand what's happening
- Fire events manually - Test specific scenarios quickly
- Capture real states - Use scenario snapshot for realistic test data
Debugging
- Start with show-relation - Most integration issues are data problems
- Check show-stored - Verify state persistence
- Use replay for production issues - Capture and replay real events
- Enable debug logging -
jhack tail -d shows detailed output
Testing
- Use scenario snapshots - Test against real charm states
- Test leadership changes - Use
elect to simulate failover
- Stress test with chaos - Find race conditions early
- Lobotomize for state inspection - Freeze charm to inspect state
Safety
- Enable devmode only in dev -
jhack conf set devmode=false for production
- Use --dry-run - Many commands support dry-run mode
- Verify nuke targets - Double-check pattern matching before confirming
- Be careful with this-is-fine - Only use when you understand why units errored
Configuration
jhack conf show
jhack conf set devmode=true
jhack --loglevel=DEBUG <command>
jhack --log-to-file=jhack.log <command>
Troubleshooting
Sync not working:
- Ensure SSH access:
juju ssh myapp/0
- Check source path exists locally
- Verify unit is active:
juju status
Events not appearing in tail:
- Check you're watching the right model:
juju models
- Switch model:
juju switch <model>
- Verify unit name:
juju status
Replay fails:
- Ensure recorder installed:
jhack replay install myapp/0
- Check database exists:
jhack replay list myapp/0
- Verify event ID: Use list output
Pebble commands fail:
- Verify container name:
juju ssh myapp/0 -- pebble version
- Check K8s charm: Machine charms don't use Pebble
- Ensure container is ready:
juju status
For comprehensive troubleshooting, see references/troubleshooting.md
Resources
Additional References
When you need detailed information:
Key reminders:
- Use
jhack sync for rapid development iteration
tail -d is your friend for debugging
- Capture production issues with
replay
- Test with real state using
scenario snapshot
- Enable devmode only in development environments