Command reference
The complete built-in command set, plus the grammar the REPL understands.
borescope ships a deliberately small command set. Pebble's own vocabulary is
first-class, the familiar file commands are implemented over Pebble's files API,
and exec runs anything else that's already in the container. Run
help at the prompt for a live list.
Line grammar
The REPL parser is intentionally tiny: one command at a time, with at most a
single | pipe between two stages. Variables ($VAR, ${VAR}) expand from
the session's tracked environment.
These shell features are not supported, and borescope reports a clear error rather than doing something surprising:
- sequencing (
;) - background jobs (
&) &&and||- redirection (
>,>>,<) - subshells (
( … ))
That covers the overwhelming majority of debug-shell use; for anything that
needs a real shell, exec a binary in the container.
Shell built-ins
State and session commands.
| Command | Usage | Description |
|---|---|---|
cd |
cd [dir] |
Change the current directory (defaults to ~). |
pwd |
pwd |
Print the current directory. |
echo |
echo [args…] |
Write arguments to output. |
env |
env |
Show the shell's tracked environment. |
clear |
clear |
Clear the screen. |
help, ? |
help |
List available commands. |
exit, quit |
exit [code] |
Leave borescope (optionally with an exit code). Ctrl-D also exits. |
File commands
These are built in, rather than left to exec, because they need either
session state (paths relative to the current directory) or Pebble's files API,
so they work against a rock with no shell and no coreutils.
| Command | Usage | Description |
|---|---|---|
ls |
ls [-l] [-a] [path…] |
List directory contents. |
cat |
cat [file…] |
Concatenate and print files. |
head |
head [-n N] [file] |
Print the first lines of input. |
tail |
tail [-n N] [-f] [file] |
Print the last lines of input; -f follows. |
find |
find [path] [-name PATTERN] [-type f|d] |
Walk the tree, filtering by name/type. |
stat |
stat <path…> |
Show file metadata. |
grep |
grep [-i] [-v] [-n] [-c] PATTERN [file…] |
Search input for a pattern. |
cp |
cp <src> <dst> |
Copy a file within the container. |
mv |
mv <src> <dst> |
Move or rename a file. |
rm |
rm [-r] [-f] <path…> |
Remove files or directories. |
mkdir |
mkdir [-p] <path…> |
Create directories. |
touch |
touch <path…> |
Create an empty file if it doesn't exist. |
pull |
pull <remote> <local> |
Copy a file from the container to the local host. |
push |
push <local> <remote> |
Copy a local file into the container. |
pull and push cross the host/container boundary; the rest operate inside the
container. See Copy files in and out.
Process commands
A rock usually has no ps binary, so exec ps fails on exactly the images
borescope is for. Everything ps reports lives in /proc, though, and
Pebble's files API can read it — so ps is built in, like the file commands.
| Command | Usage | Description |
|---|---|---|
ps |
ps [-aAdefl] [-o format]… [-p pidlist] [-t termlist] [-u|-U userlist] [-g|-G grouplist] |
Report process status, read from /proc. |
The option surface follows
POSIX ps:
-e selects every process, -f and -l are the full and long listings, and
-o takes the POSIX field names (pid, ppid, pgid, user, ruser,
group, rgroup, pcpu, vsz, nice, etime, time, tty, comm,
args) with optional field=HEADER renaming. BSD-style ps aux is not
supported; use ps -ef.
pebble:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:14 ? 00:00:04 /usr/bin/pebble run --create-dirs
app 14 1 0 09:14 ? 00:12:02 myapp --config /etc/myapp/config.yaml
One deliberate divergence from POSIX: with no selection options, ps lists
every process, as if -e were given. POSIX's default selects processes
matching the invoker's effective user ID and controlling terminal, but
borescope is not a process inside the container, so there is nothing to match.
Pebble-native commands
Pebble's operational vocabulary, exposed directly, no pebble prefix.
| Command | Usage | Description |
|---|---|---|
services |
services [--format=json|yaml] [--no-headers] [name…] |
List services and their status. |
start |
start <service…> |
Start services. |
stop |
stop <service…> |
Stop services. |
restart |
restart <service…> |
Restart services. |
replan |
replan |
Apply the plan: stop/start services as the plan requires. |
plan |
plan |
Show the merged Pebble plan (YAML). |
logs |
logs [-f|--follow] [-n N] [service…] |
Show service logs; -f streams. |
checks |
checks [--format=json|yaml] [--no-headers] [name…] |
List health checks and their status. |
health |
health |
Report overall health (are all checks up?). |
notices |
notices [--format=json|yaml] [--no-headers] |
List recent notices. |
notice |
notice <id> |
Show a single notice by ID. |
notify |
notify <key> [data-key=value…] |
Record a custom notice. |
changes |
changes [--format=json|yaml] [--no-headers] |
List recent changes. |
version |
version |
Show the Pebble and borescope versions. |
tasks |
tasks [--format=json|yaml] [--no-headers] [change-id] |
Show tasks for a change (defaults to the most recent). |
start, stop, restart, and replan change the running container. logs --follow and tail -f stream until you press Ctrl-C and can't be
used inside a pipe.
version prints labelled rows — the Pebble daemon being inspected first, then
borescope itself:
pebble 1.32.0
borescope 0.1.0
Inside the shell, a bare version most often means "which Pebble am I talking
to?", so that row comes first; outside the shell, borescope --version (or
borescope version) still reports only borescope's version, without needing a
container to connect to.
Over the Juju relay, a third row appears: the
pebble binary the relay drives (/charm/bin/pebble, shipped by the charm
container) is a client of the workload's daemon, and can be older than it.
pebble 1.32.0
pebble client 1.31.0
borescope 0.1.0
That's the pair that matters when a command fails on an older Pebble — see
Pebble compatibility. --socket and --here speak
HTTP to the daemon directly, with no pebble binary in the picture, so there
is no client row to show.
Tabular output
The list commands above (services, checks, notices, changes, tasks)
follow the same convention:
- Headers are UPPER CASE and bold; columns are separated by two spaces. Pass
--no-headersto suppress the header line (handy for piping intoawk,cut, orsort). - When the listing is empty, a short note goes to stderr (
No services configured.,No checks configured., …) and the exit code stays0. Stdout is empty, soborescope myapp/0 --command services | wc -lreports0when there are no services. --format=jsonand--format=yamlemit a machine-readable form instead of the table. Empty lists render as[](JSON) oritems: [](YAML), again with exit code0and no stderr noise.
exec
exec <command> [args…]
The escape hatch. exec runs a program that is already present in the
container, in your current session directory, and reports its stdout, stderr,
and exit code:
pebble:/# exec id
pebble:/# exec myapp-ctl reload
pebble:/# exec /usr/bin/myapp --version
If the binary isn't in the rock, exec reports that it couldn't run it, which
is expected on a minimal image. borescope doesn't bundle tools into the
container; exec only reaches what's there. See
Scope and philosophy.
Getting help in-session
help (or ?) lists every built-in command with its one-line summary, and
reminds you that anything else can be run with exec:
pebble:/# help
Built-in commands (anything else: 'exec <cmd> ...' runs it in the container):
cat Concatenate and print files
cd Change the current directory
…