diff --git a/lib/cli.js b/lib/cli.js
index b659650..21a8891 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -48,13 +48,24 @@ function CLI() {
             {name: 'version', type: 'bool', help: 'Print version and exit.'},
             {names: ['verbose', 'v'], type: 'bool',
                 help: 'Verbose/debug output.'},
-            {names: ['profile', 'p'], type: 'string', env: 'SMRT_PROFILE',
-                helpArg: 'NAME', help: 'SMRT Profile to use.'}
+            // XXX disable profile selection for now
+            //{names: ['profile', 'p'], type: 'string', env: 'TRITON_PROFILE',
+            //    helpArg: 'NAME', help: 'Triton client profile to use.'}
         ],
         helpOpts: {
             includeEnv: true,
             minHelpCol: 23 /* line up with option help */
-        }
+        },
+        helpSubcmds: [
+            'help',
+            { group: 'VMs/Machines/Containers' },
+            'create',
+            'vms',
+            'vm-audit',
+            { group: 'Images' },
+            'images',
+            { group: 'Other', unmatched: true }
+        ]
     });
 }
 util.inherits(CLI, Cmdln);
@@ -84,240 +95,21 @@ CLI.prototype.init = function (opts, args, callback) {
     Cmdln.prototype.init.apply(this, arguments);
 };
 
-CLI.prototype.do_foo = function do_foo(subcmd, opts, args, callback) {
-    console.log('XXX', subcmd, opts, args);
-
-    this.triton.cloudapi.getAccount(function (err, body, res) {
-       console.log('XXX getAccount', err);
-       console.log('XXX getAccount', body);
-        callback();
-    });
-};
 
 
+//CLI.prototype.do_profile = require('./do_profile');
 
-CLI.prototype.do_profile = require('./do_profile');
+// Images
 CLI.prototype.do_images = require('./do_images');
 
