In this first post of this new blog, I’m going to show you how to add your own custom commands to the meteor command line tool, and how to publish them for the benefit of the meteor community. Once we’ve covered that, you will be able to create your own release of the meteor command line tool, with your commands, that people can use by running:

meteor --release practicalmeteor:METEOR@0.9.3.1 YourCommand

Overview

Meteor introduced a new command in version 0.9.3, called publish-release. It allows you to create your own “track” of meteor, which is basically your own releases of meteor that others can use. The steps involved in adding your own custom commands to the meteor command line tool and publishing them are:

  1. Customizing the meteor command line tool from a checkout and publishing your customizations as a meteor-tool package to the meteor packaging server.

  2. Create a new meteor track referencing your custom meteor-tool package using meteor publish-release.

Let’s go through the steps of creating a new meteor command called ‘awesome’, which will not do anything special, other than just tell you how awesome you are.

If you don’t yet have a meteor developer account, get one now.

Checking out meteor

Let’s use the latest official release of meteor at the time of this writing, 0.9.3.1, as a base for our release:


git clone https://github.com/meteor/meteor.git cd meteor git checkout release/METEOR@0.9.3.1 # Let's create a new branch not only for our awesome command, but for our entire release track, which we can later on merge new meteor releases into. Replace practicalmeteor with your meteor developer account name. git checkout -b practicalmeteor # Now let's create a branch of it for our new awesome command. git checkout -b awesome

Let’s add the checked out meteor to our path before our installed meteor:


export PATH=$PWD:$PATH # Let's verify this which meteor

Adding the awesome command

The meteor command line tool is a plain node.js program. In the checked out repo, to add our awesome command to meteor, edit tools/commands.js and append the following to the end of the file:


main.registerCommand({ name: 'awesome', maxArgs: 0, options: { name: { type: String, short: "n", default: "whoever you are" } } }, function (options) { try { Console.stdout.write('You are awesome, ' + options.name + '!'); } catch (err) { Console.stderr.write(err.message); return 1; } });

Let’s verify it works:


# The first time you run meteor from a checkout will take some time, since meteor needs to download it's stuff meteor awesome

And now, just to feel good about yourself, run it with -n YourName:


meteor awesome -n YourName

Publishing your modified command line tool as a meteor package

Now that you feel so good about yourself, why don’t you let others feel good about themselves too. Meteor treats it’s command line tool as a package as well, called meteor-tool, which you can modify and publish as your own YourAccount:meteor-tool package to the package server. Let’s do that. Edit the file packages/meteor-tool/package.js and modify Package.describe as follows (replace practicalmeteor with your meteor developer account):


Package.describe({ name: 'practicalmeteor:meteor-tool', summary: "The Meteor command-line tool with extended awesomeness", version: '1.0.33_1' });

We have added a name to the package, so we can publish it under our own meteor developer account. We have also appended _1 to the end of the package version. This utilizes the new “wrapper package” version format, introduced in meteor 0.9.3. It will help you and everybody else know which meteor_tool version you are working of as well as let you increment the package version to _2, _3 etc. every time you publish a new version of the modified meteor command line tool for the same meteor-tool package version.

Note the Package.includeTool(); line in package.js. This tells meteor to add the entire pure node.js meteor command line program source code to the package.

Let’s publish the package:


cd packages/meteor_tool meteor login # This will take a bit... meteor publish --create

You will get a warning stating that you will need to use publish-for-arch to support architectures other than the one you are publishing from. So, if you plan to support more than one architecture, you will need to publish the package using publish-from-arch from each one.

Goto Atmosphere and verify that your package has actually been published.

Publishing your own meteor release with your modified command line tool package

meteor publish-release accepts a json file as an argument, which includes details about your release, including the modified packages it includes. Create the following release.json file, replacing practicalmeteor with your meteor developer account:


{ "track": "practicalmeteor:METEOR", "version": "0.9.3.1-rc0", "recommended": false, "tool": "practicalmeteor:meteor-tool@1.0.33_1", "description": "meteor with extended awesomeness", "packages": { } }

The tool key is where you specify the command line tool package for this release, which in this case, is the one you just published. The release version is the same as the meteor one we are working of, with -rc0 appended, signifying it’s our first release candidate of our meteor command line tool release. Since it’s a release candidate, we also set recommend to false. In a future post I will explain more about the format of the json file.

Let’s publish the release:

# Since it's the first time we publish our release track, we need to use --create-track
meteor publish-release --create-track release.json

Testing it all works

Logout and log back in so you can go back to using the installed version of meteor and not the checked out one we added to the PATH, and then run the following, replacing practicalmeteor with your meteor developer account:


# This will take some time, since meteor will download and install the new release in your home folder. meteor --release practicalmeteor:METEOR@0.9.3.1-rc0 awesome

That’s it! Pretty awesome, wasn’t it?

Don’t forget to commit and merge your changes to your release track branch.

Notes & Resources

  • For now, due to a bug, you cannot add new files to the meteor tools folder, since it will not be picked up when you publish your meteor-tool package. The workaround is to just modify existing files.

  • For more info about publish-release, I recommend you read the source code.

  • IMPORTANT: Don’t update your meteor app to your track release using meteor --release ... update. To create a track release based on a complete official meteor release, not just the command line tool, you will need to specify the package versions for all the meteor core packages in the release.json, which, it seems for now, there is no easy way to do it. I expect this to become more streamlined soon. A workaround, that I haven’t thoroughly checked (so no guaranties it will work), is to do the following every time a new release of meteor is published:

  1. Update your meteor app to the latest release of meteor.
  2. Run it
  3. Create a new track release for your commands based on the new meteor release.
  4. Update your app to your new track release using meteor --release practicalmeteor:METEOR@0.9.3.1 update.

This way, you will be able to use your commands without --release practicalmeteor:METEOR@0.9.3.1. Note that the first 2 steps should update all the packages in your app and the packages they depend on to the latest meteor release versions, whenever possible.

Possible Applications

  • Creating your own versions of meteor with modifications and extensions to other core packages, not just the meteor-tool package. More about that in a future post.

  • Adding a jslint or coffeelint or just lint command to meteor.

  • Customizing the package build process to make it more flexible, with build time options, as suggested by Andrew Mao here.

  • The meteor community velocity team, which I am part of, is trying to create a one size fits all tool for all your meteor app and package testing needs, including running your unit and functional tests in both dev and ci environments. For now, it uses a separate code base, duplicating a lot of the functionality that is already part of the meteor command line tool, to start a separate meteor mirror app with unit tests from the tests folder in your app included. It would be nice to build upon the meteor code base to create a test-app command that works similar to test-packages, i.e. creating another meteor app on the fly, just for testing purposes, with hot-code reloads.

  • And many more. With meteor, the sky is the limit…