This extension adds a sidebar to the Nova editor with a couple of Tools to help you make your day better!.


Create your own repository of quick commands to automate tasks in vanilla js. Tasks are not associated to a workspace/project like Nova's tasks, nor are they tied to a build-run cycle, they are simple scripts that you can run as needed or even trigger them when a document is saved.


A notion of projects without projects! Quickly create a named project and associate multiple folders instead of a single folder. Browse the contents of your project right from the same Sidebar.

To create a project simply right click on the Project folder and select "New Project..." from the context menu. Use "Open Project..." to activate the project. Use "Add path to project..." to add a folder(s) to your project. When you select the Project folder you can also use the "Add" button to create a project.

For when your tab bar is out of control (always!) you can also view your Open Tabs and navigate to your open files...

Code Browser

Navigate your code right on the sidebar. Similar to Nova's Symbols you can quickly view your hierarchy of classes and functions. You can add markers to your code and access them from the code browser.

Your source code is parsed using grammar definitions that can easily be modified to accommodate your needs. The first time this extension is used a default grammar is placed in the file ~/Library/Application Support/Nova/Extensions/EXPW.Tools/symbols.js. Open this file to make your modifications and relaunch Nova. The default config includes grammar for JS, PHP, CSS and C.

You can add special markers in your code, for example bookmarks, to-do reminders or even add meta entries.

//MARK: Swift style...
//#MARK My comment here...
//#TODO Review this function

Markers use the syntax of single line comments for the given source code language. For example in css we would use:

/* #MARK My comment here... */


This is an attempt to port my Atom's extensions to Nova. This extension is undergoing a lot of work and may have a lot of rough edges.


This is a vanilla extension and does not require any additional software.

Task Scripts

The sidebar will display a Tasks folder which lists all the tasks that you have created or install.

A task is a vanilla javascript that you can use to automate tasks in Nova.

The sidebar will show a basic set of icons on its tool bar to add, edit and refresh your tools.

Create a Task

Select the Tasks folder and press the "Plus" button to create a new task. This will open a new js document in Nova with the template code of a tool skeleton.

You can also edit the contents of the folder ~/Library/Application Support/Nova/Extensions/EXPW.Tools/tools/ and add your own js file manually.

If you get a tool script from somebody else, check the source code and only install scripts you obtained from a trusted source.

Select the Tasks folder and press the "Refresh" to reload changes made directly in the file system.

Edit a Task

Select a task and press the pencil icon on the sidebar to edit your task. When you save your task the changes are automatically reloaded.

Running a Task

Double click a task to run it.

Anatomy of a task

A task is a vanilla javascript object with some required properties and functions.

The basic structure of a task is:

