node package manager


Planemo logotype

Planemo [we are working on creating 1.0!]

Planemo is a plugin-friendly open source software quality platform written in JavaScript running on the Node.js platform.

No seriously, what is it?

Planemo is basically a static code analysis tool written for the Node.js platform. Its main goal is to read everything in given directory (and recursively downwards) and checks any found file (no matter if its its .js, .css, .html or whatever) and its contents against a set of rules, configurable by the user.

The whole idea is that Planemo should help your project to maintain coding conventions, best practices and other fun rules your software project might have, for any source code file or language.

Currently it has a lot of available built in plugins to choose from, but it also super easy to write your own plugin and even contribute it back to the project.

Fun fact #184: The word Planemo comes from planetary-mass object!

Table of Contents

  • How the versioning works
  • Continuous build status
  • Downloading and running Planemo
    • Via npm (preferred way for end users)
    • Via git clone (preferred way for plugin developers)
    • Download as a ZIP file (preferred way for people who really like ZIP files)
  • The configuration file
  • Available plugins
  • Writing your own plugin
  • Running the testsplugins
  • Writing tests
  • Found a bug or have a questions?
  • Plugin and Data Collector hooks
  • Major changes
  • Contributors
  • License

How the versioning works

Two things you need to know:

  • The code on GitHub should be regarded as unstable builds. We don't have any restrictions when and how things can be checked in there (within common sense though).
  • The project on npm should be regarded as the stable builds. We will only publish a new version to npm once we feel Planemo is stable and has any new end user value.

Continuous build status

Planemo is continuously built by You can find the build history here.

Build Status

Downloading and running Planemo

Planemo runs on Node.js, so make sure you have that installed. If you want to contribute you need to have Git installed as well.

Via npm (preferred way for end users)

Since Planemo is published on npm, you maybe simply type npm install planemo. This should download Planemo and all its dependencies.

To start Planemo you may simply type cd node_modules/planemo/ && node planemo <configuration file>.

Via git clone (preferred way for plugin developers)

You can clone the Git project directly by typing git clone

After it you need to install the Node.js dependencies with npm install.

Now you should be able to start Planemo using a configuration file by using the command node planemo <configuration file>

Download as a ZIP file (preferred way for people who really like ZIP files)

On the Planemo GitHub page there is a button on the page with the text "Download ZIP".

After it you need to install the Node.js dependencies with npm install.

Now you should be able to start Planemo using a configuration file by using the command node planemo <configuration file>

The configuration file

In order to launch Planemo you need to specify a JSON formatted configuration file as the first argument. The best way to describe it is to look at a sample file, and then look at the property explanations below to better understand what and how the different parts works.

