{"__v":115,"_id":"551c456223a1ee190034d19b","category":{"__v":2,"_id":"551c453a23a1ee190034d19a","pages":["551c456223a1ee190034d19b","551c45a448564a2f0024d7ed"],"project":"54d53c7b23010a0d001aca0c","version":"54d5635532d98b0d00384afb","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-04-01T19:21:30.273Z","from_sync":false,"order":12,"slug":"installer","title":"Installer"},"parentDoc":null,"project":"54d53c7b23010a0d001aca0c","user":"54cfa8e1a8a4fd0d00b7fd1d","version":{"__v":10,"_id":"54d5635532d98b0d00384afb","forked_from":"54d53c7c23010a0d001aca0f","project":"54d53c7b23010a0d001aca0c","createdAt":"2015-02-07T00:59:01.934Z","releaseDate":"2015-02-07T00:59:01.934Z","categories":["54d5635632d98b0d00384afc","54d5635632d98b0d00384afd","54d5635632d98b0d00384afe","54d5635632d98b0d00384aff","54d5635632d98b0d00384b00","54d5635632d98b0d00384b01","54d5635632d98b0d00384b02","54d652097e05890d006f153e","54dd1315ca1e5219007e9daa","54e21e2b22de1c230094b147","54e68e62a43fe13500db3879","54fa1d3fe7a0ba2f00306309","551c453a23a1ee190034d19a","551df586e52a0b23000c62b6","551f39be6886f8230055f02a","55a6720751457325000e4d97"],"is_deprecated":false,"is_hidden":false,"is_beta":true,"is_stable":true,"codename":"","version_clean":"0.1.0","version":"0.1"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2015-04-01T19:22:10.518Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":0,"body":"The *Cloud9 Installer* installs dependencies for plugins into the user's workspace. This can be npm modules apt-get or yum packages, tar.gz files that are downloaded et cetera. An installer for your package is a simple .js file that defines the steps that the installer needs to take to install the dependencies. This guide will walk you through the steps for creating your own installer.\n\nThe screenshot below is of the Cloud9 installer running the main Cloud9 install script, which is used when Cloud9 is connected to a workspace that is not hosted on c9.io, such as SSH workspaces or your own local machine or server.\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/KWgZVuvTmGC5v6liKMxa_2015-04-01_1255.png\",\n        \"2015-04-01_1255.png\",\n        \"1570\",\n        \"848\",\n        \"#7b7b7b\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n# Use cases\n\nYou *should* create an install script when your plugin depends on additional packages that should be installed in the user's workspace. For instance when you are creating a language plugin that uses a server side analyzer, create an install script that installs that analyzer when your plugin gets installed.\n\nAnother use case is when you want to configure a workspace to be ready for your framework, library or sdk. Simply create an installer that installs all the components needed by your plugin.\n\n# Scaffolding\n\nThe basic scaffolding of your installer is the typical AMD module wrapper containing a function that takes a `session` and `options` argument. It is common practice to call this file `install.js` and put it in the root dir of your package.\n\n```\ndefine(function(require, exports, module) {\n    \nmodule.exports = function(session, options){\n    \n};\n\n// version of the installer. Increase this when installer changes and must run again\nmodule.exports.version = 1; \n\n});\n```\n\nThe `session` argument is an installer session. More about this below. The `options` contain two properties.\n[block:html]\n{\n  \"html\": \"<table>\\n  <tr><th>platform</th><td>The platform of the workspace. Valid options are 'darwin', 'freebsd', 'linux', 'sunos' or 'win32'</tr></tr>\\n  <tr><th>arch</th><td>The architecture of the workspace. Valid options are 'arm', 'ia32', or 'x64'</tr></tr>\\n</table>\"\n}\n[/block]\n## Package.json\n\nAdd your `install.js` script to the package.json file in your package folder to enable the installer. The `installer` field expects an object with a `version` field and a `main` field. The `main` field is relative to the package root. The `version` field is the version of your plugin when install.js was updated last.\n\n```\n{\n    \"name\": \"yourplugin\",\n    \"version\": \"1.0.0\",\n    \n    \"installer\": \"install.js\",\n    \n    \"plugins\": {\n        \"yourplugin\": {}\n    }\n}\n```\n\nFor more information see [this guide](http://cloud9-sdk.readme.io/v0.1/docs/publishing-packages#prepare-your-package).\n\n# Introduction Text\n\nYou can *optionally* set an introduction text that will be displayed to the user on the first page of the installation wizard. If you don't set the introduction text, the first page of the wizard will be the overview page that shows the components that are going to be installed. Use HTML to mark up your text.\n\n```\nmodule.exports = function(session, options){\n    session.introduction = require(\"text!./intro.html\");\n```\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/wu9cyksqQ8CRLL9SMWVr_2015-04-01_1253.png\",\n        \"2015-04-01_1253.png\",\n        \"1570\",\n        \"850\",\n        \"#7c7c7c\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Headless Installation\",\n  \"body\": \"When the dependencies for your plugin are all required and you don't want to notify the user of the installation, then leave out the intro text. This will start the installer automatically without presenting a UI to the user. Note that if there is another plugin that triggered the installer a user might see your dependencies listed as well. Those dependencies will be marked as required.\"\n}\n[/block]\n# Pre and Post Installation Script\n\nThe pre and post installation scripts give you an easy way to execute a `bash` script before and after the installation process. Note that any failure that occurs in these scripts will fail the entire installation. This enables you to use the pre installation script to check for dependencies and other environmental aspects that might prevent the installation from succeeding. Similarly you can use the post installation script to check whether the installation succeeded.\n\n```\nmodule.exports = function(session, options){\n    session.preInstallScript = require(\"text!./pre-install.sh\");\n    session.postInstallScript = require(\"text!./post-install.sh\");\n```\n\n# Adding an Installation Task\n\nEach installation `session` consists of installation `tasks`. The definition of a task consists of a set of options, such as a `name` and `description` to display in the UI, and a set of sub-tasks that tell the installer what to install where and which installation methods to try.\n\nThe following example creates a task that installs a single npm module. The task is optional (the user can choose to not install this item) and it will be installed in the `~/.c9` directory.\n\n```\nsession.install({\n    \"name\": \"Sequelize\",\n    \"description\": \"Sequalize NPM module\",\n    \"cwd\": \"~/.c9\",\n    \"optional\": true\n}, {\n    \"npm\": \"sequelize:::at:::2.0.0-beta.0\"\n});\n```\n\nSimilar to the `optional` field, set the `ignore` field to false to set the checkbox for this component unchecked by default.\n\n## Options\n\nThe first argument to the `session.install()` method is the `options` object. The `options` object is passed to any of the package managers and thus can contain any arbitrary options for that package manager. \n\nThe table below lists the four default fields of the `option` object.\n[block:html]\n{\n  \"html\": \"<table>\\n  <tr><th>name</th><td>The name of the item that is installed</td></tr>\\n  <tr><th>description</th><td>The description of the item that is installed, explaining to the user what it is for</td></tr>\\n  <tr><th>cwd</th><td>The working directory where the installation will take place</td></tr>\\n  <tr><th>optional</th><td>Whether the user can choose to not install this package</td></tr>\\n</table>\"\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"The `options` argument is optional and any task that is lacking an options object will not show up in the installer ui.\"\n}\n[/block]\n## Installation Description\n\nThe installation description is a declarative format to describe the steps involved in installing dependencies. Simple tasks might have a single step, others might have multiple steps.\n\n*To make the examples more clear the `options` argument is left out.*\n\nThis is an installation step with one task; the installation of an npm module.\n```\nsession.install({\n    \"npm\": \"sequelize@2.0.0-beta.0\"\n});\n```\n\nThis is an installation step with two tasks; the installation of *two* npm modules.\n```\nsession.install({\n    \"npm\": [\"sqlite3@2.1.18\", \"sequelize@2.0.0-beta.0\"]\n});\n```\n\n*Please find a complete list of supported package managers further down in this guide*\n\nMultiple steps can either be AND - the tasks will all be executed, or OR - only one tasks succeeds.\n\n### AND\n\nThe following example comes from the `c9.ide.collab` plugin and it installs SQLite. For this to work, we need the npm module and sqlite database installed and a symlink created. The following definition does just that.\n\n```\nsession.install([\n    {\n        \"npm\": \"sqlite3@2.1.18\"\n    },\n    {\n        \"tar.gz\": {\n            \"url\": \"https://raw.githubusercontent.com/c9/install/master/packages/sqlite3.tar.gz\",\n            \"target\": \"~/.c9/lib/sqlite3\",\n            \"dir\": \"sqlite3\"\n        }\n    },\n    {\n        \"symlink\": {\n            \"source\": \"~/.c9/lib/sqlite3/sqlite3\",\n            \"target\": \"~/.c9/bin/sqlite3\"\n        }\n    }\n]);\n```\n\n### OR\n\nSometimes you want to try different strategies that lead to the same or a similar result. The following example comes from the main cloud9 install script and it installs `tmux`. It first tries one of the package managers and if those don't work it tries a bash script instead.\n\n```\nsession.install({\n    \"ubuntu\": \"tmux\",\n    \"centos\": \"tmux\",\n    \"bash\": require(\"text!./tmux.sh\")\n});\n```\n\n### AND and OR\n\nSimply combine the AND and OR approach as you need. The following example installs `tmux` through one of two package managers and then creates a symlink through a small bash script.\n\n```\nsession.install([\n    {\n        \"ubuntu\": \"tmux\",\n        \"centos\": \"tmux\"\n    },\n    {\n        \"bash\": 'ln -sf $(which tmux) ~/.c9/bin/tmux'\n    }\n]);\n```\n\nA special case is the inverse of this; combining OR and AND. To do this there's a special command called `install`. The following example shows how to use this to get to the actual installation step used by the main Cloud9 installer. It will try the step under `install`. If that fails it will try the next one, which is a bash script.\n\n```\nsession.install({\n    \"install\": [\n        {\n            \"ubuntu\": \"tmux\",\n            \"centos\": \"tmux\"\n        },\n        {\n            \"bash\": 'ln -sf $(which tmux) ~/.c9/bin/tmux'\n        }\n    ],\n    \"bash\": require(\"text!./tmux.sh\")\n});\n```\n\n\n# Package Managers\n\nA \"package manager\" is a plugin that performs one step in the installation process. In the examples above we've seen `tar.gz`, `bash`, `ubuntu` and `centos`. Below you'll find each of the default package managers and the options that they take.\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Anyone can create custom package managers. Check out [this guide](doc:extending-the-installer) for more information.\"\n}\n[/block]\n## Ubuntu (Debian)\n\nUse this package manager to install apt-get packages into the workspace. It accepts a single argument, which is a string specifying the package to install.\n\n```\n{\n    \"ubuntu\": \"tmux\"\n}\n```\n\n## Centos (RHEL, Fedora)\n\nUse this package manager to install yum packages into the workspace. It accepts a single argument, which is a string specifying the package to install.\n\n```\n{\n    \"centos\": \"tmux\"\n}\n```\n\n## NPM\n\nUse this package manager to install npm packages into the workspace. It accepts a single argument, which is a string specifying the package to install.\n\n```\n{\n    \"npm\": \"pty.js@0.2.3\"\n}\n```\n\n## tar.gz\n\nUse this package manager to install tar.gz packages from disk or from urls. If a `url` is specified it will download the package and untar.gz it into the `target` directory. If a `url` field is not specified, a `source` field *must* be present. When a `dir` field is specified it will expect the package to contain that directory and will move all its contents into the `target` directory. \n\n*Note that specifying `dir` will assume that `target` is a directory path specifically for this package and it will first delete any pre-existing directory before untarring*\n\n```\n{\n    \"tar.gz\": {\n        \"url\": \"https://raw.githubusercontent.com/c9/install/master/packages/sqlite3.tar.gz\",\n        \"target\": \"~/.c9/lib/sqlite3\",\n        \"dir\": \"sqlite3\"\n    }\n}\n```\n\nYou may wonder why in the example above we don't set the `target` field to `\"~/.c9/lib\"`. The reason is that tar.gz will fail if the `~/.c9/lib/sqlite3` directory already exists. Doing it as specified above will always make sure that directory is removed prior to untarring.\n\n## symlink\n\nUse this package manager to create a symlink from `source` to `target`.\n\n```\n{\n    \"symlink\": {\n        \"source\": \"~/.c9/lib/sqlite3/sqlite3\",\n        \"target\": \"~/.c9/bin/sqlite3\"\n    }\n}\n```\n\n## bash\n\nUse this package manager to execute a bash script.\n\n```\n{\n    \"bash\": require(\"text!./node.sh\")\n},\n{\n    \"bash\": 'ln -sf $(which tmux) ~/.c9/bin/tmux'\n}\n```\n\n# Starting the installation\n\nAt the end of your installation script you *must* call `session.start()` to start the installation and let the installer know your session is ready. This allows you to perform asynchronous calls in your installer before it is started.\n\n```\nsession.start();\n```\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/EHpaw6CSrOT7YASx4ZBI_2015-04-01_1301.png\",\n        \"2015-04-01_1301.png\",\n        \"1570\",\n        \"836\",\n        \"#7b7b7c\",\n        \"\"\n      ]\n    }\n  ]\n}\n[/block]\n# Full Example\n\nThis is the main Cloud9 installation script.\n\n```\ndefine(function(require, exports, module) {\n    \nmodule.exports = function(session, options){\n    session.introduction = require(\"text!./intro.html\");\n    session.preInstallScript = require(\"text!./check-deps.sh\");\n    \n    // Node.js\n    var NODEVERSION = \"v0.10.28\";\n    var nodeName = \"node-\" + NODEVERSION + \"-\" \n        + options.platform + \"-\" + options.arch;\n    \n    session.install({\n        \"name\": \"Node.js\", \n        \"description\": \"Node.js \" + NODEVERSION\n    }, [\n        {\n            \"tar.gz\": { \n                \"url\": \"http://nodejs.org/dist/\" + NODEVERSION + \"/\" + nodeName + \".tar.gz\",\n                \"target\": \"~/.c9/node\",\n                \"dir\": nodeName\n            }\n        },\n        {\n            \"bash\": require(\"text!./node.sh\")\n        }\n    ]);\n\n    // Pty.js\n    session.install({\n        \"name\": \"Pty.js\",\n        \"description\": \"Pseudo Terminal support. Used by the Cloud9 Terminal\",\n        \"cwd\": \"~/.c9\"\n    }, {\n        \"npm\": [\"node-gyp\", \"pty.js@0.2.3\"]\n    });\n    \n    // Tmux\n    session.install({\n        \"name\": \"tmux\", \n        \"description\": \"Tmux - the terminal multiplexer\",\n        \"cwd\": \"~/.c9\"\n    }, {\n        \"install\": [\n            {\n                \"ubuntu\": \"tmux\",\n                \"centos\": \"tmux\"\n            },\n            {\n                \"bash\": 'ln -sf $(which tmux) ~/.c9/bin/tmux'\n            }\n        ],\n        \"bash\": require(\"text!./tmux.sh\")\n    });\n\n    // Show the installation screen\n    session.start();\n};\n\n});\n```","excerpt":"","slug":"adding-an-installer","type":"basic","title":"Adding an Installer"}

Adding an Installer


The *Cloud9 Installer* installs dependencies for plugins into the user's workspace. This can be npm modules apt-get or yum packages, tar.gz files that are downloaded et cetera. An installer for your package is a simple .js file that defines the steps that the installer needs to take to install the dependencies. This guide will walk you through the steps for creating your own installer. The screenshot below is of the Cloud9 installer running the main Cloud9 install script, which is used when Cloud9 is connected to a workspace that is not hosted on c9.io, such as SSH workspaces or your own local machine or server. [block:image] { "images": [ { "image": [ "https://files.readme.io/KWgZVuvTmGC5v6liKMxa_2015-04-01_1255.png", "2015-04-01_1255.png", "1570", "848", "#7b7b7b", "" ] } ] } [/block] # Use cases You *should* create an install script when your plugin depends on additional packages that should be installed in the user's workspace. For instance when you are creating a language plugin that uses a server side analyzer, create an install script that installs that analyzer when your plugin gets installed. Another use case is when you want to configure a workspace to be ready for your framework, library or sdk. Simply create an installer that installs all the components needed by your plugin. # Scaffolding The basic scaffolding of your installer is the typical AMD module wrapper containing a function that takes a `session` and `options` argument. It is common practice to call this file `install.js` and put it in the root dir of your package. ``` define(function(require, exports, module) { module.exports = function(session, options){ }; // version of the installer. Increase this when installer changes and must run again module.exports.version = 1; }); ``` The `session` argument is an installer session. More about this below. The `options` contain two properties. [block:html] { "html": "<table>\n <tr><th>platform</th><td>The platform of the workspace. Valid options are 'darwin', 'freebsd', 'linux', 'sunos' or 'win32'</tr></tr>\n <tr><th>arch</th><td>The architecture of the workspace. Valid options are 'arm', 'ia32', or 'x64'</tr></tr>\n</table>" } [/block] ## Package.json Add your `install.js` script to the package.json file in your package folder to enable the installer. The `installer` field expects an object with a `version` field and a `main` field. The `main` field is relative to the package root. The `version` field is the version of your plugin when install.js was updated last. ``` { "name": "yourplugin", "version": "1.0.0", "installer": "install.js", "plugins": { "yourplugin": {} } } ``` For more information see [this guide](http://cloud9-sdk.readme.io/v0.1/docs/publishing-packages#prepare-your-package). # Introduction Text You can *optionally* set an introduction text that will be displayed to the user on the first page of the installation wizard. If you don't set the introduction text, the first page of the wizard will be the overview page that shows the components that are going to be installed. Use HTML to mark up your text. ``` module.exports = function(session, options){ session.introduction = require("text!./intro.html"); ``` [block:image] { "images": [ { "image": [ "https://files.readme.io/wu9cyksqQ8CRLL9SMWVr_2015-04-01_1253.png", "2015-04-01_1253.png", "1570", "850", "#7c7c7c", "" ] } ] } [/block] [block:callout] { "type": "info", "title": "Headless Installation", "body": "When the dependencies for your plugin are all required and you don't want to notify the user of the installation, then leave out the intro text. This will start the installer automatically without presenting a UI to the user. Note that if there is another plugin that triggered the installer a user might see your dependencies listed as well. Those dependencies will be marked as required." } [/block] # Pre and Post Installation Script The pre and post installation scripts give you an easy way to execute a `bash` script before and after the installation process. Note that any failure that occurs in these scripts will fail the entire installation. This enables you to use the pre installation script to check for dependencies and other environmental aspects that might prevent the installation from succeeding. Similarly you can use the post installation script to check whether the installation succeeded. ``` module.exports = function(session, options){ session.preInstallScript = require("text!./pre-install.sh"); session.postInstallScript = require("text!./post-install.sh"); ``` # Adding an Installation Task Each installation `session` consists of installation `tasks`. The definition of a task consists of a set of options, such as a `name` and `description` to display in the UI, and a set of sub-tasks that tell the installer what to install where and which installation methods to try. The following example creates a task that installs a single npm module. The task is optional (the user can choose to not install this item) and it will be installed in the `~/.c9` directory. ``` session.install({ "name": "Sequelize", "description": "Sequalize NPM module", "cwd": "~/.c9", "optional": true }, { "npm": "sequelize@2.0.0-beta.0" }); ``` Similar to the `optional` field, set the `ignore` field to false to set the checkbox for this component unchecked by default. ## Options The first argument to the `session.install()` method is the `options` object. The `options` object is passed to any of the package managers and thus can contain any arbitrary options for that package manager. The table below lists the four default fields of the `option` object. [block:html] { "html": "<table>\n <tr><th>name</th><td>The name of the item that is installed</td></tr>\n <tr><th>description</th><td>The description of the item that is installed, explaining to the user what it is for</td></tr>\n <tr><th>cwd</th><td>The working directory where the installation will take place</td></tr>\n <tr><th>optional</th><td>Whether the user can choose to not install this package</td></tr>\n</table>" } [/block] [block:callout] { "type": "warning", "body": "The `options` argument is optional and any task that is lacking an options object will not show up in the installer ui." } [/block] ## Installation Description The installation description is a declarative format to describe the steps involved in installing dependencies. Simple tasks might have a single step, others might have multiple steps. *To make the examples more clear the `options` argument is left out.* This is an installation step with one task; the installation of an npm module. ``` session.install({ "npm": "sequelize@2.0.0-beta.0" }); ``` This is an installation step with two tasks; the installation of *two* npm modules. ``` session.install({ "npm": ["sqlite3@2.1.18", "sequelize@2.0.0-beta.0"] }); ``` *Please find a complete list of supported package managers further down in this guide* Multiple steps can either be AND - the tasks will all be executed, or OR - only one tasks succeeds. ### AND The following example comes from the `c9.ide.collab` plugin and it installs SQLite. For this to work, we need the npm module and sqlite database installed and a symlink created. The following definition does just that. ``` session.install([ { "npm": "sqlite3@2.1.18" }, { "tar.gz": { "url": "https://raw.githubusercontent.com/c9/install/master/packages/sqlite3.tar.gz", "target": "~/.c9/lib/sqlite3", "dir": "sqlite3" } }, { "symlink": { "source": "~/.c9/lib/sqlite3/sqlite3", "target": "~/.c9/bin/sqlite3" } } ]); ``` ### OR Sometimes you want to try different strategies that lead to the same or a similar result. The following example comes from the main cloud9 install script and it installs `tmux`. It first tries one of the package managers and if those don't work it tries a bash script instead. ``` session.install({ "ubuntu": "tmux", "centos": "tmux", "bash": require("text!./tmux.sh") }); ``` ### AND and OR Simply combine the AND and OR approach as you need. The following example installs `tmux` through one of two package managers and then creates a symlink through a small bash script. ``` session.install([ { "ubuntu": "tmux", "centos": "tmux" }, { "bash": 'ln -sf $(which tmux) ~/.c9/bin/tmux' } ]); ``` A special case is the inverse of this; combining OR and AND. To do this there's a special command called `install`. The following example shows how to use this to get to the actual installation step used by the main Cloud9 installer. It will try the step under `install`. If that fails it will try the next one, which is a bash script. ``` session.install({ "install": [ { "ubuntu": "tmux", "centos": "tmux" }, { "bash": 'ln -sf $(which tmux) ~/.c9/bin/tmux' } ], "bash": require("text!./tmux.sh") }); ``` # Package Managers A "package manager" is a plugin that performs one step in the installation process. In the examples above we've seen `tar.gz`, `bash`, `ubuntu` and `centos`. Below you'll find each of the default package managers and the options that they take. [block:callout] { "type": "info", "body": "Anyone can create custom package managers. Check out [this guide](doc:extending-the-installer) for more information." } [/block] ## Ubuntu (Debian) Use this package manager to install apt-get packages into the workspace. It accepts a single argument, which is a string specifying the package to install. ``` { "ubuntu": "tmux" } ``` ## Centos (RHEL, Fedora) Use this package manager to install yum packages into the workspace. It accepts a single argument, which is a string specifying the package to install. ``` { "centos": "tmux" } ``` ## NPM Use this package manager to install npm packages into the workspace. It accepts a single argument, which is a string specifying the package to install. ``` { "npm": "pty.js@0.2.3" } ``` ## tar.gz Use this package manager to install tar.gz packages from disk or from urls. If a `url` is specified it will download the package and untar.gz it into the `target` directory. If a `url` field is not specified, a `source` field *must* be present. When a `dir` field is specified it will expect the package to contain that directory and will move all its contents into the `target` directory. *Note that specifying `dir` will assume that `target` is a directory path specifically for this package and it will first delete any pre-existing directory before untarring* ``` { "tar.gz": { "url": "https://raw.githubusercontent.com/c9/install/master/packages/sqlite3.tar.gz", "target": "~/.c9/lib/sqlite3", "dir": "sqlite3" } } ``` You may wonder why in the example above we don't set the `target` field to `"~/.c9/lib"`. The reason is that tar.gz will fail if the `~/.c9/lib/sqlite3` directory already exists. Doing it as specified above will always make sure that directory is removed prior to untarring. ## symlink Use this package manager to create a symlink from `source` to `target`. ``` { "symlink": { "source": "~/.c9/lib/sqlite3/sqlite3", "target": "~/.c9/bin/sqlite3" } } ``` ## bash Use this package manager to execute a bash script. ``` { "bash": require("text!./node.sh") }, { "bash": 'ln -sf $(which tmux) ~/.c9/bin/tmux' } ``` # Starting the installation At the end of your installation script you *must* call `session.start()` to start the installation and let the installer know your session is ready. This allows you to perform asynchronous calls in your installer before it is started. ``` session.start(); ``` [block:image] { "images": [ { "image": [ "https://files.readme.io/EHpaw6CSrOT7YASx4ZBI_2015-04-01_1301.png", "2015-04-01_1301.png", "1570", "836", "#7b7b7c", "" ] } ] } [/block] # Full Example This is the main Cloud9 installation script. ``` define(function(require, exports, module) { module.exports = function(session, options){ session.introduction = require("text!./intro.html"); session.preInstallScript = require("text!./check-deps.sh"); // Node.js var NODEVERSION = "v0.10.28"; var nodeName = "node-" + NODEVERSION + "-" + options.platform + "-" + options.arch; session.install({ "name": "Node.js", "description": "Node.js " + NODEVERSION }, [ { "tar.gz": { "url": "http://nodejs.org/dist/" + NODEVERSION + "/" + nodeName + ".tar.gz", "target": "~/.c9/node", "dir": nodeName } }, { "bash": require("text!./node.sh") } ]); // Pty.js session.install({ "name": "Pty.js", "description": "Pseudo Terminal support. Used by the Cloud9 Terminal", "cwd": "~/.c9" }, { "npm": ["node-gyp", "pty.js@0.2.3"] }); // Tmux session.install({ "name": "tmux", "description": "Tmux - the terminal multiplexer", "cwd": "~/.c9" }, { "install": [ { "ubuntu": "tmux", "centos": "tmux" }, { "bash": 'ln -sf $(which tmux) ~/.c9/bin/tmux' } ], "bash": require("text!./tmux.sh") }); // Show the installation screen session.start(); }; }); ```