blob: 8296170d46db16b240c936e636b13f2ae40ecca8 [file] [view] [edit]
# Getting started with ffx
This doc will guide you through some of the features of `ffx`. For an overview
of the design and components of `ffx`, see [the ffx overview](/docs/development/tools/ffx/overview.md).
## Contacting the ffx team
If you discover possible bugs or have questions or suggestions,
[file a bug](https://issues.fuchsia.dev/issues/new?component=1378294&template=1838957).
## Prerequisites
To follow the examples in this doc, you'll need a Fuchsia device running. If you
don't have a physical device connected, you can use an emulator.
To start an emulator with networking enabled but without graphical user
interface support, run `ffx emu start --headless`.
For more information on configuring the emulator
see, [Start the Fuchsia emulator](/docs/get-started/set_up_femu.md).
Your device must be running a `core`
[product configuration](/docs/development/build/build_system/boards_and_products.md)
or a product configuration that extends `core` (such as `workstation_eng`).
Optionally, you can run `ffx log`, which will provide some additional information
about the interactions between `ffx` and your Fuchsia target device.
## Introduction
After following all the prerequisites, run the following in a terminal:
```posix-terminal
ffx help
```
This will list all of the available `ffx` subcommands. You'll see something
like:
```none
Usage: ffx [-c <config>] [-e <env>] [-t <target>] [-d] [<command>] [<args>]
Fuchsia's developer tool
Options:
-c, --config override default configuration
-d, --direct make a direct connection to the target
-e, --env override default environment settings
-t, --target apply operations across single or multiple targets
-o, --log-output specify destination of log output
--help display usage information
Commands:
component Discover and manage components
config View and switch default and user configurations
daemon Interact with/control the ffx daemon
diagnostic Run diagnostic tests on Fuchsia targets
docs View suite of docs for ffx and for Fuchsia
doctor Run common checks for the ffx tool and host environment
emulator Start and manage Fuchsia emulators
overnet Interact with the Overnet mesh
package Create and publish Fuchsia packages
sdk Modify or query the installed SDKs
target Interact with a target device or emulator
version Print out ffx tool and daemon versions
```
You can use `ffx help <subcommand>` or `ffx <subcommand> --help` to see
more about any subcommand.
## Interacting with target devices
In a terminal, run the following:
```posix-terminal
ffx target list
```
You'll see a list of devices that `ffx` has discovered. For example, with a
single emulator running, output looks like:
```none
NAME SERIAL TYPE STATE ADDRS/IP RCS
fuchsia-emulator <unknown> Unknown Product [fe80::5054:ff:fe63:5e7a%4] N
```
`RCS`: Indicates whether we have connected to the Remote Control Service on the
device. This connection is vital to all other `ffx` operations, but it is
established lazily, so it's not unusual to see an `N` here when we haven't
interacted with the device yet.
If multiple devices are connected, you must follow the steps in
[Interacting with multiple devices](#interacting-with-multiple-devices) to
specify which target to interact with.
In most cases, if you just interact with a target that should be
sufficient to start a connection. For example:
```posix-terminal
ffx target echo
```
Then the next time you list targets you should see that an `RCS` connection
is active.
```none
$ ffx target list
NAME SERIAL TYPE STATE ADDRS/IP RCS
fuchsia-emulator <unknown> Unknown Product [fe80::5054:ff:fe63:5e7a%4] Y
```
If you had `ffx log` running, you should also see something like the following in
the logs:
```none
[00009.776170][28540][28542][remote-control, remote_control_bin] INFO: published remote control service to overnet
```
## Interacting with multiple devices
When multiple targets are visible in `ffx target list`, you must specify which
target to use. Most `ffx` commands will fail if it is ambiguous which device
they should operate on.
The easiest way to specify the target is with a default target.
### Referring to a target
Whether setting a default target or explicitly specifying a target for a single
command, you will need some way to refer to targets on the command line.
Where `ffx` accepts a target on the command line it may be specified as:
- The target nodename.
- The target's IP address (any address mentioned in `ffx target list`).
- The target's serial number.
IPv6 and IPv4 addresses are both acceptable. If the address being
queried is ipv6 and includes a port number, the address (and
scope id if present) must be enclosed in square brackets. Scope and port
number are both optional, but may be present.
If a port number is specified, it will match only with targets with
that same port number (with no port set on the target being treated as
the default ssh port, 22).
Specifying 0 for the port will match specifically with hosts with
no port specified.
### Setting a default target
To set a default target, run:
```posix-terminal
fx set-device $NODENAME
```
You can run the following command to verify that the default target was set
correctly:
```posix-terminal
ffx target default get
```
The target list command shows an asterisk (`*`) next to the name of the
default target. To see the target list:
```posix-terminal
ffx target list
```
### Explicitly specifying a target
To specify which target to use in one-off cases (such as flashing), you can specify
the `-t` or `--target` flag to `ffx` and `fx` commands, for example:
```posix-terminal
# These commands will all use the same target.
fx -t $NODENAME serve
fx --target $NODENAME serve
ffx -t $NODENAME repository server start
ffx --target $NODENAME repository server start
```
### Making a direct connection
The normal behavior of `ffx` is to make an indirect connection to the target, mediated
by the `ffx daemon`. The daemon will eventually be deprecated and removed, however,
due to its complexity and statefulness. It is possible, meanwhile, to make a connection
without going through the daemon, by passing the `-d`/`--direct` flag, e.g.
```posix-terminal
ffx -d target echo
```
To change the default behavior for all `ffx` invocations, you can instead set
the `connectivity.direct` configuration option to `true`:
```posix-terminal
ffx config set connectivity.direct true
```
#### Mitigating connection delays
Direct connections provide improved predictability and reliability over
daemon-based connections, but they also introduce some delays. The next two
sections describe how to remove both delays. With both of these mitigations
enabled, target connections are as fast as when running with the daemon.
##### Caching the discovered targets
When using a direct connection, the `ffx` invocation must first determine
how to connect to the desired target, by finding its address (or if no target
is specified, by discovering all accessible targets). When using the daemon,
discovery results are stored by the daemon. But when making the connection
directly, every command may need to perform a (relatively) slow discovery
process, which can take a second or more.
To eliminate this delay, you can run `ffx target discover`, which will start
a background process to discover the available targets and make them available
when connecting to the target. This discovery cache is refreshed by default
every 6o seconds, but if you want to refresh it more quickly (e.g. because you
have just disconnected a target), you can simply run `ffx target discover` again
to update the cache immediately.
See `ffx target discover help` for more information.
##### Speeding up `ssh` connections
Direct connections can introduce another delay when connecting to targets over
the network (i.e. via `ssh`). This connection can add a noticeable delay on every
`ffx` invocation. To mitigate this delay, you can use `ssh`'s `ControlMaster`
functionality, by setting the following configuration option:
```posix-terminal
ffx config set ssh.controlmaster.mode managed
```
This will cause `ffx` to use a shared `ssh` connection when establishing
communication with the target. After this, the initial `ffx` invocation to the
target will set up the `ssh` channel, and future `ffx` connections will reuse
the same channel. For more information see the `ControlMaster` documentation in
`man 5 ssh_config`.
### Controlling the state of target devices
You can use the `target off` and `target reboot` subcommands to power-off or
reboot a device, respectively.
## `ffx` logs
### Destination
Logs normally go to a cache directory (on Linux, usually
`$HOME/.local/share/Fuchsia/ffx/cache/logs`).
The location can be found by running
```posix-terminal
ffx config get log.dir
```
However, the location can be overridden with `-o/--log-output <destination>`,
where `<destination>` can be a filename, or stdout (by specifying `stdout`
or `-`), or stderr (by specifying `stderr`).
### Log Level
The debugging level can be specified with `-l/--log-level <level>`,
where `<level>` is one of `off`, `error`, `warn`, `info`, `debug`, or `trace`.
The default is `info`.
It can also be permanently set by configuring `log.level`, e.g.:
```posix-terminal
ffx config set log.level debug
```
### Interactive Use
A common use of the above options is to see debugging for a specific command:
```posix-terminal
ffx -l debug -o - target echo
```
The above command will produce debugging logs on the command line as part
of the invocation.
#### Target Levels
Specific log "targets" can have a different level, by specifying
configuration entries under `log.target_levels`. For instance, to
see debug logs only for `analytics`:
```posix-terminal
ffx config set log.target_levels.analytics debug
```
Log "targets" are simply prefixes to a log line.
## Configuration
See documentation for the [config command](/docs/development/tools/ffx/commands/config.md).
## Interacting with Components
### Monikers
Many `ffx` commands that use components take monikers as a parameter. You can read more about
monikers and their syntax in [component moniker documentation](/docs/reference/components/moniker.md).
### Finding components
The `component list` command will output monikers of all components that currently exist
in the component topology.
```none
$ ffx component list
/
/bootstrap
/bootstrap/archivist
/bootstrap/base_resolver
/bootstrap/console
/bootstrap/console-launcher
/bootstrap/cr50_agent
/bootstrap/device_name_provider
/bootstrap/driver_index
/bootstrap/driver_manager
/bootstrap/flashmap
/bootstrap/fshost
/bootstrap/fshost/blobfs
/bootstrap/fshost/blobfs/decompressor
...
```
You can use the `component capability` command to search for components that use/expose
a capability with a given name.
The following command will display all components that use/expose the `diagnostics` capability:
```none
$ ffx component capability diagnostics
Exposed:
/bootstrap/archivist
/bootstrap/base_resolver
/bootstrap/driver_manager
/bootstrap/fshost
/bootstrap/fshost/blobfs
/bootstrap/fshost/blobfs/decompressor
/bootstrap/fshost/minfs
/bootstrap/pkg-cache
/bootstrap/power_manager
...
```
### Inspecting a component
You can use the `component show` command to get detailed information about a specific
component.
`component show` allows partial matching on URL, moniker and component instance ID.
The following command will display information about the `/core/network/dhcpd` component:
```none
$ ffx component show dhcpd
Moniker: /core/network/dhcpd
URL: #meta/dhcpv4_server.cm
Instance ID: 20b2c7aba6793929c252d4e933b8a1537f7bfe8e208ad228c50a896a18b2c4b5
Type: CML Component
Component State: Resolved
Incoming Capabilities: /svc/fuchsia.net.name.Lookup
/svc/fuchsia.posix.socket.packet.Provider
/svc/fuchsia.posix.socket.Provider
/svc/fuchsia.stash.SecureStore
/svc/fuchsia.logger.LogSink
Exposed Capabilities: fuchsia.net.dhcp.Server
Merkle root: 521109a2059e15acc93bf77cd20546d106dfb625f2d1a1105bb71a5e5ea6b3ca
Execution State: Running
Start reason: '/core/network/netcfg' requested capability 'fuchsia.net.dhcp.Server'
Running since: 2022-09-15 16:07:48.469094140 UTC
Job ID: 28641
Process ID: 28690
Outgoing Capabilities: fuchsia.net.dhcp.Server
### Exploring a component
You can use the `component explore` command to interactively explore the namespace of a component.
This allows you to see exactly what capabilities are available to the component at runtime.
```posix-terminal
ffx component explore /core/network/dhcpd
```
Inside the shell, you can use `ls` to browse the `/svc` directory (and other
namespace entries) to verify that expected capabilities are available.
### Verifying capability routes
You can use the `component doctor` command to verify that all capabilities
exposed and used by a component are successfully routed.
For example:
```none
$ ffx component doctor /bootstrap/archivist
Querying component manager for /bootstrap/archivist
URL: fuchsia-boot:///#meta/archivist.cm
Instance ID: None
Used Capability Error
[✓] fuchsia.boot.ReadOnlyLog N/A
[✓] fuchsia.boot.WriteOnlyLog N/A
[✓] fuchsia.component.DetectBinder N/A
[✓] fuchsia.component.KcounterBinder N/A
[✓] fuchsia.component.PersistenceBinder N/A
[✓] fuchsia.component.SamplerBinder N/A
[✓] fuchsia.sys.internal.ComponentEvent N/A
Provider
[✓] fuchsia.sys.internal.LogConnector N/A
[✓] config-data N/A
Exposed Capability Error
[✓] fuchsia.diagnostics.ArchiveAccessor N/A
feedback
[✓] fuchsia.diagnostics.ArchiveAccessor N/A
.legacy_metrics
[✓] fuchsia.diagnostics.ArchiveAccessor N/A
.lowpan
[✓] diagnostics N/A
[✓] fuchsia.diagnostics.ArchiveAccessor N/A
[✓] fuchsia.diagnostics.LogSettings N/A
[✓] fuchsia.logger.Log N/A
[✓] fuchsia.logger.LogSink N/A
```
```none
$ ffx component doctor /core/feedback
Querying component manager for /core/feedback
URL: fuchsia-pkg://fuchsia.com/forensics#meta/feedback.cm
Instance ID: eb345fb7dcaa4260ee0c65bb73ef0ec5341b15a4f603f358d6631c4be6bf7080
Used Capability Error
[✓] fuchsia.boot.ReadOnlyLog N/A
[✓] fuchsia.boot.WriteOnlyLog N/A
[✓] fuchsia.diagnostics.FeedbackArchive N/A
Accessor
[✓] fuchsia.hardware.power.statecontrol N/A
.RebootMethodsWatcherRegister
[✓] fuchsia.hwinfo.Board N/A
[✓] fuchsia.hwinfo.Product N/A
[✓] fuchsia.metrics.MetricEventLoggerFa N/A
ctory
[✓] fuchsia.net.http.Loader N/A
[✓] fuchsia.process.Launcher N/A
[✓] fuchsia.sysinfo.SysInfo N/A
[✓] fuchsia.ui.activity.Provider N/A
[✗] fuchsia.feedback.DeviceIdProvider `/core/feedback` tried to use `fuchsia.feedback.DeviceIdProvider` from its parent,
but the parent does not offer that capability. Note, use clauses in CML default to
using from parent.
...
```
### Running a component
The `component run` command can create and launch components in a given isolated collection.
Note: `fx serve` must be running in order to run a package that is not
[in base or cached](/docs/development/build/build_system/boards_and_products.md#dependency_sets).
Here's an example of running the Rust `hello-world` component in the `/core/ffx-laboratory`
collection. First, you'll need the hello-world package in your universe:
```none
$ fx set <product>.<board> --with //examples/hello_world/rust:hello-world-rust && fx build
...
```
Then use the `component run` command to create and launch a component instance from the URL
`fuchsia-pkg://fuchsia.com/hello-world-rust#meta/hello-world-rust.cm` with the moniker
`/core/ffx-laboratory:hello-world-rust`:
```none
$ ffx component run /core/ffx-laboratory:hello-world-rust fuchsia-pkg://fuchsia.com/hello-world-rust#meta/hello-world-rust.cm
URL: fuchsia-pkg://fuchsia.com/hello-world-rust#meta/hello-world-rust.cm
Moniker: /core/ffx-laboratory:hello-world-rust
Creating component instance...
...
$ ffx component show hello-world-rust
Moniker: /core/ffx-laboratory:hello-world-rust
URL: fuchsia-pkg://fuchsia.com/hello-world-rust#meta/hello-world-rust.cm
Type: v2 dynamic component
Execution State: Running
Job ID: 50775
Process ID: 50819
...
```
## Resolving connectivity issues
If you're experiencing problems communicating with a target device using `ffx`,
run the `ffx doctor` command to diagnose and attempt to resolve them:
```posix-terminal
ffx doctor
```
If you file a bug that involves a target device, we'll typically ask for the
output from `ffx doctor` to provide information about where the problem is.
The `ffx doctor` command attempts to communicate with the ffx daemon, killing
and restarting it if needed. If this is successful, it attempts to SSH into
a target device and start the Remote Control Service.
If you run `ffx doctor` under normal circumstances, you should see output
similar to the following:
```none
$ ffx doctor
Doctor summary (to see all details, run ffx doctor -v):
[✓] FFX Environment Context
[✓] Kind of Environment: Fuchsia.git In-Tree Rooted at /usr/local/google/home/username/fuchsia, with default build directory of /usr/local/google/home/username/fuchsia/out/default
[✓] Environment-default build directory: /usr/local/google/home/username/fuchsia/out/default
[✓] Config Lock Files
[✓] /usr/local/google/home/username/global_ffx_config.json locked by /usr/local/google/home/username/global_ffx_config.json.lock
[✓] SSH Public/Private keys match
[✓] Checking daemon
[✓] Daemon found: [3338687]
[✓] Connecting to daemon
[✓] Searching for targets
[✓] 1 targets found
[✓] Verifying Targets
[✓] Target: fuchsia-emulator
[i] Running `ffx target show` against device
[✓] No issues found
```
If `ffx doctor` fails, it will try to suggest a resolution to the problem. You
can [file a bug](https://issues.fuchsia.dev/issues/new?component=1378294&template=1838957)
for the ffx team if you persistently have problems. For example, if `ffx doctor`
is unable to start the RCS, you would see the following:
```none
$ ffx doctor -v
Doctor summary:
[✓] FFX doctor
[✓] Frontend version: 2025-03-25T18:48:31+00:00
[✓] abi-revision: 0xB5D2EBDA9DA50585
[✓] api-level: 26
[i] Path to ffx: /usr/local/google/home/username/fuchsia/out/default/host_x64/ffx
[✓] FFX Environment Context
[✓] Kind of Environment: Fuchsia.git In-Tree Rooted at /usr/local/google/home/username/fuchsia, with default build directory of /usr/local/google/home/username/fuchsia/out/default
[✓] Environment File Location: /usr/local/google/home/username/.local/share/Fuchsia/ffx/config/.ffx_env
[✓] Environment-default build directory: /usr/local/google/home/username/fuchsia/out/default
[✓] Config Lock Files
[✓] /usr/local/google/home/username/global_ffx_config.json locked by /usr/local/google/home/username/global_ffx_config.json.lock
[✓] SSH Public/Private keys match
[✓] Checking daemon
[✓] Daemon found: [3338687]
[✓] Connecting to daemon
[✓] Daemon version: 2025-03-25T18:48:31+00:00
[✓] path: /usr/local/google/home/username/fuchsia/out/default/host_x64/ffx
[✓] abi-revision: 0xB5D2EBDA9DA50585
[✓] api-level: 26
[✓] Default target: (none)
[✓] Searching for targets
[✓] 1 targets found
[✗] Verifying Targets
[✗] Target: fuchsia-emulator
[✓] Compatibility state: supported
[✓] Host overnet is running supported revision
[✓] Opened target handle
[✗] Timeout while connecting to RCS
[✗] Doctor found issues in one or more categories.
```
## Testing with ffx
The `ffx` command is useful when writing integration tests which need to interact
with the Fuchsia environment. However, since `ffx` is primarily designed for
developers, it inspects the current environment for configuration and also starts
a daemon in the background to coordinate communication with Fuchsia devices. This
makes it more complex to write automated tests that use `ffx` since the configuration
and daemon should be isolated in order to avoid side effects, or interference from
the global environment.
To achieve this isolation, test authors need to use [isolate directories][isolate-dir]
when running tests which use `ffx`.
## Next steps
- Please provide feedback on this doc by [reaching out to the ffx team](#contacting_the_ffx_team)!
- Learn how to [extend `ffx`](/docs/development/tools/ffx/development/README.md).
<!-- Reference links -->
[isolate-dir]: development/integration_testing/README.md