Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 207 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

5.2.0

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...

Loading...

Introduction

CommandBox Manual - Version 5.2.1

Versioning

<major>.<minor>.<patch>.<buildID>

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

License

  • 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.

Discussion & Help

Reporting a Bug

Professional Open Source

  • Custom Development

  • Professional Support & Mentoring

  • Training

  • Server Tuning

  • Security Hardening

  • Code Reviews

Resources

HONOR GOES TO GOD ABOVE ALL

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

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.

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:

Ortus Solutions
Semantic Versioning
LGPL v3 GNU LESSER GENERAL PUBLIC LICENSE
https://community.ortussolutions.com/c/communities/commandbox/
https://github.com/ortus-solutions/commandbox
https://ortussolutions.atlassian.net/browse/COMMANDBOX
Ortus Solutions, Corp
Much More
http://www.ortussolutions.com/products/commandbox
https://github.com/ortus-solutions/commandbox
https://ortussolutions.atlassian.net/browse/COMMANDBOX
@ortussolutions
https://www.facebook.com/ortussolutions
https://google.com/+OrtusSolutions
http://vimeo.com/channels/commandbox
CommandBox
Ortus Solutions, Corp

Setup

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.

Getting Started Guide

Congratulations on your choice of CommandBox, the next generation of CFML productivity tooling! We're pleased you've chosen this product 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

1. Download

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.8 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!

2. Unzip & First Run

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.

3. Setup & Usage

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:

C:\ > box version
CommandBox 1.2.3.00000
C:\ > _

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.

CommandBox> version help

Now, let's see if your installation is up to date with the upgrade command:

CommandBox> upgrade

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.

CommandBox> repl
Enter any valid CFML code in the following prompt in order to evaluate it and print out any results (if any)
Type 'quit' or 'q' to exit!
CFSCRIPT-REPL: _

Type these lines one at a time and press enter to see what you get.

fruits = [ 'apples', 'oranges' ]
fruits.append( 'bananas' )

( fruits.len() ? 'Start eating!' : 'Time to run to the store' )

for( fruit in fruits ) {
  echo( fruit & chr(10) )
}

When you're done, just type quit to exit the REPL. How does it feel to master CFML from the command line?

Package Manager

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.

CommandBox> mkdir C:\playground
CommandBox> cd C:\playground

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.

CommandBox> forgebox search Luis

Wow, that Luis guy is busy! Let's install the the ColdBox MVC Platform. Don't worry, this won't hurt a bit.

CommandBox> install coldbox

We can create a skeleton ColdBox app really easy with the ColdBox generator commands. Let's give them a try:

CommandBox> coldbox create app MyApp

Embedded Server

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.

CommandBox> start

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:

CommandBox> edit views/main/index.cfm

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.

CommandBox> stop
CommandBox> cd ../
CommandBox> rm playground --recurse --force

Next Steps

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 .

If you run into issues or just have questions, please jump on our and ask away.

CommandBox is 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.

http://www.ortussolutions.com/products/commandbox
Command API Docs
CommandBox Google Group
Professional Open Source

About This Book

  • The majority of code examples in this book are done in cfscript.

External Trademarks & Copyrights

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.

Notice of Liability

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.

Contributing

Charitable Proceeds

Shalom Children's Home

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.

The source code for this book is hosted in GitHub: . You can freely contribute to it and submit pull requests. The contents of this book is copyright by and cannot be altered or reproduced without author's consent. All content is provided "As-Is" and can be freely distributed.

We highly encourage contribution to this book and our open source software. The source code for this book can be found in our where you can submit pull requests.

15% of the proceeds of this book will go to charity to support orphaned kids in El Salvador - . 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 () 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.

https://github.com/ortus-solutions/commandbox-docs
Ortus Solutions, Corp
GitHub repository
http://www.harvesting.org/
http://www.harvesting.org/

Requirements

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.

Operating System

  • Windows XP+

  • Mac OS

  • Linux

Hardware

  • 256MB+ RAM

  • 250MB+ free hard drive space

  • Multi-core CPU recommended

Software

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.

Download

Info The non-JRE versions are all around 80MB in size, while the embedded JRE versions will go up to 120MB in size.

Stable Release

Bleeding Edge

Info Keep in mind, bleeding edge builds may contain experimental features that are likely to change or bugs.

Auto Updates

upgrade --latest

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.

If you already have a Java JRE installed level 1.8 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.

Below you can see an image of the available downloads from the Ortus Solutions page:

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. .

download
download
installation
download
http://www.ortussolutions.com/products/commandbox#download
https://downloads.ortussolutions.com/#/ortussolutions/commandbox/
Upgrade API docs

Light and Thin Binaries

If you are just installing CommandBox to use on your PC as a local development tool, the standard version of the box binary should be fine. It contains a full version of Lucee with all its default extensions pre-installed. However, if you are creating an automation or a distributable such as a Docker container you may want to look into one of these alternative box binaries.

CommandBox Light

CommandBox Light does not include the full version of Lucee, but rather Lucee Light which only comes with the Compress extension (because CommandBox requires this extension to run). The CommandBox Light binary is roughly half the size of the normal version. The on-disk size of the CommandBox home is about 1/3rd of the size. This can be handy for places where disk size is very important.

Starting a default web server in CommandBox will give you a Lucee Light server, which may not run your app since it lacks extensions such as JBDC drivers and the admin. You can still ask for a specific version of Lucee with the cfengine parameter. If you delete the engine folder from a CommandBox Light installation, Lucee will not be able to work since the Lucee.jar file in CommandBox Light has had it's core.lco file removed to make it smaller. Deleting the entire .CommandBox folder will work however.

Any Task Runners or CLI automations in CommandBox light will also not be able to use things like JDBC drivers unless you install the extensions. Extensions can be installed by placing them in the CLI's server context deploy folder and waiting a minute:

~/.CommandBox/engine/cfml/cli/lucee-server/deploy

You can download the CommandBox Light binary directly from our S3 artifacts repo:

  • box-light - Mac/Linux

  • box-light.exe - Windows

  • box-light.jar - Executable jar

CommandBox Thin

The CommandBox Thin binary cannot be used by itself as it contains nothing inside of it but the Java bootstrap. It does not contain any of the other libraries, jars, or Lucee versions that CommandBox needs to load. it is only 300KB in size. The way that the 'thin" binary is to be used is to first download and run the normal CommandBox or CommandBox Light binary which will extract itself into the CommandBox Home. Once this has been completed, you can delete that box binary and replace it with the box-thin binary (renamed to box ). The new thin binary will take up less disk space and will simply use the existing CommandBox home that has been extracted.

The thin binary does not care whether the CommandBox home was extracted with a full or "light" version. This can create additional disk savings in an environment like Docker, but would not serve much of a purpose on your local development PC. If you delete your .CommandBox folder, the CommandBox thin binary will not be able to recreate it.

You can download the CommandBox Light binary directly from our S3 artifacts repo:

  • box-thin - Mac/Linux

  • box-thin.exe - Windows

  • box-thin.jar - Executable jar

Installation

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:

commandbox_home=E:\\CommandBox

Windows

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.

Mac/ *Unix

Homebrew (Mac)

brew install commandbox

To stay with current bleeding edge releases use the following:

brew tap ortus-solutions/homebrew-boxtap
brew install --head ortus-solutions/homebrew-boxtap/commandbox

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]

If you want to use a commandbox.properties file as mentioned above, your box binary file will be in the /usr/local/Cellar/commandbox/<version>/bin/, or the /usr/local/Cellar/commandbox/<version>/bin/libexec/bin/, directory where you should place your commandbox.properties file. There will also be a box alias in the /usr/local/bin/ directory where you should place the jre if you want CommandBox to use a version of Java that is different from your default version reported by java -version.

When using Homebrew to install CommandBox you must use Homebrew for any upgrade, minor or major. To upgrade CommandBox with Homebrew:

brew upgrade commandbox

NOTE: If you use Homebrew to upgrade your version of CommandBox it will erase your commandbox.properties file.

Manual Installation

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 the box command in any terminal window.

Linux apt-get

Please note that if you are running Ubuntu 18.04 or greater, or Debian 8 (Jessie) or greater, it's necesarry to have the libappindicator-dev package in order to have the tray icon working correctly.

sudo apt install libappindicator-dev

Run the following series of commands to add the Ortus signing key, register our Debian repo, and install CommandBox.

Stable

curl -fsSl https://downloads.ortussolutions.com/debs/gpg | sudo apt-key add -
echo "deb https://downloads.ortussolutions.com/debs/noarch /" | sudo tee -a /etc/apt/sources.list.d/commandbox.list
sudo apt-get update && sudo apt-get install apt-transport-https commandbox

Then run the box binary to begin the one-time unpacking process.

Linux yum

Stable

Add the following to: /etc/yum.repos.d/commandbox.repo

[CommandBox]
name=CommandBox $releasever - $basearch
failovermethod=priority
baseurl=http://downloads.ortussolutions.com/RPMS/noarch
enabled=1
metadata_expire=7d
gpgcheck=0

Then run:

sudo yum update && yum install commandbox

Debian Linux manual install

After you have downloaded the commandbox.deb file, install it using the dpkg command.

sudo dpkg -i commandbox-debian-1.2.3.deb

Run the box binary to begin the one-time unpacking process.

Redhat Linux manual install

After you have downloaded the commandbox.rpm file, install it using the rpm command.

rpm –ivh commandbox-rpm-1.2.3.rpm

Upgrading

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.

Stable

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.

Bleeding Edge

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.

Use The Force

If you already have the latest version installed, but you still want to force an upgrade, use the force parameter.

Brute Force

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.

Mac/ *Unix

If you have used Hombrew to install CommandBox you must use Homebrew for any upgrade, minor or major. To upgrade CommandBox with Homebrew:

Hint You can make the box.exe available in any Windows terminal by adding its location to the PATH system environment variable. See

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:

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 . To determine what version you have installed, use the version command.

http://www.computerhope.com/issues/ch000549.htm
Homebrew
box version
box upgrade
box upgrade --latest
upgrade --force
upgrade --latest --force
brew upgrade commandbox
WireBox

Authors

Luis Fernando Majano Lainez

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 Wood

Brad's CommandBox Snake high score is 141.

Contributors

  • Jorge Reyes - ColdBox Aficionado

Luis Majano is a Computer Engineer with over 15 years of software development and systems architecture experience. He was born in 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 . Luis resides in Houston, Texas with his beautiful wife Veronica, baby girl Alexia and baby boy Lucas!

He is the CEO of , 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 . You can read his blog at

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 (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 () and likes to work on solder-at-home digital and analog circuits with his daughter as well as building projects with Arduino-based microcontrollers.

San Salvador, El Salvador
Florida International University
Ortus Solutions
Inland Empire
www.luismajano.com
MidAmerica Nazarene University
http://www.codersrevolution.com
LogoOrtus Solutions Artifacts Server
LogoOrtus Solutions Artifacts Server

Recipes

Ingredients

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.

buildSite.boxr

# Start with an empty folder
rm mySite --recurse --force
mkdir mySite
cd mySite

# Initialize this folder as a package
init name=mySite version=1.0.0 slug=mySlug

# Scaffold out a site and a handler
coldbox create app mySite
coldbox create handler myHandler index

# Add some required package
install coldbox
install cbmessagebox,cbstorages,cbvalidation

# Set the default port
package set defaultPort=8081

# Start up the embedded server
start

Get Cooking

Execute your recipe with the recipe command, giving it the path to the recipe file.

recipe buildSite.boxr

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.

Spice It Up

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.

Named arguments

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

echo "Hello there, ${name}, You've won a ${prize}!"

You would call it like so:

recipe recipeFile=notifyWinner.boxr name=Luis prize="NEW CAR"

Output:

Hello there, Luis, You've won a NEW CAR!

Note, all parameters to the recipe command needed to be named, including the recipeFile.

Positional Parameters

Now let's look at the same recipe set up to receive positional parameters.

echo "Hello there, ${1}\n You've won a ${2}!"

You would call it like so:

recipe notifyWinner.boxr Luis "NEW CAR"

Output:

Hello there, Luis, You've won a NEW CAR!

Missing Args

If an argument is not passed, you can use the default value mechanism:

echo "Hello there, ${name:human}, You've won a ${prize:something cool}!"

Is there an echo in here?

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.

# Now you see me
echo on
version

# Now you don't
echo off
version

Output:

version
CommandBox 1.2.3.00000
echo off
CommandBox 1.2.3.00000

Exiting a recipe

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.

exit 1

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.

package show foobar || echo "Missing property!" && exit 999

On The Fly Commands

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.

echo myCommands.txt | recipe

This can also give you some interesting ability to do dynamic evaluation of command strings.

set cmd=version
echo ${cmd} | recipe

If you want to automate several commands from your native shell, it will be faster to use our 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 .

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 .

recipe
Command API docs
CFML functions

Overview

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.

Features at a Glance

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

CommandBox
In The Package
Open the package
Setup
CommandBox Icon
First Run
Start Using
Embedded Server
Embedded Server
Next Steps

Non-Oracle JREs

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:

Amazon Corretto

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

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.

Azul Zulu

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.

Installing on Windows

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)

JavaSoft-Registry-Keys.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft]

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit]
"CurrentVersion"="8.0.192"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Development Kit\8.0.192]
"JavaHome"="C:\\Program Files\\Amazon Corretto\\jre8"
"RuntimeLib"="C:\\Program Files\\Amazon Corretto\\jre8\\bin\\server\\jvm.dll"

Installing on *nix

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.

export JAVA_HOME=/opt/ibm/java-x86_64-60/
export PATH=$JAVA_HOME/bin:$PATH

The JRE Folder

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.

If you want to debug what JRE is being used by the CommandBox CLI, use the -clidebug flag when starting CommandBox and the first few lines will tell you what version of Java is being used, and where on disk it lives.

For macOS users who have installed CommandBox via HomeBrew, the installer creates a box alias in /usr/local/bin/ which points to the box binary in the /usr/local/Cellar/commandbox/<version>/bin/ directory. If you want CommandBox to use a particular version of the JRE then put the jre folder in the /usr/local/bin/ directory. If you want CommandBox to have , place your commandbox.properties file in the /usr/local/Cellar/commandbox/<version>/bin/ directory.

a different home .CommandBox directory

Common Errors

Here are some common issues starting up CommandBox and troubleshooting help.

Could not load library. Reasons: [no jansi in java.library.path ... Access is denied]

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.

