Extending Muse

Custom Tool APIs are interface specifications about program arguments, standard input and standard output formats a tool must support in order to interoperate with Muse. The configuration reference presents how to configure your repository so that each analysis will invoke such a tool.

Execution Environment

Each tool runs in an Ubuntu 20.04 environment specifically for analysis of either the source or destination branches of a pull request. Shell scripts are used in examples below because they are a common platform supported, but there is no requirement to use shell scripts. More complex tools might benefit from a shell wrapper that verifies the environment before invoking the analysis tool.

After running a tool on both the source and destination branches, issues discovered by the tool are categorized into those that are introduced (appearing only in the source branch), fixed (appearing only in the destination branch), and preexisting (appearing in both branches). Only introduced issues are propagated to the user by way of a pull request comment.

For each issue discovered by a tool it should emit a tool note specifying the type of the issue, a detailed message, and location including file and line.

The Android SDK will be available on the file system accessible under $ANDROID_HOME.


BYO tools are called with arguments of a repository directory, commit hash, and a command. In addition, they must output a JSON value specific to the command. These tools is called once on the whole repository and are expected to analyze every relevant file in the repository.

API Commands

The command and their associated standard outputs are:

  • version: Always print the number 1 on standards out and return with exit success (zero).
  • applicable: Perform any needed analysis of the repository to determine if this tool is applicable (ex: a tool might only be applicable to particular lanugages). Print the string true or false to standard out dependingly and return with exit success.
  • run: Evaluate the repository and emit JSON results, detailed below.

The run command must emit JSON of:

[ { "type"    : <string>,
    "message" : <string>,
    "file"    : <string>,
    "line"    : <int>,

The tool is always passed arguments of repository directory, branch of interest, and command. An example of running the three commands is:

$ ./tool.sh /muse/code/path ce44de9a version
$ ./tool.sh /muse/code/path ce44de9a applicable
$ ./tool.sh /muse/code/path ce44de9a run
[{"type" : "Invalid configuration keyword",
  "message": "The keyword 'customTols' is not a valid configuration value.",
  "file": "configs/config.toml",
  "line": 12
 {"type" : "Invalid configuration keyword",
  "message": "The keyword 'riika' is not a valid configuration value.",
  "file": "configs/config.toml",
  "line": 11

The tool must always exits successfully, returning exitcode 0.

BYO API Hello World

Let’s make a hello-world example of a Muse custom tool at work. We’ll use a shell script to case over the commands and take appropriate action. As a framework lets start with:

#!/usr/bin/env bash
# dir=$1 but it is not needed

# ... to be filled in ...

if [[ "$cmd" = "run" ]] ; then
if [[ "$cmd" = "applicable" ]] ; then
if [[ "$cmd" = "version" ]] ; then

Now we’ll fill in functions for each command. The version command is the simplest as there is no decision needing made. Just echo 1 out:

function version() {
    echo 1

For applicability let’s always run - this tool isn’t specific to configuration files, languages, times of day, or any other variable.

function applicable() {
    echo "true"

Before tackling run, recall that Muse runs on both the source and destination branches before classifying the bugs as introduced/fixed/prexisting. Only introduced bugs are sent as comments. Therefore we need to do something branch specific and not just emit a tool note saying “hello world”. Our hello world tool will emit issues including the commit hash:

function run() {
    echo "[{ \"type\": \"Hello World\", \
            \"message\": \"We are analyzing commit $commit\", \
            \"file\": \"N/A\", \
            \"line\": 0 \