Ruby, PHP, JVM and others

The three levels work the same everywhere. What changes per ecosystem is which provider builds the environment and what the runtime is allowed to do by default.

Read the three levels first if you haven't.

Providers

-e @<provider>:<file> builds a layered environment image from a dependency file. Most providers answer to two names — the package manager's, and the runtime's — so -e @gem:Gemfile and -e @ruby:Gemfile are the same thing.

ProviderAlso answers toTypical file
piprequirements.txt
uvrequirements.txt
poetrypyproject.toml
npmpackage.json
yarnpackage.json
gemrubyGemfile
composerphpcomposer.json
mavenjava, javac, mvnpom.xml
cargorustcCargo.toml
go-installgo— (installs named packages)
cabalghc.cabal
cpanmperlcpanfile
hexelixirmix.exs
renvrrenv.lock
luarockslua.rockspec
galaxyansiblerequirements.yml
aptubuntu— (installs named packages)

The environment image is cached by the content hash of the file, so an unchanged dependency file means no rebuild.

Runtime capabilities

Verified with boks --info <tool>. "None" means the strongest default boks has: working directory mounted read-only, no network.

ToolDefault capabilities
ruby, php, java, R, Rscript, lua, perlnone
python, node, go, javac, mvn, gradle, elixir, mixrw
composer, uvnet, rw
cargo, rustcnone

Two patterns are worth noticing:

  • Runtimes that only interpret are locked down hardest. ruby, php, perl, lua and R cannot even write the working directory. If your script writes a file, that is a --cap rw or a capabilities: [rw] line in .boksrc — and the fact that you had to say so is the feature.
  • Build tools mostly grant rw, and Rust's doesn't. javac, mvn, gradle, go and mix all write their own output directories by default. cargo/rustc are the exception — see Go, Rust and C/C++.

Known wart: boks --info npm and boks --info pip display CAPS rw and omit the net they really run with. Those two get their network from a per-tool-name entry in the index policy rather than from the shared image label the view reads. The grant is real; the display under-reports it.

Ruby

# level 1
boks -e @gem:Gemfile ruby app.rb

# level 2 — .boksrc
tools:
  ruby:
    env_file: Gemfile

boks ruby app.rb

# level 3
boks -i ruby
ruby app.rb

bundle install has no working-tree equivalent under boks the way npm install does — the environment image is the bundle. -e @gem:Gemfile runs bundle install into a layered boks-env-ruby-* image, including gems with native extensions, which build against a compiler-having variant.

Remember that ruby itself has no capabilities: a script that writes a file needs rw granted explicitly.

See ruby-gemfile and ruby-simple.

PHP

boks -e @composer:composer.json php app.php

composer is one of the few tools shipping net+rw on its own image label, so boks composer require … works with no flags — and php itself still has none, so a request your app makes is a capability you granted on purpose.

See php-composer.

JVM

boks -e @maven:pom.xml java -jar target/app.jar
boks --cap net mvn package
boks --cap net gradle build

mvn and gradle have rw (they write target/, build/) but not net — the first dependency resolution needs --cap net, or a capabilities: [net] line in .boksrc. java itself has neither, which is the right default for running a jar.

Gradle writes a per-directory cache wherever it is invoked, so a project .gitignore wants .gradle/.

See java-maven-simple, kotlin-gradle-simple, scala-sbt-simple, clojure-lein-simple.

Elixir

boks -e @hex:mix.exs elixir app.exs
boks --cap net mix deps.get

elixir and mix both have rw. See elixir-hex.

R

boks -e @renv:renv.lock Rscript analysis.R

R/Rscript have no capabilities, so writing a plot or a CSV needs rw granted. See r-renv and the R environments reference.

Perl, Lua, Ansible

boks -e @cpanm:cpanfile perl script.pl
boks -e @luarocks:app.rockspec lua app.lua
boks -e @galaxy:requirements.yml ansible-playbook site.yml

See perl-simple, lua-luarocks, ansible-galaxy.

A note on tool names

Not every package-manager name is a runnable tool. gem and bundle are provider names — -e @gem:Gemfile works — but there is no boks gem in the index; boks gem install colorize answers Unknown tool 'gem'. When in doubt, boks --search <name> is the reliable check.

(boks --info <name> is not, currently: for a name that is in neither the index nor your own config it invents a boks.sh/<name>:latest entry and reports it as "not pulled yet" rather than saying the tool is unknown.)