-
-
-CLI.prototype.do_provision = function (subcmd, opts, args, callback) {
-    if (opts.help) {
-        this.do_help('help', {}, [subcmd], callback);
-        return;
-    } else if (args.length > 1) {
-        return callback(new Error('too many args: ' + args));
-    }
-    var sdc = this.sdc;
-
-    assert.string(opts.image, '--image 
');
-    assert.string(opts['package'], '--package ');
-    assert.number(opts.count)
-
-    // XXX
-    /*
-     * Should all this move into sdc.createMachine? yes
-     *
-     * - lookup image, package, networks from args
-     * - assign names
-     * - start provisions (slight stagger, max N at a time)
-     * - return immediately, or '-w|--wait'
-     */
-    async.series([
-        function lookups(next) {
-            async.parallel([
-                //XXX
-                //sdc.lookup(image)
-            ])
-        },
-        function provisions(next) {
-
-        },
-        function wait(next) {
-            next();
-        }
-    ], function (err) {
-        callback(err);
-    });
-};
-CLI.prototype.do_provision.options = [
-    {
-        names: ['help', 'h'],
-        type: 'bool',
-        help: 'Show this help.'
-    },
-    {
-        names: ['dc', 'd'],
-        type: 'string',
-        helpArg: '',
-        help: 'The datacenter in which to provision. Required if the current'
-            + ' profile includes more than one datacenter. Use `sdc profile`'
-            + ' to list profiles and `sdc dcs` to list available datacenters.'
-    },
-    {
-        names: ['image', 'i'],
-        type: 'string',
-        helpArg: '
',
-        help: 'The machine image with which to provision. Required.'
-    },
-    {
-        names: ['package', 'p'],
-        type: 'string',
-        helpArg: '',
-        help: 'The package or instance type for the new machine(s). Required.'
-    },
-    {
-        names: ['name', 'n'],
-        type: 'string',
-        helpArg: '',
-        help: 'A name for the machine. If not specified, a short random name'
-            + ' will be generated.',
-        // TODO: for count>1 support '%d' code in name: foo0, foo1, ...
-    },
-    {
-        names: ['count', 'c'],
-        type: 'positiveInteger',
-        'default': 1,
-        helpArg: '',
-        help: 'The number of machines to provision. Default is 1.'
-    },
-];
-CLI.prototype.do_provision.help = (
-    'Provision a new virtual machine instance.\n'
-    + 'Alias: create-machine.\n'
-    + '\n'
-    + 'Usage:\n'
-    + '     {{name}} provision \n'
-    + '\n'
-    + '{{options}}'
-);
-
-
-CLI.prototype.do_machines = function (subcmd, opts, args, callback) {
-    var self = this;
-    if (opts.help) {
-        this.do_help('help', {}, [subcmd], callback);
-        return;
-    } else if (args.length > 1) {
-        return callback(new Error('too many args: ' + args));
-    }
-
-    var machines = [];
-    var errs = [];
-    var res = this.sdc.listMachines();
-    res.on('data', function (dc, dcMachines) {
-        for (var i = 0; i < dcMachines.length; i++) {
-            dcMachines[i].dc = dc;
-            machines.push(dcMachines[i]);
-        }
-    });
-    res.on('dcError', function (dc, dcErr) {
-        dcErr.dc = dc;
-        errs.push(dcErr);
-    });
-    res.on('end', function () {
-        if (opts.json) {
-            p(JSON.stringify(machines, null, 4));
-        } else {
-            /* BEGIN JSSTYLED */
-            // TODO: get short output down to something like
-            //  'us-west-1  e91897cf  testforyunong2  linux  running       2013-11-08'
-            //  'us-west-1  e91897cf  testforyunong2  ubuntu/13.3.0  running       2013-11-08'
-            /* END JSSTYLED */
-            common.tabulate(machines, {
-                columns: 'dc,id,name,image,state,created',
-                sort: 'created',
-                validFields: 'dc,id,name,type,state,image,package,memory,'
-                    + 'disk,created,updated,compute_node,primaryIp'
-            });
-        }
-        var err;
-        if (errs.length === 1) {
-            err = errs[0];
-        } else if (errs.length > 1) {
-            err = new errors.MultiError(errs);
-        }
-        callback(err);
-    });
-};
-CLI.prototype.do_machines.options = [
-    {
-        names: ['help', 'h'],
-        type: 'bool',
-        help: 'Show this help.'
-    },
-    {
-        names: ['json', 'j'],
-        type: 'bool',
-        help: 'JSON output.'
-    }
-];
-CLI.prototype.do_machines.help = (
-    'List machines.\n'
-    + '\n'
-    + 'Usage:\n'
-    + '     {{name}} machines [...]\n'
-    + '\n'
-    + '{{options}}'
-);
+// VMs/Containers/Machines
+CLI.prototype.do_create = require('./do_create');
+CLI.prototype.do_vms = require('./do_vms');
+CLI.prototype.do_vm_audit = require('./do_vm_audit');
 
 
 
-CLI.prototype.do_machine_audit = function (subcmd, opts, args, callback) {
-    var self = this;
-    if (opts.help) {
-        this.do_help('help', {}, [subcmd], callback);
-        return;
-    } else if (args.length > 1) {
-        //XXX Support multiple machines.
-        return callback(new Error('too many args: ' + args));
-    }
 
-    var id = args[0];
-    this.sdc.machineAudit({machine: id}, function (err, audit, dc) {
-        if (err) {
-            return callback(err);
-        }
-        for (var i = 0; i < audit.length; i++) {
-            audit[i].dc = dc;
-        }
-        if (opts.json) {
-            p(JSON.stringify(audit, null, 4));
-        } else {
-            return callback(new error.InternalError("tabular output for audit NYI")); // XXX
-            //common.tabulate(audit, {
-            //    columns: 'dc,id,name,state,created',
-            //    sort: 'created',
-            //    validFields: 'dc,id,name,type,state,image,package,memory,'
-            //        + 'disk,created,updated,compute_node,primaryIp'
-            //});
-        }
-        callback();
-    });
-};
-CLI.prototype.do_machine_audit.options = [
-    {
-        names: ['help', 'h'],
-        type: 'bool',
-        help: 'Show this help.'
-    },
-    {
-        names: ['json', 'j'],
-        type: 'bool',
-        help: 'JSON output.'
-    }
-];
-CLI.prototype.do_machine_audit.help = (
-    'List machine actions.\n'
-    + '\n'
-    + 'Note: On the *client*-side, this adds the "dc" attribute to each\n'
-    + 'audit record.\n'
-    + '\n'
-    + 'Usage:\n'
-    + '     {{name}} machine-audit \n'
-    + '\n'
-    + '{{options}}'
-);
 
 
 //---- mainline
diff --git a/lib/do_create.js b/lib/do_create.js
new file mode 100644
index 0000000..e8b842d
--- /dev/null
+++ b/lib/do_create.js
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015 Joyent Inc. All rights reserved.
+ *
+ * `triton images ...`
+ */
+
+var format = require('util').format;
+var tabula = require('tabula');
+
+var errors = require('./errors');
+
+
+function do_create(subcmd, opts, args, callback) {
+    if (opts.help) {
+        this.do_help('help', {}, [subcmd], callback);
+        return;
+    } else if (args.length > 1) {
+        return callback(new Error('too many args: ' + args));
+    }
+    var triton = this.triton;
+
+    // XXX The smarts here should move to Triton class.
+
+    assert.string(opts.image, '--image 
');
+    assert.string(opts['package'], '--package ');
+    assert.number(opts.count)
+
+    // XXX
+    /*
+     * Should all this move into sdc.createMachine? yes
+     *
+     * - lookup image, package, networks from args
+     * - assign names
+     * - start provisions (slight stagger, max N at a time)
+     * - return immediately, or '-w|--wait'
+     */
+    async.series([
+        function lookups(next) {
+            async.parallel([
+                //XXX
+                //sdc.lookup(image)
+            ])
+        },
+        function provisions(next) {
+
+        },
+        function wait(next) {
+            next();
+        }
+    ], function (err) {
+        callback(err);
+    });
+};
+do_create.options = [
+    {
+        names: ['help', 'h'],
+        type: 'bool',
+        help: 'Show this help.'
+    },
+    {
+        names: ['dc', 'd'],
+        type: 'string',
+        helpArg: '',
+        help: 'The datacenter in which to provision. Required if the current'
+            + ' profile includes more than one datacenter. Use `sdc profile`'
+            + ' to list profiles and `sdc dcs` to list available datacenters.'
+    },
+    {
+        names: ['image', 'i'],
+        type: 'string',
+        helpArg: '
',
+        help: 'The machine image with which to provision. Required.'
+    },
+    {
+        names: ['package', 'p'],
+        type: 'string',
+        helpArg: '',
+        help: 'The package or instance type for the new machine(s). Required.'
+    },
+    {
+        names: ['name', 'n'],
+        type: 'string',
+        helpArg: '',
+        help: 'A name for the machine. If not specified, a short random name'
+            + ' will be generated.',
+        // TODO: for count>1 support '%d' code in name: foo0, foo1, ...
+    },
+    {
+        names: ['count', 'c'],
+        type: 'positiveInteger',
+        'default': 1,
+        helpArg: '',
+        help: 'The number of machines to provision. Default is 1.'
+    },
+];
+do_create.help = (
+    'Create a new VM/container/machine.\n'
+    + '\n'
+    + 'Usage:\n'
+    + '     {{name}} provision \n'
+    + '\n'
+    + '{{options}}'
+);
+do_create.aliases = ['create-vm'];
+
+module.exports = do_create;
\ No newline at end of file
diff --git a/lib/do_vm_audit.js b/lib/do_vm_audit.js
new file mode 100644
index 0000000..ec5d62b
--- /dev/null
+++ b/lib/do_vm_audit.js
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 Joyent Inc. All rights reserved.
+ *
+ * `triton vms ...`
+ */
+
+var format = require('util').format;
+var tabula = require('tabula');
+
+var errors = require('./errors');
+
+
+do_vm_audit = function do_vm_audit(subcmd, opts, args, callback) {
+    var self = this;
+    if (opts.help) {
+        this.do_help('help', {}, [subcmd], callback);
+        return;
+    } else if (args.length > 1) {
+        //XXX Support multiple machines.
+        return callback(new Error('too many args: ' + args));
+    }
+
+    var id = args[0];
+    this.sdc.machineAudit({machine: id}, function (err, audit, dc) {
+        if (err) {
+            return callback(err);
+        }
+        for (var i = 0; i < audit.length; i++) {
+            audit[i].dc = dc;
+        }
+        if (opts.json) {
+            p(JSON.stringify(audit, null, 4));
+        } else {
+            return callback(new error.InternalError("tabular output for audit NYI")); // XXX
+            //common.tabulate(audit, {
+            //    columns: 'dc,id,name,state,created',
+            //    sort: 'created',
+            //    validFields: 'dc,id,name,type,state,image,package,memory,'
+            //        + 'disk,created,updated,compute_node,primaryIp'
+            //});
+        }
+        callback();
+    });
+};
+do_vm_audit.options = [
+    {
+        names: ['help', 'h'],
+        type: 'bool',
+        help: 'Show this help.'
+    },
+    {
+        names: ['json', 'j'],
+        type: 'bool',
+        help: 'JSON output.'
+    }
+];
+do_vm_audit.help = (
+    'List instance actions.\n'
+    + '\n'
+    + 'Usage:\n'
+    + '     {{name}} vm-audit \n'
+    + '\n'
+    + '{{options}}'
+);
+
+
+
+module.exports = do_vm_audit;
\ No newline at end of file
diff --git a/lib/do_vms.js b/lib/do_vms.js
new file mode 100644
index 0000000..e6ab786
--- /dev/null
+++ b/lib/do_vms.js
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015 Joyent Inc. All rights reserved.
+ *
+ * `triton vms ...`
+ */
+
+var format = require('util').format;
+var tabula = require('tabula');
+
+var errors = require('./errors');
+
+
+do_vms = function do_vms(subcmd, opts, args, callback) {
+    var self = this;
+    if (opts.help) {
+        this.do_help('help', {}, [subcmd], callback);
+        return;
+    } else if (args.length > 1) {
+        return callback(new Error('too many args: ' + args));
+    }
+
+    var machines = [];
+    var errs = [];
+    var res = this.sdc.listMachines();
+    res.on('data', function (dc, dcMachines) {
+        for (var i = 0; i < dcMachines.length; i++) {
+            dcMachines[i].dc = dc;
+            machines.push(dcMachines[i]);
+        }
+    });
+    res.on('dcError', function (dc, dcErr) {
+        dcErr.dc = dc;
+        errs.push(dcErr);
+    });
+    res.on('end', function () {
+        if (opts.json) {
+            p(JSON.stringify(machines, null, 4));
+        } else {
+            /* BEGIN JSSTYLED */
+            // TODO: get short output down to something like
+            //  'us-west-1  e91897cf  testforyunong2  linux  running       2013-11-08'
+            //  'us-west-1  e91897cf  testforyunong2  ubuntu/13.3.0  running       2013-11-08'
+            /* END JSSTYLED */
+            common.tabulate(machines, {
+                columns: 'dc,id,name,image,state,created',
+                sort: 'created',
+                validFields: 'dc,id,name,type,state,image,package,memory,'
+                    + 'disk,created,updated,compute_node,primaryIp'
+            });
+        }
+        var err;
+        if (errs.length === 1) {
+            err = errs[0];
+        } else if (errs.length > 1) {
+            err = new errors.MultiError(errs);
+        }
+        callback(err);
+    });
+};
+do_vms.options = [
+    {
+        names: ['help', 'h'],
+        type: 'bool',
+        help: 'Show this help.'
+    },
+    {
+        names: ['json', 'j'],
+        type: 'bool',
+        help: 'JSON output.'
+    }
+];
+do_vms.help = (
+    'List VMs/machines/containers.\n'
+    + '\n'
+    + 'Usage:\n'
+    + '     {{name}} vms [...]\n'
+    + '\n'
+    + '{{options}}'
+);
+
+
+module.exports = do_vms;
\ No newline at end of file