Could not load library. Reasons: [no jansi in java.library.path, C:\Users\some.user\AppData\Local\Temp\1\jansi-64-9170657940034638384.dll: Access is denied]
        at org.fusesource.hawtjni.runtime.Library.doLoad(Library.java:182):182
        at org.fusesource.hawtjni.runtime.Library.load(Library.java:140):140
        at org.fusesource.jansi.internal.CLibrary.<clinit>(CLibrary.java:42):42
        at org.fusesource.jansi.AnsiConsole.wrapOutputStream(AnsiConsole.java:48):48
        at org.fusesource.jansi.AnsiConsole.<clinit>(AnsiConsole.java:38):38
        at jline.AnsiWindowsTerminal.detectAnsiSupport(AnsiWindowsTerminal.java:57):57
        at jline.AnsiWindowsTerminal.<init>(AnsiWindowsTerminal.java:27):27
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method):-2
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source):-1
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source):-1
        at java.lang.reflect.Constructor.newInstance(Unknown Source):-1
        at java.lang.Class.newInstance(Unknown Source):-1
        at jline.TerminalFactory.getFlavor(TerminalFactory.java:211):211
        at jline.TerminalFactory.create(TerminalFactory.java:102):102
        at jline.TerminalFactory.get(TerminalFactory.java:186):186
        at jline.TerminalFactory.get(TerminalFactory.java:192):192
        at jline.console.ConsoleReader.<init>(ConsoleReader.java:243):243
        at jline.console.ConsoleReader.<init>(ConsoleReader.java:235):235
        at jline.console.ConsoleReader.<init>(ConsoleReader.java:227):227
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method):-2
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source):-1
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source):-1
        at java.lang.reflect.Constructor.newInstance(Unknown Source):-1
        at lucee.runtime.reflection.pairs.ConstructorInstance.invoke(ConstructorInstance.java:52):52
        at lucee.runtime.reflection.Reflector.callConstructor(Reflector.java:809):809
        at lucee.runtime.java.JavaObject.init(JavaObject.java:295):295
        at lucee.runtime.java.JavaObject.call(JavaObject.java:222):222
        at lucee.runtime.java.JavaObject.call(JavaObject.java:259):259
        at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:743):743
        at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1599):1599
        at system.util.readerfactory_cfc$cf.udfCall(/commandbox/system/util/ReaderFactory.cfc:38):38

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.

/usr/bin/box: 87: exec: java: not found

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.

Execution

There are two ways to run commands via CommandBox: inside the CommandBox interactive shell, or one-at-a-time commands from your native shell.

Multiple Commands

C:\>box.exe

   _____                                          _ ____            
  / ____|                                        | |  _ \           
 | |     ___  _ __ ___  _ __ ___   __ _ _ __   __| | |_) | _____  __
 | |    / _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` |  _ < / _ \ \/ /
 | |___| (_) | | | | | | | | | | | (_| | | | | (_| | |_) | (_) >  < 
  \_____\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|____/ \___/_/\_\  v1.2.3.00000

Welcome to CommandBox!
Type "help" for help, or "help [command]" to be more specific.
CommandBox> version
CommandBox 1.2.3.00000
CommandBox> pwd
C:\
CommandBox> echo "Hello World!"
Hello World!
CommandBox> exit

C:\>

One-Off Commands

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.

C:\>box version
CommandBox 1.2.3.00000

C:\>

The box text is calling the CommandBox binary, and the version bit is passed along to the CommandBox shell to execute once it loads.

Debug Mode

You can also activate CommandBox in debug mode by passing the -clidebug flag in the command line. This will give you much more verbose information about the running CommandBox environment. This only one-off commands

box -clidebug

Output

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.

Search

cat myLogFile.txt | grep "variable .* undefined"

Pagination

forgebox show | more

Redirection

Redirect output into a file, overwriting if it exits like so:

dir > fileList.txt

Use the double arrows to append to an existing file.

echo "Step 3 complete" >> log.txt

Tail files

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.

forgebox search luis | tail
system-log | tail lines=50
tail myLogFile.txt --follow

Ad-hoc Java properties for the CLI

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:

BOX_JAVA_PROPS="foo=bar;brad=wood"

That would create a property called foo and a property called brad with the values bar and wood respectively. This environment variable works the same on all operating systems.

Ad-hoc JVM args for the CLI

Similar to above, you may want to add ad-hoc JVM args to the java process that powers the CLI. The steps differ per operating system. For *nix (Linux, Mac), set an environment variable called BOX_JAVA_ARGS in the environment that box will run in.

BOX_JAVA_ARGS="-Xms1024m -Xmx2048m -Dfoo=bar"
box

For Windows, create a file called box.l4j.ini in the same directory as the box.exe file and place a JVM arg on each line. Escape any backslashes with an additional backslash like a properties file format.

box.l4j.ini
-Xms1024m
-Xmx2048m
-Dfoo=bar

Both of those examples would set the min/max heap size of the CLI process and also set a Java System Property called "foo" equal to "bar". There is no effective difference between setting system properties this way as opposed to using BOX_JAVA_PROPS as shown in the previous section, but actual JVM -X settings must be set as described in this section.

Noninteractive Mode

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.

config set nonInteractiveShell=true

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.

Custom working directory

CommandBox will start its current working directory in the same folder that you started the box process from. Once you are in the interactive shell, you can always change the current working directory with the cd command. If you want to change the default working directory or just want to run a one-off command in another folder, you can use the -cliworkingDir flag to the box binary when you start it.

box -cliworkingDir=C:/my/path/here/
# This works too
box -cliworkingDir C:/my/path/here/
# And can be coupled with a command to run
box -cliworkingDir C:/my/path/here/ install

Usage

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.

Interactive Shell

Starting and Stopping

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.

One-Off Commands

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.

$ box version
$ box install coldbox-be
$ box upgrade

Info Executing one-off commands might have a delay when executing as the CommandBox environment needs to load first.

Special Path Expansions

On Windows, / or \ will be treated as the current drive root based on the current working directory. This is the same as DOS.

cd /windows/system32

On all OS's, ~ will expand to the current user's home directory.

cd ~
ls ~/.ssh

CFML Files

CommandBox's true power comes from it's command-based architecture, but we also support just running plain-jane .cfm files as well.

Running plain CFML files

Take the following file for example:

test.cfm

<cfoutput>#now()#</cfoutput>

We can execute this file directly from our native OS prompt by simply passing the filename straight into the box binary.

C:\> box test.cfm
{ts '2015-02-19 20:14:13'}

Or, I can run it from within the CommandBox interactive shell using the execute command:

CommandBox> execute test.cfm
{ts '2015-02-19 20:12:41'}

#! Goodness

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

#!/usr/bin/env box

<cfoutput>#now()#</cfoutput>

All we need to do is make it executable

chmod +x test

And then just run it like any other shell script!

$> ./test

{ts '2015-02-19 20:31:32'}

CFML Engine

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.

Exit Codes

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 counterintuitive to CFML developers since we are used to positive numbers as being truthy and zero as being falsely, but it is the industry standard for shells. It makes more sense if you think of it in terms of what Windows calls it-- %errorlevel%. if the error level is 0 there was no error!

Command Exit Codes

> !git status
fatal: not a git repository (or any of the parent directories): .git
Command returned failing exit code [128]
​
> echo ${exitCode}
128

Shell Exit Code

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

$> box testbox run

from a Travis-CI build will automatically fail the build if the tests don't pass.

Manual Exit Code

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.

exit 123

Command Chaining

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.

mkdir foo && cd foo

||

You can use || to run the second command only if the previous one failed.

mkdir foo || echo "I couldn't create the directory"

;

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.

mkdir foo; echo "I always run"

Assertions

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.

pathExists

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.

pathExists box.json && package show

You can specify if the path needs to be a file or a folder.

pathExists --file server.json && server show
pathExists --directory foo || mkdir foo

assertTrue

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

assertTrue `package show private` && run-script foo
assertTrue ${ENABLE_DOOM} && run-doom
assertTrue `#fileExists foo.txt` && echo "it's there!"

assertEqual

Returns a passing (0) or failing (1) exit code whether both parameters match. Comparison is case insensitive.

assertEqual `package show name` "My Package" || package set name="My Package"
assertEqual ${ENVIRONMENT} production && install --production

OS Binaries

Hint This behavior is dependent on your operating system.

Using 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.

run myApp.exe
run /path/to/myApp

Using !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.

!myApp.exe
!/path/to/myApp
!dir
!netstat -pan
!npm ll
!ipconfig
!ping google.com -c 4
!java -jar myLib.jar

Current Working Directory Aware

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.

!git init
touch index.cfm
!git add .
!git commit -m "Initial Commit"

Building On

#listlast `!pwd` /

Parsing Rules

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.

!ver && ver

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.

echo "ver" | run && ver
!git status | find "`package show name`"

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.

echo 'git status | find "`package show name`"' | run

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.

When you prepare the native binary ahead of time and then pipe it into the run command, you are allowed to pipe the result back into another CommandBox command in that specific case. This is only possible when run appears with nothing after it.

echo 'git status | find "`package show name`"' | run | #ucase

Piping to the native binary's standard input

You can pipe the output of a previous command in CommandBox directly to a native binary like so:

#createguid | !clip
or
#createguid | run clip

In this case, clip is a Windows binary that will read the standard input and place that text on the clipboard. When the run command receives two inputs, it will assume the first input is the piped input and the second input is the actual command to run.

You can even pipe commands to an interpreter that normally reads from a keyboard on the standard input, but be aware that some binaries such as Windows cmd require line breaks after the input or it won't process. In the specific case of Windows cmd it seems to require at least two line breaks for some reason (this is also true outside of CommandBox)

echo "ping google.com`#chr 10``#chr 10`" | !cmd

In the previous example we use a backtick expansion to grab a line feed from the CFML chr() function.

Limitations of piping

There are limitations. When you pipe into the run command, the command will not also be able to read from your keyboard (this is true of any shell) and it will execute in a non-interactive manner, which means the ping's output above would appear all at once as opposed to flowing in one line at a time.

When piping into the run command you cannot also pipe the output of the run command like so:

#createguid | !clip | #ucase

As soon as any text appears after run or !, then the rest of the line is "eaten" and passed to the native shell.

Also you cannot build up a command like so and also pipe input into the native binary at the same time:

echo "clip" | run

This is because only one parameter can be piped into a command at a time.

Debugging

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.

config set debugNativeExecution=true

Setting the Native Shell

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)

Exit Codes

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}.

CLI Environment Variables

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.

set name=brad
!echo %name%
set name=brad
!echo $name

Using a DB in CFML scripts

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.

Lucee allows datasource to be a struct

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.

ds = {
  class: 'org.gjt.mm.mysql.Driver',
  connectionString: 'jdbc:mysql://localhost:3306/bradwood?useUnicode=true&characterEncoding=UTF-8&useLegacyDatetimeCode=true',
  username: 'root',
  password: 'encrypted:bc8acb440320591185aa10611303520fe97b9aa92290cf56c43f0f9f0992d88ba92923e215d5dfd98e632a27c0cceec1091d152cbcf5c31d'
};

var qry = queryExecute( sql='select * from cb_role', options={ datasource : ds } );

for( var row in qry ) {
  echo( row.role & chr( 10 ) );
}

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.

Another method

appSettings = getApplicationSettings();
dsources = appSettings.datasources ?: {};

dsources[ 'myNewDS' ] = {
    class: 'org.gjt.mm.mysql.Driver',
    connectionString: 'jdbc:mysql://localhost:3306/bradwood?useUnicode=true&characterEncoding=UTF-8&useLegacyDatetimeCode=true',
    username: 'root',
    password: 'encrypted:bc8acb440320591185aa10611303520fe97b9aa92290cf56c43f0f9f0992d88ba92923e215d5dfd98e632a27c0cceec1091d152cbcf5c31d'
};
application action='update' datasources=dsources;

var qry = queryExecute( sql='select * from cb_author', options={ datasource : 'myNewDS' } );

for( var row in qry ) {
    echo( row.firstName & chr( 10 ) );
}

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.

Notes

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:

username: 'root',
password: 'clear text password'

CFML Functions

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().

#function

As a handy shortcut, you can invoke the cfml command by simply typing the name of the CFML function, preceded by a # sign.

Function parameters

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' ).

Piping them together

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.

Complex 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.

Named Parameters

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.

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 and .

This example show running the box.exe executable from a Windows DOS prompt, executing the , , and commands, and then exiting back to DOS.

Pipe output into the command to apply a regex upon it. will only emit lines matching the regex.

Pipe output into the 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.

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 () 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 escape codes and will only work correctly if you're using an ANSI-compatible shell to run CommandBox from.

So let's go a little deeper into

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 .

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 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 called exitCode.

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 .

The output of native calls can be used in or piped into other commands. Here's a Unix example that uses from the command line to parse the parent folder from the current working directory:

Additionally, any or 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):

Get DS definition from the Lucee administrator

There are a couple tags inside Lucee that don't support this just yet. `<CFDBInfo>` is one of them. [ 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.

tab complete
command history
version
pwd
echo
grep
grep
more
API Docs for fileWrite.
API Docs for fileAppend.
See API Docs
ANSI
CommandBox execution.
CommandBox commands
CommandBox Bullet Train
System Setting
here
http://apidocs.ortussolutions.com/commandbox/current/index.html?commandbox/system/modules/system-commands/commands/run.html
expressions
CFML functions
Ticket Here]
cfml now
#now
#hash mypass
#reverse abc
#listGetAt www.foo.com 2 . | #ucase | #reverse
#arrayAvg [1,2,3]
package list --JSON | #structFind dependencies | #structKeyArray
echo "java -version" | run  | #listToArray `#chr 10` | #arrayFirst | sed 's/java version "(.*)"/\1/'
#directoryList path=D:\\ listInfo=name

Escaping Special Characters

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.

Spaces

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.

echo 'Hello World'
echo "Good Morning Vietnam"

Quotes

Quotes are actually allowed unescaped in a value like so:

echo O'reilly

However, if the parameter contains whitespace and is surrounded by quotes, you'll need to escape them with a backslash.

echo 'O\'reilly Auto Parts'
echo "Luis \"The Dev\" Majano"

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.

echo "O'reilly Auto Parts"
echo 'Luis "The Dev" Majano'

Backticks

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.

echo "Nothing to \`see\` here"

Equals Signs

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.

echo 2+2\=4
echo "2+2=4"

Line Breaks

Line breaks can't be escaped directly since 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.

Tabs

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.

Backslash

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.

echo foo\\\=bar

This will print foo\=bar

Commands

Commands

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.

Namespaces

artifacts list
artifacts clean
artifacts remove

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 typing help after the namespace.

artifacts help
coldbox create handler

Aliases

expansions you put in your command string with backticks

For a full list of all the commands that ship with CommandBox as well as all their parameters and samples, please visit our 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 namespace. It contains several commands inside of it including , , and . Calling each of them would look like this:

Namespaces can be more than one level. Another example would be which contains commands such as , , and .

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 or the CLI help command to see if a command has aliases. For instance, the command is aliases as q for quick typing. Another example would be the command that is aliased to just init.

Command API docs
artifacts
list
clean
remove
coldbox create
app
view
handler
Command API docs
quit
package init

Globbing Patterns

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.

"?" matches a single character

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.

"*" matches any number of characters within name

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.

"**" matches any number of characters across all directories

To extend the previous example, if we did models/**.cfc that would match any cfc file in any subdirectory, no matter how deep.

Globbing examples

Here's some examples of what file globbing might look like:

CommandBox> rm temp*.txt
CommandBox> cp *.cfm backup/
CommandBox> touch build/*.properties

Here's some more examples of how the wildcards work

// Match any file or folder starting with "foo"
foo*

// Match any file or folder starting with "foo" and ending with .txt
foo*.txt

// Match any file or folder ending with "foo"
*foo 

// Match a/b/z but not a/b/c/z
a/*/z

