[Tutorial] Extending Juju with plugins

Juju :juju: is a very extensible system. If you would like to integrate Juju into your own tooling you have two main options: first, to use the client libraries (in Python :snake: and JavaScript :coffee:) and secondly to write a plugin. This guide documents plugin development.

Juju client libraries: The Juju team maintains Python and JavaScript libraries as open source software. You are welcome to use them to create command-line and web applications that interact with a Juju controller and its models.

What is a Juju plugin?

Juju plugins :electric_plug: are executable files that conform to the convention of being named juju-<plugin> that are available on your $PATH.

Tiny Example: juju-ip

Let’s say that we want to reduce the burden of downstream scripts needing to parse Juju’s status output by hand to extract IP addresses of machines within our model. We create a plugin that does the heavy lifting on our future scripts’ behalf.

Before looking at how it’s implemented, take a look at how it is used. We add a file–our plugin–to the $PATH as juju-ip, then allow juju to call it on our behalf:

juju ip 0

Producing something like this:

This particular plugin uses from fairly arcane syntax to work around the shell escaping and jq query rules. (Improvements to increase readability are very welcome!)

#!/usr/bin/env bash

# minimalist juju plugin to print a machine's IP address

query=$(printf '.machines."%d"."dns-name"' "$1")
juju status --format=json |\
  jq -r "$query"

Although this example uses the bash shell scripting language, you are not limited to that. Use whichever programming language that make sense for your environment, and for the environment of your intended users.

This minimal example does have some limitations:

  • inability to declare dependencies (e.g. jq)
  • minimal facilities to provide help

To get around them, it’s generally recommended to use a more fully-fledged system that can handle these nuances.


There is no set format for distributing your plugin. A general pattern for plugins that are intended to be widely available is the following steps:

Before publishing

You’ve coded up your plugin idea. That’s great. Now you need to pause and check that you’re not going to get yourself or anyone else into trouble by installing it!

  • Create an account on the Discourse (https://discourse.jujucharms.com/). It’s the primary medium for the community to interact.
  • Ensure that you are legally entitled to release the code. If you’ve developed the plugin at work, your employer may be the copyright holder.
  • Do a final check and attempt to install Juju and the plugin on a fresh machine. Your installation instructions should “just work”.

Alpha/beta quality releases

At this stage, you want to receive feedback and add polish.

  • Post a note on Discourse inviting people to be beta testers
  • Where relevant, upload the plugin to a relevant package manager
  • Make sure that your project has a complete README file with installation instructions and dependency requirements

General release

Your plugin is mature and should now be fully functional. To announce that it is generally available, make it simple to find and install.

  • Submit a pull request to have it included in the plugins repository
  • Consider making the plugin install-able via snap. This will enable everyone on Linux to install it, regardless of their local environment.


Your plugin is doing well and your users are happy. Great work. Growing your userbase will mean that more lives can be simplified.

  • Add a usage tutorial on Discourse. Short is great.
  • For wider reach, add your tutorial on tutorials.ubuntu.com. The process is really simple. All you need is a text file and a pull request on GitHub.

Next steps

Take a look at the Juju plugins repository on GitHub.

Review our plugins documentation