Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The source code for this book is hosted in GitHub: https://github.com/ortus-solutions/commandbox-docs. You can freely contribute to it and submit pull requests. The contents of this book is copyright by Ortus Solutions, Corp and cannot be altered or reproduced without author's consent. All content is provided "As-Is" and can be freely distributed.
The majority of code examples in this book are done in cfscript
.
Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc. Railo is a trademark and copyright of Railo Technologies, GmbH. Lucee is a trademark and copyright of Lucee Association Switzerland.
The information in this book is distributed “as is”, without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity with respect to loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software and resources described in it.
We highly encourage contribution to this book and our open source software. The source code for this book can be found in our GitHub repository where you can submit pull requests.
15% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - http://www.harvesting.org/. Please donate and purchase the printed version of this book as every book sold can help a child for almost 2 months.
Shalom Children’s Home (http://www.harvesting.org/) is one of the ministries that is dear to our hearts located in El Salvador. During the 12 year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children came on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded.
Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education and life skills training in a Christian environment. The home is supported by a child sponsorship program.
We have personally supported Shalom since 2006; it is a place of blessing for many children in El Salvador that either have no families or have been abandoned. This is good earth to seed and plant.
Here are the requirements for installing and using CommandBox on your system. Notice some of these such as RAM and disk space depend on how many features you will plan on using. For instance, the shell only allocates about 256MB of RAM to run, but if you plan on starting embedded servers, that will spawn additional threads-- each of which will consume their own memory.
Windows XP+
Mac OS
Linux
256MB+ RAM
250MB+ free hard drive space
Multi-core CPU recommended
A Java JRE is listed as a software requirement, but if you have a brand new PC with no JRE we have a download option that contains the Java Runtime bundled with it.
If you already have a Java JRE installed level 1.7 or higher (and set in your environment variables) you can the non-JRE version for your Operating System. If you don't have a JRE installed or aren't sure, we would recommend you the version with a JRE included. Below you will find the way to get the latest stable and bleeding edge releases. Please also note that in our page you will find much more detail information on how to install CommandBox with modern Operating System package managers as well.
Info The non-JRE versions are all around 40MB in size, while the embedded JRE versions will go up to 90MB in size.
Below you can see an image of the available downloads from the Ortus Solutions page:
Info Keep in mind, bleeding edge builds may contain experimental features that are likely to change or bugs.
Info Please note that the upgrade command will not update the main CommandBox binary. If there are major updates or you get a message about updating the binary, you will need to download the latest binary and re-install it.
Welcome to the CommandBox Manual. CommandBox is a standalone, native tool for Windows, Mac, and Linux that will provide you with a Command Line Interface (CLI) for developer productivity, tool interaction, package management, embedded CFML server, application scaffolding, and sweet ASCII art. It seamlessly integrates to work with any of *Box products, but it is also open for extensibility for any ColdFusion (CFML) project as it is written in ColdFusion (CFML) using our concepts of CommandBox Commands.
And constructed with the following guidelines:
Breaking backward compatibility bumps the major (and resets the minor and patch)
New additions without breaking backward compatibility bumps the minor (and resets the patch)
Bug fixes and misc changes bumps the patch
Copyright by Ortus Solutions, Corp
CommandBox is a registered trademark by Ortus Solutions, Corp
Info The CommandBox Websites, Documentation, logo and content have a separate license and they are a separate entity.
Custom Development
Professional Support & Mentoring
Training
Server Tuning
Security Hardening
Code Reviews
Because of His grace, this project exists. If you don't like this, then don't read it, it's not for you.
"Therefore being justified by **faith**, we have peace with God through our Lord Jesus Christ: By whom also we have access by **faith** into this **grace** wherein we stand, and rejoice in hope of the glory of God." Romans 5:5
Stable versions of CommandBox can be downloaded from the downloads section of our product page.
We use a Jenkins integration server to automate our builds. You can download a bleeding-edge version of CommandBox directly from our integration server here:
Another way to get the bleeding edge version of CommandBox is to install the stable version and run our upgrade
command using the latest flag. .
CommandBox is maintained under the guidelines as much as possible. Releases will be numbered with the following format:
CommandBox is open source and bound to the
The CommandBox help and discussion group can be found here:
We all make mistakes from time to time :) so why not let us know about it and help us out. We also love pull requests, so please star us and fork us:
CommandBox is professional open source software backed by offering services like:
Official Site:
Source Code:
Bug Tracker:
Twitter:
Facebook:
Google+:
Vimeo Channel:
Regardless of where you place the box binary, the first time you execute it, a .CommandBox
folder will be created in your user's home directory and CommandBox will be extracted into that location. If you delete this directory, it will be replaced the next time the CommandBox executable is run.
You can specify a different install location by adding -commandbox_home=E:\CommandBox
when you run the box binary.
To avoid specifying the commandbox_home variable every time you can create a file called commandbox.properties
(case sensitive) in the same directory as the binary, and fill it with this line:
Unzip the executable box.exe and just double click on it to open the shell. When you are finished running commands, you can just close the window, or type exit
.
Hint You can make the
box.exe
available in any Windows terminal by adding its location to thePATH
system environment variable. See http://www.computerhope.com/issues/ch000549.htm
Homebrew is a great Mac package manager, it can easily install and keep your CommandBox installation up to date (even binary releases), just run the following for stable releases:
To stay with current bleeding edge releases use the following:
Then run the box
binary to begin the one-time unpacking process.
Versions will be installed in /usr/local/Cellar/commandbox
. To switch between versions, simply use brew switch commandbox [version number]
When using Homebrew to install CommandBox you must use Homebrew for any upgrade, minor or major. To upgrade CommandBox with Homebrew:
Unzip the binary box and just double click on it to open the shell terminal. When you are finished running commands, you can just close the window, or type exit
.
Hint You can place the binary in your
/usr/bin
directory so it can be available system-wide via thebox
command in any terminal window.
Please note that if you are running Ubuntu 18.04 or greater, or Debian 8 (Jessie) or greater, it's necessary to have the
libappindicator-dev
package in order to have the tray icon working correctly.
Run the following series of commands to add the Ortus signing key, register our Debian repo, and install CommandBox.
Then run the box
binary to begin the one-time unpacking process.
Add the following to: /etc/yum.repos.d/commandbox.repo
Then run:
After you have downloaded the commandbox.deb
file, install it using the dpkg
command.
Run the box
binary to begin the one-time unpacking process.
After you have downloaded the commandbox.rpm
file, install it using the rpm
command.
Luis Majano is a Computer Engineer with over 15 years of software development and systems architecture experience. He was born in San Salvador, El Salvador in the late 70’s, during a period of economic instability and civil war. He lived in El Salvador until 1995 and then moved to Miami, Florida where he completed his Bachelors of Science in Computer Engineering at Florida International University. Luis resides in Houston, Texas with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!
He is the CEO of Ortus Solutions, a consulting firm specializing in web development, ColdFusion (CFML), Java development and all open source professional services under the ColdBox and ContentBox stack. He is the creator of ColdBox, ContentBox, WireBox, MockBox, LogBox and anything “BOX”, and contributes to many open source ColdFusion projects. He is also the Adobe ColdFusion user group manager for the Inland Empire. You can read his blog at www.luismajano.com
Luis has a passion for Jesus, tennis, golf, volleyball and anything electronic. Random Author Facts:
He played volleyball in the Salvadorean National Team at the tender age of 17
The Lord of the Rings and The Hobbit is something he reads every 5 years. (Geek!)
His first ever computer was a Texas Instrument TI-86 that his parents gave him in 1986. After some time digesting his very first BASIC book, he had written his own tic-tac-toe game at the age of 9. (Extra geek!)
He has a geek love for circuits, microcontrollers and overall embedded systems.
He has of late (during old age) become a fan of running and bike riding with his family.
Keep Jesus number one in your life and in your heart. I did and it changed my life from desolation, defeat and failure to an abundant life full of love, thankfulness, joy and overwhelming peace. As this world breathes failure and fear upon any life, Jesus brings power, love and a sound mind to everybody!
“Trust in the LORD with all your heart, and do not lean on your own understanding.” – Proverbs 3:5
Brad grew up in southern Missouri where he systematically disassembled every toy he ever owned which occasionally led to unintentional shock therapy (TVs hold charge long after they've been unplugged, you know). After high school he majored in Computer Science with a music minor at MidAmerica Nazarene University (Olathe, KS). Today he lives in Kansas City with his wife and three girls where he still disassembles most of his belongings (including automobiles) just with a slightly higher success rate of putting them back together again.) Brad enjoys church, all sorts of international food, and the great outdoors.
Brad has been programming CFML for 12+ years and has used every version of CF since 4.5. He first fell in love with ColdFusion as a way to easily connect a database to his website for dynamic pages. Brad blogs at (http://www.codersrevolution.com) and likes to work on solder-at-home digital and analog circuits with his daughter as well as building projects with Arduino-based microcontrollers.
Brad's CommandBox Snake high score is 141.
Jorge Reyes - ColdBox Aficionado
Here are some common issues starting up CommandBox and troubleshooting help.
If you have a Windows machine which has been locked down to not allow DLL files in the user's appData
folder, you may receive a message similar to this when attempting to start CommandBox.
If you don't have the option of changing the security controls on your PC, then you can try changing your Windows environment variables of TMP
and TEMP
to repoint to another folder which does not have this restriction.
If you receive a message like the one above, which was taken from a Linux machine, when starting CommandBox, this means that you do not have Java installed. You can solve this in three ways: 1. Download the JRE-included CommandBox install which comes with a folder called jre
2. Download your own jre and place it in a folder called jre
in the same folder as the box
binary. 3. install Java onto your machine and ensure the correct JAVA_HOME
and JRE_HOME
environment variables are set.
CommandBox is a Java-based tool that involves several pieces including native Java classes, CFML code, and the embedded Railo CLI. However, most changes are confined to the CFML code managed by WireBox. To determine what version you have installed, use the version
command.
The auto-upgrade commands shown below will not upgrade the main CommandBox Java Binary. If there are any major upgrades to this binary, you will see a message that you will need to download the new Java binary and replace your current one.
To upgrade to the last stable version of the shell and commands, use the upgrade
command.
This command will connect to our server to determine the last stable build. If there is an upgrade, it will be downloaded and installed for you.
To upgrade to the bleeding edge version of the shell and commands, use the latest flag.
This command will connect to our server to determine the latest build. If there is an upgrade, it will be downloaded and installed for you.
If you already have the latest version installed, but you still want to force an upgrade, use the force parameter.
Note, if you delete your {user}/.CommandBox
folder and re-run the executable, the version of CommandBox in the executable will be unpacked regardless of any upgrades you may have installed in the mean time. On that note, another way to force an upgrade is to simply download the new executable, wipe the .CommandBox
folder in your user directory and re-run. This will also erase any saved command history, embedded servers, or installed user commands. servers, or installed user commands.
If you have used Hombrew to install CommandBox you must use Homebrew for any upgrade, minor or major. To upgrade CommandBox with Homebrew:
There are two ways to run commands via CommandBox: inside the CommandBox interactive shell, or one-at-a-time commands from your native shell.
If you open the interactive shell, you will see the CommandBox splash screen (ASCII art) and then you'll be presented with the CommandBox>
prompt. You can enter as many commands as you wish in order and after each command is finished executing, you will be returned to the CommandBox prompt. If you have multiple commands you want to execute manually, this is the fastest method since CommandBox only loads once. This is also the only way to make use of features like tab complete and command history.
This example show running the box.exe
executable from a Windows DOS prompt, executing the version, pwd, and echo commands, and then exiting back to DOS.
You can also spin up CommandBox from your native shell to execute a single command inline. You can do this if you only have one command to run, or you want to automate a command from a Unix shell script or Windows batch file. This mode will not show the ASCII splash screen, but keep in mind it still loads CommandBox up and unloads it in the background. Any output from the command will be left on your screen, and you will be returned to your native OS prompt.
Here is an example of running the version command from a Windows DOS screen. Note, you'll need to either do this from the directory that holds the box executable, or add the executable to your default command path so it is found.
The box
text is calling the CommandBox binary, and the version
bit is passed along to the CommandBox shell to execute once it loads.
You can also activate CommandBox in debug mode by passing the -debug
flag in the command line. This will give you much more verbose information about the running CommandBox environment. This affects both the interactive shell or one-off commands
Output from commands will be ANSI-formatted text which, by default, streams directly to the console. When in the interactive shell, you can capture the output of commands and manipulate it, search it, or write it to a file. Use a pipe (|
) to pass the output of one command into another command as its first input. Output can be piped between more than one command. Use a right bracket (>
) and double right bracket (>>
) to redirect output to the file system.
Pipe output into the grep command to apply a regex upon it. grep will only emit lines matching the regex.
Pipe output into the more command to output it line-by-line or page-by-page. Press the spacebar to advance one line at a time. Press the Enter key to advance one page at a time. Press ESC or “q” to abort output.
Redirect output into a file, overwriting if it exits like so:
Use the double arrows to append to an existing file.
You can pipe a large amount of text or a file name into the tail
command to only output the few lines of the text/file. Adding the --follow
flag when tailing a file will live-stream changes to the file to your console until you press Ctrl-C to stop.
If you want to add ad-hoc Java Properties to the actual CLI process, you can set an environment variable in your OS called BOX_JAVA_PROPS
in this format:
That would create a property called foo
and a property called brad
with the values bar
and wood
respectively.
If you are using CommandBox in a continuous integration server such as Jenkins or Travis-CI, you may find that features like the progress bar which redraw the screen many times create hundreds of lines of output in the console log for your builds. You can enable a non interactive mode that will bypass the output from interactive jobs and the download progress bar.
If there is no nonInteractiveShell
setting, CommandBox will automatically default it to true if there is an environment variable named CI
present, which is standard for many build servers such as Travis-CI.
CommandBox is a Java-based executable that will run on most recent desktop operating systems (Linux, Mac OS X, Windows). Since it is a command line tool that uses a shell interface, it does not even require an operating system using a GUI. CommandBox can be used as a development aid and automation tool alongside your favorite CFML engine and IDE, but neither of those are requirements for installation of CommandBox.
If you want to automate several commands from your native shell, it will be faster to use our recipe command that allows you to run several CommandBox commands at once. This will allow you to only load the CommandBox engine once for all those commands, but still be dumped back at your native prompt when done. Recipes can also just be useful for a series of commands you run on a regular basis.
Read more about the recipe command in our Command API docs.
Think of a recipe as a simple batch file for Windows or a shell script for Unix. It's just a text file where you place one command on each line and they are executed in order. Enter the commands exactly as you would from the interactive shell.
Technically a recipe can have any file extension, but the default recommendation is .boxr
which stands for "box recipe". Lines that start with a pound and whitespace characters (e.g. "# My Comments") will be ignored as comments. The pound character followed immediately by word-like characters is the mechanism for invoking CFML functions.
buildSite.boxr
Execute your recipe with the recipe
command, giving it the path to the recipe file.
If any commands in the recipe stop and ask for input, the recipe will pause until you supply that input. All commands that have confirmations, etc should have a --force
flag for this purpose so you can run them headlessly without requiring your input. See the rm
command above for an example.
You can also bind the recipe with arguments that will be replaced inside of your recipe at run time. Pass any arguments as additional parameters to the recipe
command and they will be passed along to the commands in your recipe.
If you use named arguments to the recipe command, they will be accessible via environment variables inside the recipe as ${arg1Name}
, ${arg2Name}
, etc.
Consider the following recipe:
notifyWinner.boxr
You would call it like so:
Output:
Note, all parameters to the recipe
command needed to be named, including the recipeFile
.
Now let's look at the same recipe set up to receive positional parameters.
You would call it like so:
Output:
If an argument is not passed, you can use the default value mechanism:
You can use echo on
and echo off
in recipes to control whether the commands output to the console as they are executed. This can be useful for debugging or confirming the success of commands with no output. Echo
is on by default.
Note, echo off
doesn't suppress the output of the commands, just the printing of the command and its arguments prior to execution. This does not use the actual echo
command and is a feature that only applies during the execution of recipes.
Output:
You can use the exit command in a recipe and instead of leaving the entire shell, the recipe will simply stop execution right there. If an exit code is passed, it will because the exit code of the recipe command as well as the entire shell.
Any command that errors or returns a non-0 exit code will end the recipe immediately and the recipe command will inherit that exit code. This line in a recipe will stop the recipe if there is not a foobar
property in your box.json
, but not before outputting a message.
In addition to passing a file path to the recipe
command for execution, you can also pipe the contents of a file directly into the command. if the input does not match a file path, it is assumed to be executable commands.
This can also give you some interesting ability to do dynamic evaluation of command strings.
CommandBox's true power comes from it's command-based architecture, but we also support just running plain-jane .cfm files as well.
Take the following file for example:
test.cfm
We can execute this file directly from our native OS prompt by simply passing the filename straight into the box binary.
Or, I can run it from within the CommandBox interactive shell using the execute command:
Now, you people on Unix-based operating systems like Mac and Linux get a special treat. You can actually create natively executable shell scripts that contain CFML! Check out this file that has the special hash bang at top:
test
All we need to do is make it executable
And then just run it like any other shell script!
The underlying engine used to execute your files will be the version of Lucee Server that the CLI is currently running on. Note, this can change between releases, and you can see the current version by running the info
command. If you want to try to use the <cfadmin>
tag to do things like create datasources, the default password for the Lucee server context is commandbox
.
Hopefully this gives you a lot of ideas of how to start using CFML on your next automation task. And if you want even more control like print objects, object oriented code, and fancy parameters, look into making custom CommandBox commands.
If a value is a single word with no special characters, you don't need to escape anything. Certain characters are reserved as special characters though for parameters since they demarcate the beginning and end of the actual parameter and you'll need to escape them properly. These rules apply the same to named and positional parameters.
If a parameter has any white space in it, you'll need to wrap the value in single or double quotes. It doesn't matter which kind you use and it can vary from one parameter to another as long as they match properly.
Quotes are actually allowed unescaped in a value like so:
However, if the parameter contains whitespace and is surrounded by quotes, you'll need to escape them with a backslash.
Hint Only like quotes need to be escaped. Single quotes can exist inside of double and vice versa without issue. These examples below are perfectly valid.
Backticks are used in parameter values to demarcate an expression to be parsed. Escape them with a backslash. All backticks need escaped regardless of whether they are encased on single or double quotes.
If you have an equals sign in your value, you'll need to escape it with a backslash unless you've quoted the entire string.
Line breaks can't be escaped directly as of Commandbox 4.0. Instead, most terminals let you enter a carriage return by pressing Ctrl-V and pressing enter. To enter a line feed, press Ctrl-V followed by Ctrl-J.
On ConEMU, which performs a paste operation with Ctrl-V, use Ctrl-Shift-V instead.
A tab character can't be escaped directly as of CommandBox 4.0. Instead, most terminals let you enter a tab char by pressing Ctrl-V followed by tab. In ConEMU which allows pasting via Ctrl-V, you can use Ctrl-Shift-V and then press tab.
Since the backslash is used as our escape character you'll need to escape any legitimate backslash that happens to precede a single quote, double quote, equals sign, or letter n.
This will print foo\=bar
CommandBox follows the standard system of exit codes. In Bash or DOS, every process has an exit code that is available to the shell after execution is complete. The are as follows:
0 - Success
Any other number - Failure
This slightly counter intuitive to CFML developers since we are used to positive numbers as being truthy and zero as being falsy, but it is the industry standard for shells.
Every command that executes has an exit code. Usually the exit code is 0 if the command ran as expected. If an error of any kind was encountered, then the exit code will be a non-zero number. Often times 1. You can easily see this if you install the CommandBox Bullet Train module as it shows you the exit code of the last command to run. Commands such as testbox run
will return a failing exit code if the tests being run didn't all pass.
You can access the last exit code from CommandBox in a System Setting called exitCode
.
The CommandBox shell also keeps track of exit code of the last command. When the shell exits, it will report that last exit code to the OS. When running a one-off command from your native shell, the exit code of that command will be passed straight through to your native shell. This means that running something like
from a Travis-CI build will automatically fail the build if the tests don't pass.
You can manually return an exit code from the shell passing the desired number to the exit
command and the native OS will receive that code from the box
binary.
Similar to bash, CommandBox allows you to chain multiple commands together on the same line and make them conditional on whether the previous command was successful or not.
You can use &&
to run the second command only if the previous one succeeded.
You can use ||
to run the second command only if the previous one failed.
You can use a single semi colon (;
) to separate commands and each command will run regardless of the success or failure of the previous command.
With the above building blocks, we can get clever to create simple conditionals to only run commands if a condition is met. Or these can simply be used to cause recipes to stop execution or to fail builds based on a condition. The following commands output nothing, but they return an appropriate exit code based on their inputs.
Returns a passing (0) or failing (1) exit code whether the path exists. In this example, we only run the package show command if the box.json
file exists.
You can specify if the path needs to be a file or a folder.
Returns a passing (0) or failing (1) exit code whether truthy parameter passed. Truthy values are "yes", "true" and positive integers. All other values are considered falsy
Returns a passing (0) or failing (1) exit code whether both parameters match. Comparison is case insensitive.
If you want to execute a native binary from inside the interactive shell or as part of a CommandBox recipe, we allow this via the run
command. You can read the API docs for run
here.
Hint This behavior is dependent on your operating system.
run binary
Execute an operation system level command using the native shell. For Windows users, cmd.exe
is used. For Unix, /bin/bash
is used. Command will wait for the OS command to finish.
The binary must be in the PATH, or you can specify the full path to it. Your keyboard will pass through to the standard input stream of the process if it blocks for input and the standard output and error streams of the process will be bound to your terminal so you see output as soon as it is flushed by the process.
!binary
A shortcut for running OS binaries is to prefix the binary with !
. In this mode, any other params need to be positional. There is no CommandBox parsing applied to the command's arguments. They are passed straight to the native shell. As such, you don't need to escape any of the parameters for CommandBox when using this syntax.
OS Commands you run are executed in the same working directory as CommandBox. This means you can seamlessly invoke other CLIs without ever leaving the interactive shell.
The output of native calls can be used in expressions or piped into other commands. Here's a Unix example that uses CFML functions from the command line to parse the parent folder from the current working directory:
When passing a command string for native execution, ALL REMAINING TEXT in the line will be "eaten" by the native execution and passed to the OS for processing. This is so the CommandBox parser doesn't "'screw up" any special syntax that your OS command processor is expecting. That means any use of piping or &&
will get passed straight to the OS. On Windows, the following string will run the ver
command twice in Windows.
In the event you want to pipe the result of an OS binary to another CommandBox command or chain another CommandBox command on the end, you can workaround this by echoing out the string and then piping that to the run
command. This example will run the Windows ver
command followed by the CommandBox ver
command.
Additionally, any expansions you put in your command string with backticks or System Setting placeholders will not be processed by CommandBox, but will be passed to the native OS directly. This Windows example won't do what you might think since the backticks are passed, untouched to the OS (so the OS can expand them if it needs):
Instead, you can pass the command text through echo
to have CommandBox process the backtick expansions first before sending it off to the OS for processing.
In the above example, written for Windows, the output of the echo
command has the package show name
expression expanded into the string and then the ENTIRE string is piped to run
where the pipe and the find
command are processed by Windows. Note, there is no need for preceding the command with !
when passing to run
since !
is just an alias for run
.
If you're having issues getting a native binary to run, you can turn on a config setting that will echo out the exact native command being run including the call to your OS's command interpreter.
You can override the default native shell from /bin/bash
to any shell of your choosing, like zsh. This will let you use shell specific aliases. You can set your native shell property using the config set
command (i.e., config set nativeShell=/bin/zsh
)
If the native binary errors, the exit code returned will become the exit code of the run
command itself and will be available via the usual mechanisms such as ${exitCode}
.
Any environment variables you set in the CommandBox shell will be available to the native process that your OS binary runs in. Here's a Windows and *nix example of setting an env var in CommandBox and then using it from the native shell.
Many Commands accept a path to a folder or file on your hard drive. You can specify a fully qualified path that starts at your drive root, or a relative path that starts in your current working directory. To find your current working directory, use the pwd
command (Print Working Directory). To change your current working directory, use the cd
command.
Here are examples of fully qualified paths in Windows and *nix-based:
Info Note that if you start a path with a single leading slash in Windows, it will be an absolute path using the drive letter of the current working directory.
For a relative path, do not begin with a slash.
File system paths will be canonicalized automatically which means the following is also valid:
If you are on Windows, CommandBox supports UNC server shares bu accessing the name of the server or the IP address. Note, you can use forward or backslashes in Windows, but a UNC path MUST start with two backslashes.
Backslashes need to be escaped from the command line and in JSON, so most usage of UNC server paths will require you to type four slashes like \\\\
which will properly escape to \\
You cannot directly list the contents of a server like \\webdev01
as that is not a true directory. You always need to access a specific share like \\webdev01/webroot
.
By default, CommandBox will access UNC paths using the same permissions of the user that the box
process was started with. There's no way to specify a user, so if you need to use a custom user, you'll need to run native NET USE
command from the CLI first to change how it is authenticating. Unfortunately, this is a limitation of how Java accesses UNC paths so CommandBox has little control over it.
CommandBox uses its own command parser that should be similar to what you're used to in other shells. Commands are not case-sensitive and don't contain any special characters except an occasional dash (-
). Each command and its parameters will be entered on a single line. Press enter when you are done typing to execute that command. If you ever need to include a line break in a parameter value, quote the value and use the \n
escape sequence.
For a full list of all the commands that ship with CommandBox as well as all their parameters and samples, please visit our Command API docs which are auto-generated each build.
To help organize our commands, we introduced the concept of namespaces. this means that commands can contain spaces and be comprised of more than one word. This is to keep things readable. Several commands that are all related will start with the same word, or namespace. An example of this is the artifacts namespace. It contains several commands inside of it including list, clean, and remove. Calling each of them would look like this:
Hint the text
artifacts
itself is not a command and you will receive an error if you hit enter after just typing that text. Context-specific help is available for all namespaces by typinghelp
after the namespace.
Namespaces can be more than one level. Another example would be coldbox create which contains commands such as app, view, and handler.
Commands can be aliased so you can call them more than one way, ever wanted to run an ls
command in Windows or a dir
command in Unix
? . Check the Command API docs or the CLI help command to see if a command has aliases. For instance, the quit command is aliases as q
for quick typing. Another example would be the package init command that is aliased to just init
.
Parameter values passed into a CommandBox command don't have to be static. Any part of the parameter which is enclosed in backticks (`) will be evaluated as a CommandBox expression. That means that the enclosed text will be first executed as though it were a separate command and the output will be substituted in its place.
Any valid command can be used as an expression, including calls to native OS binaries, CFML functions, or REPL one-liners. Note that any text that a command immediately flushes to the console during its execution (like a download progress bar) will not be returned by the expression, though it will display on the console.
Take for instance, this simple command that prints out the contents of a file:
It can be used as a dynamic parameter like so:
In the example above, the contents of the defaultServer.txt
file will be passed in as the value of the "name" parameter to the "server start" command. If the contents of the file was the text myServer
, the equivalent final command would be:
There can be more than one expression in a single parameter value. Expressions can also be combined with static text and they will all be evaluated in the order they appear:
That would output something similar to:
If you need to use an actual backtick in a parameter value, escape it with a backslash.
Which outputs
This unlocks a new world of scripting potential when combined with other abilities like native OS binary execution and CFML functions from the CLI. Here's some examples to get your gears turning:
Set a package property in box.json
equal to the current date passed through a CFML date mask
Set properties based on manipulations of previous values:
Perform CFML opertaions on local files:
Execute environment-aware install scripts based on local files. (isProduction.txt
would contain the text true
or false
in this ex.)
In the past, 99% of people used the Oracle (previously SUN) version of Java for all their Java needs. As of January 2019, the license is changing on Oracle Java which makes it no longer free for commercial use as well as the end of updates for Java 8. This has led to many people looking at alternatives to Oracle. Java itself is open source, so it will always be free and there are several other organizations offering their own builds of Java. If you want support, it matters which provider you get Java from.
This page is a work in progress to track the non-Oracle JREs and how to use them. Please send pull requests to this page with any additional information you have as this is a changing landscape right now.
You can read more about Oracle's changes in this post:
Corretto is a build of OpenJDK maintained by Amazon. It is free and will have long term support. Initial tests show that Corretto 1.8 works with CommandBox and ACF 11.
OpenJDK is Oracle's free version of Java. it comes with a 6 month support window. CommandBox has received a fair amount of testing on OpenJDK and everything seems to work.
Zulu is free and offers long term support. Zulu provides supported builds of OpenJDK. Initial tests show that Corretto 1.8 works with CommandBox and ACF 11.
When running box.exe
on Windows, the registry is used to determine the current versions of java that are installed. If you install a some non-Oracle JRE such as Corretto, you will not currently have the necessary registry entries created for box to find Java.
Oracle - No manual action needed
Azul - No manual action needed
OpenJDK - Manual creation of registry keys required
Corretto - Manual creation of registry keys required
You can manually create the needed keys by modifying and running the following registry entries. (Contributed by Jim Pickering)
The box
binary on *nix uses your OS environment variables to locate Java. In the absense of an env var called JAVA_HOME
, box will look for java
in the default system path.
Oracle - No manual action needed
Azul - No manual action needed
OpenJDK - Manual creation of JAVA_HOME
required
Corretto - Manual creation of JAVA_HOME
required
To manually configure the JAVA_HOME
env var on a *nix system, edit your /etc/profile
file to have these lines. Adjust the path as necessary based on your installation.
And as always, on any operating system and with any JRE provider, you can override what version of java is used by creating a folder called JRE
in the same directory as the box
or box.exe
binary that contains the JRE you wish CommandBox to use. This will bypass all registry and env var checks above.
CommandBox is a standalone, native Command Line Interface (CLI), Package Manager, Embedded CFML Server and Read Eval Print Loop (REPL) aimed to help ColdFusion (CFML) developers become more productive through automation, dependency management, command line-based tools, and ASCII snake games.
CommandBox is an amalgamation of many different tools and borrows concepts from NPM, Grunt/Gulp, Maven, Bower, and Node. Features include:
Command Line for ColdFusion (CFML)
Operating System integration for executing commands
Ability to create and execute commands built using ColdFusion (CFML)
ForgeBox integration for cloud package management and installations
ColdBox Platform, TestBox, and ContentBox CMS Integrations
Integrated servlet server with rewrite capabilities
Ability to create command recipes and execution
REPL (Read-Evaluate-Print-Loop) console for immediate ColdFusion
(CFML) interaction
Ability to interact with user via CLI and create workflows and
installers
Ability to execute workflows and tasks
Built-in Help system
Congratulations on your choice of CommandBox, the next generation of CFML productivity tooling! We're pleased you've chosen this produsddct and we can't wait to help you get started with it. Setup is easy and painless. We'll walk you through the steps you need to become the jealous rage of your peers with the class of a Java guru, the hipster appeal of a Rubyist, and the ASCII art fetish of a Node.js developer.
Your CommandBox download was quality checked and shipped from our integration server with the following items. You'll want to check the contents of the package to ensure you received everthing.
CLI
Package Manager
Embedded CFML Server
REPL
Built-in Help
ASCII Art
If you don't already have CommandBox in hand, download it from the product page on the Ortus Solutions site:
If you already have Java 1.7 or higher installed on your PC, choose the No JRE Included download for your operating system. Otherwise, you can grab the With JRE Included for a single-download solution.
You're well on your way now. While you wait for arrival you might want to secure any loose hair or shirt sleeves and clear a clean space to work on your desktop. Safety first!
Your CommandBox is sent to you via a zip archive. Decompress the archive to a location of your choice. The No JRE Included download will only have one file in it named box
. For Windows users, this will be an exe
file. For unix-based users, it will be an executable binary. The With JRE Included version will have a jre
folder. You can move box.exe
, but keep the jre
folder in the same relative location as the executable so it can be found.
Now just double click the file from your GUI, or execute it via a console window. This will start a short, quick, one-time process of unpacking CommandBox into your user's home directory. Congratulations, CommandBox is now installed! You'll still run the same executable binary every time you want to use the CLI, but the extraction process won't need to happen again.
The green CommandBox>
prompt is what we call the interactive shell. Type exit
to close the window or be returned to your OS's native shell.
To open up the interactive shell at any time, just double click on the box
executable. If you prefer to stay in your OS's native shell, then just place the box
file in your system path and add it before any CommandBox commands like so:
The rest of this guide, however, will assume you're sitting at the interactive shell, where you can enjoy cross-platform command consistency, custom history, and tab completion.
The first command you'll want to try out is help
. Type it after a command, or even a partial command to get context-specific assistance. Check out the help for the version
command and then run it to see what you get.
Now, let's see if your installation is up to date with the upgrade
command:
Looking good. Let's try a bit of CFML code from the REPL, shall we? Type the repl
command to be dropped into the REPL prompt.
Type these lines one at a time and press enter to see what you get.
When you're done, just type quit
to exit the REPL. How does it feel to master CFML from the command line?
It's about time we did something useful. CommandBox allows you to install stuff and it makes it really easy. You now have ForgeBox on speed dial. Let's create a little playground to experiment in. Adjust these paths accordingly for Unix-based OS's.
I wonder how many projects Luis Majano has posted on ForgeBox. We can look with the forgebox search
command: Hint, try pressing tab
while typing a command for auto-completion.
Wow, that Luis guy is busy! Let's install the the ColdBox MVC Platform. Don't worry, this won't hurt a bit.
We can create a skeleton ColdBox app really easy with the ColdBox generator commands. Let's give them a try:
Now that we have a nifty little test app, let's give it a spin. Wait, you don't need to install a CF server, CommandBox has one built in! You can start up an ad-hoc server in any folder on your hard drive simply by typing start
. It really couldn't be any simpler.
In a few seconds, a browser window will appear with your running application. This is a full server with access to the web administrator where you can add data sources, mappings, or adjust the server settings. Notice the handy icon added to your system tray as well. You can even edit the files in your new site from the command line:
When you're done playing, just shutdown your server with the stop
command. It will save all of its settings for the next time you start it. Feel free to delete the playground directory at any time. It won't break a thing.
You're well on your way to becoming a more productive you. Experiment with CommandBox to see what else you can do with it. This rest of this documentation book is a good place to start. Also, we have full documentation of every command in our Command API Docs.
If you run into issues or just have questions, please jump on our CommandBox Google Group and ask away.
CommandBox is Professional Open Source under the LGPL license. We'd love to have your help with the product. Commands are actually implemented in CFML which means you can write your own and share them on ForgeBox. See if you can figure out how to find and install the "Chuck Norris" or "Image To ASCII" commands. Also, the snake
game is a good way to cure boredom. These should give you some ideas of how you can contribute.
One common question is how to access the database from one of these scripts. Your code is executed on Lucee Server (version 4.5 at the time of this writing) which is the version of Lucee that the core CLI runs on. The CLI has the full power of a Lucee server running under the covers, but there's no web-based administrator for you to acess to do things like adding datasources for your scripts to use. It would considered poor form anyway since standalone scripts are best if they're self-contained and don't have external dependencies like server settings necessary to run.
So the easiest way to accomplish this is simply to exploit a little known but very cool feature of Lucee that allows the datasource attribute of most tags to be not only a string which contains the name of the datasource, but also a struct that contains the _definition_ of the datasource. This will create an on-the-fly connection to your database without any server config being necessary which is perfect for a stand-alone script. Here is what that looks like. Note, I'm using queryExecute(), but it would work just as well in a cfquery tag.
So, the first block simply declares a struct that represents a datasource connection. Then I use that struct as my datasource. You might be thinking, "where the heck did he get that struct??". Glad you asked. Start up a Lucee 4 server, edit a datasource that has the connection properties you want and then at the bottom of the edit page you'll see a code sample you can just copy and paste from. This is the code for an `Application.cfc`, but you can re-use the same struct here.
There are a couple tags inside Lucee that don't support this just yet. `<CFDBInfo>` is one of them. [Ticket Here] In this case, you need a "proper" datasource defined that you can reference by name. Lucee has some more tricks up its sleeve for this. You can simulate the same thing that happens when you add a datasource to your `Application.cfc` with the following code. This will define a datasource for the duration of the time the CLI is running in memory, but it will be gone the next time you start the CLI.
So let's break this down real quick. First we get the current settings of the CLI Lucee context and the list of current databases (may be null). Then we simply add the same datasource definition as above to the struct with the name we wish to use to reference this datasource. And finally we `update` the application with the new struct of datasources. Now we can use this datasource name just we would in a "normal" web application.
The internal CLI of CommandBox still runs on Luce 4.5 so make sure you copy the data source definitions from a Lucee 4.5 server, and not a 5.0 server. Also, you'll note I used encrypted passwords above. You can also just put the plain text password in. Just omit the `encrypted:` text like so:
Since CommandBox is a command line tool, it requires no GUI. If you are using an OS with a GUI (like Windows) and you run the box
executable, the CommandBox interactive shell will open in a new window. CommandBox looks and behaves like a Bash or DOS window, but the command prompt is not your native OS-- it's CommandBox running INSIDE your native shell and interpreting what you type.
As such, operating system commands won't execute (unless we've implemented a similar one in CommandBox). However, we also have a command called run
(See API Docs) which can be used to run native commands from within CommandBox. Command input parameters and flags won't necessarily match your OS's native shell. CommandBox uses its own parser and commands/parameters will be formatted as documented here.
Selecting and copy/paste may differ based on your operating system and how it treats command windows. CommandBox uses some color and formatting in its output. This uses ANSI escape codes and will only work correctly if you're using an ANSI-compatible shell to run CommandBox from.
If you have launched the CommandBox executable from your OS's GUI, it will run inside of a native shell window. When finished running commands, you can simply close the window, or type exit
an the window will close for you. If you have a series of commands to run, this is the recommended approach.
If you manually open your native shell and execute the box executable, it will take over the screen and the prompt will now become a CommandBox prompt. When you type exit
the CommandBox program will drop you back at your native OS shell.
You can also leverage CommandBox as another operating system binary if you want to execute one-off commands without having the need to go into the interactive shell. This is useful if you are integrating CommandBox with other system binaries, task runners, ANT, or you just want to execute a CFML template or CommandBox recipe.
Info Executing one-off commands might have a delay when executing as the CommandBox environment needs to load first.
So let's go a little deeper into CommandBox execution.
On Windows, /
or \
will be treated as the current drive root based on the current working directory. This is the same as DOS.
On all OS's, ~
will expand to the current user's home directory.
CommandBox allows you to access Java System Properties from the CLI and environment variables from your operating system via the ${name_here}
mechanism. But CommandBox also gives you the ability to create variables of your own directly in the shell. The scope (life) of these environment variables depends on how and where they are declared.
Every shell instance has its own set of environment variables you can set and read. These live for the duration of the shell and have the same lifespan as Java system properties in the CLI. There is an env
namespace of commands for dealing with environment variables.
To set a new variable, you can run this:
You can view the contents of that variable from anywhere in the same shell session like so:
Clear out an environment variable like so:
In addition to the global shell environment, each executing command receives its own set of environment variables that go away when the command finishes executing. Unlike Bash, the parent variables are not copied into each command, but a hierarchy is maintained and when a variable is not found, the parent command is checked and so on until the global shell variables. After that, the Java system properties and then OS's actual environment is checked.
Here is a contrived example of an echo
command that run a sub command as part of a command expression (backtick expansion). The sub command sets an environment variable and then outputs it.
The first line will output the text "Cheese" but the second line will output the default value of "myDefaul" since the variable only existed in the inner context of the expression and isn't visible to the outer shell.
Recipes behave like a subshell and any variables set in a recipe will live for the duration of that recipe but will be gone once the recipe exits.
To view the environment variable for the current command context, run:
The output is a JSON serialized struct, which makes it suitable for programmatically accessing.
There is a command to help you debug what variables are set in each command context as well as the global shell. Here we pipe some commands into a recipe for execution. The context for the env debug
command has no variables, the recipe
command has a variable called inRecipe
and the global shell as the 2 variables from the example above.
Any environment variables you set in the CommandBox shell will be available to the native process that your OS binary runs in. Here's a Windows and *nix example of setting an env var in CommandBox and then using it from the native shell.
Any ComandBox environment variables present in the shell will automatically be passed to the environment of the server process. This means, given an example like this:
The CFML code running that server process will be able to "see" the foo
environment variable.
When a command has an argument with a type of Globber
for a file path, that means you can use file globbing patterns to affect more than one file at a time. Globbing patterns are common in Bash as well as places like your .gitignore
file. They use common wildcard patterns to provide a partial path that can match zero or hundreds of files all at the same time.
If a globbing pattern contains a question mark, that will match any single character. So a pattern of ca?.txt
would match car.txt
, and cat.txt
, but not cart.txt
. You can use a wildcard more than once. p?p?.cf?
would match files named papa.cfm
and pipe.cfc
.
If a globbing pattern contains a single asterisks, that will match zero or more characters inside a filename or folder name. So d*o
matches doodoo
, dao
, and just do
. The wildcard only counts inside a file or folder name, so models/*.cfc
will only match cfc files in the root of the models folder.
To extend the previous example, if we did models/**.cfc
that would match any cfc file in any subdirectory, no matter how deep.
Here's some examples of what file globbing might look like:
Here's some more examples of how the wildcards work
You can already execute CFML functions in the REPL
command to play in a sandbox, but sometimes you want to go further and actually use CFML directly in the CLI. This is where the cfml
command comes in handy. The following runs the now() function. It is the equivalent to repl now()
.
As a handy shortcut, you can invoke the cfml
command by simply typing the name of the CFML function, preceded by a #
sign.
When you pass parameters into this command, they will be passed directly along to the CFML function. The following commands are the equivalent of hash( 'mypass' )
and reverse( 'abc' )
.
This really gets useful when you start piping input into CFML functions. Like other CFML commands, piped input will get passed as the first parameter to the function. This allows you to chain CFML functions from the command line like so. (Outputs "OOF")
By piping commands together, you can use CFML functions to transform output and input on the fly to generate very powerful one-liners that draw on the many CFML functions already out there that operate on simple values.
Since this command defers to the REPL for execution, complex return values such as arrays or structs will be serialized as JSON on output. As a convenience, if the first input to an array or struct function looks like JSON, it will be passed directly as a literal instead of a string.
The first example averages an array. The second outputs an array of dependency names in your app by manipulating the JSON object that comes back from the package list
command.
The sky is the limit with the mashups you can create. This example runs your native java
binary, uses CFML functions to strip out the first line, and then grabs a portion of that string via regex in the sed
command.
You must use positional parameters if you are piping data to a CFML function, but you do have the option to use named parameters otherwise. Those names will be passed along directly to the CFML function, so use the CF docs to make sure you're using the correct parameter name.
Do you ever get tired of typing some built in commands and you'd like to just alias them as something simpler? You can create arbitrary alises now that reduce the amount of typing you do.
In the above example, it's the same thing as typing coldbox create app myApp
.
Aliases are treated as in-place shell expansions so you can alias anything including default parameters as well as multiple commands chained together.
In the above example, typing foobar
is the same as running the giant command string that's being set into the alias.
If you create an alias that matches an existing command name, your alias will take precedence since aliases are expanded before commands are resolved.
Here we can change the name of a common command like echo
that we really wish had been named print
.
Let's take it a step further and alias the alias!
Running cout brad
is the same as running print brad
which is the same as running echo brad
. Try not to get dizzy when doing this, please.
Do you also always type certain parameters every time you run a command, like always typing --force
after rm
? Any command parameter can be defaulted at a global level so you don't have to type it every time. These defaults will always be overridden if you actually supply the parameter when running the command.
The above example is the same as running rm myFile.txt --force
since we've defaulted the force
parameter to always be true when not otherwise specified. If you wanted to override your default, you could do so by actually specifying the parameter from the CLI like this:
CommandBox contains a REPL
command which is a powerful tool to execute ad-hoc CFML code from the command line. A REPL reads user input, evaluates it, prints the result, and then repeats the process. The CommandBox REPL supports the inline execution of both CF script or tags.
The default mode of the REPL
command is to accept script. You can enter most any CF Script into the prompt for execution. If the script is an expression that returns a value, or sets a variable, that value/variable will be output. Variables that you set will be available to you until you exit the REPL
command.
Multi-line statements are also allowed. If you have typed a starting {
without an ending }
, the REPL will keep accepting lines until it has determined the statement to be finished. The prompt changes to ...
until the statement is finished.
If you would like to abort a multi-line statement, simply type exit
at the prompt.
You can also enter tags at the REPL. Switch to this mode by setting the script
flag to false.
Any output from the tags will be returned to the console.
Multi-line statements are not currently supported in the tag REPL.
The script and tag REPL have their only history. Use the up
and down
arrows to access previous things you typed. Your REPL history can be viewed and managed by the history
command (once you exit the REPL).
Tab completion is currently not supported in either of the REPLs.
You can use environment variable expansions in the REPL with the same syntax that works in the CLI and JSON files. Consider this example which sets an environment variable in the shell and then enters the REPL command and references the variable. Note, the variable is expanded in-place, so you still need to wrap it in quotes so the resulting CFML code is valid.
Escapes work the same way in the REPL
Many commands accept parameters to control how they function. Parameters are entered on the same line as the command and separated by a space and can be provided as named OR positional, similar to how CFML functions can be called. You cannot mix named and positional parameters in the same command though or an error will be thrown. There is also a concept of "flag" for boolean parameters that can be combined with named or positional parameters for brevity and readability.
Named parameters can be specified in any order and follow the format name=value
. Multiple named parameters are separated by a space.
Positional parameters omit the name=
part and only use the value. They must be supplied in the order shown in the or help command. We try to place the most common parameters at the beginning so you can use named parameters easily. Here is the equivalent of the named command above:
Of course, only the required parameters must be specified. I'm only including all of them here for the completeness of the example.
If you do not provide a parameter that is required for the command execution, the shell will stop and ask you for each of the missing parameters before the command will execute.
Info It is not necessary to escape special characters in parameter values that are collected in this manner since the shell doesn't need to parse them. The exact value you enter is used.
Any parameter that is a boolean type can be specified as a flag in the format --name
. Flags can be mixed with named or positional parameters and can appear anywhere in the list. Putting the flag in the parameter list sets that parameter to true. This can be very handy if you want to use positional parameters on a command with a large amount of optional parameters, but you don't want to specify all the in-between ones.
You can also negate a flag by putting an exclamation point or the word "no" before the name in the format --no{paramName}
. This sets the parameter to false which can be handy to turn off features that default to true.
Now that we're starting to use CommandBox in a lot of cloud scenarios like Docker, we're looking for more and more ways to have dynamic configuration. The most common way to do this is via Java system properties and environment variables. We've wrapped up those two into a new concept called System Settings. Now any time you use ${mySetting}
in a command parameter, a box.json
property, server.json
property, or a Config Setting, that place holder will be replaced with a matching JVM property or env var (in that order) at runtime. This is great for setting things like ports, default directories, or passwords and other secrets as an env variable so it can be different per server and not part of your code.
You can test it out easily by outputting your system path like so:
If a system setting can't be found in a Java property or an environment variable, an empty string will be returned. You can provide a default value like so.
This does assume that your default value will never contain a colon!
System settings are looked up in the following order. If the same variable exists in more than one place, the first one found will be used:
Environment variables for the currently executing command
Environment variables for the parent (calling) command (if applicable)
Global shell environment variables
JVM System Properties in the CLI process
Environment Variables from your actual operating system
For example, if you run the following it will output the contents of your OS's PATH
environment variable.
However, if you set a shell environment variable from inside CommandBox called path
and then output it, you will see the contents of your variable since it overrides.
When box.json
or server.json
files are read, they automatically have all system setting setting placeholders swapped out. For instance, you can specify the port for your server in your server.json
like so:
Note, we escaped the system setting by putting a backslash (\
) in front of it. That's because we wanted to insert the actual text into the file and not the value of it! The resultant server.json
is this. Note the system setting needs to be encased in quotes so it's just a string for the JSON.
Now, if your server has an environment variable called WEB_PORT
, it will be used as the port for your server.
System settings can also be used in object key names as well in your JSON files. Here is an example of a .cfconfig.json
file with a dynamic datasource name.
Note if there are duplicate key names after the system settings are expanded, the last one expanded will win.
You can use system settings and environment variables in the REPL using the same syntax as the CLI
If you're writing a custom command or task runner that reads a JSON file of your own making, you can do easy system setting replacements on the file.
The expandDeepSystemSettings()
method will recursively crawl the struct and find any strings with system setting placeholders inside them. Be careful not to write back out the same struct after you've done replacements on it. Otherwise, you'll overwrite the placeholders with the current values!
You can also manually replace system setting placeholders in a single string like so:
The SystemSettings
service also gives you programmatic access to individual system settings in your custom commands and task runners.
The CommandBox interactive shell already allows for a command to pipe data into another Command.
Since CommandBox commands don't have a "standard input", the output of the previous command is passed into the second command as its first parameter. In this instance, the grep
command's first parameter is called input
so it receives the value returned by the cat
command. The "find me"
text becomes the second parameter-- in this case, expression
.
There is nothing special about a parameter that can received piped input. In fact, any command can receive piped input for its first parameter. The following commands all accomplish the same thing.
This allows you to get creative by combining commands together like so:
This takes a package name and replaces some text on output. One benefit is that Windows users don't have a native sed
command in their OS, but those commands inside a CommandBox Recipe will execute consistently on any machine.
What if you aren't using the interactive shell and you want to pipe into CommandBox from your OS's native shell? This is also supported, and as long as there is a command specified, the piped input will become the first parameter as before.
If you pipe text directly into the box executable with no command specified in the parameters, each line of your piped text will be read from the standard input as a command.
Help is integrated at every level in CommandBox. You can help global help, namespace help, or command help at any time.
To get an overall list of all the commands you have available to run, simply type help
at the shell.
Next, drill down and get help on a specific namespace like server
.
And finally, get help on a single command such as server stop
. We can see the command is also aliased as just stop
as well as all the possible parameters and their types along with a few sample ways to call the command.
For a full list of all the commands that ship with CommandBox as well as all their paramaters and samples, please visit our which are auto-generated each build. This is the same information available to you via the help
command, but in a searchable format you can browse outside of the CLI.
Sometimes, you need to view the CommandBox log file. Maybe it is to debug a command you are writing or to . The system-log
command outputs the path to the CommandBox log file. You can use it creatively by piping its output in to other commands:
When you run box
without any parameters, you get the CommandBox interactive shell. We use a library called JLine for this interaction and it has a number of bash-like behaviors to make you more productive. CommandBox also bundles several bash-like commands to give you a consistent shell regardless of whether you're on Windows or Linux.
Pressing Ctrl-C will send an interrupt signal to the terminal which will end any currently executing command and exit you back to the shell's prompt. Pressing Ctrl-C if you're already at the prompt won't do anything at all.
Pressing Ctrl-D from a prompt sends an OEF signal and will exit out of the shell entirely, just like if you had run the exit
command.
CommandBox allows you to re-run items from your command and/or REPL history by pressing the up arrow to cycle through previous commands. You can type a partial command like cd
and then hit up arrow and the history items will be filtered to items starting with that. You can also use what's commonly known as i-search
. Press Ctrl-Shift-R to open a search from the console where you can search your entire command history by keyword. Keep pressing Ctrl-Shift-R to cycle through the results. Press Ctrl-Shift-S to cycle backwards through the results.
Like Powershell or Bash, you can type the following to switch back to the previous working directory:
If you run this same command more than once, you will keep toggling between the same two directories (bash behavior)
One of the most productive features of the shell is tab completion. This means you can type a partial command and hit the tab key on your keyboard to be prompted with suggestions that match what you've typed so far. If there is only one match, it will be finished for you. This can save a lot of typing and will be a familiar concept to those already living in a CLI environment.
When "tab" is pressed, the text you've entered so far is run through the CommandBox command parser to see if it can match a namespace, command, or parameters. If you press tab at an empty prompt, all top level commands and namespaces will display. Since tab completion is run through the standard command parser, that means it works on command aliases as well.
The tab completion options are broken up into groups to visualize the commands, parameters, flags, etc. As you type, the list of available options will auto-filter for you. You can keep hitting tab to toggle through the available options and you can press enter to select the one you want.
If your text matches only command, namespace, or alias, it will be auto-filled in for you. For instance, if you type the following and press tab...
the coldbox namespace will be filled in and followed by a space so you are ready to continue typing.
If you then press tab again, you will be presented with a list of second-level namespaces inside of coldbox and the same prompt will be output again below it so you can continue typing.
If the parser finds a complete command, it will move on to parameter completion which is slightly more complicated since at first, there is no way to tell if you are going to named parameters, positional parameters, and/or flag. Based on what parameters you've typed so far, if any, CommandBox will do it's best to give you only relevant options. If it is unsure, it will provide you with every possibility it can think of. Don't be afraid to try pressing tab while typing parameters, you may be surprised how often we can guess where you're going!
Here is CommandBox giving every option possible for the delete command. Note, force and recurse are booleans, so they can be specified as flags.
If you have started typing named parameters, CommandBox will only suggest unused named parameters and flags.
If you are using named parameters, and you have typed the name of a parameter followed by an equals sign and no space, CommandBox will attempt to prompt valid values. This includes but is not limited to booleans and file system paths.
Here, true and false are offered as possible values for the force parameter.
Here, all files and folders in the current working directory are offered as possibilities for the path parameter of the delete command.
Tab completion for positional parameters works the same as the "value" portion of named parameters. Parameter names will also show up when you hit tab even when using positional parameters. This is on purpose to remind you of what options you have, but you obviously won't type them.
Tab completion will always work for flags if your command has any boolean parameters. Here we type --
in the delete command and we are prompted with --force
and --recurse
.
Commands have the ability to give hints in the form of a static list or a runtime function with dynamic output.
Here the forgebox show command dynamically provides completion for its type
attribute based on the current types returned by the ForgeBox REST API.
When writing code inside the REPL, you can also press tab to get completion on
CFML function names
Member function names like .append()
Variable names you have created as part of your REPL session
The foreach
command will execute another command against every item in an incoming list. The list can be passed directly or piped into this command. The default delimiter is a new line so this works great piping the output of file listings directly in, which have a file name per line.
This powerful construct allows you to perform basic loops from the CLI over arbitrary input. Most of the examples show file listings, but any input can be used that you want to iterate over.
This example will use the echo command to output each filename returned by ls. The echo is called once for every line of output being piped in.
The default command is "echo" but you can perform an action against the incoming list of items. This example will use "cat" to output the contents of each file in the incoming list.
You can customize the delimiter. This example passes a hard-coded input and spits it on commas. So here, the install command is run three times, once for each package. A contrived, but effective example.
If you want a more complex command, you can choose exactly where you wish to use the incoming item by referencing the default system setting expansion of ${item}. Remember to escape the expansion in your command so it's resolution is deferred until the forEach runs it internally. Here we echo each file name followed by the contents of the file.
You may also choose a custom placeholder name for readability.
The forEach
can also iterate over JSON representations of objects or arrays. This means you can pipe in JSON from a file, a command such as package show
or any REPL operation that returns complex data. The delimiter
parameter is ignored for JSON input.
If iterating over an array, each item in the array will be available as ${item}
. If iterating over a object, the object keys will be in ${item}
and the values will be in ${value}
. You can customize the system setting name for value with the valueName
parameter to forEach
.
Even though you can run CommandBox from your favorite terminal window, there are a number of nice IDE integrations out there that are designed to allow you to run command line utilities from inside your favorite editor. Here's a few that we're aware of and how to use them. If you have more, please let us know!
We believe all work and no play makes you a dull boy (or girl!). You'll notice the interactive shell has a handful of quotes and tips that show up when the shell starts. If you have ideas or suggestions for new ones, please send pull requests or let us know.
If you remember the "Magic Eye" books from your childhood, you'll be pleased to know CommandBox has an ASCII Art Stereogram for every day of the month. You'll find it hiding inside the info
command. The image will change every day at midnight.
If you're not familiar with how to view these, you want to "diverge" your eyes. This is what happens when you look at something far away and it's the opposite of crossing your eyes. Start with your face closer to the monitor and looking square on. Relax your vision and look past the monitor until the image starts to overlap itself (that's your eyes diverging) until the repeated elements match up again (like the clouds above). Different parts of the image will appear to be different distances away from you.
If you can't see it right away, don't worry. Practice makes perfect and the more you do it, the easier it is. You'll get the hang of it, we promise!
CommandBox has a global configuration file that stores user settings. It is located in ~/.CommandBox/CommandBox.json
and can be used to customize core CommandBox behaviors as well as overriding module settings. Config settings are managed by the config set
, config show
, and config clear
commands.
Nested attributes may be set by specifying dot-delimited names or using array notation. If the set value is JSON, it will be stored as a complex value in the commandbox.json.
Set module setting
Set item in an array
Set multiple params at once
Override a complex value as JSON
Structs and arrays can be appended to using the "append" parameter. Add an additional settings to the existing list. This only works if the property and incoming value are both of the same complex type.
Output a setting:
Nested attributes may be accessed by specifying dot-delimited names or using array notation. If the accessed property is a complex value, the JSON representation will be displayed
To Remove a setting out of the CommandBox.json
use the config clear
command. Nested attributes may be set by specifying dot-delimited names or using array notation.
A plugin to run your Commandbox tasks from within Sublime plus some handy snippets too.
Install Via Package Control Commandbox
If you have PackageControl installed, you can use it to install the package.
Just type cmd-shift-p
/ctrl-shift-p
to bring up the command pallete and pick Package Control: Install Package
from the dropdown, search and select the CommandBox
package there and you're all set.
You can clone the repo in your /Packages
(Preferences -> Browse Packages...) folder and start using/hacking it.
If you are having trouble running the plugin in Mac OSX it's possible that your path isn't being reported by your shell. In which case give the plugin SublimeFixMacPath a try. It may resolve our issue.
If you still can't get it to run properly, first make sure your Commandbox tasks run from a terminal (i.e. outside of sublime) and if so then submit an issue.
You may select pre-configured commands from Menu -> Commandbox
, including the ability enter a custom command.
Ctrl+Shift+B
- Run Commandbox Command: A prompt input will open for you to enter your command
Ctrl+Shift+T
- Start the Embedded Server: Your Commandbox cwd
is always the root of your Sublime Project so any box.json
configuration will be honored
Ctrl+Shift+P
- Stop the Embedded Server
Alt+P
- Show the Commandbox Output Panel ( also available in the View -> Commandbox
menu )
Alt+[Command|Windows]+P
- Hide the Commandbox Output Panel ( also available in the View -> Commandbox
menu )
The file Commandbox.sublime-settings
is used for configuration, you can change your user settings in Preferences -> Package Settings -> Commandbox -> Settings - User
.
The defaults are:
You may override your PATH
environment variable as follows:
box installed locally
If box is installed locally in the project, you have to specify the path to the box executable. Threfore, adjust the path to /bin:/usr/bin:/usr/local/bin:node_modules/.bin
If set to true
, a new tab will be used instead of a panel to output the results.
Defines the delay used to autoclose the panel or tab that holds the Commandbox results.
If true it will open the output panel when running Commandbox (silent)
only if the task failed
Toggles the creation of sublime-commandbox.log
if any error occurs.
Syntax file for highlighting the box results. You can pick it from from the command panel as Set Syntax: Commandbox results
.
Set the setting to false
if you don't want any colors (you may need to restart Sublime if you're removing the syntax).
When enabled, the package will read the streams from the task process using two threads, one for stdout
and another for stderr
. This allows all the output to be piped to Sublime live without having to wait for the task to finish.
If set to false
, it will read first from stdout
and then from stderr
.
You can use a shortcut for running a specific task like this:
It's important to note that each server you start opens a new Java process on your host operating system. This allows each server to have it's own settings and configuration independent of any other server. Start as many as you need and simply stop them when you're done. Just keep in mind each server gets its own heap space so keep an eye on your available RAM.
The embedded server instances are also a separate process from the actual CommandBox CLI process, which also runs on Java. This means you can open the interactive shell, start a few servers, then quit the shell, yet the servers will still continue to run. You can use the CLI to issue a stop
command in the servers web root, or just right click on the tray icon.
There is currently no way to have servers start automatically when your computer boots, though there's nothing preventing you from setting up a local script to run the start commands for you.
You may be used to having your server's WEB-INF folder living in your web root. The CommandBox embedded server still has a dedicated WEB-INF folder for each server you start, but it lives under the main CommandBox installation directory in your user folder. Changes you make to the WEB-INF such as adding jars or new tas will be persisted until you issue a server forget
command.
CommandBox allows you full control over the servers you start. This includes the port and host, custom JVM args, URL rewriting, web aliases, custom error pages, and custom welcome files.
Configuration can be set at several different levels:
Passed as parameters to the server start
command
Stored in a server.json
file for that server
Global defaults in the server.defaults
config setting
Internal defaults from the ServerService
Settings will be used in that order. Also, any parameters passed to the start
command will automatically be saved to your server.json
file unless you pass the --noSaveSettings
flag.
A lot of settings used to start a server involve file paths. Paths starting with a drive letter like C:/
, a UNC network path like \\
, or a leading slash like /
are considered absolute paths and will not be expanded. Try to avoid absolute paths if you want to make your server config portable.
Paths that start with a file/folder name like foo/bar.jar
or ../../lib/my.jar
are relative and the root folder that they are relative to depends on where there are specified.
If the path is passed as a parameter to the start command, the path is relative to the current working directory
If the path is in the server.json
file, it is relative to the folder containing the JSON file. (Remember the server.json
doesn't have to be in the web root!)
If the path is in a global server.defaults
config setting, it is relative to the web root of the server.
This module will customize your CommandBox prompt while in the interactive shell. It has multiple "cars" that are part of the train and each car can contribute some output to the prompt that is working directory-aware.
THIS MODULE REQUIRES COMMANDBOX 4.0.0!
This project is based on the Zsh Bullet Train theme which is based on the Powerline shell prompt. The goal is to add in additional information to your prompt that is specific to the current working directory, or the last command you ran.
Install the module like so:
This module uses some special Unicode characters to draw the prompt that may not be in your default terminal. You can turn off all Uniode chars and live with an uglier shell like so:
Or try a font like Consolas
, DejaVu Sans Mono
, or Fira Code
. The best way to get all the characters to work is to install a "Powerline patched" font and set your terminal to use it. This may differ based on your operating system.
https://github.com/powerline/fonts.git
Here is a guide for setting a new font up to be used with the Windows cmd terminal:
https://www.techrepublic.com/blog/windows-and-office/quick-tip-add-fonts-to-the-command-prompt/
For Windows users, we also recommend using ConEMU as your terminal.
You don't need to do anything special. Just continue to use the CommandBox interactive shell like you always do. You'll notice that the prompt is spanned across two lines and contains additional information. Cars that do not apply to the current directory will simply not be displayed. Familiarize yourself with what each bullet train "car" represents and soon you'll be using the data in the prompt without even thinking about it!
You can customize the cars that show, change the colors of existing cars and even create your own custom additions to Bullet Train. Read all about it in the readme of the Module homepage on ForgeBox.
CommandBox has support for 256 colors in the console, but this is limited by the terminal in use. For instance, SSHing into a Linux server with PutTTY only supports 8 colors. Windows cmd only supports 16 colors. Most Mac terminals seem to support 256 colors by default.
For Windows users, we recommend using an add-on terminal like ConEMU which has good 256 color support out of the box. To find out how many colors your terminal supports, you can run this command:
This will show you at the top how many colors are supported. It will also output a sample of each of the 256 colors. Terminals that support less than 256 colors will "round" down and show the next closest color automatically. Some darker colors might turn to black. Note, some advanced terminals allow the user to choose color themes which will also change the default colors. CommandBox has no control over how colors show up for you.
The names and numbers of each color are unique and important if you want to do any Task Runners, custom commands that make use of these colors. Modules like Bullet Train also allow you to customize their colors. You can specify a color by its name like LightGoldenrod5
or its number (221
).
In a Task Runner or custom command, the print helper would look like this:
Here's an example of customizing your Bullet Train module to use fancy colors. (Color 21 is Blue1
)
Never miss an update again by installing the CommandBox update check module for ForgeBox. It will check for new versions of the core CommandBox CLI as well as any of your installed system modules once a day when the CLI starts up in interactive mode. Internet connection required.
These settings affect how CommandBox loads modules.
array
You can store CommandBox modules outside of the default installation directory. This may be useful to point to modules you are developing or to keep custom modules around even if CommandBox gets uninstalled.
array
An array of module names to load. Be careful of using this setting as once you set it, no other modules will be loaded which includes all of CommandBox's core modules.
array
An array of module names NOT to load. This can be useful when you have an installed module that's erroring on load and preventing CommandBox from starting up.
struct
When you install a CommandBox module, it may contain settings that affect how it works. Don't edit the CFML code in the module, instead use the config set
command to create config settings that will override the module's defaults. The pattern is modules.moduleName.settingName
.
When a module is loaded, the config settings (that exist) for that module are loaded as well. Any time you set a new module setting, that setting will be loaded into memory immediately for that module.
You can easily see what settings are set for our TestModule
like so:
If you need to use CommandBox behind a corporate proxy, these settings will be necessary for it to successfully connect to the Internet.
string
This is the URL of the proxy server on your network.
integer
This is the port to connect to on the proxy server.
string
This is the username to connect to the proxy server with, if required.
string
This is the password to connect to the proxy server with, if required.
These are some one-off settings that doen't really belong anywhere else.
string
This setting affects how CommandBox invokes the shell for the run
command or when using the !binary
shortcut. The default *nix shell used for the run
command is /bin/sh
but you can override it to use a custom shell. Set the full path to the shell binary.
boolean
Running the bump
command from a Git repo will attempt to tag the repo unless you provide the tagVersion
parameter. This setting provides a global default to prevent CommandBox from trying to tag Git repos.
string
Running the bump
command from a Git repo will tag the repo using the format v{version}
such as v1.0.0
or v4.3.6
. You can remove the v
or swap it for another prefix using the tagPrefix
parameter. Remember, another string like foo1.2.3
will not be parseable by CommandBox as a valid semver. This setting can be overriden by the tagPrefix
parameter to the bump
command.
string
You can control where your artifact cache is stored with the artifactsDirectory
config setting. This can be useful to keep your primary drive from filling up, or to point your files to a shared network drive that your coworkers can share.
Sometimes you may wish to start a server on a computer that doesn't have access to the Internet. However, you may notice that running a command such as the following will throw an error trying to connect to ForgeBox:
That is because 5.x
is a semver range and not a specific version. CommandBox must connect to ForgeBox to see what versions of the CF engine lucee
can be found to use the latest one.
If you know that a CF engine is already downloaded in your server's artifacts directory, start your server with a specific major, minor, and patch version to skip the ForgeBox check.
NOTE: If this fails, check the location of the folder structure below the artifacts folder for it's exact path. e.g. /artifacts/lucee/5.0.0+252/lucee.zip - The box command for this would be: start cfengine=lucee@5.0.0+252 This follows the pattern: /artifacts/[server-type]/[server-version]/[server-type].zip Useful if you've manually downloaded the file from forgebox and need to rename it.
If CommandBox needs to connect to ForgeBox to resolve a version number and ForgeBox is unavailable, it will look in your local artifacts cache to try and find a cached version of that CF engine that satisfies your semver range. This means you may not get the latest version of that CF Engine, but at least your server will start up.
These settings are used to configure CommandBox's endpoints.
string
The API Token provided to you when you signed up for . This will be set for you automatically when you use the forgebox register
or forgebox login
commands. This token will be sent to ForgeBox to authenticate you. Please do not share this secret token with others as it will give them permission to edit your packages!
string
This is the URL of the ForgeBox REST API. Remove this setting to use the default. If you wish to test submitting package in an environment other than production, you may point to our staging server. Note, this will funnel ALL ForgeBox calls to the staging server where your APIToken may be different.
One of the most useful features of CommandBox is the ability to start an ad-hoc server quickly and easily. Any folder on your hard drive can become the web root of a server. To start up the server, cd
into a directory containing some CFML code, and run the start
command. An available port will be chosen by default and in a few seconds, a browser window will open showing the default document (index.cfm
).
To stop the embedded server, run the stop
command from the same directory.
You can start as many embedded server instances as you want. Each running server will add an icon in your system tray with the logo of your currently running engine. Click on it for options:
Stop Server
Open Browser
Open Admin
Open File System
If you don't want the tray integration, then you can turn it off in your server.json
with this setting.
Or turn it off at a global level in your config settings.
Any ComandBox environment variables present in the shell will automatically be passed to the environment of the server process. This means, given an example like this:
The CFML code running that server process will be able to "see" the foo
environment variable.
If a server isn't starting, the first thing to run is the server log
command. It will show you the console log for that server. Note, this dumps the entire log file to the console, which may be very large. We recommend using the tail
or --follow
tricks below.
If the log is very large, use the tail
command to just see the last few lines of it.
To get a live stream of the console log from a running server, use the --follow
flag and the command will continue streaming new lines to the console until you press Ctrl-C to stop.
You can also look at your server's access log (if enabled) and rewrite log (if enabled).
You can use the --console
flag to the server start
command to start a server in the foreground. The console log will be live-streamed to the CLI and the log will continue streaming as long as the server is running. Press Ctrl-C to stop the server and stop streaming the log file.
You can get additional information about a server start with the --debug
flag. When debug is set, the start
command will not exit immediately, but wait for the server to come up and live stream the debugging information and server logs to the console while the server is coming up.
You may still really be having issues getting your server to start up correctly due to a setting not getting picked up, rewrites not working, or maybe a jar not loading. You can "drink from the firehose" so to speak by turning on trace
level logging. This works best when starting the server via the console so you can watch the logging as it streams past.
Here are suggestions for using VSC (Visual Studio Code) for developing in CFML.
What do you want to do with VSC?
Install it?
Key Extensions?
Working with the shell/terminal
Git Extensions?
This IDE has it's own domain. ( ) with downloads for macOS, Windows and Linux on the home page. :+1:
You can approach this different ways. It is pretty nice to have the command prompt running right inside your IDE. Pressing CTRL +` will show and/or hide your terminal. This will let you run Commandbox directly inside your terminal.
Go to File > Preferences > Settings
and search for shell.windows
. Hover over the item in DEFAULT SETTINGS
and you will see an edit pencil. Click on that and it will copy the values over to USER SETTINGS
. (NOTE: You can also set stuff up in WORKSPACE SETTINGS
for different projects. Now set the location of commandbox on your system like we did in our system in the example below.
"terminal.integrated.shell.windows": "/path/to/box",
When adding a path, follow the rules for adding platform specific path seperators.
Install Shell Launcher and reload the IDE.
Now open your user settings like is shown in the Commandbox only section just above. Add the following to your USER SETTINGS
.
//Shell launcher
// A list of shell configurations for Windows
"shellLauncher.shells.windows": [
{
"shell": "C:\\Windows\\sysnative\\cmd.exe",
"label": "cmd"
},
{
"shell": "/path/to/box",
"label": "Commandbox"
}
],
If you have commandbox mapped to a path you can of course just call box like you would from any terminal and it will load right up for you. Just use any terminal in VSC that would load box
outside VSC and it will run the same.
You should also install a few extensions. (These extensions can also be added from the built in Extensions item.)
Additional Extensions ( of course, choose the ones you want and ignore the others )
More information to follow. (Including video guides to show how to get started that may not be as familiar with different parts.)
You can specify the CFML engine via the command line arguments:
This will start an Adobe ColdFusion 9 server in your webroot. That's it!
By default, CommandBox uses the cfengine
slug to search for the engine on ForgeBox. The format is slug@version
where the version is optional. Ortus Solutions maintains the versions of the engines available on ForgeBox.
Supported engines are:
Adobe ColdFusion 9 **
Adobe ColdFusion 10
Adobe ColdFusion 11
Adobe ColdFusion 2016
Adobe ColdFusion 2018
Railo 4.2
Lucee 4.5
Lucee 5
Here are some examples:
Engines are downloaded and stored in your CommandBox artifacts folder. You can view your engines and clear them using the standard artifacts commands:
While Lucee asks for a password the first time running the admin, ColdFusion requires a username and password when CommandBox sets it up. The default username and password for the Adobe ColdFusion servers used are:
Username: admin
Password: commandbox
Additionally, CommandBox can start any WAR given to it using the WARPath
argument.
If you run a regular start
command inside of a folder that has a /WEB-INF/web.xml
file, CommandBox will treat that folder as a WAR.
The cfengine
parameter can accept any valid CommandBox endpoint ID. That means it can be an HTTP URL, a Git repo, a local folder path to your company's network share, or a custom ForgeBox entry you've created. As long as that endpoint resolves to a package that contains these files, you're good:
box.json
Engine.[zip|war]
(file name doesn't matter)
CommandBox will download the package, unzip it and use the WAR/zip file as the engine for your app.
Normally, the artifacts cache isn't used for non-ForgeBox packages, but CommandBox will only download the engine once per server and then assume the file hasn't changed. You will need to forget the server to trigger a new download.
Here's an example of starting up a web server using a direct download link to a package containing a WAR file:
You can set the cfengine
and other related configuration options in your server.json
to use them every time you start your app.
These commands would create the following server.json
Just a reminder that starting a server with any command line arguments will save the arguments to your server.json
by default.
This command would add adobe@9
to your server.json
. If this is not what you want, you can append saveSettings=false
or even --!saveSettings
when you start your server and CommandBox will not save the arguments you specify to your server.json
.
CommandBox stores information about each of the servers you've ever started inside ~/.CommandBox/servers.json
so it can remember settings from one run to the next.
You can see an overview of your servers and what state they're in with the server list
command.
If you have many servers, you can provide parameters to help filter the results from server list
To list only the servers that have been started in a given directory, use the --local
flag.
You can take a quick look at the what's been happening with the server log
command or use the server status
command to see more detailed information including the arguments used previously to start/stop the server.
Servers are uniquely identified by their full path, but they also have a short name which defaults to the immediate folder containing their web root. The stop
, start
, etc commands can be run in the web root for a server, or in any working directory as long as you reference the server's short name.
Another handy shortcut is the server cd
command that will change the current working directory of the interactive shell to the web root of a named server.
Info Server name is the first parameter to all server commands and tab completion works too, making it as easy as possible for you.
You can get information about a server using the server info
command. Add the --JSON
flag to get the data back in a JSON format. The property
parameter will allow you to retrieve a single value for scripting mashups.
If you want to wipe all configuration, logs, and WEB-INF files for a server, use the server forget
command. This will also remove any administrator settings you may have saved including data sources, mail servers, and server mappings.
You can forget all your servers at once too if you want to start with a clean slate. This command will stop and forget all servers.
Your CF engine (Lucee, Adobe, etc) or Java app may have application logs of its own and their locations will vary based on what you have running. In any case, they will most likely be located under the server home directory.
You can find out where your server home is by running:
You can also get the full path to your servlet's "out" log with this command:
This log file is the equivalent of your catalina.out file on a typical Lucee/Tomcat install or the equivalent of your coldfusion-out.log file on a typical ColdFusion install.
The Servlet's "out" log can be tailed with this command:
Your console "out" log will auto-rotate every 10MB to keep it from getting too big. Don't use the --debug
or --trace
flag on a production server or you'll get a lot of logging information! Without those flags, the "out" log doesn't log anything for each request. With debug enabled, you'll get basic information for each request that comes in as well as whether a rewrite rule fired, and with trace, you'll get a ton of information about every request as well as every local path resolution by the path resource manager.
There are many log files for Lucee. For the guide below, I'm assuming you haven't set a custom serverConfigDir or webConfigDir for your servers. If you have, adjust the paths for the server and web context to be whatever it is you've configured. Here are the three locations you'll find log file and is pretty much the same for Lucee 4 and Lucee 5.
Lucee's server context log files - The server context is located under the server home which you can find with the command server info property=serverHomeDirectory. Open that directory and then navigate to WEB-INF/lucee-server/context/logs/.
Lucee's web context log files - The web context is also located under the server home. Open that directory and then navigate to WEB-INF/lucee-web/logs/.
So, to give real examples-- a Lucee server I just looked at on my machine has the three folders of log files I just covered above in these locations:
Since Adobe doesn't have the separation of server and web contexts, it only has two log locations which are as follows on all versions.
ColdFusion server log files - The remaining log files are located under the server home which you can find with the command server info property=serverHomeDirectory. Open that directory and then navigate to WEB-INF\cfusion\logs/.
So, to give real examples-- a ColdFusion server I just looked at on my machine has the two folders of log files I just covered above in these locations:
CommandBox servers use a powerful Java-based web server which we've tested to have throughput just as good as Apache or IIS. You can enable "access" logs which output one line for each HTTP request (even for static assets like JS or image files) in the same "common" format that Apache web server uses.
View the location of this log or tail the log contents like so:
Your access log will be auto-rotated every day.
CommandBox servers use the java-based Tuckey rewrite engine for easy URL rewriting. There's a lot of good debugging information available to help figure out why your rewrites aren't working. You can enable a separate rewrite log to view this information. Keep in mind this can generate a lot of logging output.
View the location of this log or tail the log contents like so:
Your rewrites log will be auto-rotated every 10MB. The amount of information that appears in the rewrites log will be affected by the --debug
and --trace
flags when you start the server.
FusionReactor is a popular tool for monitoring performance and gathering metrics for ColdFusion and Java J2EE applications. You may wish to use FusionReactor with the servers you start up via CommandBox. We've created a CommandBox module that will add FusionReactor support to your CommandBox servers which you can view here on ForgeBox.
The CommandBox FusionReactor module is a separate project that you can optionally install by typing this:
That's it-- now every server you start with the start
command will automatically have the JVM args added to it to load up FusionReactor.
There's nothing special you have to do in order for FusionReactor to load. A random port will be chosen for FusionReactor to use so you can have more than one server running at a time and each of them will have their own FusionReactor instance running. When you start a server, you should see some output similar to this:
To open FusionReactor in your browser, you can run the following command:
If you right click on the tray icon for this server, you'll see there is a new menu item at the bottom called Open Fusion Reactor
that will do the same thing.
FusionReactor is a commercial product and requires a license to use. If your company has a license for you to use on your PC, then you can register your CommandBox FusionReactor license with this command:
FusionReactor will bind the port on whatever host address is used for your server.
You may want to turn the FusionReactor functionality on or off based on your testing or for specific sites. There is now an enable flag for just that. It can be set per server and for all servers as well.
You can set a license key per server if you wish like so:
The module is regularly updated to use the latest version of FusionReactor. Note however that your license key may not be for the latest FR version. When the internal default version of FR is updated for a major release, the version of the actual FR module will also have a "major" version increment. This is so you can always run upgrade --system
and you won't have to worry about suddenly getting a major FR upgrade one day that doesn't work with your license key.
If you want to upgrade your CommandBox FusionReactor module to a new major release, just re-run the installation command.
If you have an older FR license you want to use, you can specify the version of FR you'd like like so:
The installID
setting can be any valid CommandBox endpoint installation ID, which means you can point to a custom HTTP URL, or ForgeBox slug, etc.
As of version 4.0 of this module, the debugger libs will be added automatically for you based on your OS. To disable the debugger libs use the following setting:
There are a handful of JVM args we can use to set things like license key or password, but there are many many settings inside of FusionReactor that have no corresponding method to externalize them. These are stored in a file called conf/reactor.conf
inside of the FusionReactor home directory. If you want to script out settings such as
E-mail servers
Notification settings
Profiler settings
Request history settings
Then you can make a copy of a reactor.conf
file that contains the settings you want the point this module at the file to be copied over when starting the server so FR will pick it up and use it. Just need in mind that this setting will override any manual setting changes you make in the FR web admin every time you start the server.
reactor.conf
file somewhere for later usePoint your server.json
to the new file. Remember, non-absolute paths are relative to the directory the server.json
lives in.
Now, a fresh new server will have these settings.
Note: the reactor.conf
file may contain passwords or other sensitive information. It is in a java properties file format, so feel free to edit it and remove items you don't want. Also, take care when committing it to a source repo or making it web accessible so you don't reveal information. There is currently no support for environment variable expansions in this file, but perhaps we'll add it if it's useful.
Here's the module setting, followed by the JVM arg it creates. Remember, you can use environment variables in your server.json
to control these dynamically on a per-server basis!
fusionreactor.password - fradminpassword
fusionreactor.RESTRegisterURL - frregisterhostname
fusionreactor.RESTShutdownAction - frshutdownaction
fusionreactor.RESTRegisterHostname - frregisterhostname
fusionreactor.RESTRegisterGroup - frregistergroup
fusionreactor.licenseDeactivateOnShutdown - frlicenseservice.deactivateOnShutdown
fusionreactor.licenseLeaseTimeout - frlicenseservice.leasetime.hint
fusionreactor.cloudGroup - fr.cloud.group
fusionreactor.requestObfuscateParameters - fr.request.obfuscate.parameters
fusionreactor.defaultApplicationName - fr.application.name
By default, FusionReactor is only available on the FR port, and not the HTTP or HTTPS port. If you want to hit FusionReactor's web UI through your main web server on the standard HTTP port, then enable the external server setting.
The start
command will scan your system and find a random port that is not currently in use to start the server on. This ensures that multiple embedded servers can run at the same time on the same host without collisions. Ensure any redirects in your applications take the port into account.
You may want to set a specific port to use-- even port 80 if nothing else is using it. Pass the HTTP port parameter to the start command like so:
It is also possible to save the default port in your server.json
. Add a web.http.port
property, or issue the following command:
Now every time you start
your server, the same port will be used.
If the server won't start or is unreachable, make sure it's port is free with your operating system's netstat
command. On Unix-based OS's:
You can start your server to listen for SSL connections too.
This will enable SSL without an approved SSL certificate. If you need an official certificate so you don't have to confirm your SSL connection you can add these entries
Although free certificates are available (e.g LetsEncrypt) this is not very convenient, because these certs are valid only for three months. Automatic renewal it is difficult if your dev site is not accessible from the web. For a few dollars a year (< 10) you can apply for a domain validated certificate from companies like Comodo, RapidSSL, Trustwave, Digicert, Geotrust and others or a reseller for these certs. For a domain validated certificate you need a valid domain which is under your control which means (depending on provider):
mail is sent to domain owner
or mail is sent to well-known administrative contact in the domain, e.g. (admin@, postmaster@, etc.)
or you can publish a DNS TXT record
So, now you have a valid domain, you have to generate a SSL key and a SSL Certificate Signing Request. With the CSR you can apply for the certificate. Generating a key and CSR with openSSL
This will generate output and some questions, and will finally result in a key file named dev_mydomain_com.key
and a certificate signing request (csr) named dev_mydomain_com.csr
You have to enter Country Name, State and City. Organization Name is preferably the same as the domain owner. Organizational Unit Name will not be checked, so enter something simple such as ICT Common Name is the hostname for your site, such as dev.mydomain.com You can skip Email Adress and optional company name. For development you don't need a challenge password, which means your key file is NOT protected. But don't give this key to others or protect it with a challenge password. If you protect your key you have to server set web.SSL.keyPass=MyChallengePassword
Now you have a CSR, which you can submit at your SSL provider. They will send you a certificate file (*.csr), and probably one or more intermediate certificates. Create a new my.csr file and copy everything from your certificate file into it, and append the intermediate certificate(s). Now you have a valid my.csr certificate file and a key file. Place both files in a location accessible for your commandbox and enter the corresponding paths to web.SSL.certFile and web.SSL.keyFile
You can start your server to listen for AJP connections too.
Your application may rely on a specific host name other than the default of 127.0.0.1
. You can set the host to anything you like, but you must add a host
file entry that resolves your host name to an IP address assigned to your network adapter (usually 127.0.0.1)
If you have multiple IP addresses assigned to your PC, you can bind the server to a specific IP using the host
parameter.
A server configuration can only have one host entry. If you require your server to be available on multiple IP addresses of the machine it runs on, you can set the host to 0.0.0.0. This will effectively bind the server to all network interfaces (including local).
Or save in server.json
By default, CommandBox will open your browser with the host and port of the server. You can customize the exact URL that opens. This setting will be appended to the current host and port.
Or you can completely override the URL if your setting starts with http://
.
You can customize the error page that CommandBox servers return. You can have a setting for each status code including a default error page to be used if no other setting applies.
Create an errorPages
object inside the web
object in your server.json
where each key is the status code integer or the word default
and the value is a relative (to the web root) path to be loaded for that status code.
This is what you server.json
might look like:
You can set error pages via the server set
command like this:
If your error page points to a CFM file, you can get access to the original path being accessed for 404s and the error that was thrown for 500s. To see all the request headers that are available, use the following snippet of code:
An example of getting the original missing path in a 404 would look like this:
The default welcome files are the usual index.cfm, index.htm, index.html, etc but you can override this with the welcomeFiles
setting in your server.json
by providing a comma-delimited list of files that you would like CommandBox to look for when a user hits a directory on a running server.
This setting is a complete override of the defaults, so you need to specify the full list.
By default, a CommandBox server will not show the contents of a directory that doesn't have an index file. You can enable directory browsing for a single server with
And you can enable it for all servers by default with
If you have custom jar files that you want to be available to a server, we recommend you use the this.javaSettings
functionality in your Application.cfc
to load those jars. If that isn't an option for you, or you want to include libs for a JDBC drivers then we offer a feature for you to specify a list of directories for which CommandBox will load jars from. This prevents you from worrying about getting your jars inside the WEB-INF/lib
which starts fresh anytime you forget a server.
To load in your jar files, the first method is to use the libDirs
parameter to the server start
command.
And the way to specify this in a portable manner in your `server.json` is like so:
Remember, paths to the start
command are relative to your current working directory and paths in your server.json
file are relative to the folder that the server.json
file lives in. Absolute paths work the same everywhere.
Have a bunch of servers and they ALL need the same jars, you can add your `libDirs` to the global server defaults config settings. Your global lib directories won't be overwritten by server-level config dirs, but instead appended to. Relative paths in your config settings are relative to the respective web root of the server. CommandBox will also ignore missing lib dirs to give you some flexibility in this.
By Default, your servers start using the same version of Java that the CommandBox CLI is using. For people needing to run Adobe ColdFusion 9, or who just want to do some testing on different JREs, you can point each of your servers at a custom JRE and CommandBox will use it when starting the server.
if you already have a JRE downloaded somewhere on your hard drive, you can manually point the server at it, or you can simply tell CommandBox which version of java you'd like, at it will automatically download that version of OpenJDK for your server to use (if it's not already downloaded)
Point CommandBox to an existing java install like so:
To set the default version of Java for all the servers you start on your machine, use the global config setting defaults.
To let CommandBox take over and acquire Java for you, pass an installation endpoint ID to the start
command
or set it in your server.json
or set a default for all servers
To review what possible IDs you can use to dial in your exact Java version, read the . You don't need to manually install Java-- CommandBox will do that for you. You just need to provide the ID so CommandBox knows what you want.
To make it easier for you to manage the Java installations CommandBox makes for you, we have a namespace of commands you can use. The Java versions CommandBox installs automatically for your servers to use are stored in a folder under your CommandBox home. CommandBox manages this folder for you. You can change where the system Java installation go like so:
Search the AdoptOpenJDk API for available versions of Java for you to use.
You can filter the version, jvm, os, CPU arch, type, and release. Most of those parameters default to match your local system. For instance, running this command on Windows will only return Windows versions. To open up the search, pass nothing to that filter.
List the installed Java installations for you to start servers with. If you have set a global default Java version it will be marked in the list.
You may change the global default Java version for your servers with this command.
You can pre-install a Java version so it's ready to go the next time you start a server with this command. This differs from the normal package install
command in that it doesn't install to the current working directory, but into the core server JRE folder that CommandBox manages for you. Use the --setDefault
flag to also set the newly installed Java version as the global default for all servers.
You can remove a java installation so it doesn't take up space on your hard drive. Use the FULL ID that shows in the java list
command to uninstall.
Note, the download will still be in your artifacts cache. Also, if you start a server up again that asks for a Java installation you've uninstalled, CommandBox will simply re-install it again.
CommandBox allows you to create web aliases for the web server that are similar to virtual directories. The alias path is relative to the web root, but can point to any folder on the hard drive. Aliases can be used for static or CFM files.
To configure aliases for your server, create an object under web
called aliases
. The keys are the web-accessible virtual paths and the corresponding values are the relative or absolute path to the folder the alias points to.
Here's what your server.json
might look like.
Here's how to create aliases from the server set
command:
info On Adobe ColdFusion servers, .cfm files will be run automatically from inside an aliases directory. On Railo and Lucee servers, you'll need to create a CF mapping that maps the alias name and path for .cfm files to work.
CommandBox's web server supports enabling Basic Auth on your sites.
That will create the following data in your server.json
, which will be picked up the next time you start your server.
The following JVM Args are supported when starting the embedded server.
You can set the max heap size the server is allowed to have (-Xmx
) by passing the heapSize
parameter to the start
command. This parameter defaults to megabytes but you can specify any valid suffix.
In server.json
You can set the starting heap size for the server (-Xms
) by passing the minHeapSize
parameter to the start
command. This parameter defaults to megabytes but you can specify any valid suffix.
In server.json
You can specify ad-hoc JVM args for the server with the JVMArgs
parameter.
In server.json
You can specify ad-hoc options for the underlying Runwar library using the RunwarArgs
parameter.
In server.json
The built in REST implementation in Adobe ColdFusion and Lucee is usually something you either love or hate. If you love it, you can enable it and customize the paths so it doesn't collide with your app's routes. if you hate it, you can turn it off. The REST servlet will be disabled unless you include a setting like so:
Note that the above setting will take over any URLs starting with /rest
or api
and you cannot use those routes or folders in your code. This is why it's handy to be able to modify or remove these. On a typical server, this is done via the web.xml
, but CommandBox will do it all for you with just the setting above.
Every time you start a server, the settings used to start it are saved in a server.json
file in the web root. Any parameters that aren't supplied to the start
command are read from this file (if it exists) and used as defaults. Here are the possible properties for a server.json
file:
/server.json
With the advent of , you may want to regularly start up the same web site with different settings (such as different CF engine's). To help with this, you can have more than one JSON file.
anything.json
The default server configuration file is server.json
, but you can actually call the file anything you want as long as you use the file's path (or unique name) when starting the server.
Let's say we want to test our app in Lucee 4, Lucee 5 and Adobe 2016. Let's start 3 servers. Note we give each server a unique name. This will come in handy when we want to start/stop the servers by name later.
Info It's important to always use a name when starting more than one server. Otherwise, the settings will override each other and only the last server will be saved. Also, you will only be able to stop the last server via the
stop
command.
You can have full control over the name of the JSON files by using the serverConfigFile
parameter, but when CommandBox sees us use the name
parameter, it will automatically create a file called server-{name}.json
. In this case, we'll have 3 new files:
server-lucee4.json
server-lucee5.json
server-adobe2016.json
If you run the server show
command, you'll see it returns {}
. This is because it looks for a file called server.json
by default. Not to worry, you can still programmatically manipulate your JSON files like so:
Info The property name and server config file path are interchangeable for the
server show
andserver clear
commands for your convenience.
Now that you have 3 JSON files-- one for each server, you can use the path to the JSON file (absolute or relative to your CWD) to control each server.
For your convenience, if you pass in a path to an existing JSON for the server name, we'll use it as the serverConfigFile
parameter.
This trick works on any server
commands
After you've started a server at least once, you can use its server name to control it as well which is a great shortcut. CommandBox will recognize the server name and remember where the server JSON for that server name is stored. Then it will pull the correct web root from the JSON file.
CommandBox's embedded server does not require any prior installations of any CFML engine to work. It does not use Apache, IIS, or Nginx. A very lightweight Java web server called is used and a context is programmatically deployed via a WAR file.
You should still have all the options you need to set up most local development servers quickly. The web-based administrator is available to you where you can edit any setting, add data sources, CF mappings, and mail servers. To see a list of all the parameters you can pass to the server start
command, refer to the or run server start help
command directly from the CLI.
Easily launch multiple shell configurations in the terminal.
This will take your git IDE to new levels.
Add TODO, FIXME or other comments to code and find quickly with this extension.
: save folders as projects and easily switch between projects
: integrated Mercurial source control
Because it is more fun, nuff said!
** Note: . To run ColdFusion 9 you must use an older version of CommandBox 3.x on Java 7 or run CommandBox 4.x on Java 8 update 92 or earlier. Several people are doing this, but beware your mileage may vary.
If you don't have a license, you can sign up for a trial and purchase a license from the website.
By default, the module always picks a random port to start FusionReactor on. You can also set your FusionReactor port on a per-server basis, or at a global level for all servers (if using the fancy which prevents port conflicts by binding each site to its own IP). The default behavior will still be to pick a random port if you don't specify one.
The CommandBox FusionReactor module has passthrough settings for every documented JVM arg. Here are the remaining ones we haven't covered. If you want to know what some of these do, read on them.
The ID follows the format from the . If the version you set as the default isn't installed yet, CommandBox will install it for you the next time a server starts or you can use the --install
flag.
When using CommandBox on a staging or production server, you may wish to start up servers as a service when the OS comes online. Here is a guide on each major OS type.
See screencast here: https://www.ortussolutions.com/blog/screencast-starting-commandbox-servers-as-a-windows-service
Coming soon...
Coming soon...
Create a .service
file
as follows:
Start the service
Give the service about a minute to load up, then check its status
Once you've verified the service is running as expected, enable the service to load at boot
The install command is used to tell CommandBox what you want. Here we ask for the stable release of the ColdBox MVC Platform. "coldbox" is the name of the ForgeBox slug.
Packages should always have a box.json
descriptor file inside them. This is especially true of packages installed from endpoints other than Forgebox since they don't have any other metadata available. CommandBox will install any zip file even if it doesn't have a box.json
, but this isn't ideal since the name, version, and type of the package must be guessed in that instance.
If you find a package on the internet that doesn't have a box.json
, please contact the maintainer and request that they add one or submit a pull request!
ForgeBox supports semantic version ranges for installing packages. Here are some examples:
When you install a package, here are the steps that are taken. Most all of this should be evident by the output streamed to the console during the install process. To get even more juicy details, use the --verbose
flag while installing.
CommandBox inspects the ID passed to the install
command to determine the endpoint to use.
The matching endpoint is asked to fetch the package represented by the ID.
For example, the ForgeBox endpoint checks the local artifact cache and possibly downloads the package.
If ForgeBox is offline, the best match package will be looked for in your artifacts.
The package is unzipped and its box.json
is read
Installation directory is finalized
Contents of package are copied based on the ignoreList
and --production
flag
The package is saved as a dependency in the root box.json
The package's dependencies are installed
server.json
allows you to package up an app that requires special start settings such as rewrites, JVM args, or heap size, and anyone can run it with the same settings you do by simply typing server start
. Make sure to not deploy the server.json
file to your production server where it may be web-accessible.
server.json
outside the web rootTo help with this, you can store your server.json
file outside of the web root and use the web.webroot
property in it to point to the location of the web root. This can be an absolute path or a relative path to the location of the JSON file.
When you start the server, you can run the start
command from the same directory that the server.json
file lives, or specifiy the path to the JSON file like so:
If there is no web root in your server.json
, CommandBox will use the folder that the JSON file is stored in. If there is no JSON file at all, the current working directory is used.
Interacting with the server.json
file uses the commands server set
, server show
, and server clear
, which work the same as the package set/show/clear
commands.
Set the port for your server:
View the port:
Remove the saved setting:
The web server in CommandBox is capable of enabling GZIp compression to reduce the size of HTTP responses. To enable GZip compress on your CommandBox server, add a web.gzipEnable
setting in your server.json
file.
Once you start using the embedded server for your development projects, you may wish to enable URL rewriting. Rewrites are used by most popular frameworks to do things like add the index.cfm
back into SES URLs.
You may be used to configuring URL rewrites in Apache or IIS, but rewrites are also possible in CommandBox's embedded server via a Tuckey servlet filter.
We've already added the required jars and created a default rewrite XML file that will work out-of-the-box with the ColdBox MVC Platform. To enable rewrites, start your server with the --rewritesEnable
flag.
http://tuckey.org/urlrewrite/manual/4.0/index.html
Now URLs like
can now simply be
In server.json
info The default rewrite file can be found in
~\.CommandBox\cfml\system\config\urlrewrite.xml
If you want to customize your rewrite rules, just create your own XML file and specify it when starting the server with the rewritesConfig
parameter. Here we have a simple rewrite rule that redirects /foo
to /index.cfm
customRewrites.xml
Then, fire up your server with its custom rewrite rules:
In server.json
You can place your custom rewrite rule wherever you like, and refer to it by using either a relative path or an absolute path. CommandBox will start looking relative to where the server.json
file resides.
or
If you're coming from Apache, Tuckey supports a large subset of the mod_rewrite
style rules like what you would put in .htaccess
. You can simply put your rules in a file named .htacess
and point the web.rewrites.config
property to that file.
Note: The name of the file matters with mod_rewrite-style rules. It must be called .htaccess
. With xml rewrites, the filename is not important, only the content.
Here are some simple rewrite rules:
Please see the docs here on what's supported:
info For more information on custom rewrite rules, consult the Tuckey docs.
Your servers come ready to accept SES-style URLs where any text after the file name will show up in the cgi.path_info
. If rewrites are enabled, the index.cfm
can be omitted.
SES URLs will also work in a sub directory, which used to only work on a "standard" Adobe CF Tomcat install. Please note, in order to hide the index.cfm
in a subfolder, you'll need a custom rewrite rule.
The Tuckey Rewrite engine has debug and trace level logging that can help you troubleshoot why your rewrite rules aren't (or are) firing. To view these logs, simply start your server with the --debug
or --trace
flags. Trace shows more details than debug. These options work best when starting in --console
mode so you can watch the server logs as you hit the site. Alternatively, you can follow the server's logs with the server log --follow
command.
The Tuckey Rewrite library that CommandBox uses under the hood. It has some extra settings that CommandBox allows you to use.
To monitor your custom rewrite file for changes without needing to restart the server, use this setting.
To enable the inbuilt Tuckey status page, use the following setting. Note, debug
mode needs to be turned on for the Tuckey status page to work. Also, you'll need to customize your rewrite file if you use a path other than /tuckey-status
.
There are several factors that determine where a package gets installed to. Here are the ways CommandBox determines the install location in order of importance.
The value of the directory
parameter passed into the install
command by the user.
The value of the installPaths.packageName
property set in the project's main box.json by the user.
The value of the directory
property in the package's box.json by the package author. Note, this must be a path relative to the current working directory (CWD).
Based on the package type convention if the package is a command, coldbox module, commandbox module, plugin, or interceptor.
The current working directory (CWD)
Once the installation directory is determined, a folder is created that matches the package's slug which is where the package is finally copied to. If the package's createPackageDirectory property is set to false in the box.json, the package will be copied to the root of the installation directory. An example of this would be a complete application that needs to go in the web root.
There are several options you can use to control how a package is installed.
By default, any package you install will be saved as a dependency. To save it as a development dependency instead, use the --saveDev
flag.
If you DON'T want the package you're installing to be saved as a dependency pass save=false
or negate the save flag as --!save
.
When you install a package, all dependencies will be installed. If you want to skip development dependencies, use the --production
flag. This will also cause CommandBox to obey the package's ignoreList property in its box.json.
If you're a glutton for information, or perhaps you just want to debug what's going on, set the --verbose
flag to get extra debugging information out of the install command including a list of every file that's installed.
If CommandBox sees the directory that it was going to install into already exists with a newer or equal version of the package inside, it will decline to install again since it would be overwriting what's already there. If you want to install anyway, use the --force
flag.
ForgeBox allows you to publish packages that only you can see and install. You'll be able to view your private package from the CLI, in the ForgeBox.io search, and in your ForgeBox.io profile, but these packages will now show up for any other users.
To create a private package, set the private
property to true
in your box.json
prior to publishing.
Replace forgeBoxUser
with your actual ForgeBox username. When you install the package, you'll need to use the full slug like so:
You can install specific versions or version ranges as you would expect:
Private packages will be a paid feature for ForgeBox Pro subscribers, though the feature is currently available to all users for free.
In the CFML world, there are no global conventions for where to install things to nor where to store dependencies. Therefore, CommandBox for the most part will just stick packages in the root of your site unless you tell it otherwise. It may not be pretty, but it's as good as stock CFML apps can get. That means a lot of the cool things other package managers like NPM can do simply won't be available to you.
If you're using the ColdBox MVC Platform, congratulation! You just unlocked advanced mode! ColdBox uses conventions that tells you where to put stuff, and most importantly it has modularity as a first class citizen. Not only that, but modules can be nested infinitely to nicely encapsulate dependencies and WireBox will automatically find and register each module's models for your application to use.
Modules are basically smart packages and when CommandBox installs or uninstalls modules it will behave a bit differently to take advantage of the functionality only available to the CFML world via the ColdBox Platform.
When installing a module, it will be placed in the modules/ directory. That means the cbvalidation module will install here:
The cbvalidation module has dependencies of its own but it is an island unto itself and will encapsulate these. Therefore the cbi18n module will be installed in a modules/ folder inside cbvalidation.
You'll be able to see a nice representation of this when you use the list
command.
What this opens the door for is more than one module to depend on different versions of the same second module. Both can be installed and nested under the respective parent. In the near future, WireBox will be smart enough to present these nested modules only to their parents so they are fully encapsulated.
The idea is that a module can "see" and use another module installed at the same level or higher in the hierarchy, but not lower. That makes dependencies a bit of a black box to their parents. This also allows us to bypass some redundancy. For instance, when installing a module, if a satisfying version of that module already exists at a higher level, we skip the installation. Consider this example:
We know that cbvaliation requires cbi18n, but since it is already installed in the root modules folder, we won't install it again under cbvalidation.
The last way modules are better than sliced papusas is in how they uninstall. We talked about how non-modules install-- just littered in the web root in a jumble of dependencies. When uninstalling a non-module package, CommandBox will recursively go through the dependencies and remove them as well. However, when uninstalling a module, that module's folder is simply deleted and that's it. Since all dependencies are contained in the "black box", there's no need to go hunting for them.
CommandBox functions as a package manager which means you can use it to locate and install code packages for you. This gives you a consistent and scriptable method to install the libraries you need in a simple manner.
By default, the list of available packages is on ForgeBox, our CFML code sharing site. Additional endpoints such as Git, HTTP/HTTPS, and local file/folder are also available. When a package is installed, all of its dependencies are automatically installed for you for quick, easy experience.
You can easily create your own packages and register them on ForgeBox so the whole community can start using them.
CommandBox can be extended by modules installed from external locations. When you install a CommandBox module, it will automatically be placed in the correct modules location (inside your CommandBox installation) regardless of where you run the install
command from.
Later, if you want to view, uninstall, update, or otherwise interact with these system modules, you can just use the standard package management commands, but add the --system
flag to them. Any time you add that flag, the current working directory will be ignored, and you'll be interacting with the core modules installed into CommandBox.
The package commands that accept a --system
flag are as follows:
package install
package uninstall
package outdated
package list
package update
package show
package set
package clear
Entire Git repos that represent a package can be installed via the Git endpoint. This can be a public Git server like GitHub or Bitbucket, or a private Git repo behind your firewall.
Make sure the root of your Git repo has a box.json
inside of it so CommandBox can tell the version and name of the package. If there is no box.json
, the name of the repo will be used as the package name.
To install a package from a Git repo, use the URL like so:
You can target a specific branch
, tag
, or commit
by adding a "commit-ish" to the end of the URL.
If the repo you wish to install is located on Github.com, you can use this shortcut to specifying the package.
You can specify packages from folder endpoints as dependencies in your box.json
in this format. Remember, JSON requires that backslashes be escaped.
Git repos that allow anonymous pulls do not require any additional configuration for authentication. CommandBox's Git endpoint supports SSH authentication via public/private keys by using the git+ssh://
protocol.
Some Git endpoints (like private Github repos) need a user before the site name in the url string like below:
Info Note the git+ssh URL is a little different than a HTTP(S) URL. There is a colon (
:
) after the host instead of a forward slash (/
).
The git+ssh
endpoint will look for a private SSH key in your ~/.ssh
directory named id_rsa
, id_dsa
, or identity
. If you are using a multi-key setup with a ~/.ssh/config
file, it will be read, and the appropriate key will be used for the host. The matching public key needs to be registered in the Git server.
Info If you are deploying to a server and you have not previously logged into the Git server from the new machine you will need to make sure the Git server is added to your
known_hosts
file. The quickest way to do this is to usegit clone git@github.com/user/repo.git
from the terminal OR add the line from your local machine to the server.
Password authentication is not supported yet for HTTP, HTTPS, or SSH Git protocols.
The Java endpoint is capable of downloading and installing any version of Java in the AdoptOpenJDK API. Use the java search
command to search the API to find what Java versions are available. The endpoint will use the local artifacts cache.
NOTE: If you simply want to start a server with a given version of OpenJDK, you don't need to use this endpoint directly, You can ask CommandBox to use a specific java version and it will handle the installation for you as well as re-using identical Java installs across servers. For example:
The installation ID consists of a series of identifiers separated by underscores that describe the Java version, type, JVM, etc that you want installed.
An example utilizing every option would be
However, everything is optional except the major version. These are also valid installation IDs
Here are the possible options for each section of the ID.
version - openjdk8, openjdk9, openjdk10, etc...
type - jdk, jre
arch - x64, x32, ppc64, s390x, ppc64le, aarch64
os - windows, linux, mac
jvm-implementation - hotspot, openj9
release - latest, jdk8u172, jdk8u172-b00, etc...
For items not specified in the endpoint ID, the endpoint will default as follows:
type - jre
arch - Whatever the current OS arch is
os - Whatever the current OS is
JVM-implementation - hotspot
release - latest
When java is installed as a package endpoint, the name of the folder that it is installed into will mirror the ID you use. This means two different installation IDs that resolve to the exact same Java version may end up in different folders. We do this for a couple reasons. One of which is simplicity, the other is that if you have configuration expecting a specific folder name, Mac users and Windows users may get a different download, but if the id is simple java:openjdk8_jdk
, they would both install into a folder called openjdk8_jdk
.
This endpoint will NOT edit your registry, create any symlinks, or add environment variables. It will simply drop the Java installation into a folder so you can point servers at it. You are free to use one of these Java installations in such a manner, but we don't do this by default so you can install as many java versions as you like and they don't fight with each other.
Packages that are either stored locally on your machine or are accessible via a network drive in an unzipped folder can be installed by using their file system path. The path can be absolute or relative.
Make sure your package folder has a box.json
inside of it so CommandBox can tell the version and name of the package. If there is no box.json
, the name of the last folder in the path will be used as the package name.
To install a package from a local folder, use the path like so:
Note if using Windows, you need to escape backslashes in the command parameter.
Relative paths will start in the directory where the command is being run from.
You can specify packages from folder endpoints as dependencies in your box.json
in this format. Remember, JSON requires that backslashes be escaped.
CommandBox can install UDFs from the popular site CFLib.org. Each project on CFLib is a single CFML function. You can find UDFs via the web site and copy the URL slug for a given UDF to use in your installation.
For example, if the URL to a given UDF is http://www.cflib.org/udf/CalculateWindChill
, the slug you'll want to use would be CalculateWindChill
.
To install a package from CFLib, use the slug from the website's URL like so:
This will create a folder in your installation directory named after the UDF containing a .cfm
file of the same name. The above command would create the following folder:
That file contains a single function that you can call. It is up to you to include that file where ever you want to use the UDF.
If you're using ColBox, you can use a slightly different version of the CFLib endpoint called CFLib-ColdBox
which will wrap up the UDF inside a CFC and place it in an ad-hoc module which automatically registers the model with WireBox.
This frees you up from needing to manually include the file. Once you install the module, you can immediately ask WireBox for the UDF using the convention UDFName@cflib
. WireBox will register this mapping by convention so there is no additional setup required to use the UDF.
Or inject the wrapped UDF to use in your handlers or models.
Packages installed from the CFLib endpoint don't have any way to get new version information. They will always show as outdated using the outdated
or update
commands and their downloads will not get stored in the artifact cache.
You can specify packages from the CFLib endpoint as dependencies in your box.json
in this format.
Packages hosted in private S3 buckets can be installed directly from S3 URLs.
To install a package from a S3 bucket, use a URL like so:
The S3 endpoint will automatically determine which region your bucket is in order to download your package. You can, however, bypass this automatic bucket region resolution by encoding the region of your bucket into the S3 path by using a :
after the bucket name:
Info If your S3 path does not end in
.zip
the S3 endpoint will make a HEAD request to S3 for the package path to determine if your package exists at that location. If it does not, then.zip
will be appended to your S3 path and that new path will be used as the location of your package. This means it is possible for you to specify a package without adding the.zip
extension:s3://my-private-bucket/myPackage
.
You can specify packages from S3 endpoints as dependencies in your box.json
in this format:
In order for S3 endpoints to be resolved, CommandBox needs an AWS access key and AWS secret key belonging to an AWS IAM user or role that has permission to get objects from the S3 bucket where the package is stored. The access and secret keys can be set in CommandBox settings either globally:
or on a per bucket basis:
If aws_access_key_id
and aws_secret_access_key
are not set in your CommandBox settings, the S3 endpoint checks for credentials in the same places and order as the AWS CLI and SDKs:
It checks for AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
environment variables containing the credentials.
It checks for an AWS credentials ini file. (If you use the AWS CLI, this file is created by the CLI when you enter your credentials during setup. The default location for this file is at~/.aws/credentials
.)
Info The location of the credentials ini file can be overwritten by setting an
AWS_SHARED_CREDENTIALS_FILE
environment variable to an alternate file path (this can also be set in your CommandBox settings:endpoint.s3.aws_shared_credentials_file
). Further, the AWS credentials file has the concept of "profiles", where the default profile is named "default". The profile to use can be changed from "default" by setting an alternate profile name in anAWS_PROFILE
environment variable or CommandBox endpoint setting (endpoint.s3.aws_profile
).
Finally the S3 endpoint will check for the presence of an IAM role from which credentials can be obtained. This credential location is only valid on AWS EC2 instances.
The full list of possible credential locations and the order in which they are checked is as follows:
Per bucket credentials in your CommandBox endpoint settings
Global credentials in your CommandBox endpoint settings
Environment variables
AWS credentials file
IAM role
For CommandBox to be able to install packages for you it needs to connect to package registry where packages are stored so it can download them for installation. CommandBox integrates seamlessly with ForgeBox, our community of ColdFusion (CFML) projects. CommandBox also integrates with HTTP(S), local file/folder, and Git endpoints.
Here is a list of the package endpoints currently supported by CommandBox.
ForgeBox - Cloud-based packages (Read more)
HTTP(S) - Point to a hosted zip file containing a package (Read more)
File - A local file containing a package (Read more)
Folder - A local folder containing a package (Read more)
Git - Any Git repo containing a package (Read more)
Java - Install OpenJDK for your servers (Read more)
Jar - A jar file hosted via HTTP that's not contained in a zip file (Read more)
S3 - A package zip stored in a private S3 bucket (Read more)
CFLib - UDFs posted on CFLib.org (Read more)
RIAForge - Projects posted to RIAForge.org (Read more)
Gist - A package hosted as a Gist from gist.github.com (Read more)
ForgeBox is an online registry of packages run by Ortus Solutions. The web UI for ForgeBox is located at http://forgebox.io. Signing up for a ForgeBox account is quick, easy, and free. You will need your own account to post packages, but anyone can browse and install packages anonymously.
Every package on ForgeBox has a unique slug. To install a package, use the slug like so:
You can also specify the version of a package you want to install from Forgebox.
Given the install command above, if the file ~/.CommandBox/artifacts/coldbox/3.8.1/coldbox.zip
exists on your hard drive, the installation will not connect to Forgebox at all. It will be a completely offline installation. This only works when you type an exact version that includes a major, minor, and patch number.
You can specify packages from ForgeBox as dependencies in your box.json
in this format:
info The caret
^
means that theupdate
command will update minor releases but not major releases.
For companies who want to host internal code endpoints for private packages, we will soon support an Enterprise version of ForgeBox that can be installed behind your company's firewall. Please contact us if this feature interests you.
Inside CommandBox, use the forgebox namespace to search for packages or show packages of your choosing.
The first command to try out is "forgebox search". It takes a single parameter which is a string to perform a case-insensitive search for. Any entry whose title, summary or author name contains that text will be displayed:
The "forgebox show" command takes several parameters and is pretty flexible. The first way to use it is to just view the details of a single entry using the slug.
You can get lists of items filtered by package type (modules, interceptors, caching, etc) and ordered by popular, new, or recent. Here's some examples:
Too many results on one page? Use the built-in pagination options:
Or just pipe the output into the built-in "more" or "grep" command.
If you have troubles remembering the valid types or order by's, remember you can always hit "tab" for autocomplete within the interactive shell. Adding "help" to the end of any command will also show you the specific help for that command.
The list of types in ForgeBox is dynamic so we don't list them out in the help. Instead, we made a handy "forgebox types" command to pull the latest list of types for you.
If you have external jars that need downloaded into your project, you can use the jar:
endpoint to download them. The jar endpoint does not expect the jars to be contained in a zip file or to have a box.json. As such, there is no real package slug or name, so CommandBox will "guess" the name based on the name of the jar (if a jar name appears in the path or query string).
Files from the jar:
endpoint will be placed in a lib/
folder by default unless you provide another folder for installation.
You can specify jars as dependencies in your box.json
in this format.
Note this installation method does not include any dependencies of the jar like a Maven installation would. That will be a future endpoint.
Packages that are either stored locally on your machine or are accessible via a network drive as a zip file can be installed by using their file system path. The path can be absolute or relative.
Make sure your package zip file has a box.json
inside of it so CommandBox can tell the version and name of the package. If there is no box.json
, the name of the file without the extension will be used as the package name.
To install a package from a local file, use the path like so:
Note if using Windows, you need to escape backslashes in the command parameter.
Relative paths will start in the directory where the command is being run from.
You can specify packages from file endpoints as dependencies in your box.json
in this format. Remember, JSON requires that backslashes be escaped.
CommandBox can install a Github Gist from gist.github.com as a package.
Make sure the root of your Git repo has a box.json
inside of it so CommandBox can tell the version and name of the package. If there is no box.json
, the name of the Gist ID will be used as the package name.
To install a package from a Github Gist, you must pass the Gist ID from gist.github.com:
The Github username is optional.
You can target a specific commit
by adding a "commit-ish" after the Gist ID.
You can specify packages from folder endpoints as dependencies in your box.json
in this format. Remember, JSON requires that backslashes be escaped.
Packages hosted on a website as a zip file can be installed by using the direct URL to the package. Both HTTP and HTTPS URLs are supported. If the URL returns a 301
or 302
redirect, it will be followed until the package is reached.
Make sure your package zip file has a box.json
inside of it so CommandBox can tell the version and name of the package. If there is no box.json
, the following rules will be decided to determine the name of the package:
If the URL has the zip file name in it, the name without ".zip" is used.
If the URL contains github.com
, the repo name will be used.
Otherwise, the entire URL will have non alpha-numeric characters removed and used.
To install a package from a website, use the full URL like so:
You can specify packages from HTTP(S) endpoints as dependencies in your box.json
in this format:
If you know a given URL will always return the exact same package, then you can request CommandBox to cache the download in local artifacts to speed up builds. To do so, use an endpoint name of https+cached
or http+cached
in your install ID.
Or
Cached artifacts will be stored under the slug HTTP_Cached
and can be viewed like so:
You can define a struct in your box.json
called scripts
that correspond to the interception points in CommandBox. Any script defined there will be ran on during that interception point. This allows you to prescribe arbitrary commands on a package-by-package basis. You may wish to set your package location any time you bump
a package version or perform a !git push
on publish
. Below is an example of some scripts
in a box.json
.
Package scripts can be named after any valid interception point and can contain any valid command that you can run from the interactive shell.
You can also create ad-hoc scripts with arbitrary names that contain a collection of often-run commands.
Call these scripts at any time with the run-script
command
Before any package script is run, CommandBox will look for another package script with the same name, but prefixed with pre
. After any package script is run, CommandBox will look for another package script with the same name, but prefixed with Post
. So if you have a package that contains 3 package scripts: foo
, preFoo
, and postFoo
, they will run in this order.
preFoo
foo
postFoo
This works for built-in package script names as well as as doc package scripts. It also works on any level. In the example above, if you created a 4th package script called prePreFoo
, it would run prior to preFoo
.
Any package script fired by an internal interception announcement in CommandBox will have access to any intercept data via environment variables in the shell. All intercept data will be prefixed with interceptData.
and will use "dot notation" for nested structs. You can see if the docs on what intercept data is available to each interception point.
For example, a preCommand
interception announcement receives a struct called commandInfo
with a key called commandString
which means your package script can access that via the following environment variable:
You can see this in action with this simple package script:
Or if you wanted to simply debug what is available to you, use the env show
command in your package script to dump out all environment variables to the console.
Here's another example that writes a file to the server home directory when a server starts, using an environment variable to dynamically obtain the proper path.
CommandBox does more than help yo install packages. It also helps you keep them up to date as well. Remember, you can always get a quick list of all the dependencies installed your app with the list
command.
To check and see if any of your installed packages can be updated to a newer version, run the update
command.
Entering "yes" will install the newest version of the package. It is also possible to get a list of outdated dependencies without the prompt to update them with the outdated
command.
If you are using a ForgeBox package, the update
command will comply with the semantic versioning range you specify. For example, if you have a dependency installed with a version saved of ^2.0.0
it will update you all the way to 2.9.9
but it will never install 3.0.0
until you ask it to. This is because breaking changes come in major versions, but minor releases are supposed to be compatible.
The way CommandBox determines whether there is a new version of a package differs based on the endpoint that installed the package. Versions are always treated as a semantic version (Major.Minor.Patch).
ForgeBox - The ForgeBox REST API is used to get the latest package version.
HTTP(S) - Package is always considered outdated, and re-downloaded.
File - The box.json's version is used from the zip. If box.json doesn't exist, the package is always considered outdated.
Folder - The box.json's version is used from the folder. If box.json doesn't exist, the package is always considered outdated.
Git - Package is always considered outdated, and re-cloned.
If you want to integrate your package updates with an external process, you can get this data back as JSON so it can be parsed and used by another system.
We've seen how any folder can be turned into a package with the init
command. Initial properties can be set as named parameters to the init
command.
The init
command can be called more than once on a package and it will keep existing properties and only overwrite the ones you specify.
Once you've created your box.json, you can edit the file directly, or there are other commands to help manage it programmatically.
Each of these commands support tab-complete that is dynamic based on what properties are currently in your box.json.
The package show
command can be used to out put any part of the box.json. You can specifiy any property name from your box.json.
Outputs package name and keywords
Nested attributes may be accessed by specifying dot-delimited names or using array notation. If the accessed property is a complex value, the JSON representation will be displayed
Outputs testbox runner(s)
Outputs the first testbox notify E-mail
Output the entire box.json
Any property in your box.json can be set from the command line with the package set
command.
Set package name
Nested attributes may be set by specifying dot-delimited names or using array notation. If the set value is JSON, it will be stored as a complex value in the box.json.
Set the repository type.
Set first testbox notify E-mail.
Set multiple params at once by passing as many named parameters as you like.
Set a complex value as JSON.
Objects and arrays can be appended to using the append
parameter. This only works if the property and incoming value are both of the same complex type.
Add an additional contributor to the existing contributors
array.
Add an additional dependency to the existing dependencies
object.
If you need to remove a property entirely from your box.json, use the package clear
command. It also works on nested properties using "dot" or array notation.
Remove the package description entirely.
The main goal of semver is to create a common ground among developers and their projects for describing the status of their releases and help users get the versions they want. Semver describes how a proper version number can be formatted as well as a special syntax for describing ranges of versions. There are many ways to describe a version number and semver is just one of them. We chose semver for CommandBox due to its popularity and usage among other common tools like npm. In fact, we've copied the npm flavor or semver specifically which you can .
If you only get one thing out of all this, at least understand the basic parts of a version. Everything but the major number is optional so remember a version can be as simple or complex as you like and there are rules for dealing with the missing pieces.
Let's digest that bit by bit:
major - This is the major version number of the software. Increase this number when making major changes or breaking compatibility with previous releases.
minor - This number gets incremented when you add new features and improvements to software that doesn't break compat. Resets to 0 on a major bump.
patch - This number gets incremented for small bug fixes. Resets to 0 on major and minor bumps.
prerReleaseID - The presence of this means the version is not stable. This string can be anything, but is typically "rc" for release candidate, "snapshot", "alpha", "beta", etc. You can have more than one prerelease with "beta.1", "beta.2", "beta.3", etc.
build - This is a number that usually comes from your build server and increments every time a commit is made that triggers a build. It can be used to track a very specific release, but should not be used for semver range comparisons. It's really just for information.
So let's take a look at some valid semantic versions.
When writing a package, we recommend using a full version number just to be as descriptive as possible. You may not wish to have a build number if you don't run an automated build. And of course, don't include a prereleaseID unless the package isn't stable. Set your package's version like so:
Ok, so far we've only talked about exact versions. Semantic versioning also gives a very powerful syntax for addressing a range of versions. This can be very useful when installing or updating if you don't care about the exact package version that you get, but you have a few parameters. One of the main ideas behind semver ranges is that you can quickly and easily upgrade 3rd party libraries to the latest version that still works with your code without breaking anything. Ranges would be used when installing a package with the install command
Or in your box.json to show what versions of a particular dependency you're willing to accept.
Let's look at the basic formats for version ranges.
Major, minor, and patch numbers can be replaced with an X (or omitted entirely) meaning you don't care what value you get.
You can use <, >, <=, and >= operators just like you would expect to request all versions above, below, or between other versions.
These are just a variation of greater/less than but easier to type. Hyphen ranges are inclusive of the start and end version.
Now we get a little interesting. These last two types of ranges are designed to allow you to keep updating a package version to get compatible versions, but stopping short of getting a breaking update on accident. You usually see these in a box.json file to control what happens when the update command is run. A tilde in front of the version will allow patch upgrades when a minor version is specified and will allow minor upgrades when only a major version is specified.
This is the default ranged used by CommandBox in your box.json when you install packages from ForgeBox which matches npm's default behavior. A caret allows changes that do not modify the left-most non-zero digit. In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for versions 0.1.0, and no updates for versions 0.0.X. The reason for the left-most non-zero digit caveat is for authors who have a whole series of 0.x version releases before ever making it to a full major release. It allows us to essentially treat the minor version as the major version until a "real" major version exists.
And one final trick. You can string together any of the ranges we showed above with two pipe characters ( || ) and each range will be evaluated until a matching one is found.
Dependencies are other packages that are required by another package for it to run. A simple package may have no dependencies, or it may have many. There are two types of dependencies: a regular dependency or a development dependency. Regular dependencies are ones required for operation of the main package. Development dependencies are optional and only necessary if you plan on making changes to the package you're installing. Dev dependencies would include testing frameworks or build tools.
When a package is installed, CommandBox will read its dependencies (from the box.json) and recursively install them as well. This encourages developers to write small, reusable libraries for everyone to use. When installing via a package manager, you don't have to worry about getting all the pieces installed.
Dependencies and development dependencies are stored in an object with the slug for the key and a version range for the value. The are several options available for these version ranges and more information can be found in the section on .
When you install a dependency , it will be automatically added to your box.json. Use the --saveDev
flag to save a development dependency. Uninstalling a dependency will remove it from your box.json unless you set the save
parameter to false.
When you distribute a package for others to use, you should omit it dependencies. This will reduce the size of your repository and will prevent you from having to mess with the 3rd party code. As long as they are saved in your box.json, you're good.
When someone installs your package, CommandBox will automatically get the latest dependencies for them. If you're sharing an entire project that other people will download or clone from GitHub, they can simply run the install
command with no parameters.
This basically installs the root box.json as the current package, which means all dependencies that don't exist already will be installed. Now your project should be assembled and ready to run!
Packages are quite simply a folder that contains some code and a box.json
file. A package can be a simple CFC, a self-contained library, or even an entire application. ColdBox and ContentBox modules also make great "smart" packages.
Remember, packages aren't just the things you install into your application, but your application is a package too! That's why when you install something in your app, we'll create a /box.json if it doesn't exist to start tracking your dependencies.
Your box.json
file describes your package, dependencies, and how to install it. To turn a boring folder into a sweet package just run the init
command in the root of the folder.
That's it. Your folder now has extra meta data in the box.json
file that describes it in a way that is meaningful to and CommandBox.
When making a package available on ForgeBox, each version of that package has its own location. Most download locations point to a zip file, that when extracted, contains a folder with a box.json in it. The box.json designates the root of the package. However, the location
property of your box.json can be any valid endpoint ID. An example would be:
In that case, the location
for version 1.0.0
of this package is the v1.0.0
tag in that GitHub repository.
If your project is stored in GitHub, an easy approach is simply to treat the root of the repository as the root of the package. That is where your box.json will live. This also means you can use GitHub's automatic zip download URL as your ForgeBox URL since it returns a zip file containing your repo contents in a folder.
Ex: https://github.com/bdw429s/Weather-Lookup-By-IP/archive/master.zip
If you choose to structure your repo differently, no problem. Just use a build process that generates a zip file in that format and make that zip publicly available for ForgeBox's download URL.
ForgeBox supports private packages. Private packages are only visible to the user who created it.
Private packages will be a paid feature for ForgeBox Pro subscribers, though the feature is currently available to all users for free.
To create a private package, pass the private
flag to the package init
command.
Note: Creating private packages requires you to be logged in to ForgeBox
ForgeBox can store the binaries for your packages in the ForgeBox Cloud. This provides you with an easy way to store multiple versions of your package distributed across the globe. To utilize ForgeBox Storage, simply set forgeboxStorage
as the value of your package's location
.
When you publish a package, CommandBox will automatically zip up your package and send it to ForgeBox.
Below is an example of the commands that would take you from scratch to a published package:
If you want more reading or examples, check out the as well as the docs for the . You can also peruse the I have for the CommandBox semver library here which tests every possible combination.