// Match a/z and a/b/z and a/b/c/z
a/**/z

// Matches hat but not ham or h/t
/h?t

Since the Globber library can handle more than one globbing pattern, any command that uses a Globber type can accept a comma-delimited list of patterns. The following will list any .cfm AND .md files in the directory.

dir *.cfm,*.md

Piping into Commands

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.

Examples

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.

Piping From The OS

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.

cat myfile.txt | grep "find me"
coldbox create app "My App"
echo "My App" | coldbox create app
echo "My App" > appName.txt
cat appName.txt | coldbox create app
package set name="hello world"
package show name | sed s/hello/goodbye/
C:\> echo coldbox | box install
C:\> echo reverse('this is a test') | box repl
C:\> echo version | box
C:\> box < commands.txt

Expressions

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.

Entire Parameter

Take for instance, this simple command that prints out the contents of a file:

cat defaultServer.txt

It can be used as a dynamic parameter like so:

server start name=`cat defaultServer.txt`

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:

server start name=myServer

Inside Parameters

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:

echo "Your CommandBox version is `ver` and this app is called '`package show name`'!!"

That would output something similar to:

Your CommandBox version is 3.0.0 and this app is called 'Brad's cool app'!

If you need to use an actual backtick in a parameter value, escape it with a backslash.

echo "Nothing to \`see\` here"

Which outputs

Nothing to `see` here

Express Yourself

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

package set createdDate="'`#now | #dateformat mm/dd/yyyy`'"
Set createdDate = 1/1/2016

Set properties based on manipulations of previous values:

package set name=brad
Set name = brad
package set name="`package show name` wood"
Set name = brad wood

Perform CFML operations on local files:

Commandbox> #hash `cat pass.txt`

Execute environment-aware install scripts based on local files. (isProduction.txt would contain the text true or false in this ex.)

install id=coldbox production=`cat /home/user/isProduction.txt`

File Paths

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.

Absolute

Here are examples of fully qualified paths in Windows and *nix-based:

Windows:

mkdir C:/sites/test
mkdir /sites/test
mkdir \\server/share/test

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.

*nix:

mkdir /opt/var/sites/test

Relative

For a relative path, do not begin with a slash.

mkdir test

File system paths will be canonicalized automatically which means the following is also valid:

mkdir ../../sites/test

UNC Server paths

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.

\\server/share/sites/test
\\10.10.1.205/webroot/logs

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 \\

cd \\\\server/share/sites/test
mkdir \\\\10.10.1.205/webroot/logs

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.

Permissions

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.

Ad-hoc Command Aliases

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.

config set command.aliases.cca="coldbox create app"
cca myApp

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.

config set command.aliases.foobar="echo brad | grep brad | sed s/rad/foo/ > foo.txt && cat foo.txt"
foobar

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.

config set command.aliases.print=echo
print brad

Let's take it a step further and alias the alias!

config set command.aliases.cout=print
cout brad

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.

Environment Variables

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.

Shell Environment Variables (Global)

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:

env set foo=bar

# or just
set foo=bar

You can view the contents of that variable from anywhere in the same shell session like so:

env show foo

# or provide a default value
env show foo myDefault

# Or via System Setting expansions
echo ${foo:myDefault}

Clear out an environment variable like so:

env clear foo

Per-Command Environment Variables

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.

echo `set myVar=cheese && echo \${myVar}`
env show myVar myDefault

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

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.

Viewing Variables

To view the environment variable for the current command context, run:

> env set color=red
> env set number=2
> env show
{
    "number":"2",
    "color":"red"
}

The output is a JSON serialized struct, which makes it suitable for programmatically accessing.

> env show | foreach "echo 'The var \${item} is set to \${value}'"
The var number is set to 2
The var color is set to red

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.

> echo "set inrecipe=true; env debug" | recipe
[
    {
        "environment":{},
        "context":"env debug"
    },
    {
        "environment":{
            "inRecipe":"true"
        },
        "context":"recipe"
    },
    {
        "environment":{
            "number":"2",
            "color":"red"
        },
        "context":"Global Shell"
    }
]

Native Binaries

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.

set name=brad
!echo %name%
set name=brad
!echo $name

Passing Environment Variables to Servers

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:

set foo=bar
server start

The CFML code running that server process will be able to "see" the foo environment variable.

System Settings

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.

Using system settings from the CLI

You can test it out easily by outputting your system path like so:

echo ${PATH}

Default values

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.

server start port=${SERVER_PORT:8080}

This does assume that your default value will never contain a colon!

Lookup Order

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:

  1. Environment variables for the currently executing command

  2. Environment variables for the parent (calling) command (if applicable)

  3. Global shell environment variables

  4. JVM System Properties in the CLI process

  5. 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.

echo ${path}

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.

set path=donuts
echo ${path}

Using system settings in JSON files

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:

 server set web.http.port=\${WEB_PORT:8080}

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.

{
    "web":{
        "http":{
            "port":"${WEB_PORT:8080}"
        }
    }
}

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.

{
  "datasources":{
    "myDSN-${environment}":{
      "database":"test",
      "dbdriver":"MSSQL",
      "dsn":"jdbc:sqlserver://{host}:{port}",
      "host":"localhost",
      "password":"password",
      "username":"user"
    }
  }
}

Note if there are duplicate key names after the system settings are expanded, the last one expanded will win.

In the REPL

You can use system settings and environment variables in the REPL using the same syntax as the CLI

CommandBox> set foo=bar
CommandBox> REPL

CFSCRIPT-REPL: echo( '${foo}' )
bar

Manual system setting replacements

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.

In a complex data structure

component {
    property name='systemSettings' inject='SystemSettings';

     function run() {
        var mySettings = deserializeJSON( fileRead( 'mySpecialConfigFile.json' ) );
        systemSettings.expandDeepSystemSettings( mySettings );
     }

}

In a string

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:

var myValue = 'User home is in ${user.home}';
myValue = systemSettings.expandSystemSettings( myValue );

Programmatic access

The SystemSettings service also gives you programmatic access to individual system settings in your custom commands and task runners.

var mySetting = systemSettings.getSystemSetting( 'settingName' );
or
var mySetting = systemSettings.getSystemSetting( 'settingName', 'defaultValue' );
System Setting placeholders

Command Help

Help is integrated at every level in CommandBox. You can help global help, namespace help, or command help at any time.

Global Help

To get an overall list of all the commands you have available to run, simply type help at the shell.

Namespace Help

Next, drill down and get help on a specific namespace like server.

Command Help

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.

HTML Command API Docs

System Logs

CommandBox> system-log | open
CommandBox> system-log | cat
CommandBox> system-log | tail

Parameters

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

Named parameters can be specified in any order and follow the format name=value. Multiple named parameters are separated by a space.

coldbox create app name=myApp skeleton=AdvancedScript directory=myDir init=true

Positional Parameters

coldbox create app myApp AdvancedScript myDir true

Of course, only the required parameters must be specified. I'm only including all of them here for the completeness of the example.

Required Parameters

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.

CommandBox> mkdir
Enter directory (The directory to create) : myDir
Created C:\myDir
CommandBox>

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.

Flags

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.

coldbox create app myApp --init --installColdBox

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.

coldbox create app myApp --noInit
Global Help
Namespace Help
Command Help

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:

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:

Command API docs
http://apidocs.ortussolutions.com/commandbox/current
submit a crash report
Command API docs

System Setting Expansion Namespaces

The default namespace when using the ${foo} system setting expansion syntax is box environment variable, Java system properties, and OS environment variables.

It is also possible to leverage built-in namespaces to allow expansions that reference:

  • server.json properties

  • box.json properties

  • arbitrary JSON file properties

  • Config settings (like the config show command)

  • Server info properties (like the server info property=name command)

  • Other properties in the same JSON file

server.json properties

If the current working directory of the shell contains a server.json file, you can reference any property in it with the serverjson. namespace.:

${serverjson.name}
${serverjson.app.cfengine}
${serverjson.web.http.port}
${serverjson.trayEnable:defaultValue}

if you have a server json file with a non-default name such as server-custom.json then you can access it with the serverjson. namespace.:

${serverjson.name@server-custom.json}
${serverjson.app.cfengine@server-custom.json}
${serverjson.web.http.port@server-custom.json}
${serverjson.trayEnable@server-custom.json:defaultValue}

box.json properties

If the current working directory of the shell contains a box.json file, you can reference any property in it with the boxjson. namespace.:

${boxjson.name}
${boxjson.slug}
${boxjson.testbox.runner}
${boxjson.description:defaultValue}

Arbitrary JSON file properties

You can can reference properties from any JSON file with either a relative path (to the current working directory) or an absolute path with the json. namespace..

${json.myProperty.name@myFile.json}
${json.myProperty.name@/path/to/myFile.json:defaultValue}

Config settings

You can expand any valid config setting with the configsetting. namespace. So getting the same value you get when you run the command

config show endpoints.forgebox.apitoken

can be expanded like this:

${configsetting.endpoints.forgebox.apitoken}
${configsetting.endpoints.forgebox.apitoken:defaultValue}

Server info properties

You can expand any valid server info property with the serverinfo. namespace. So getting the same value you get when you run the command

server info property=serverHomeDirectory

can be expanded like this:

${serverinfo.serverHomeDirectory}
${serverinfo.serverHomeDirectory:defaultValue}

By default, the expansion looks at the default server in the current working directory. To grab a server property by server name, use this syntax:

${serverinfo.serverHomeDirectory@serverName}
${serverinfo.serverHomeDirectory@serverName:defaultValue}

Other properties in the same JSON file

You can self-reference other properties in the same JSON file using the @ namespace. So given the following JSON file:

{
    "appFileGlobs" : "models/**/*.cfc,tests/specs/**/*.cfc",
    "scripts":{
        "format":"cfformat run ${@appFileGlobs} --overwrite",
        "format:check":"cfformat check ${@appFileGlobs} --verbose"
    }
}

The expansion of ${@appFileGlobs} self-references the appFileGlobs property inside the same file, allowing for easy re-use of that value.

Custom namespaces

Modules can register an onSystemSettingExpansion interceptor to contribute custom system setting namespace expansions. The interceptor gets the following data in interceptData

  • setting - The name of the setting to be expanded (with ${} and :defaultValue removed)

  • defaultValue - The default value, or empty string if none specified

  • resolved - A boolean that should be set true if the interceptor was able to resolve the setting

  • context - A struct of the original JSON being expanded or the parameters from the command line where the expansion was used.

A hypothetical example would be:

function onSystemSettingExpansion( struct interceptData ) {	
  // ${luceeInfo.property}
  if( interceptData.setting.lcase().startsWith( 'luceeinfo.' ) ) {
		
    var settingName = interceptData.setting.replaceNoCase( 'luceeInfo.', '', 'one' );
				
    interceptData.setting = server.lucee[ settingName ] ?: interceptData.defaultValue;
		
    // Stop processing expansions on this setting
    interceptData.resolved=true;
    return true;
  }	
}

And then we would use our hypothetical namespace to reference any Lucee information like so

echo ${luceeinfo.version}

It's important if you implement your own onSystemSettingExpansion interceptor that you check the incoming setting to see if it applies to you. If you process the system setting, you must place the final expanded value back in the interceptData.setting struct key, set interceptData.resolved to true and return true from the interception method so the chain stops processing.

Tab Completion

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.

Commands

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...

CommandBox> cold
CommandBox> coldbox
CommandBox> coldbox

Commands
  help
  reinit  (This command will reinitialize a running ColdBox application if a server was started with CommandBox)
Namespaces
  create

Parameters

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!

CommandBox> delete

Flags
  --force     (Force deletion without asking)    --recurse   (Delete sub directories)
Parameters
  path=        (file or directory to delete.)    recurse=    (Delete sub directories)
  force=      (Force deletion without asking)

Named

If you have started typing named parameters, CommandBox will only suggest unused named parameters and flags.

CommandBox> delete path=myDir force=true

Flags
  --recurse  (Delete sub directories)
Parameters
  recurse=   (Delete sub directories)

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.

CommandBox> delete path=myDir force=

Values
  force=true     force=false
CommandBox> delete path=

Directories
  path=tests/       path=models/      path=coldbox/     path=modules/
Files
  path=box.json     path=index.cfm    path=server.json

Positional

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.

Flags

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.

CommandBox> delete myDir --

Flags
  --force  (Force deletion without asking)   --recurse   (Delete sub directories)

Custom

Commands have the ability to give hints in the form of a static list or a runtime function with dynamic output.

CommandBox> forgebox show type=

Values
type=di                      type=caching                 type=projects
type=cms                     type=logging                 type=cf-engines
type=mvc                     type=modules                 type=interceptors
type=demos                   type=plugins                 type=wirebox-aspects

REPL

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 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 and the same prompt will be output again below it so you can continue typing.

Here is CommandBox giving every option possible for the command. Note, force and recurse are booleans, so they can be specified as flags.

Here, all files and folders in the current working directory are offered as possibilities for the path parameter of the command.

Here the command dynamically provides completion for its type attribute based on the current types returned by the .

coldbox
coldbox
delete
delete
forgebox show
ForgeBox REST API

Default Command Parameters

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.

config set command.defaults.rm.force=true
rm myFile.txt

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:

rm myFile.txt --NoForce

forEach Command

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.

ls --simple | forEach

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.

ls *.json --simple | forEach cat

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.

forEach input="coldbox,testbox,cborm" delimiter="," command=install

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.

ls *.json --simple | foreach "echo \${item} && cat \${item}"

You may also choose a custom placeholder name for readability.

ll *.json --simple | foreach "echo \${filename} && cat \${filename}" filename

Here's an example that has several things going on. It takes a list of globbing patterns to get all CFC and CFM files recursively in a directory, then it loops over each file path, outputting it preceded by the current working directory, with backslashes replaced with forward slashes.

dir **.cfc,**.cfm --simple | foreach "echo `pwd | #listchangedelims / \\`/\${item}"

Iterating over JSON

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.

package show dependencies | foreach

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}.

package show dependencies | foreach "echo 'You have \${item} version \${value} installed'"

You can customize the system setting name for value with the valueName parameter to forEach.

package show dependencies | foreach command="echo 'You have \${package} version \${version} installed'" itemName=package valueName=version

watch command

There are some specific commands that make use of the Watcher library in CommandBox such as testbox watch and coldbox watch-reinit. However, there is also a generic watch command that will run any arbitrary command of your choosing when a path matching your file globbing pattern is added/updated/deleted.

The following environment variables will be available to your command

  • watcher_added - A JSON array of relative paths added in the watch directory

  • watcher_removed - A JSON array of relative paths removed in the watch directory

  • watcher_changed - A JSON array of relative paths changed in the watch directory

Since escaping meta characters can get tricky with nested strings, you can declare the command as an environment variable and then just reference it like so:

