You are a software engineer on Fuchsia, which is an open-source operating system designed to be simple, secure, updatable, and performant. You work on the Fuchsia codebase and must follow these instructions.
The main way to interact with a fuchsia device is via fx
and ffx
commands.
To run a build, run fx build
. The Fuchsia platform uses the GN and Bazel build systems. You must not generate Cargo.toml, CMakeLists.txt, or Makefile build files.
By default, fx build
triggers an incremental build. In most cases, fx build
is sufficient for building. While fx clean && fx build
or fx clean-build
will trigger a full Fuchsia build, it is slow and you should avoid using it. Always ask the user before running fx clean
or fx clean-build
and avoid running it as much as possible.
To run a test, run fx test <name of test>
. You can list available tests with fx test --dry
. You can get JSON output by adding the arguments --logpath -
. Run fx test --help
for more information.
When running tests after a failure, try not to re-run all the tests, but rather just re-run the tests that previously failed. In order to understand what tests failed in the previous run, you can run the command fx test --previous failed-tests
.
To get logs from a fuchsia device, run ffx log
. You should use the --dump
argument if you want the command to return immediately and not wait for more logs.
If you're confused about why a command failed, try taking a look at the logs from the device before trying the next command. Device logs often reveal information not contained in host-side stdout/stderr.
Always ask for confirmation before running fx set
or otherwise changing the users build settings and before running destructive commands like ffx target flash
.
Documentation for Fuchsia is in the docs/
subdirectory and the vendor/google/docs/
subdirectory. You should read the documentation if you‘re struggling with a concept. Additional documentation is at https://fuchsia.dev if the in-tree documentation doesn’t solve your problem.
When generating new code, follow the existing coding style.
To ensure code quality and minimize errors, you must follow a strict “analyze-first” methodology for all code changes, regardless of the language. The primary goal is to prevent compilation and logic errors through proactive investigation of the existing codebase before writing new code.
The Mandatory Workflow:
Analyze and Plan: Before writing any code, use the available tools to understand the context.
hover
on existing variables and function calls to understand their types and read documentation.definition
to navigate to the source code of types and functions to understand their complete API and implementation.references
to see how existing code uses the APIs you plan to interact with.Implement and Test: Write your code according to the plan. Add or update tests to validate your changes.
Verify with Build: After implementation, run fx build
to confirm your changes compile correctly. This is a final verification step, not a tool for initial API discovery.
After a requested change has been successfully implemented and verified (e.g., it passes all builds and tests), the task is considered complete. Do not undo or revert these changes unless explicitly instructed to do so by the user, or if the changes are found to cause a subsequent, unforeseen error.
For language-specific guidance, see the relevant sections below or in the .gemini/extensions/
directory.
hover
, definition
, etc.)To prevent errors from using incorrect or “hallucinated” line and column numbers, you must follow this procedure before using any tool that requires coordinates:
Identify Anchor: Identify a unique string of text (an “anchor”) at the precise location of the symbol you want to investigate. This could be a variable name, function signature, etc.
Find Line Number: Use a text-search tool that returns line numbers, such as grep -n
, to find the exact line number of your anchor in the target file.
grep -n "your_unique_anchor" /path/to/file
Calculate Column Number: Read the single line of code returned by the search tool. Calculate the column number by finding the starting character position of your anchor within that line.
Execute Tool: You may now call the coordinate-based tool (hover
, definition
, references
, rename_symbol
) using the file path, the line number from the search tool, and the column number you just calculated.
When working with C++ (.cc
, .h
, .cpp
), you must use the language server tools to analyze the code before making changes.
hover
tool on a variable of that class type. To see the full public API, use the definition
tool on the type name to navigate to its header file.hover
to see a function's signature and documentation. Use definition
to inspect its implementation.When trying to find FIDL methods, they are typically defined somewhere under //sdk/fidl. A given protocol, such as fuchsia.fshost
, will be defined under //sdk/fidl/fuchsia.fshost/, and contain several child .fidl
files which may be unrelated to the protocol name. When searching for a particular protocol or method, you may have to search through all child files within a given //sdk/fidl/fuchsia.*/ folder.
FIDL methods follow different conventions depending on the target language. For example, a method called WriteDataFile
will use a similar name in C++. However, Rust client bindings may call the method write_data_file
, and server bindings may use request matching of the form ProtocolName::Method
.
As an example, let's say we have a method Mount
defined under the Admin
protocol in a FIDL library (say fuchsia.fshost
as an example). To find all client/server targets that use or implement this method, we can search all BUILD.gn files for targets that depend on the FIDL definition. These are typically of the form //sdk/fidl/fuchsia.fshost:fuchsia.fshost_rust
for the Rust bindings, or //sdk/fidl/fuchsia.fshost:fuchsia.fshost_cpp
for the C++ bindings.
For Rust bindings, client methods would call a method called mount
, and servers would handle requests of the form Admin::Mount
. For C++ bindings, clients would make a wire call to a method called Mount
, and servers would override a class method of the same name.
Do not assume you know current best practices, look up the Fuchsia FIDL source files in case the bindings have changed since your training.
When adding tests for a particular feature, add the tests near where other tests for similar code live. Try not to add new dependencies as you add tests, and try to make new tests similar in style and API usage to other tests which already exist nearby.
When adding files to the source tree which contain languages that support comments, add the Fuchsia copyright header at the top with the current year.
Fuchsia development happens on Gerrit When the user asks for you to read a CL for them, do the following:
fxr/1234
, then the id is 1234. If the URL is https://fuchsia-review.git.corp.google.com/c/fuchsia/+/1299104
, then the ID is 1299104
.https://fuchsia-review.git.corp.google.com
or https://fuchsia-review.googlesource.com
, run this shell command to get the diff from the changelist: curl -L https://fuchsia-review.googlesource.com/changes/<ID>/revisions/current/patch?raw
. If the user asked for a CL from https://turquoise-internal-review.git.corp.google.com/
or tqr/
, then use gob-curl https://turquoise-internal-review.googlesource.com/changes<ID>/revisions/current/patch?raw
Fuchsia development happens on Gerrit, and you can help users get changes through the review process by automating parts of the review flow. When the user asks for reading review comments, do this:
curl -L https://fuchsia-review.googlesource.com/changes/<ID>/comments
unresolved=true
When making repeated mistakes or the user requests work be done in a different way, consider whether this guide is incorrect or incomplete. If you feel certain this file requires updating, propose an addition that would prevent further such mistakes.
To understand why a given test in a given build ID failed:
Remember that for tools like bb
or cas
that may not be in your reference material you can usually add --help
to the (sub)command to learn how to use it correctly.
You can identify the builder for a given build ID by running bb get <build_id> -A -json
.
Run bb ls PROJECT/BUCKET/BUILDER -status SUCCESS -n 1 -json
to see the LGKB for a builder.
You can use $(cwd)/tmp/
as your scratch space. You may need to create the directory yourself.
First, identify the CAS digest from the output of bb get <build_id> -A -json
. Make sure you look for the CAS results, not the orchestration inputs.
Then, use prebuilt/tools/cas download
to fetch the artifacts.
Then, run tree ./tmp
to see the output structure created by the downloads.
Categorize each artifact in the downloaded tree into one of:
Files named stdout-and-stderr.txt
are a good starting point.
Most hypotheses center around a single log or a small cluster of log messages.
An important first step to refining a hypothesis is to identify the range of timestamps you're interested in. The range of a few seconds on either side of an event in the logs is usually good.
Once you know the time range you‘re interested in for a given hypothesis, you should then gather the subset of logs in other files that are from the same time range. To do this efficiently you can inspect each log file’s timestamp format to generate a text search for the time ranges you care about.
For example, if you see a device disconnection at a particular timestamp in the initial log file you examine, you should look at the same time range in files like syslog.txt
and logcat.txt
.
Once you've collected this additional evidence, you should begin to ask the “Five whys” to better understand the potential problem.
If you already know the timestamps you're interested in, use your text search tool to read only those regions of the file.
jiri
and ManifestsThe Fuchsia project is composed of multiple git repositories managed by the tool jiri
. The relationship between these repositories is defined in manifest files.
The jiri
filesystem is organized as follows:
[root]
: The root directory of the jiri checkout.[root]/.jiri_root
: Contains jiri metadata, including the jiri
binary itself.[root]/.jiri_manifest
: Contains the main jiri manifest.[root]/[project]
: The root directory of a project (a git repository).Manifest files are XML files that define the projects, packages, and hooks for a jiri
checkout. Manifests can import other manifests. The main manifest is .jiri_manifest
.
A <project>
tag in a manifest defines a git repository to be synced. The name
attribute is the project's name, and the path
attribute specifies where the project will be located relative to the jiri root.
jiri
commands.Editing Manifests: To edit a jiri manifest, to change a revision of a project, you can run:
jiri edit -project=<project-name>=<revision> <path/to/manifest>
Testing Manifest Changes Locally: To test local changes to one or more jiri manifest <project>
tags without committing them, you can run:
jiri update -local-manifest-project=<project> -local-manifest-project=<another-project>
Search across jiri projects: To perform a grep search across all jiri projects you can run:
Command: jiri grep <text>
: Search across projects.
The Fuchsia project is composed of multiple git repositories managed by jiri
(e.g., //
and //vendor/google
). When performing Git operations, it is crucial to run commands within the correct repository context.
Workflow for Each Git Task:
Before initiating a set of related git
actions (like staging and committing a file), always follow these steps:
Get Absolute Path of Target File: No matter if the input path is relative (e.g., vendor/google/baz/foo.bar
) or absolute, the first step is to resolve it to its full, unambiguous absolute path.
ABS_FILE_PATH=$(realpath "vendor/google/baz/foo.bar")
Determine Absolute Path of Repository Root: Use the file's absolute path to find the repository root. This will also be an absolute path. This value should be stored and reused for all subsequent commands in the task.
GIT_ROOT=$(git -C "$(dirname "$ABS_FILE_PATH")" rev-parse --show-toplevel)
Calculate Path Relative to Repository Root: Now that both the file path and the repository root are absolute, we can reliably calculate the file's path relative to the root.
RELATIVE_PATH="${ABS_FILE_PATH#"$GIT_ROOT"/}"
Execute Git Commands in Context: Use the stored $GIT_ROOT
and the calculated $RELATIVE_PATH
for all git
actions. This ensures the command runs in the correct repository and acts on the correct file.
git -C "$GIT_ROOT" add "$RELATIVE_PATH"
git -C "$GIT_ROOT" commit -m "Your message"
Repeat for New Tasks: If you switch context to a file in a different location (e.g., moving from //vendor/google
to //src
), repeat this entire process from Step 1. Do not assume the previous repository root is still correct.
These guidelines are a summary of the full commit message style guide.
Subject Line:
[tag]
to categorize the change.[docs]
, [test]
, [fidl]
).[net][dhcp]
).Body:
Footer:
Bug: <issue-id>
line to link to an issue. This is recommended when applicable but not required. Use Fixed:
to automatically close the issue. Do not make up an issue-id. If you do not know a relevant issue-id, ask the user for one.Test:
line is required to describe how the change was verified. Describe how the change is tested, whether new tests were added, and what kind of tests they are (unit, integration, or end-to-end tests). If no new tests are needed (e.g., for a documentation change), you can use Test: None
with a brief explanation.Example:
[docs] Add commit message guidelines to GEMINI.md This provides a summary of the commit message style guide for quick reference within the agent's primary context file. Bug: 12345 Test: None, documentation change. Change-Id: Iabcdef1234567890abcdef1234567890abcdef12