tool = {
name: "Hello World",

//... we add hooks here

The script must assign the task object to a tool variable.

The following properties are available in the task object:

Key Description
id String, A unique identifier for your tool.
name String, A human readable name for the tool.
tooltip String, A brief description of the tool for humans.
onAction FunctionSignature: function()A hook that will be executed when the user double clicks on the tool or it is executed from a menu.Parameters: none.
onSave FunctionSignature: function(path, textEditor)A hook that will be executed when the user saves a document in Nova.Parameter:path String with the file path.textEditor Instance of TextEditor.

Writing a task script

Basic task is invoked when the user double clicks the entry on the sidebar. This type of task implements the onAction hook.

The onAction hook is a property of our task object whose value is a function. Inside our hook function we write our code.

When automating a task you may optionally implement the onSave hook. This function will be called automatically whenever Nova saves a document. This functions takes two arguments a string with the path of the file and the textEditor with the instance of the TextEditor.

In your code you have access to Nova's API in addition we provide a simple helper with common tasks.


This extension adds some JS objects to help you create quick tasks without having to dive into Nova's API.

The ide object provides a set of functionality to interact with NOVA and the filesystem. This object is available globally in your script.

ide.revealInFinder( aPath )

Reveals the file or folder given in aPath.

ide.readFile( aPath )

Returns a string with the contents of a file given in the absolute path aPath or null if unable to read the file.

ide.isPathOpen(aPath, workspace)

Returns true if the absolute path in aPath is currently open in Nova.


Displays an alert with the given message in the string msg.


The editor object is a helper that simplifies interaction and common tasks related to a TextEditor. This object is available globally in your script.

editor.syntaxString property with the syntax of the editor.
editor.pathString property with the path to the document open or null.
editor.filenameString property with the file name of the document open or null.
editor.directoryString property with the directory of the document open or null.
editor.textEditorThe instance of the active TextEditor.
editor.getSelectedText()Returns the selected text.
editor.insertText(text)Insert the string given in text in the current insertion point. If the editor had a selection it will be replaced.
editor.insertSnippet(text)Insert the string given in text in the current insertion point as a snippet. If the editor had a selection it will be replaced. the text editor contents.


Nova provides a process object that you can use to run shell commands among others.

Alternatively we provide the ide.process(cmd, args) function to simplify executing shell commands.

ide.process(cmd, args) Creates a process in a shell for the command with the arguments in the array args (string array).

The process is an event emitter with the following events:

Event Description
close The close event is emitted after a process has ended and the stdio streams of a child process have been closed. Arguments:code number The exit code if the child exited on its own.
error The error event is emitted whenever an error occurred. Arguments:code number The exit code if the child exited on its own.
data The 'data' event is emitted whenever data from StdOut is available. Arguments:data string.
stderr The stderr event is emitted whenever data from StdErr is available. Arguments:data string.


Method Description Executes the process asynchronously. Returns a promise.
subprocess.kill([signal]) The subprocess.kill() method sends a signal to the child process. If no argument is given, the process will be sent the 'SIGKILL' signal. Available signals are 'SIGINT', 'SIGTERM', or 'SIGHUP'.
subprocess.terminate() Helper method to kill process with a 'SIGTERM' signal.
subprocess.write(inData) Writes the contents of the string given by inData to StdIn.


Method Description
pid Readonly The process PID.
cwd The current working directory. Can be set anytime before you call run(). The default value of cwd is the folder of the active TextEditor or the home folder of the user.
shell If true then /bin/sh is used, else set to a string with the path to the desired shell. Can be set anytime before you call run().
results String. The output of the command received in StdOut.
stdErr String. The output of the command received in StdErr.
exitCode Numeric. The exit code of the child process.

Example 1:

//use async/await to wait for process to run...
onSave: async function(path, textEditor){
    const p = helper.process("ls", ["-la", path]);
    console.log("out=%s", p.results);

Example 2:

onSave: function(path, textEditor){
    console.log("Saving files 2 %s", path);

    const p = helper.process("ls", ["-la", path]);
    p.on("data", (data)=>{
        console.log("my data=%s", data);

    p.on("close", (status)=>{
        console.log("Command done");
        console.log("out=%s", p.results);
//use promise...
onSave: function(path, textEditor){
    const p = helper.process("ls", ["-la", path]);>{
        console.log("out=%s", data);


  1. Use Nova's path object to manipulate paths. For example:
    let filePath = nova.path.join(path1, dirName, "file.js");
  1. To get the active TextEditor:

    //using wrapper
    let textEditor1 = editor.textEditor; 

    //using Nova's API
    let textEditor2 = nova.workspace.activeTextEditor;
    if(!textEditor2) return;


Version 1.2

Major rewrite of internals. Ported more of my Atom's extensions.


Automatically detects tasks created in Gulp, Grunt, Builder configuration files...

Port Builder capabilities, so we can easily build fancier tasks without the need of external tools like Grunt...

Add more languages to the symbol parser.

Allow to change name of project without having to manually edit the projects.js file.

Allow to remove a project without having to manually edit the projects.js file.

Version 1.1

Minor fixes and corrections to readme.

Version 1.0

Initial release