That example runs the foreach command over each item in the watcher_added array and then runs an echo statement to output the name of each added path.

watch *.json "echo 'config file updated!'"
set command = "echo 'You added \${item}!'"
watch command="foreach '\${watcher_added}' \${command}" --verbose

Interactive Shell Features

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.

Ctrl-C & Ctrl-D

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.

History Search

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.

Change to Previous Directory

Like Powershell or Bash, you can type the following to switch back to the previous working directory:

cd -

If you run this same command more than once, you will keep toggling between the same two directories (bash behavior)

Auto Update Checks

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.

REPL

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.

CFSCRIPT-REPL: 5+5
=> 10

Script REPL

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.

CFSCRIPT-REPL: breakfast = ['bacon','eggs']
=> [
    "bacon",
    "eggs"
]
CFSCRIPT-REPL: breakfast.len()
=> 2
CFSCRIPT-REPL: breakfast.append( 'orange juice' )
=> [
    "bacon",
    "eggs",
    "orange juice"
]

Multi-line

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.

CFSCRIPT-REPL: for( item in breakfast ) {
...echo( item & chr(10) )
...}
=> bacon
eggs
orange juice

If you would like to abort a multi-line statement, simply type exit at the prompt.

Tag REPL

You can also enter tags at the REPL. Switch to this mode by setting the script flag to false.

REPL --!script

Any output from the tags will be returned to the console.

CFML-REPL: plain text
=> plain text
CFML-REPL: <cfset name = "Brad Wood">
=>
CFML-REPL: <cfoutput>#reverse( name )#</cfoutput>
=> dooW darB
CFML-REPL: <cfif 1 eq 2>yes<cfelse>no</cfif>
=> no

Multi-line statements are not currently supported in the tag REPL.

History

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).

history type=scriptrepl
history type=tagrepl --clear

Tab completion is currently not supported in either of the REPLs.

Environment Variable Expansions

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.

CommandBox> set foo=bar
CommandBox> REPL

CFSCRIPT-REPL: echo( '${foo}' )
bar

Escapes work the same way in the REPL

CFSCRIPT-REPL: echo( '\${foo}' )
${foo}

LogoFORGEBOX: CommandBox Update Check
CommandBox Update Check Module

256 Color Support

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.

Color Names

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)

system-colors
print.lightGoldenrod5Line( 'This is pretty' );
print.color221( 'This is the same color as above' );
config set modules.commandbox-bullet-train.packageBG=lightGoldenrod5
config set modules.commandbox-bullet-train.packageText=color21
256 Color support from ConEMU in Windows

IDE Integrations

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!

A Little Fun

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.

ASCII Art Stereograms

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!

Sublime Text

Quickstart

Installation

via PackageControl

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.

Manually

You can clone the repo in your /Packages (Preferences -> Browse Packages...) folder and start using/hacking it.

cd ~/path/to/Packages
git clone git://github.com/Ortus-Solutions/sublime-commandbox.git Commandbox

Troubleshooting

Usage

Running a Commandbox Command

You may select pre-configured commands from Menu -> Commandbox, including the ability enter a custom command.

Keyboard Shortcuts:

  • 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 )

Settings

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:

{
    // Override your environment PATH
    "exec_args": {},
    // Use a new tab when showing the results. If it's false it'll use a panel.
    "results_in_new_tab": false,
    // Defines the delay used to autoclose the panel or tab that holds the box results.
    // If false (or 0) it will remain open.
    "results_autoclose_timeout_in_milliseconds": 0,
    // If true it will open the output panel when running Commandbox(silent) only if the task failed
    "show_silent_errors": true,
    // Create the file 'sublime-commandbox.log' to report errors
    "log_errors": true,
    // Syntax file for highlighting the box results
    // Set to false if you don't want any colors (you may need to restart Sublime)
    "syntax": "Packages/Commandbox/syntax/CommandboxResults.tmLanguage",
    // Read from stdout and stderr without blocking (both at the same time)
    "nonblocking": true,
    // Add a custom flag to a particular box command. Format: { "task_name": "flags" }
    // For example: { "concat": "--silent" }
    "flags": {},
    // If `false` the package will run even if no `box.json` is found on the root folders currently open.
    "check_for_boxjson": true,
}

exec_args

You may override your PATH environment variable as follows:

{
    "exec_args": {
        "path": "/bin:/usr/bin:/usr/local/bin"
    }
}

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

results_in_new_tab

If set to true, a new tab will be used instead of a panel to output the results.

results_autoclose_timeout_in_milliseconds

Defines the delay used to autoclose the panel or tab that holds the Commandbox results.

show_silent_errors

log_erros

Toggles the creation of sublime-commandbox.log if any error occurs.

syntax

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).

nonblocking

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.

Bind Your Own Keyboard Shortcuts

You can use a shortcut for running a specific task like this:

{ "keys": ["KEYS"], "command": "commandbox", "args": { "task_name": "watch" } }

A plugin to run your tasks from within Sublime plus some handy too.

Install Via Commandbox

If you have installed, you can use it to install the package.

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 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 .

If true it will open the output panel when running only if the task failed

Package Control
PackageControl
SublimeFixMacPath
issue
Commandbox
snippets
Commandbox (silent)

Bullet Train Prompt

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.

Installation

Install the module like so:

install commandbox-bullet-train

Fonts

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:

config set modules.commandbox-bullet-train.unicode=false

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.

Here is a guide for setting a new font up to be used with the Windows cmd terminal:

For Windows users, we also recommend using ConEMU as your terminal.

Usage

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!

Customize 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.

Visual Studio Code

Here are suggestions for using VSC (Visual Studio Code) for developing in CFML.

What do you want to do with VSC?

  1. Install it?

  2. Key Extensions?

  3. Working with the shell/terminal

  4. Git Extensions?

Installing VSCode

Using The Terminal/Shell

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.

Commandbox only

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.

Commandbox and Shells of Choice

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" } ],

Or loading it as desired

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.

Key Extensions

You should also install a few extensions. (These extensions can also be added from the built in Extensions item.)

Git Extensions

Additional Extensions ( of course, choose the ones you want and ignore the others )

P.S. A couple of other nice plugins.

More information to follow. (Including video guides to show how to get started that may not be as familiar with different parts.)

CommandBox Bullet Train Prompt

This IDE has it's own domain. ( ) with downloads for macOS, Windows and Linux on the home page. :+1:

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!

https://github.com/powerline/fonts.git
https://www.techrepublic.com/blog/windows-and-office/quick-tip-add-fonts-to-the-command-prompt/

Module Settings

These settings affect how CommandBox loads modules.

ModulesExternalLocation

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.