01		"source": {
			"root": "C:\\project\\src\\"
05		"verbose": false,
06		"plugins": {
07			"check-directory-name-plugin": {
08				"regexp": "^[a-z]+$"
07			"check-file-name-plugin": {
08				"regexp": "^[a-z|-]+\\.(?:js|html|css|less)$"

Row explanations:

  • 01: The source property is required to specify the starting directory which Planemo will start analyzing files in.
  • 05: Verbose setting, meaning if you want Planemo to be verbose or not. Valid options are true or false. If you are using plugins that should show warnings instead of errors, having verbose to false is recommended.
  • 06: Here the user can define a list of plugins that should be invoked during the code analysis
  • 07: The plugin name which should be used during the analysis is specified as a property
  • 08: The the value of the property is the options that should be sent to the plugin

Available plugins

You can enable what plugins you want Planemo to run by defining them in your configuration file.

Below is a list of all the current available plugins, a brief description of their individual options and an example.


Checks a directory name.

  • pattern - A regular expression pattern which the directory name must comply with.


"check-directory-name-plugin": {
    "pattern": "^[a-z]+$"


Checks a file name.

  • pattern - A regular expression pattern which the file name name must comply with.


"check-file-name-plugin": {
	"pattern": "^[a-z|-]+\\.(?:js|html|css|less)$"


Checks the contents of a LESS file.

  • disallow - An array of strings which must not occur in a found LESS file.


"check-file-contents-less-plugin": {


Checks the conents of a JavaScript file.

  • disallow - An array of regular expression that must not occur in a found JavaScript file.
  • mustcontain - An array of regular expressions that has to occur in a found JavaScript file.


"check-file-contents-javascript-plugin": {
			"@owner \\w+ \\w+ \\(\\w{3}\\)"


Checks the properties and values of a HTML-file.

  • disallowPropertiesStartingWith - An array of Strings that properties should not start with
  • disallowValuesStartingWith - An object structure where the property is a regular expression of an HTML-property, and the value is the HTML-value should not start in a specific way.


"check-html-properties-and-values-plugin": {
	"disallowValuesStartingWith": {
		"-translation$": "^MyApplication\\."

Writing your own plugin

Writing new plugins to Planemo is fairly easy. A plugin is a stand alone file that is located in the /plugins/ folder.

To get a better understanding of how a simple plugin looks like, lets look at an existing one. The check-directory-name-plugin.js plugin that has the responsibility to validate directory names:

01	/*
02	 * Licensed under the Apache License, Version 2.0 (the "License");
03	 * you may not use this file except in compliance with the License.
04	 * You may obtain a copy of the License at
05	 *
06	 *
07	 *
08	 * Unless required by applicable law or agreed to in writing, software
09	 * distributed under the License is distributed on an "AS IS" BASIS,
10	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11	 * See the License for the specific language governing permissions and
12	 * limitations under the License.
13	 *
14	 * See the NOTICE file distributed with this work for additional
15	 * information regarding copyright ownership.
16	 */
18	/*
19	 * Dependencies
20	 */
22	var observerService = require( "../services/observer-service.js" );
23	var errorUtil = require( "../utils/error-util.js" );
25	/*
26	 * Public functions
27	 */
29	exports.init = function ( options ) {
31		observerService.onDirectoryFound( function checkDirectoryNameOnDirectoryFound ( basePath, fullPath, directoryName, responseFunction ) {
32			exports.onDirectoryFound( options, basePath, fullPath, directoryName, responseFunction );
33		} );
35	};
37	exports.onDirectoryFound = function onDirectoryFound ( options, basePath, fullPath, directoryName, responseFunction ) {
39		if ( !options ) {
40			throw errorUtil.create( "No options were defined." );
41		}
43		if ( !options.regexp ) {
44			throw errorUtil.create( "Invalid regexp option." );
45		}
47		if ( !options.regexp ) {
48			throw errorUtil.create( "Invalid regexp option." );
49		}
51		var pattern = new RegExp( options.regexp );
53		var isLegalFilename = pattern.test( directoryName );
55		if ( !isLegalFilename ) {
57	    	responseFunction( errorUtil.create( "The directory name \"" + directoryName + "\" is not valid.", {
58				basePath: basePath,
59				fullPath: fullPath,
60				directoryName: directoryName
61			} ) );
63		}
65	}

Row explanations:

  • 01 - 16: This is the Apache 2.0 license information all source files needs to embed.
  • 22 - 23: Module dependencies are declared here
  • 29: Each Plugin needs to have a public exports.init function. The argument to the function will be the options the user has specified in the configuration file. The Plugin developer can come up with any (or no) options as they like. However, all options should be properly documented for other Planemo end users.
  • 31: In this plugin we simply hook into a new function once a new directory found is found. A plugin can hook function into a wide range of hooks. In this plugin we are only interested in the onDirectoryFound hook.
  • 37: This is the primary function that will be called each time Planemo finds a directory. Since we did a fancy closure hook on row 32, we now get both the user options (options) and the hook information details ( basePath, fullPath, directoryName) and a specific callback function (responseFunction) to our function. The reason why this function is public (meaning its declared on the export object like export.onDirectoryFound =) is because we want to be able to unit test it later.
  • 39-45: Basic validation to make sure that the options are as we expect them to be.
  • 57: Since the plugin's responsibility is to check a directory name towards a regular expression, we also need to be able tell Planemo that this plugin has found a problem. This is simply done returning an Error as the first argument of the responseFunction.

Plugin and Data Collector hooks

Not yet written.

Running the tests

You can execute the tests by running npm test if you are running from a Windows Command Prompt or run_tests.bat is you are using a Shell, such as Git Bash.

Writing tests

For obvious reasons, the more tests we have for Planemo the happier we are. So it is encouraged that we write supporting unit tests for our code.

Planemo is currently using Mocha and Chai as a part of its test framework. If you are planning to write tests it would be a good idea to look at their individual examples and documentation to better understand how to write new or maintain old tests. If you looking for examples you can find them in the /tests/ folder in this project.

Found a bug or have a questions?

If you have found a bug and want to report it, or have any other feedback or questions, you can simply create an issue.

Major changes

Not yet written.



  • Planemo licensed under the Apache License, Version 2.0. See the NOTICE file distributed with this work for additional information regarding copyright ownership.
  • Planemo logotype images Copyright (C) Christoffer Pettersson, christoffer[at]christoffer[dot]me. All Rights Reserved! Please contact Christoffer regarding the possible use of these images.