config set ModulesExternalLocation=[\"/var/my/external/modules\"]
config show ModulesExternalLocation

modulesInclude

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.

config set modulesInclude=[\"moduleName\",\"anotherModuleName\"]
config show modulesInclude

ModulesExclude

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.

config set ModulesExclude=[\"moduleName\",\"anotherModuleName\"]
config show ModulesExclude

modules.*

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.

config set modules.TestModule.mySetting=overridden
config set modules.TestModule.somethingEnabled=false

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:

config show modules.TestModule

Config Settings

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.

Set Config Settings

config set name=mySetting

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

config set modules.myModule.mySetting=foo

Set item in an array

config set myArraySetting[1]="value"

Set multiple params at once

config set setting1=value1 setting2=value2 setting3=value3

Override a complex value as JSON

config set myArraySeting="[ 'test@test.com', 'me@example.com' ]"

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.

config set myArraySetting="[ 'another value' ]" --append

Show Config Settings

Output a setting:

config show settingName

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

config show modules.myModule.settingName
config show mySettingArray[1]

Clear Config Setting

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.

config clear description

JSON Settings

You can customize the way that JSON is formatted when it's written to files such as server.json and box.json as well as how it displays in the console when using commands such as server show and package show

JSON.indent

string

String to use for indenting lines. Defaults to four spaces.

config set JSON.indent="  "

JSON.lineEnding

string

String to use for line endings. Defaults to CRLF on Windows and LF on *nix. Pass the actual character to use, not a placeholder.

config set JSON.lineEnding=`#chr 10`

JSON.spaceAfterColon

boolean

Add space after each colon like "value": true instead of "value":true Defaults to false

config set JSON.spaceAfterColon=true

JSON.sortKeys

string

Specify a sort type to sort the keys of json objects: text or textnocase

config set JSON.sortKeys=textnocase

JSON.ANSIColors

struct

A struct of colors to use when displaying JSON in the CLI. You can use any color name from the system-colors command or a direct ANSI escape sequence.

JSON.ANSIColors.constant

string

The color to use for constant values (true/false/null). Defaults to "red".

config set JSON.ANSIColors.constant=PaleTurquoise1

JSON.ANSIColors.key

string

The color to use for object key names. Defaults to "blue".

config set JSON.ANSIColors.key=Purple5

JSON.ANSIColors.number

string

The color to use for numbers. Defaults to "aqua".

config set JSON.ANSIColors.number=SeaGreen3

JSON.ANSIColors.string

string

The color to use for quoted string values. Defaults to "lime".

config set JSON.ANSIColors.string=MistyRose3

Proxy Settings

If you need to use CommandBox behind a corporate proxy, these settings will be necessary for it to successfully connect to the Internet.

proxy.server

string

This is the URL of the proxy server on your network.

config set proxy.server=myProxy.com
config show proxy.server

proxy.port

integer

This is the port to connect to on the proxy server.

config set proxy.port=9000
config show proxy.port

proxy.user

string

This is the username to connect to the proxy server with, if required.

config set proxy.user=proxyUser
config show proxy.user

proxy.password

string

This is the password to connect to the proxy server with, if required.

config set proxy.password=proxyPass
config show proxy.password
https://code.visualstudio.com/
Shell Launcher
CFML Language Support
CFLint Support
Tag Comment Support
Git Lens
TODO Highlight
Project Manager
Hg
Great Icons

Server Settings

These settings control how servers start in CommandBox.

server.defaults

struct

config set server.defaults.web.rewrites.enable=true
config set server.defaults.openbrowser=false
config set server.defaults.jvm.heapsize=1024
config show server.defaults

Misc Settings

These are some one-off settings that doen't really belong anywhere else.

nativeShell

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.

config set nativeShell=/bin/zsh
config show nativeShell

tagVersion

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.

config set tagVersion=false
config show tagVersion

tagPrefix

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.

config set tagPrefix=''
config show tagPrefix

artifactsDirectory

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.

config set artifactsDirectory=/path/to/artifacts
config show artifactsDirectory

preferredBrowser

string

Used to override the default browser to open when a server starts, or when using a command like server open or calling the openURL() method from a command or Task Runner. Possible values are:

  • firefox

  • chrome

  • opera

  • edge (Windows and Mac only)

  • ie (Windows only)

  • safari (Mac only)

  • konqueror (Linux only)

  • epiphany (Linux only)

config set preferredBrowser=chrome
config show preferredBrowser

tabCompleteInline

boolean

You can change CommandBox's default tab completion to be an inline list that follows your cursor. This setting requires you to close and re-open the shell to take affect.

config set tabCompleteInline=true
config show tabCompleteInline

Endpoint Settings

These settings are used to configure CommandBox's endpoints.

endpoints.forgebox.APIToken

string

config set endpoints.forgebox.APIToken=my-very-long-secret-key
config show endpoints.forgebox.APIToken

endpoints.forgebox.APIURL

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.

config set endpoints.forgebox.APIURL=https://forgebox.stg.ortussolutions.com/api/v1
config show endpoints.forgebox.APIURL
Visual Studio Code Snapshot

This struct can contain any . These settings are used as global default settings if there is not a corresponding setting provided by the user via a parameter to the start command or in the server's server.json file.

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!

setting that is valid in a server.json file
ForgeBox.io

Debugging Server Starts

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.

server log
server log serverName

Tailing and Following logs

If the log is very large, use the tail command to just see the last few lines of it.

server log | tail
server log | tail lines=100

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.

server log --follow

You can also look at your server's access log (if enabled) and rewrite log (if enabled).

server log --follow -access
server log --follow --rewrite

Start server in console mode

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.

server start --console

Debug Logging

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.

server start --debug
server start --debug --console

Maximum logging! (trace)

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.

server start --trace --console

Start HTML Server

You may want to start up a local server that does not have a CF Engine such as Lucee or Adobe ColdFusion installed. You can do this as of CommandBox 5.1.0 by setting the cfengine parameter to none like so:

server start cfengine=none

Or in your server.json like this

server set app.cfengine=none
server start

This server will support everything that you are used to including the server.json file, heap settings, ports, and virtual directories. The only difference is it will server everything as static files. (.cfm or .cfc files will not be processed)

Embedded Server

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).

CommandBox> cd C:\sites\test
CommandBox> start

To stop the embedded server, run the stop command from the same directory.

CommandBox> stop

OS Integration

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

Disable the tray icon

If you don't want the tray integration, then you can turn it off in your server.json with this setting.

server set trayEnable=false

Or turn it off at a global level in your config settings.

config set server.defaults.trayEnable=false

Full Control

Environment Variables

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:

set foo=bar
server start

The CFML code running that server process will be able to "see" the foo environment variable.

CommandBox Server Tray Menu

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.

Undertow
CommandBox API Docs

Multi-Engine Support

You can specify the CFML engine via the command line arguments:

CommandBox> start cfengine=adobe@2018

This will start an Adobe ColdFusion 2018 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

  • Adobe ColdFusion 2021

  • Railo 4.2

  • Lucee 4.5

  • Lucee 5

Here are some examples:

# Start the default engine
CommandBox> start

# Start the latest stable Railo engine
CommandBox> start cfengine=railo

# Start a specific engine and version
CommandBox> start cfengine=adobe@10.0.12

# Start the most recent Adobe server that starts with version "11"
CommandBox> start cfengine=adobe@11

# Start the most recent adobe engine that matches the range
CommandBox> start cfengine="adobe@>9.0 <=11"

Engines are downloaded and stored in your CommandBox artifacts folder. You can view your engines and clear them using the standard artifacts commands:

CommandBox> artifacts list

# Removes all adobe servers currently in the artifacts
# These servers will need to be re-downloaded the next time they are started
CommandBox> artifacts remove adobe

ColdFusion Admin settings

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

WAR Support

Additionally, CommandBox can start any WAR given to it using the WARPath argument.

CommandBox> start WARPath=/var/www/myExplodedWAR
CommandBox> start WARPath=/var/www/myWAR.war

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.

Custom Engines

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:

  1. box.json

  2. 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:

CommandBox> start cfengine=http://downloads.ortussolutions.com/adobe/coldfusion/9.0.2/cf-engine-9.0.2.zip

server.json Configuration

You can set the cfengine and other related configuration options in your server.json to use them every time you start your app.

CommandBox> server set app.cfengine=adobe
CommandBox> server set app.WARPath=/var/www/my-app

These commands would create the following server.json

{
    "app":{
        "cfengine":"adobe",
        "WARPath":"/var/www/my-app"
    }
}

Just a reminder that starting a server with any command line arguments will save the arguments to your server.json by default.

CommandBox> start cfengine=adobe@9

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.

FusionReactor

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.

Installation

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.

Usage

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.

Licensing

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:

Hide License Key

By default, the license key will always be displayed on the home page after login. You can turn off the display of the key on a per-server basis or at a global level for all servers.

Custom Port

FusionReactor will bind the port on whatever host address is used for your server.

Disable the module

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.

Per-server License Key

You can set a license key per server if you wish like so:

Managing Versions

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.

Custom Version of FusionReactor

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.

Debugger Libs

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:

Provide External reactor.conf File

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.

Start up a test server with the FR module installed

Navigate to the FR admin, login, and set your desired settings

Copy the populated reactor.conf file somewhere for later use

Point 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.

Additional JVM args

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 - frregisterwith

  • 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.autoApplicationNaming - fr.application.auto_naming

  • fusionreactor.defaultApplicationName - fr.application.name

External Server

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.

Offline Server Starts

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.

Be More Specific

If you know that a CF engine is already downloaded in your server's artifacts directory, start your server with a specific major, minor, patch, and build 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.

Fail Safe

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.

Server Versions

Remember to use Semantic Versions

One minor difference to keep in mind is Lucee server and Adobe ColdFusion use a typical versioning scheme for java projects which looks like this:

The important thing to remember is, when starting a server via CommandBox always use the second format shown above since that is how ForgeBox recognizes each release.

What versions exist?

Questions about what versions are available? No problem! Here are some ways you can find out:

  • View the last few versions via the CLI with the command forgebox show lucee

  • Start typing your cfengine and hit the <tab> key to invoke the tab-completion feature. This actually phones out to ForgeBox as you hit tab to get the current valid list of versions that match what you've typed so far

You can also follow the Lucee bleeding edge, which means every time you start your CommandBox server you'll get the very latest Lucee snapshot release. Please only use this for local development and not production!

Pinning Exact Version

It is a nice feature of CommandBox to have it automatically grab the latest version of your favoriate CF engine every time it starts.

However, you may have good reason to NEVER want a new version automatically installed. In order to do this, you must specify a COMPLETE version number, including the build number, making sure to use the proper version format. This means you need a major, minor, patch, and build number.

Lucee Light builds on ForgeBox

We're now publishing CF Engines to ForgeBox based on the Lucee Light builds which allows you to start up a Lucee Light server. These are under a ForgeBox package named lucee-light and we've also backfilled all the same versions that exist for the normal lucee engine. Note, the three bullets points above apply to Lucee Light as well, Just replace lucee with lucee-light and you're good to go.

If you have questions about how to install extensions into a Lucee light server, please hit us up on Slack and we can show you several ways to manage that.

** 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.

However, and use the (semver) which is slightly different. Basically the build ID is moved to the end after a plus (+) sign.

Visit the ForgeBox listing for the Lucee package and view all the versions in the versions tab

Lucee has a modular core and comes bundled with a bunch of extensions that approximate the functionality that comes bundled with Adobe ColdFusion. But that means you are loading the Hibernate libraries, PDF libraries or JDBC drivers even if you don't need them. There is a second type of Lucee server called "Lucee Light" which contains all the core engine, but with zero extensions. People creating custom docker builds for example will start with Lucee Light and then add back only the extensions their app needs. To get a feel for all the Lucee extensions available, see that lists all official extensions.

Adobe ColdFusion 9 does not support the latest Java 8
install commandbox-fusionreactor
******************************************
* CommandBox FusionReactor Module Loaded *
******************************************

FusionReactor will be available at the URL http://127.0.0.1:2871
fr open
fr register "myLicenseKey"
// Server specific
server set fusionreactor.hideLicenseKey=true
// global default
config set server.defaults.fusionreactor.hideLicenseKey=true
// Server specific port
server set fusionreactor.port=8088
// global default port
config set server.defaults.fusionreactor.port=8088
server set fusionreactor.enable=false
config set server.defaults.fusionreactor.enable=false
server set fusionreactor.licenseKey=XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
install commandbox-fusionreactor
// Server specific version
server set fusionreactor.installID=fusionreactor@7.x
// global default version
config set server.defaults.fusionreactor.installID=fusionreactor@7.x
// Server specific version
server set fusionreactor.debugEnable=false
// global default version
config set server.defaults.fusionreactor.debugEnable=false
install commandbox-fusionreactor
server start
fr open
cp "`server info property=FRHomeDirectory`conf/reactor.conf" ./reactor.conf
server set fusionreactor.reactorconfFile=reactor.conf
server stop 
server forget --force
server start
// Server specific version
server set fusionreactor.externalServerEnable=true
// global default version
config set server.defaults.fusionreactor.externalServerEnable=true
start cfengine=lucee@5.x
start cfengine=lucee@5.0.0+252
<major>.<minor>.<patch>.<build>[-<preReleaseID>]

# Ex of an unstable build
5.3.4.84-SNAPSHOT

# Or a stable build
5.3.4.80
<major>.<minor>.<patch>[-<preReleaseID>]+<build>

# Ex of an unstable build
5.3.4-SNAPSHOT+84

# Or a stable build
5.3.4+80
server start cfengine=lucee@be
# Latest Lucee 5.3.7 build
server start cfengine=lucee@5.3.7

# Latest Adobe 2018 update
server start cfengine=adobe@2018

# Lucee bleeding edge-- latest snapshot
server start cfengine=lucee@be
# Pinned exact Adobe version
server start cfengine=adobe@2018.0.10+320417

# Pinned exact Lucee version
server start cfengine=lucee@5.3.7+48
# Latest stable
server start cfengine=lucee-light

# Specific version
server start cfengine=lucee-light@5.3.4.77

# Bleeding edge
server start cfengine=lucee-light@be

Server Processes

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.

Server Runs Independant of CLI

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.

WEB-INF

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.

Server Profiles

CommandBox has profiles you can assign to a server when you start it to configure the default settings. This is to provide easy secure-by-default setups for your production servers, and to make it easier to switch between a development mode and production mode.

There are 3 currently supported profiles. Custom profiles will be added as a future feature.

  • Production - Locked down for production hosting

  • Development - Lax security for local development

  • None - For backwards compat and custom setups. Doesn't apply any web server rules

Setting the profile

You can set the profile for your server in your server.json

server set profile=production

Which create this property

{
  "profile": "production"
}

Or you can specify it when starting the server like so:

server start profile=production

Default Profile

If a profile is not set, these rules are used to choose the default value:

  • If there is an env var called environment, it is used to set the default profile (same convention as ColdBox MVC)

  • If the site is bound on localhost, default the profile to "development". Localhost is defined as any IP address starting with 127.

  • If neither of the above are true, the default profile is "production". This makes CommandBox servers secure by default.

Production profile

When profile is set to "production", the following defaults are provided:

  • web.directoryListing = false

  • web.blockCFAdmin = external

  • web.blockSensitivePaths = true

  • web.blockFlashRemoting = true

Development profile

When profile is set to "development", the following defaults are provided:

  • web.directoryListing = true

  • web.blockCFAdmin = false

  • web.blockSensitivePaths = true

  • web.blockFlashRemoting = true

None profile

When profile is set to "none", the following defaults are provided:

  • web.directoryListing = true

  • web.blockCFAdmin = false

  • web.blockSensitivePaths = false

  • web.blockFlashRemoting = false

Customizing your profile

The defaults above only apply if you do not have am explicit server.json or server.defaults config setting. If you have an explicit setting, it will override the profile's default. Therefore, if you set the profile toproduction but set web.blockCFAdmin to false, your CF administrator will be public, but the remaining production defaults will still be applied. This allows even the default profiles to be customizable.

{
  "profile": "production"
  "web": {
    "blockCFAdmin": false
  }
}

Manage Servers

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.

List your server

You can see an overview of your servers and what state they're in with the server list command.

server list

site1 (starting)
  https://127.0.0.1:8081
  C:\site1

site1 (running)
  https://127.0.0.1:8082
  C:\site2

site3 (stopped)
  https://127.0.0.1:8083
  C:\site3

If you have many servers, you can provide parameters to help filter the results from server list

# All servers containing the word "foo"
server list foo

# Running servers
server list --running

To list only the servers that have been started in a given directory, use the --local flag.

server list --local

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.

Multiple Servers

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.

start site1
start site2
restart site3
stop site2
stop --all

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.

server cd site1
start
server cd site2
install myPackage
restart

Info Server name is the first parameter to all server commands and tab completion works too, making it as easy as possible for you.

Get Server Information

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.

server info
server info --JSON
server info property=serverHomeDirectory
server info property=consoleLogPath

Forgetting Servers

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.

server forget

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.

server stop --all --forget

Server Rules

CommandBox servers have a method of locking down secure URLs and or implementing any of the Undertow predicate and handlers via a nice text based language. Undertow supports a “predicate language” that allows a string to be parsed into a graph of predicates (conditions) and handlers (actions to take). Ex:

path-suffix(/box.json) -> set-error(404)

These rules can be used for any of the following:

  • Security - Block paths, IPs, or users

  • URL rewrites - Rewrite incoming URLs to something different

  • Modifying HTTP requests on the fly - Set headers, cookies, or response codes

Much of this functionality overlaps with the existing Tuckey-based rewrites in CommandBox, but this functionality is built directly into Undertow, has a more streamlined syntax, and allows for easier ad-hoc rules to be layered into a server that allows for you to have custom rules layered on top of built in rules. It can be used to replace what Tuckey does, or added on top.

If you have Tuckey rewrites enabled AND use the Undertow predicate-based server rules, the server rules will fire BEFORE the Tuckey rewrites.

Create your Rules

Unlike custom Tuckey-based rewrites that must be placed in a single XML file, sever rule can be provided ad-hoc in a variety of locations. They are combined and passed to the server in the order defined. This allows you to easily "layer" custom rules along with out-of-the-box lockdown profiles.

For maximum configuration options, the following mechanisms are supported for specifying the rules for a given server. Rules are processed in the order listed. i.e., a rule defined in your server.json is processed prior to a rule in your server.default config setting.

  1. Ad-hoc rule array in server.json

  2. External rules files in server.json in the order defined

  3. Ad-hoc rule array in config setting server.defaults

  4. External rules files in config setting server.defaults in the order defined

  5. CommandBox built-in rules (web.blockCFAdmin, web.blockConfigPaths)

  6. Any module listening to server interceptions can inject their rules wherever they please in the array.

server.json Rules

You can specify ad-hoc rules in the web.rules property as an array of strings in your server.json as well as specify one or more external rule files in the web.rulesFile property as an array or list of file glob patterns.

{
    "web" : {
        "rules" : [
            "path-suffix(/box.json) -> set-error(404)",
            "path-suffix(hidden.js) -> set-error(404)",
            "path-prefix(/admin/) -> ip-access-control(192.168.0.* allow)",
            "path(/sitemap.xml) -> rewrite(/sitemap.cfm)",
		"disallowed-methods(trace)"
        ],
	      "rulesFile" : "../secure-rules.json"
        // Or...
	      "rulesFile" : ["../security.json","../rewrites.txt","../app-headers.json"]
        // Or...
	      "rulesFile" : "../rules/*.json"
    }
}

External rule files with a .json suffix will be expected to be a valid JSON file containing an array of strings. Ex:

myRuleFile.json
[
  "path-suffix(/box.json) -> set-error(404)",
  "path-suffix(hidden.js) -> set-error(404)"
]

External rule files with any extension OTHER than .json will be expected to be a raw text file with one rule per line. Emtpy lines are ignored and the rules are processed in the order defined.

myRuleFile.txt
path-suffix(/box.json) -> set-error(404)
path-suffix(hidden.js) -> set-error(404)

Rules specified directly in the server.json or in an external JSON file must be escaped for the JSON they are a part of. Using a plain text external file can help readability since no additional escaping is required for the rules.

config setting server.defaults Rules

Like all other config server defaults, they follow the same pattern as the server.json file.

config set server.defaults.web.ruleFile=/path/to/rules.json

Configuring Your Server

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.

Ways to provide configuration

Configuration can be set at several different levels:

  1. Passed as parameters to the server start command

  2. Stored in a server.json file for that server

  3. Global defaults in the server.defaults config setting

  4. 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.

File path handling

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.

Server Logs

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.

CF App server logs

You can find out where your server home is by running:

server info property=serverHomeDirectory

You can also get the full path to your servlet's "out" log with this command:

server info property=consolelogPath

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:

server log --follow
server log myServerName --follow

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.

Lucee Server's Log Files

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.

  1. 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/.

  2. 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:

C:/users/brad/.CommandBox/server/{hash}-cfconfig/lucee-4.5.5.006/logs/server.out.txt

C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/application.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/datasource.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/deploy.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/gateway.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/mapping.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/memory.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/orm.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/remoteclient.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/rest.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/scope.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/search.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-server/context/logs/thread.log

C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/application.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/datasource.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/deploy.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/gateway.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/mapping.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/memory.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/orm.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/remoteclient.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/rest.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/scope.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/search.log
C:/users/brad/.CommandBox/server/{hash}cfconfig/lucee-4.5.5.006/WEB-INF/lucee-web/logs/thread.log

Adobe ColdFusion's Log Files

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.

  1. 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:

C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/logs/server.out.txt

C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/application.log
C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/audit.log
C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/eventgateway.log
C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/exception.log
C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/monitor.log
C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/scheduler.log
C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/server.log
C:/users/brad/.CommandBox/server/{hash}-testSite/adobe-2016.0.03.300466/WEB-INF/cfusion/logs/websocket.log

Access Log

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.

server set web.accessLogEnable=true

View the location of this log or tail the log contents like so:

server info property=accessLogPath
server log --follow --access
server log myServername --follow --access

Your access log will be auto-rotated every day.

Rewrite Log

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.

server set web.rewrites.logEnable=true

View the location of this log or tail the log contents like so:

server info property=rewritesLogPath
server log --follow --rewrites
server log myServername --follow --rewrites

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.

https://www.forgebox.io/view/commandbox-fusionreactor
http://www.fusion-reactor.com/
host updater module
the official FR docs
CommandBox
ForgeBox
npm-flavored semantic versioning
https://www.forgebox.io/view/lucee#versions
https://www.forgebox.io/view/adobe#versions
this page

Allowed Static Files

The Undertow-based web server built into CommandBox will only serve up static files if they are in a list of valid extensions. This is to prevent prying eyes from hitting files they shouldn't be able to access on your server.

The current list of valid extensions is:

If you have a common static file you need to serve, you can add your own custom extensions to the list like so:

3gp,3gpp,7z,ai,aif,aiff,asf,asx,atom,au,avi,bin,bmp,btm,cco,crt,css,csv,deb,der,dmg,
doc,docx,eot,eps,flv,font,gif,hqx,htc,htm,html,ico,img,ini,iso,jad,jng,jnlp,jpeg,jpg,
js,json,kar,kml,kmz,m3u8,m4a,m4v,map,mid,midi,mml,mng,mov,mp3,mp4,mpeg,mpeg4,mpg,msi,
msm,msp,ogg,otf,pdb,pdf,pem,pl,pm,png,ppt,pptx,prc,ps,psd,ra,rar,rpm,rss,rtf,run,sea,
shtml,sit,svg,svgz,swf,tar,tcl,tif,tiff,tk,ts,ttf,txt,wav,wbmp,webm,webp,wmf,wml,wmlc,
wmv,woff,woff2,xhtml,xls,xlsx,xml,xpi,xspf,zip,aifc,aac,apk,bak,bk,bz2,cdr,cmx,dat,
dtd,eml,fla,gz,gzip,ipa,ia,indd,hey,lz,maf,markdown,md,mkv,mp1,mp2,mpe,odt,ott,odg,
odf,ots,pps,pot,pmd,pub,raw,sdd,tsv,xcf,yml,yaml 
server set web.allowedExt=jar,exe,dll

Debugging Server Rules

And to test/debug your rules, start your server with the trace flag and tail the console output. Every hit in your browser will output several lines of debugging for each rule that is processed.

server start --trace --console 

With the custom rule above, you'd see something like this:

[DEBUG] requested: '/CFIDE/main/ide.cfm'
[TRACE] io.undertow.predicate: Path(s) [/CFIDE/main/ide.cfm] MATCH input [/CFIDE/main/ide.cfm] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[TRACE] io.undertow.predicate: Predicate [path( '/CFIDE/main/ide.cfm' )] resolved to true. Next handler is [done] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[TRACE] io.undertow.predicate: Predicate chain marked done. Next handler is [Runwar PathHandler] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[WARN ] responded: Status Code 200 (/CFIDE/main/ide.cfm)

Baked in Rules

Baked-in Rules

CommandBox has a few baked in rules that you can apply ad-hoc or as part of a server profile.

  • web.blockCFAdmin - Returns 404 error page for any Adobe CF or Lucee Server admin administrator paths

  • web.blockSensitivePaths - Returns 404 error page for common config files such as box.json or .env

  • web.blockFlashRemoting - Blocks all paths related to Flash and Flex remoting calls

If you want to customize the rules above, simply turn them off and include the rules directly in your server.json where you can modify them as you see fit.

Block CF Admin

This setting has three possible settings:

  • true - Block ALL access to ColdFusion and Lucee admins

  • false - Do not block anything

  • external - Only block access not coming from localhost.

The exact rule activated when you set this property to true is:

block-cf-admin()

The exact rule activated when you set this property to external is:

cf-admin() -> block-external()

Block Sensitive Paths

This setting only allows true/false. This is a bit of a catch-all rule for any sort of paths that a user should never be able to make on production that could reveal information or access secret parts of your CF installation. When set to true, the following rules are activated:

// track and trace verbs can leak data in XSS attacks
disallowed-methods( methods={trace,track} )

// Common config files and sensitive paths that should never be accessed, even on development
regex( pattern='.*/(box.json|server.json|web.config|urlrewrite.xml|package.json|package-lock.json|Gulpfile.js)', case-sensitive=false ) -> set-error(404)

// Any file or folder starting with a period
regex('/\.')-> set-error( 404 )

// Additional serlvlet mappings in Adobe CF's web.xml
path-prefix( { '/JSDebugServlet','/securityanalyzer','/WSRPProducer' } ) -> set-error( 404 )

// java web service (Axis) files
regex( pattern='\.jws$', case-sensitive=false ) -> set-error( 404 )

When the profile is set to production, the following rule is also added which blocks the ColdFusion RDS access from CF Builder and access to TestBox runners:

regex( pattern='.*/(CFIDE/multiservermonitor-access-policy.xml|CFIDE/probe.cfm|CFIDE/main/ide.cfm|tests/runner.cfm|testbox/system/runners/HTMLRunner.cfm)', case-sensitive=false ) -> set-error(404)

If you need to legitimately access any of these paths, you'll need to turn off this setting and custom-add the rules that you want to keep. This setting is a convenience that adds several rules at once.

Block Flash Remoting

This setting only allows true/false. When set to true, the following rules are activated:

// These all map to web.xml servlet mappings for ACF
path-prefix( { '/flex2gateway','/flex-internal','/flashservices/gateway','/cfform-internal','/CFFormGateway' } ) -> set-error( 404 )

// Files used for flash remoting
regex( pattern='\.(mxml|cfswf)$', case-sensitive=false ) -> set-error( 404 )

If you need to legitimately access any of these paths, you'll need to turn off this setting and custom-add the rules that you want to keep. This setting is a convenience that adds several rules at once.

Override just part of a baked-in rule

What if you want to go one step deeper? For instance, the blockSensitivePaths setting blocks a whole bunch of stuff all in one shot. An example might be wanting to open up JUST the RDS IDE integration for your developers, which funnels through the /CFIDE/main/ide.cfm path which you can see is blocked above.

The solution to this is quite simple and is all based on the ORDER in which your rules are processed. Built-in CommandBox rules are the last to process. This means that if you hijack the predicates with a custom rule FIRST, you can override the behavior of the built in rules. So, if we want to allow access to the /CFIDE/main/ide.cfm path, we just need to add a custom rule that matches that path and then aborts the predicate chain so no further rules fire.

server set web.rules="['path(/CFIDE/main/ide.cfm)->done']" --append 

Which gives you the following server.json

{
    "web":{
        "rules":[
            "path(/CFIDE/main/ide.cfm)->done"
        ]
    }
}

The done handler is what bypasses all subsequent rules for the request.

Since your custom rules are processed BEFORE the built-in rules, that also means that you have the ability to accidentally bypass security rules by applying another rule that intercepts the request! By default a custom rule won't block subsequent rules from firing unless you rewrite the request or use the special done handler.

JVM Args

The following JVM Args are supported when starting the embedded server.

heapSize

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.

start heapSize=1024

In server.json

server set JVM.heapSize=1024
server set JVM.heapSize=2G
server show JVM.heapSize

minHeapSize

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.

start minHeapSize=1024

In server.json

server set JVM.minHeapSize=1024
server set JVM.minHeapSize=2G
server show JVM.minHeapSize

Ad Hoc JVM Args

You can specify ad-hoc JVM args for the server with the JVMArgs parameter.

start JVMArgs="-XX:MaxGCPauseMillis\=200"

In server.json

server set JVM.args="-XX:MaxGCPauseMillis\=200"
server show JVM.args

Ad Hoc Runwar Options

You can specify ad-hoc options for the underlying Runwar library using the RunwarArgs parameter.

start RunwarArgs="--sendfile-enable false"

In server.json

server set runwar.args="--sendfile-enable false"
server show runwar.args

Rule Examples

There are endless combinations of predicates and handlers you can apply to your apps. Here's an assortment of examples to get you going. Many of these are contrived, but are just mean to show the range of syntax and functionality.

Rewrite a URL:

path('/healthcheck') -> rewrite('/healthcheck.cfm')

Stop processing rules for a given request:

path(/healthcheck) -> done
path(/healthcheck) -> response-code(503)  // This rule is skipped

For all GET requests, set a response header called type with a value of get

method(GET) -> set(attribute='%{o,type}', value=get)

If the incoming path ends with .css it will rewrite the request to .xcss and set a response header called rewritten to true.

regex('(.*).css') -> { rewrite('${1}.xcss'); set(attribute='%{o,rewritten}', value=true) } 

Redirect all jpg requests to the same file name but with the png extension. The ${1} exchange attribute is used to reference the first regex group.

regex('(.*).jpg$') -> redirect('${1}.png')

Set a request header that you can access in your CFML app just like a normal HTTP header.

set(attribute='%{i,someHeader}', value=someValue)

Match certain SES-style URLs and store the place holders (referenced as exchange attributes) into HTTP request headers.

path-template('/product/{productid}') -> set(attribute='%{i,productid}', value='${productid}')

In this example, hitting the server with /restart skips the first rule, the second rule rewrites the request and then restarts back at the first rule which fires the second time through.

path(/foo/a/b) -> response-code(503)
path(/restart) -> { rewrite(/foo/a/b); restart; }

Block access to a URL unless coming from a specific IP.

path-prefix(/admin/) and not equals('%{REMOTE_IP}', 127.0.0.1) -> set-error( 404 )

For more control over IP address matches, use the ip-access-control() handler.

path-prefix(value="/admin/") -> ip-access-control[default-allow=false, acl={'127.0.0.* allow'}, failure-status=404]

Leading slash is NOT required. Both of these rules are the same:

path(box.json) -> set-error( 404 )
path(/box.json) -> set-error( 404 )

It is not required to include .* at the end of a regex path unless you’ve set full-match=true

regex( "^/tests/" ) -> set-error( 404 ) 
regex( pattern='^/tests/.*", full-match=true ) -> set-error( 404 )

Perform a regex a case insensitive search like so:

regex(pattern="Googlebot", value="%{i,USER-AGENT}", case-sensitive=false ) -> set-error( 404 )

When attribute values are not quoted, all leading and trailing whitespace will be trimmed. The following are all the same:

path( "/foobar" )
path(/foobar)
path( /foobar )

But this example is different. The leading and trailing spaces will be preserved in the path string.

path( " /foobar " )

Basic MVC rewrite:

not regex( pattern='.*\.(bmp|gif|jpe?g|png|css|js|txt|xls|ico|swf|cfm|cfc|html|htm)$', case-sensitive=false ) -> rewrite('/index.cfm/%{RELATIVE_PATH}')

Custom Error Pages

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:

{
  "web" : {
    "errorPages" : {
      "404" : "/path/to/404.html",
      "500" : "/path/to/500.html",
      "default" : "/path/to/default.html"
    }
  }
}

You can set error pages via the server set command like this:

server set web.errorPages.404=/missing.htm

Accessing error variables

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:

req = getPageContext().getRequest();
names = req.getAttributeNames();
while( names.hasMoreElements() ) {
    name = names.nextElement();
    writeDump( name & ' = ' & req.getAttribute( name ) );
}

An example of getting the original missing path in a 404 would look like this:

var originalPath = getPageContext().getRequest().getAttribute( "javax.servlet.error.request_uri" );

Rule Language

CommandBox's server rules are based directly on the "Predicate Language" feature of JBoss Undertow. All of the official documentation for Undertow's predicate language applies to CommandBox. CommandBox doesn't limit the power of what Undertow provides at all. In fact, we give you some additional out-of-the box predicates and handlers you can use.

There are three concepts you need to understand and you'll be writing your own rules in no time.

  • Handler - A wrapper around the request that takes some sort of action such as returning a status code or rewriting the request.

  • Predicate - A conditional that evaluates to true or false. Used to Conditionally apply a handler

  • Exchange Attribute - An abstracted way to refer to any piece of information about the request or response. Can include URL, query string, cookies, headers, or CGI variables.

Since the parsing of your rules is handled by Undertow, it is case sensitive in many areas and CommandBox cannot control this. The following must always be lower case:

  • Predicate names

  • Handler names

  • Parameter names

  • Keywords like and, or, else

Handler

A handler will take action on the request. This can redirect the request, rewrite it, abort it, or modify attributes of the request such as setting an HTTP header or status code. If the predicate is omitted, the handler will always fire for all requests. Ex:

disallowed-methods(trace)

Common handlers:

  • set() - Sets an exchange attribute (see below)

  • rewrite() - Rewrite the request URL

  • redirect() - Redirect to another URL

  • header() - Sets an HTTP response header

  • set-error() - Set HTTP response code and returns the corresponding error page

  • ip-access-control() - Configure IP-based allow/deny rules (wildcards and IP ranges allowed)

  • done - Skips remaining rules

  • request-limit() - Limits concurrent requests

  • restart - Restarts process back at start of predicate rule chain (combine with rewrite, etc)

  • reverse-proxy() - Creates a round robin reverse proxy to a list of URLs

  • allowed-methods() / disallowed-methods() - Enforces whitelist/blacklist of HTTP methods on current request

A handler is called using the “name” from the docs and passing any required parameters. Params can be named or positional (if there is only one). Quoting values is only required if they have a space, comma or brace. The following are all equivalent:

set-error(404)
set-error("404")
set-error(response-code=404)
set-error(response-code="404")

Handler parameters that accept an array use the Java array literal syntax which is a comma-delimited list of values in curly braces.

reverse-proxy( { 'http://host.com', 'http://host2.com' } )

More than one handler can be run by wrapping them in curly braces and using semicolons between them

path(/restart) -> { rewrite(/foo/a/b); restart; }

A chain of handlers can be configured for the true AND false evaluation of a single predicate using the “else” keyword.

regex('(.*).css') -> set(attribute='%{o,css}', value='true') else set(attribute='%{o,css}', value='false');

Predicates

A predicate is a condition that must be matched for the handler to kick in.

Common predicates:

  • path() - match the incoming request path

  • path-suffix() - match full file/folder names at the end of the path like file.cfm

  • path-prefix() - match full file/folder names at the start of the path like /lucee/admin

  • method() - Match the HTTP method

  • regex() - Match a regular expression against any exchange attribute

  • equals() / contains() - Do a text compare on any exchange attribute

  • path-template() - match a path with placeholders like /foo/{bar} and the placeholders become variables for use in later predicates or handlers in the chain.

A predicate is called by placing parentheses after the name and passing in the required arguments as specified in the docs for that predicate. Quoting values is only required if they have a space, comma or brace. The following are all equivalent:

method(GET)
method("GET")
method(value=GET)
method(value="GET")

Complex conditions can be constructed with more than one predicate using the keywords “and” or “or”.

path-prefix(/tests/) OR path-prefix(/workbench)

A predicate can be negated with the keyword “not”

not method(POST)

Exchange Attributes

Exchange attributes are an abstraction Undertow provides to reference any part of the HTTP request or response. There is a textual placeholder that can be used in predicates and handlers that will be expanded in-place.

Common Exchange Attributes:

  • %{REMOTE_IP} - Remote IP address

  • %{PROTOCOL} - Request protocol

  • %{METHOD} - Request method

  • %{REMOTE_USER} - Remote user that was authenticated

  • %{RESPONSE_TIME} - Time taken to process the request, in ms

  • %{c,cookie_name} - Any cookie value

  • %{q,query_param_name} - Any query parameter

  • %{i,request_header_name} - Any request header

  • %{o,response_header_name} - Any response header

  • ${anything-here} - Any value from the predicate context (such as regex capture groups or path-template placeholders)

Use an exchange attribute like you would a variable as the parameter to a handler or predicate.

set(attribute='%{o,someHeader}', value=myValue)
not equals('%{REMOTE_IP}', 127.0.0.1) -> set-error(403)

Attributes, Cookie, query params, request headers, and response header names are not case sensitive.

These are all equivalent:

regex(pattern="/(MSIE 6\.0)", value="%{i,user-agent}" ) -> response-code( 404 )
regex(pattern="/(MSIE 6\.0)", value="%{i,USER-AGENT}" ) -> response-code( 404 )
regex(pattern="/(MSIE 6\.0)", value="%{i,UsEr-AgEnT}" ) -> response-code( 404 )

Custom Predicates/Handlers

CommandBox bundles some custom predicates and handlers to make your life easier.

The predicate cf-admin() will returns true if the incoming URL is to the Lucee or ColdFusion admin:

cf-admin() -> set-error( 404 ); 

// Is the equivalent of 
regex(pattern='^/(CFIDE/administrator|CFIDE/adminapi|CFIDE/AIR|CFIDE/appdeployment|CFIDE/cfclient|CFIDE/classes|CFIDE/componentutils|CFIDE/debug|CFIDE/images|CFIDE/orm|CFIDE/portlets|CFIDE/scheduler|CFIDE/ServerManager|CFIDE/services|CFIDE/websocket|CFIDE/wizards|lucee/admin)/.*', case-sensitive=false) -> set-error(404) 

The handler block-external() blocks any request not from localhost with a 404 response code. You can pair this with any predicate you choose.

cf-admin() -> block-external() 

// Is the equivalent of 
cf-admin() -> ip-access-control( default-allow=false, failure-status=404, acl={ 127.*.*.* allow } ) 

The handler block-cf-admin() blocks any request to the Lucee or ColdFusion admin with a 404 response code.

block-cf-admin() 

// Is the equivalent of 
cf-admin() -> set-error( 404 ); 

Build Your Own

You can build your own predicates and handlers by compiling java classes that implement the io.undertow.predicate.PredicateBuilder or io.undertow.server.handlers.builder.HandlerBuilder interfaces. If the proper service metadata is present in your jar's META-INF folder, undertow will automatically find and register your builders via Java's service loader.

This isn't super difficult but involves a few moving parts. If you're interested in writing your own handlers and predicates to use in your server rules, reach out on the mailing list and we'll walk you through it.

You can see the custom handlers and predicates documented above in our Runwar source code here:

Custom handlers:

Custom Predicates:

URL Rewrites

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.

Default Rules

start --rewritesEnable

Now URLs like

http://localhost/index.cfm/main

can now simply be

http://localhost/main

In server.json

server set web.rewrites.enable=true
server show web.rewrites.enable

info The default rewrite file can be found in ~\.CommandBox\cfml\system\config\urlrewrite.xml

Custom Rules

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

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 4.0//EN" "http://tuckey.org/res/dtds/urlrewrite4.0.dtd">
<urlrewrite>
    <!-- this will redirect the user from /foo to /index.cfm -->
    <rule>
        <from>^/foo$</from>
        <to type="redirect">/index.cfm</to>
    </rule>
    <!-- internally redirect the requested URL from /gallery to /index.cfm?page=gallery with query string appended -->
    <rule>
        <from>^/gallery</from>
        <to type="passthrough" qsappend="true">/index.cfm?page=gallery</to>
    </rule>

</urlrewrite>

Then, fire up your server with its custom rewrite rules:

start --rewritesEnable rewritesConfig=customRewrites.xml

In server.json

server set web.rewrites.enable=true
server set web.rewrites.config=customRewrites.xml


server show web.rewrites.enable
server show web.rewrites.config

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.

server set web.rewrites.enable=true
server set web.rewrites.config=/my/custom/path/customRewrites.xml

or

server set web.rewrites.enable=true
server set web.rewrites.config=~\.CommandBox\cfml\system\config\customRewrites.xml

Apache mod_rewrite-style rules

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 .htaccess 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:

RewriteEngine on

#The ColdBox index.cfm/{path_info} rules.
RewriteRule ^$ index.cfm [QSA,NS]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.cfm/%{REQUEST_URI} [QSA,L,NS]

RewriteRule ^/foo/                         /

# Defend your computer from some worm attacks
RewriteRule .*(?:global.asa|default\.ida|root\.exe|\.\.).* . [F,I,O]

# Redirect Robots to a cfm version of your robots.txt
RewriteRule ^/robots\.txt                   /robots.cfm

# Change your default cfm file to index.cfm
RewriteRule ^/default.cfm                   /index.cfm [I,RP,L]
RewriteRule ^/default.cfm((\?.+)|())$       /index.cfm$1  [I,RP,L]

RewriteRule ^/News.html((\?.+)|())$         /News/index.cfm$1 [I,RP,L]

# redirect mozilla to another area
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/no-moz-here$                 /homepage.max.html  [L]

Please see the docs here on what's supported:

SES URLs

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.

site.com/index.cfm/home/login

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.

site.com/myFolder/index.cfm/home/login

Logging

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.

start --debug
server log --follow

Additional Tuckey Settings

The Tuckey Rewrite library that CommandBox uses under the hood. It has some extra settings that CommandBox allows you to use.

Watch rewrite file for changes

To monitor your custom rewrite file for changes without needing to restart the server, use this setting.

server set web.rewrites.configReloadSeconds=30

Internal Tuckey status page

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.

server set web.rewrites.statusPath=/tuckey-status

Custom Java Version

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)

Manual Java Config

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.

Automatic Java Download

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

Java Namespace

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:

java search

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.

java list

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.

java setDefault

You may change the global default Java version for your servers with this command.

java install

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.

java uninstall

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.

Aliases

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.

GZip Compression

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.

By default GZip compression will be applied to any file over 1500 KB in size. This is because 1500 KB or smaller can fit inside a single network packet, so there's no real benifit in zipping small files and it just causes CPU overhead.

Since ANY valid Undertow predicate language can be used here you can combined predicates to control exactly when GZip compression is applied. This example would apply GZip compression to any CSS files over 500 KB that were not in the /admin folder.

Performance Tuning

Here are some settings for performance tuning your servers

Max Requests

This setting limits how many requests will be passed through the Undertow listener to your app server. It defaults to 30. Please note that your web server connector and Adobe ColdFusion may also have their own max request setting.

Or as a global setting for all servers:

Welcome Files

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.

Directory Browsing

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

Basic Authentication

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.

Adding Custom Libs

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.

Global Custom Libs

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.

Server Port and Host

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.

Any Port in the Storm

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:

HTTPS

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

AJP

You can start your server to listen for AJP connections too.

A Gracious Host

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

Customize URL that opens for server

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://.

The full undertow docs can be found here:

Full list here:

Full list here:

Full list here:

You may be used to configuring URL rewrites in Apache or IIS, but rewrites are also possible in CommandBox's embedded server via a .

We've already added the required jars and created a default rewrite that will work out-of-the-box with the ColdBox MVC Platform. To enable rewrites, start your server with the --rewritesEnable flag.

info For more information on custom rewrite rules, consult the .

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.

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.

If you wish to customize the file size or any other aspect of when GZip compression is applied, you can specify a custom that, when true, will trigger GZip for the request.

https://undertow.io/undertow-docs/undertow-docs-2.0.0/
https://undertow.io/undertow-docs/undertow-docs-2.0.0/#built-in-handlers-2
https://undertow.io/undertow-docs/undertow-docs-2.0.0/#textual-representation-of-predicates
https://undertow.io/undertow-docs/undertow-docs-2.0.0/#exchange-attributes-2
Tuckey servlet filter
http://tuckey.org/urlrewrite/
XML file
http://tuckey.org/urlrewrite/manual/4.0/index.html
http://cdn.rawgit.com/paultuckey/urlrewritefilter/master/src/doc/manual/4.0/index.html#mod_rewrite_conf
Tuckey docs
server set jvm.javaHome="C:\Program Files\Java\jdk1.8.0_25"
config set server.defaults.jvm.javaHome="C:\Program Files\Java\jdk1.8.0_25"
server start javaVersion=openjdk8
server set jvm.javaVersion=openjdk8
config set server.defaults.jvm.javaVersion=openjdk8
config set server.javaInstallDirectory=C:/path/to/JREs/
java search version=openjdk8
java search version=openjdk8 os=
java list
server java setDefault openjdk11
server java install openjdk11 --setDefault
server java uninstall openjdk9_jre_x64_windows_hotspot_jdk-9.0.4+11
{
  "web" : {
    "aliases" : {
      "/foo" : "bar",
      "/js" : "C:\static\shared\javascript"
    }
  }
}
server set web.aliases./foo = bar
server set web.aliases./js = C:\static\shared\javascript
server set web.gzipEnable=true
server set web.gzipPredicate="request-larger-than(500)"
server set web.gzipPredicate="not path-prefix( admin ) and regex( '(.*).css' ) and request-larger-than(500)"
server set web.maxRequests=100
config set server.defaults.web.maxRequests=100
server set web.welcomeFiles='go.cfm,main.cfm,index.html'
server set web.directoryBrowsing=true
config set server.defaults.web.directoryBrowsing=true
server set web.basicAuth.enabled=true
server set web.basicAuth.users.brad=pass
server set web.basicAuth.users.luis=pass2
{
    "web":{
        "basicAuth":{
            "users":{
                "brad":"pass",
                "luis":"pass2"
            },
            "enabled":"true"
        }
    }
}
server start libDirs=path/to/libs,another/path/to/libs
server set app.libDirs=path/to/libs,another/path/to/libs
server start
config set servers.defaults.app.libDirs=/path/to/global/libs
 start port=8080
server set web.http.port=8080
server show web.http.port
 $> netstat -pan | grep 80
start SSLEnable=true SSLPort=443
server set web.SSL.enable=true
server set web.SSL.port=8080
server show web.SSL.enable
server show web.SSL.port
server set web.SSL.certFile=/path/to/dev_mydomain_ext.crt
server set web.SSL.keyFile=/path/to/dev_mydomain_ext.key
openssl req -utf8 -nodes -sha256 -newkey rsa:2048 -keyout dev_mydomain_com.key -out dev_mydomain_com.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:NL
State or Province Name (full name) [Some-State]:YourState
Locality Name (eg, city) []:YourCity
Organization Name (eg, company) [Internet Widgits Pty Ltd]:YourCompany
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:dev.mydomain.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
start AJPEnable=true AJPPort=8009
server set web.AJP.enable=true
server set web.AJP.port=8009
server show web.AJP.enable
server show web.AJP.port
 start host=mycoolsite.local
 start host=192.168.10.15 port=80
 start host=0.0.0.0 port=80
server set web.host=mycoolsite.local
server show web.host
server set openBrowserURL=/bar.cfm
server set openBrowserURL=http://127.0.0.1:59715/test.cfm

Single Server Mode

CommandBox is designed to allow you to start, stop, and manage as many servers as you like. However, when using CommandBox in an environment such as Docker containers where you only ever want to have a single server, this can cause issues where warming up the server with different names creates more than one server. You can enable Single Server Mode which will only allow CommandBox to have a single server that shows when you run the server list command.

config set server.singleServerMode=true

This is a global setting that takes immediate effect. If you already have more than one server defined, it will not remove the extra ones, it will simply re-use the first server it finds. In this mode, the server name becomes essentially meaningless. Each of these commands would use the same default server

start name=foo
stop name=bar
restart name=brad

External Web Server

You can place CommandBox downstream behind another external web server if you wish. Here is an overview of how to do that.

Microsoft IIS

Apache HTTP

Nginx

server {

  server_name  example.net www.example.net;

  root /app;

  index index.cfm index.html index.htm;

  proxy_redirect           off;
  proxy_set_header         X-Real-IP $remote_addr;
  proxy_set_header         X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header         Host $http_host;
  proxy_set_header         X-Forwarded-Proto $scheme;

  location ~ /WEB-INF/  { access_log off; log_not_found off; deny all; }
  location ~ /META-INF/  { access_log off; log_not_found off; deny all; }
  location ~ /META-INF/ { return 404; }
  location ~ /WEB-INF/ { return 404; }
  location ~ \.config$ { return 404; }
  location ~ /\. { return 404; } ## e.g. .htaccess, .gitignore etc.
  location ~ ~$ { return 404; }
  location ~ \.aspx?$ { return 404; } ## most likely hackers testing the site
  location ~ \.php$ { return 404; } 

  # this prevents hidden files (beginning with a period) from being served
  location ~ /\. {
    access_log off; log_not_found off; deny all;
  }

  # Do not log missing favicon.ico errors
  location ^/(favicon\.ico|apple-touch-icon.*\.png)$ { 
    access_log off; log_not_found off; 
  } 
  location = /robots.txt  { 
    access_log off; log_not_found off; 
  }

  location / {
    try_files $uri $uri/ @rewrites;
  }

  #set indexfileinurls=0 in Mura's settings.ini.cfm     
  location @rewrites {
    rewrite ^/(.*)? /index.cfm/$1 last;
    rewrite ^ /index.cfm last;
  }

  # Main Railo/Lucee proxy handler
  location ~ \.(cfm|cfml|cfc|jsp|cfr)(.*)$ {
    proxy_pass http://127.0.0.1:8080;
  }

  # Some basic cache-control for static files to be sent to the browser
  location ~* \.(?:jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|otf|woff|eot|mp4|ogg|ogv|webm|js|css)$ {
    expires 1M;
    #expires modified +90d;
    access_log off;
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
  }

  listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
  listen 443 ssl http2; # managed by Certbot
  ssl_certificate /etc/letsencrypt/live/example.net/fullchain.pem; # managed by Certbot
  ssl_certificate_key /etc/letsencrypt/live/example.net/privkey.pem; # managed by Certbot
  include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {

  if ($host ~ ^[^.]+\.example\.net$) {
      return 301 https://$host$request_uri;
  } # managed by Certbot

  if ($host = example.net) {
      return 301 https://$host$request_uri;
  } # managed by Certbot


  listen 80;
  listen [::]:80;
  server_name  example.net www.example.net;
  return 404; # managed by Certbot

}

REST Servlet

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:

server set app.restMappings=/rest/*,/api/*

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.

Custom Tray Menus

For every server you start, there is a corresponding icon in your PC's system tray. In addition to the menu options you get out of the box, you can add in custom menu items. Menus are defined as nested arrays of structs, where each struct represents a single menu item. A menu item can be informational, have an action, or contain sub menus.

[
    {
        "label" : "My Custom Menu Item!",
        "disabled" : true
    }
]

You can customize the tray menus for a server via 3 different methods:

  • The trayOptions array in a specific server's server.json file. These menu additions will be specific to that server.

  • The server.defaults.trayOptions config setting. These menu additions will be added to every server you start

  • A custom CommandBox Module with an interceptor listening to the onServerStart interception point that modifies the serverInfo.trayOptions array.

Each menu item struct can have the following keys. Only label is required.

  • label - This text appears on the menu and is the unique name

  • action - This controls what the menu item does when clicked. Possible options are:

    • openfilesystem - Opens a folder on the file system. Requires path to be set as well.

    • openbrowser - Opens a URL in your default browser. Requires url to be set as well.

    • stopserver - Stops the current server

    • run - Runs an arbitrary native command synchronously. Requires command to be set as well.

    • runAsync - Runs an arbitrary native command asynchronously Requires command to be set as well.

    • runTerminal - Runs an arbitrary native command in a new Terminal window. Requires command to be set as well.

  • path - The file system path to use for the openfilesystem action.

  • url - The HTTP URL to use for the openbrowser action

  • image - A custom image file to use for the icon. Relative paths in the server.json will be relative to the JSON file Relative paths in the global config will be relative to the web root of the server.

    • command - The native command to run for the run, runAsync, or runTerminal actions.

  • workingDirectory - The working directory to use for the run, runAsync or runTerminal actions.

  • shell - Override the native shell to use on your OS. Defaults to your nativeShell config setting.

  • items - An array that contains a struct of sub menus.

  • disabled - Boolean that greys out menu item and disables any action. Use for informational items.

openfilesystem Example

[
    {
        "label" : "Open Downloads",
        "action" : "openfilesystem",
        "path" : "D:/downloads",
        "image" : "C:/pictures/folder.png"
    }
]

openbrowser Example

[
    {
        "label" : "Open Google",
        "action" : "openbrowser",
        "url" : "https://www.google.com",
        "image" : "C:/pictures/cat.png"
    }
]

stopserver Example

[
    {
        "label" : "Kill it!",
        "action" : "stopserver",
        "image" : "images/bomb.png"
    }
]

run Example

Commands executed by the run action will display their output in a popup window. The PID of the process is available if running on Java 9 or later. Also, there is a button to kill the process, but your mileage may vary. Only use this option to run command line apps that have console output you want to see.

[
    {
        "label" : "Does the Internet work?",
        "action" : "run",
        "command" : "ping google.com"
    }
]

runAsync Example

Commands executed by the runAsync action work like the run action except there is no windows to show you the output. This is what you want to use to fire off an app such as an IDE.

[
    {
        "label" : "Math is math!",
        "action" : "runAsync",
        "command" : "calc.exe"
    }
]

runTerminal Example

Commands executed by the runTerminal action work like the run action except a new terminal window is opened to run the command. The terminal windows stays open and you can continue to interact with it when the command finishes.

[
    {
        "label" : "Update dependencies",
        "action" : "runTerminal",
        "command" : "box update"
    }
]

You can customize how your command is run by setting the optional workingDirectory and shell properties. If not set, the working directory will be the web root of the server.

[
    {
        "label" : "Clear Temp Dir",
        "action" : "runAsync",
        "command" : "rm -rf",
        "workingDirectory" : "/var/tmp",
        "shell" : "/bin/zsh"
    }
]

Sub Menus

You can nest menus by supplying another array of structs in the items property of a menu. A menu cannot have an action and have sub menus.

[
    {
        "label" : "Top menu",
        "items" : [
            {
                "label" : "Sub 1"
            },
            {
                "label" : "Sub 2"
            },
            {
                "label" : "Sub 3"
            }
        ]
    }
]

Override Existing Menus

Menu items are layered "on top" of existing options whichs mean you can add new sub menu items to an existing top level menu. You can even override the action or image of a built-in menu. Menu items are registered in this order:

  • Built-in menus

  • Config setting server defaults

  • server.json trayOptions

  • onServerStart interceptor

This example server.json will add a new sub menu into the existing "Open..." top level menu.

{
    "trayOptions":[
        {
            "label":"Open...",
            "items":[
                {
                    "action":"runAsync",
                    "command":"calc.exe",
                    "label":"Calculator"
                }
            ]
        }
    ]
}

There is no way to remove existing menu items via your config settings or server.json. To do that, you'd need to directly manipulate the trayOptions array in an interceptor.

Undertow Predicate

Undertow Options

CommandBox uses JBoss Undertow to power it's lightweight servlet containers. Undertow also powers JBoss Wildfly and has a lot of configurable options, not all of which have first-class CommandBox settings. These low-level settings come in two different categories:

  • Undertow Options - Settings that apply to the servlet and web server aspects of Undertow

  • XNIO Options - Part of the underlying XNIO library which powers all low-level I/O in undertow

Undertow Options

Undertow has its own set of options which can be found here:

To set an XNIO option that CommandBox doesn't already expose with a first-class setting, you can set them into your server.json like so:

server set runwar.undertowOptions.ALLOW_UNESCAPED_CHARACTERS_IN_URL=true

You can also set global XNIO objects that will apply to all servers. Global options will be appended to server-level options.

config set server.defaults.runwar.undertowOptions.WORKER_NAME=myWorker

XNIO Options

XNIO (which is a refined version of NIO (Non-blocking I/O) has its own set of options that apply to the low level network transport functions it provides. You can find the full set of XNIO options here:

To set an XNIO option that CommandBox doesn't already expose with a first-class setting, you can set them into your server.json like so:

server set runwar.XNIOOptions.WORKER_NAME=myWorker

You can also set global XNIO objects that will apply to all servers. Global options will be appended to server-level options.

config set server.defaults.runwar.XNIOOptions.WORKER_NAME=myWorker

Starting as a Service

See screencast here:

Alternatively, you can manually do so following one of these community guides.

Windows

MacOS

Coming soon...

CentOS/RHEL/Ubuntu (system.d)

Create a .service file

nano /usr/lib/systemd/system/mySite.service

as follows:

[Unit]
Description=mySite Service

[Service]
ExecStart=/usr/bin/box server start /var/www/mySiteAPI/server.json
Type=forking

[Install]
WantedBy=multi-user.target

Start the service

systemctl start mySite.service

Give the service about a minute to load up, then check its status

systemctl status mySite.service

Once you've verified the service is running as expected, enable the service to load at boot

systemctl enable mySite.service

Installing Packages

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 Semantic Versioning Support

ForgeBox supports semantic version ranges for installing packages. Here are some examples:

Install Process

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.

  1. CommandBox inspects the ID passed to the install command to determine the endpoint to use.

  2. The matching endpoint is asked to fetch the package represented by the ID.

  3. For example, the ForgeBox endpoint checks the local artifact cache and possibly downloads the package.

  4. If ForgeBox is offline, the best match package will be looked for in your artifacts.

  5. The package is unzipped and its box.json is read

  6. Installation directory is finalized

  7. Contents of package are copied based on the ignoreList and --production flag

  8. The package is saved as a dependency in the root box.json

  9. The package's dependencies are installed

Packaging Your Server

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.

Storing server.json outside the web root

To 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:

Determining the web root

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.

Using Multiple server.json Files

Create 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

Interacting with non-standard JSON file names

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 and server clear commands for your convenience.

Use server JSON files to control servers

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

Use server names to control servers

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.

Package Management

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.

Working with server.json

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:

Server.json

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

When using CommandBox on a staging or production server, you may wish to start up servers as a service when the OS comes online. The recommended approach is to use the , which is a commercial module that handles all major operating systems (Linux, Mac, Windows) automatically.

CommandBox Service Manager

See screencast here:

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.

CommandBox Service Manager Module
https://www.ortussolutions.com/blog/screencast-starting-commandbox-servers-as-a-windows-service
install coldbox
# Latest stable version
CommandBox> install foo

# Same as above
CommandBox> install foo@stable

# latest version, even if pre release (bleeding edge)
CommandBox> install foo@be

# A specific version
CommandBox> install foo@1.2.3

# Any version with a major number of 4 (4.1, 4.2, 4.9, etc)
CommandBox> install foo@4.x

# Any version greater than 1.5.0
CommandBox> install foo@>1.5.0

# Any version greater than 5.2 but less than or equal to 6.3.4
CommandBox> install "foo@>5.2 <=6.3.4"

# Any version greater than or equal to 1.2 but less than or equal to 3.2
CommandBox> install "foo@1.2 - 3.2"

# Allows patch-level changes if a minor version is specified. Allows minor-level changes if not.  (2.1.2, 2.1.3, 2.1.4, etc)
CommandBox> install foo@~2.1

# Any greater version that does not modify the left-most non-zero digit.  4.2, 4.3, 4.9, etc
CommandBox> install foo@^4.1.4
server set web.webroot=www
start /path/to/server.json
start cfengine=lucee@4 name=lucee4
start cfengine=lucee@5 name=lucee5
start cfengine=adobe@2016 name=adobe2016
{
    "app":{
        "cfengine":"lucee@4"
    },
    "name":"lucee4"
}
{
    "app":{
        "cfengine":"lucee@5"
    },
    "name":"lucee5"
}
{
    "app":{
        "cfengine":"adobe@2016"
    },
    "name":"adobe2016"
}
# Show all properties
server show server-lucee5.json

# Show one property
server show server-lucee5.json name

# named args are required to set properties
server set serverConfigFile=server-lucee5.json jvm.heapSize=1024 

# Clear properties
server clear server-lucee5.json jvm
start serverConfigFile=server-lucee4.json
start server-lucee4.json
stop server-lucee4.json
start server-adobe2016.json
# Open your Lucee 5 site in the browser
server log server-lucee5.json

# cd into the web root for your Adobe 2016 web
server cd /path/to/server-adobe2016.json
start lucee4
start lucee5
start adobe2106

restart adobe2016
stop lucee4
install myPackage
server set web.http.port=8080
server show web.http.port
server clear web.http.port
{
    "name": "",
    "openBrowser": true,
    "openBrowserURL" : "http://localhost/admin/login",
    "startTimeout": 240,
    "stopsocket": 50123,
    "debug": false,
    "trace": false,
    "console": false,
    "profile": "prod",
    "dockEnable": true,
    "trayEnable": true,
    "trayicon": "/path/to/trayicon.png",
    "trayOptions": [
        {
            "label": "Foo",
            "action": "openbrowser",
            "url": "http://${runwar.host}:${runwar.port}/foobar.cfm",
            "disabled": false,
            "image": "/path/to/image.png"
        }
    ],
    "jvm": {
        "heapSize": 512,
        "minHeapSize": 256,
        "args": "",
        "javaHome" : "/path/to/java/home",
        "javaVersion" : "openjdk11"
    },
    "web": {
        "host": "127.0.0.1",
        "webroot": "src/cfml",
        "directoryBrowsing": true,
        "accessLogEnable": true,
        "maxRequests":30,
        "gzipEnable": true,
        "gzipPredicate": "regex( '(.*).css' ) and request-larger-than( 500 )",
        "aliases": {
            "/foo": "../bar",
            "/js": "C:/static/shared/javascript"
        },
        "errorPages": {
            "404": "/path/to/404.html",
            "500": "/path/to/500.html",
            "default": "/path/to/default.html"
        },
        "welcomeFiles": "index.cfm,main.cfm,go.cfm",
        "HTTP": {
            "enable": true,
            "port": 8080
        },
        "SSL": {
            "enable": false,
            "port": 443,
            "certFile": "",
            "keyFile": "",
            "keyPass": ""
        },
        "AJP": {
            "enable": false,
            "port": 8009
        },
        "rewrites": {
            "enable": true,
            "logEnable": true,
            "config": "/path/to/config.xml",
            "statusPath": "/rewriteStatus",
            "configReloadSeconds": 60
        },
        "basicAuth": {
            "enable": true,
            "users": {
                "userName1": "password1",
                "userName2": "password2"
            }
        },
        "rules": [
          "path-suffix(/box.json) -> set-error(404)",
          "path-prefix(.env) -> set-error(404)",
          "path-prefix(/admin/) -> ip-access-control(192.168.0.* allow)",
          "path(/sitemap.xml) -> rewrite(/sitemap.cfm)",
          "disallowed-methods(trace)"
        ],

    //3 ways to specify rulesFile
        "rulesFile": "../secure-rules.json",
        // Or... 
        "rulesFile": [
          "../security.json",
          "../rewrites.json",
          "../app-headers.json"
        ],
        // Or...
        "rulesFile":"../rules/*.json",

        "blockCFAdmin": false,
                "blockSensitivePaths":  true,
                "blockFlashRemoting":  true
    },
    "app": {
        "logDir": "",
        "libDirs": "",
        "webConfigDir": "",
        "serverConfigDir": "",
        "webXML": "",
        "WARPath": "",
        "cfengine": "lucee@5.x",
        "restMappings": "/rest/*,/api/*",
        "serverHomeDirectory": "",
        "sessionCookieSecure": true,
        "sessionCookieHTTPOnly": true
    },
    "runwar": {
        "jarPath": "/path/to/runwar.jar",
        "args": "",
        "XNIOOptions": {
            "WORKER_NAME": "MyWorker"
        },
        "UndertowOptions": {
            "ALLOW_UNESCAPED_CHARACTERS_IN_URL": true
        }
    }
}

Installation Path

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.

  1. The value of the directory parameter passed into the install command by the user.

  2. The value of the installPaths.packageName property set in the project's main box.json by the user. Where packageName is the name of the package you are installing like logbox.

  3. 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).

  4. Based on the package type convention if the package is a command, coldbox module, commandbox module, plugin, or interceptor.

  5. If the package being installed is of type lucee-extensions and if the current working directory is found to have a Lucee server in it, the lex file will instead be installed to the server context's deploy folder.

  6. 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.

System Modules

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.

install commandbox-fusionreactor

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.

package list --system
package update --system
package uninstall commandbox-fusionreactor --system

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

Installation Options

There are several options you can use to control how a package is installed.

Saving dependencies

By default, any package you install will be saved as a dependency. To save it as a development dependency instead, use the --saveDev flag.

install testbox --saveDev

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.

install cborm --!save

Production Installation

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.

install cbvalidation --production

Verbose Installation

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.

install cbi18n --verbose

Forced Installation

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.

install cbsoap --force

Advanced Installation

Advanced Installation

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.

Module Conventions

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:

<webroot>/modules/cbvalidation

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.

<webroot>/modules/cbvalidation/modules/cbi18n

You'll be able to see a nice representation of this when you use the list command.

CommandBox> list
Dependency Hierarchy myApp (1.0.0)
├── coldbox (4.2.0)
└─┬ cbvalidation (1.0.0)
  └── cbi18n (1.0.0)

Moduleplicity

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:

install cbi18n
install cbvalidation

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.

Smart Uninstall

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.

Multi-server functionality

Private Packages

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.

Publishing private packages to ForgeBox

To create a private package, set the private property to true in your box.json prior to publishing.

package init
package set private=true
package set slug=my-slug@forgeBoxUser
etc...
publish

Installing private packages from ForgeBox

Replace forgeBoxUser with your actual ForgeBox username. When you install the package, you'll need to use the full slug like so:

install my-slug@forgeBoxUser

You can install specific versions or version ranges as you would expect:

install my-slug@forgeBoxUser@1.0.0
install my-slug@forgeBoxUser@be

Private packages will be a paid feature for ForgeBox Pro subscribers, though the feature is currently available to all users for free.

docs on our Java endpoint
Java endpoint
LogoHomeAzul | Better Java Performance, Superior Java Support
LogoOracle Will Charge for Java Starting in 2019 | USU Software
LogoIntroducing Amazon Corretto, a No-Cost Distribution of OpenJDK with Long-Term Support | Amazon Web ServicesAmazon Web Services
LogoOpenJDK
LogoOptions (XNIO API 3.1.0.Beta1 API)
LogoFORGEBOX: CommandBox Bullet Train
CommandBox Bullet Train Module on ForgeBox.io
UndertowOptions (Undertow 2.0.30.Final API)
LogoCommandBox Service Manager
https://github.com/Ortus-Solutions/runwar/tree/develop/src/main/java/runwar/undertow/handler
https://github.com/Ortus-Solutions/runwar/tree/develop/src/main/java/runwar/undertow/predicate