Note on Document Formatting: This document (AGENTS.md) should be
maintained with lines word-wrapped to a maximum of 80 characters to ensure
readability across various editors and terminals.
This document provides context and guidance for AI agents (like Jules) when
making changes to the Firebase C++ SDK repository. It covers essential
information about the repository's structure, setup, testing procedures, API
surface, best practices, and common coding patterns.
For a detailed view of which Firebase products are supported on each C++
platform (Android, iOS, tvOS, macOS, Windows, Linux), refer to the official
Firebase library support by platform table.
The Firebase C++ SDKs for desktop platforms (Windows, Linux, macOS) are
entirely open source and hosted in the main firebase/firebase-cpp-sdk GitHub
repository. The C++ SDKs for mobile platforms (iOS, tvOS, Android) are built
on top of the respective native open-source Firebase SDKs (Firebase iOS SDK and
Firebase Android SDK).
The goal is to enable agents to understand the existing conventions and
contribute effectively to the codebase.
Before building the Firebase C++ SDK, ensure the following prerequisites are
installed. Refer to the main README.md for detailed installation
instructions for your specific platform.
- CMake: Version 3.7 or newer.
- Python: Version 3.7 or newer.
- Abseil-py: Python package.
- OpenSSL: Required for desktop builds, unless you build with the
-DFIREBASE_USE_BORINGSSL=YES cmake flag.
- libsecret-1-dev: (Linux Desktop) Required for secure credential storage.
Install using sudo apt-get install libsecret-1-dev.
- Android SDK & NDK: Required for building Android libraries. sdkmanager
can be used for installation. CMake for Android (version 3.10.2
recommended) is also needed.
- (Windows Only) Strings: From Microsoft Sysinternals, required for
Android builds on Windows.
- Cocoapods: Required for building iOS or tvOS libraries.
To build for Desktop, you can install prerequisites by running the following
script in the root of the repository: scripts/gha/install_prereqs_desktop.py
To build for Android, you can install prerequisites by running the following
script in the root of the repository: build_scripts/android/install_prereqs.sh
The SDK uses CMake for C++ compilation and Gradle for Android-specific parts.
CMake (Desktop, iOS, tvOS)
-
Create a build directory (e.g., mkdir desktop_build && cd desktop_build).
-
Run CMake to configure: cmake ..
- For Desktop: Run as is. You can use BORINGSSL instead of OpenSSL (for fewer
system dependencies with the -DFIREBASE_USE_BORINGSSL=YES parameter.
- For iOS, include the -DCMAKE_SYSTEM_NAME=iOS
parameter. This requires running on a Mac build machine.
-
Build specific targets: cmake --build . --target firebase_analytics
(replace firebase_analytics with the desired library).
Or omit the entire --target parameter to build all targets.
For development, building specific targets
(e.g., cmake --build . --target firebase_app) is generally faster and
recommended once CMake configuration is complete. The full build
(cmake --build .) can be very time-consuming (but can be sped up by adding
-j4 to the command-line).
You can also use the scripts/gha/build_desktop.py script to build the full
desktop SDK.
Refer to README.md for details on CMake generators and providing custom
third-party dependency locations.
Each Firebase C++ library is a Gradle subproject. To build a specific library
(e.g., Analytics):
./gradlew :analytics:assembleRelease
This command should be run from the root of the repository. Proguard files are
generated in each library's build directory (e.g.,
analytics/build/analytics.pro).
You can build the entire SDK for Android by running ./gradlew build or
build_scripts/android/build.sh.
Unfortunately, the iOS version of the SDK cannot be built on Linux, it can only
be built in a MacOS environment. You will have to rely on GitHub Actions to
build for iOS, and have the user inform you of any build issues that come up.
Troubleshooting Desktop Builds
-
Linux: Missing libsecret-1-dev:
CMake configuration may fail if libsecret-1-dev is not installed.
The scripts/gha/install_prereqs_desktop.py script should handle this.
If it doesn't, or if the package is removed, you might need to install it
manually: sudo apt-get update && sudo apt-get install -y libsecret-1-dev.
-
Linux: LevelDB Patch Failure when building Firestore:
If you are building the SDK with Firestore enabled
(-DFIREBASE_INCLUDE_FIRESTORE=ON, which is the default for desktop) and
encounter a patch error related to leveldb-1.23_windows_paths.patch (e.g.,
util/env_windows.cc: patch does not apply), you can ignore this issue if
it does not prevent the rest of the build from running. The patch is only
important on Windows.
Common system library dependencies for desktop:
- Windows: Common dependencies include advapi32.lib, ws2_32.lib,
crypt32.lib. Specific products might need others (e.g., Firestore:
rpcrt4.lib, ole32.lib, shell32.lib).
- macOS: Common dependencies include pthread (system library) and
frameworks like CoreFoundation, Foundation, and Security.
- Linux: Common dependencies include pthread (system library). When
using GCC 5+, define -D_GLIBCXX_USE_CXX11_ABI=0.
On all desktop platforms, building with -DFIREBASE_USE_BORINGSSL=YES can help
bypass any OpenSSL dependency issues.
Including the SDK in Projects
Use add_subdirectory() in your CMakeLists.txt:
add_subdirectory("[[Path to the Firebase C++ SDK]]")
target_link_libraries([[Your CMake Target]] firebase_analytics firebase_app)
In addition to CMake setup, use Android/firebase_dependencies.gradle in your
build.gradle:
apply from: "[[Path to the Firebase C++ SDK]]/Android/firebase_dependencies.gradle"
firebaseCpp.dependencies {
analytics
}
For more detailed instructions and examples, always refer to the main
README.md and the
C++ Quickstarts.
The primary method for testing in this repository is through integration
tests for each Firebase library. While the README.md mentions unit tests
run via CTest, the current and preferred approach is to ensure comprehensive
coverage within the integration tests.
-
Integration Test Location: Integration tests for each Firebase product
(e.g., Firestore, Auth) are typically located in the integration_test/
directory within that product's module (e.g.,
firestore/integration_test/).
Because building integration tests requires internal google-services files,
Jules cannot do it in its environment; instead, we rely on GitHub Actions's
Integration Test workflow to build and run the integration tests.
When adding new features or fixing bugs:
- Prioritize adding or updating integration tests within the respective
product's integration_test/ directory.
- Ensure tests cover the new functionality thoroughly and verify interactions
with the Firebase backend or other relevant components.
- Follow existing patterns within the integration tests for consistency.
The Firebase C++ SDK exposes its functionality through a set of classes and
functions organized by product (e.g., Firestore, Authentication, Realtime
Database).
- firebase::App: This is the central entry point for the SDK.
- It must be initialized first using firebase::App::Create(...).
- On Android, this requires passing the JNI environment (JNIEnv*) and
the Android Activity (jobject).
- firebase::AppOptions can be used to configure the app with specific
parameters if not relying on a google-services.json or
GoogleService-Info.plist file.
- Service Instances: Once firebase::App is initialized, you generally
obtain instances of specific Firebase services using a static
GetInstance() method on the service's class, passing the firebase::App
object.
- Examples for services like Auth, Database, Storage, Firestore:
- firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app, &init_result);
- firebase::database::Database* database = firebase::database::Database::GetInstance(app, &init_result);
- firebase::storage::Storage* storage = firebase::storage::Storage::GetInstance(app, &init_result);
- Always check the init_result (an InitResult enum, often
firebase::kInitResultSuccess on success) to ensure these services
were initialized successfully.
- Note on Analytics: Some products, like Firebase Analytics, have a
different pattern. Analytics is typically initialized with
firebase::analytics::Initialize(const firebase::App& app) (often
handled automatically for the default App instance). After this,
Analytics functions (e.g., firebase::analytics::LogEvent(...)) are
called as global functions within the firebase::analytics namespace,
rather than on an instance object obtained via GetInstance().
Refer to the specific product's header file for its exact
initialization mechanism if it deviates from the common
GetInstance(app, ...) pattern.
Asynchronous Operations: firebase::Future<T>
All asynchronous operations in the SDK return a firebase::Future<T> object,
where T is the type of the expected result.
- Status Checking: Use future.status() to check if the operation is
kFutureStatusPending, kFutureStatusComplete, or
kFutureStatusInvalid.
- Getting Results: Once future.status() == kFutureStatusComplete:
- Check for errors: future.error(). A value of 0 (e.g.,
firebase::auth::kAuthErrorNone,
firebase::database::kErrorNone) usually indicates success.
- Get the error message: future.error_message().
- Get the result: future.result(). This returns a pointer to the result
object of type T. The result is only valid if future.error()
indicates success.
- Completion Callbacks: Use future.OnCompletion(...) to register a
callback function (lambda or function pointer) that will be invoked when
the future completes. The callback receives the completed future as an
argument.
- k?????Fn_* enums: A list of each SDK's asynchronous functions is usually
kept in an enum in that SDK. For example, all of Auth's asynchronous
functions are named kAuthFn_* and kUserFn_*. Only asynchronous operations
(which return a Future) need to be in those function enums; these are used
internally to hold a reference to the FutureHandle for the *LastResult()
methods. If you add a new asynchronous operation, it should be added to
that enum, and that ID should be used for all of the internal FutureApi
operations. Non-async functions never need to touch this.
- Asynchronous functions ONLY: Only asynchronous functions need to use
the Future pattern, e.g. anything with a callback. If you are simply
calling an underlying SDK function that finishes its work and returns
immediately, with no callback, there is no need to use a Future. See
STYLE_GUIDE.md for more details on asynchronous operations.
Core Classes and Operations (Examples from Auth and Database)
While each Firebase product has its own specific classes, the following
examples illustrate common API patterns:
- firebase::auth::Auth: The main entry point for Firebase
Authentication.
- Used to manage users, sign in/out, etc.
- Successful authentication operations (like
SignInWithEmailAndPassword()) return a
Future<firebase::auth::AuthResult>. The firebase::auth::User
object can then be obtained from this AuthResult (e.g.,
auth_result.result()->user() after result() is confirmed
successful and the pointer is checked).
- Example: firebase::auth::User* current_user = auth->current_user();
- Methods for user creation/authentication:
CreateUserWithEmailAndPassword(), SignInWithEmailAndPassword(),
SignInWithCredential().
- firebase::auth::User:
- Represents a user account. Data is typically accessed via its methods.
- Methods for profile updates: UpdateEmail(), UpdatePassword(),
UpdateUserProfile().
- Other operations: SendEmailVerification(), Delete().
- firebase::database::Database: The main entry point for Firebase
Realtime Database.
- Used to get DatabaseReference objects to specific locations in the
database.
- firebase::database::DatabaseReference:
- Represents a reference to a specific location (path) in the Realtime
Database.
- Methods for navigation: Child(), Parent(), Root().
- Methods for data manipulation: GetValue(), SetValue(),
UpdateChildren(), RemoveValue().
- Methods for listeners: AddValueListener(), AddChildListener().
- firebase::database::Query:
- Used to retrieve data from a Realtime Database location based on
specific criteria. Obtained from a DatabaseReference.
- Filtering: OrderByChild(), OrderByKey(), OrderByValue(),
EqualTo(), StartAt(), EndAt().
- Limiting: LimitToFirst(), LimitToLast().
- Execution: GetValue() returns a Future<DataSnapshot>.
- firebase::database::DataSnapshot: Contains data read from a Realtime
Database location (either directly or as a result of a query). Accessed
via future.result() or through listeners.
- Methods: value() (returns a firebase::Variant representing the
data), children_count(), children(), key(), exists().
- firebase::Variant: A type that can hold various data types like
integers, strings, booleans, vectors (arrays), and maps (objects),
commonly used for reading and writing data with Realtime Database and other
services.
- Operation-Specific Options: Some operations might take optional
parameters to control behavior, though not always through a dedicated
"Options" class like Firestore's SetOptions. For example,
User::UpdateUserProfile() takes a UserProfile struct.
Listeners for Real-time Updates
Many Firebase services support real-time data synchronization using listeners.
- firebase::database::ValueListener /
firebase::database::ChildListener: Implemented by the developer and
registered with a DatabaseReference.
- ValueListener::OnValueChanged(const firebase::database::DataSnapshot& snapshot)
is called when the data at that location changes.
- ChildListener has methods like OnChildAdded(), OnChildChanged(),
OnChildRemoved().
- firebase::auth::AuthStateListener: Implemented by the developer and
registered with firebase::auth::Auth.
- AuthStateListener::OnAuthStateChanged(firebase::auth::Auth* auth) is
called when the user's sign-in state changes.
- Removing Listeners: Listeners are typically removed by passing the
listener instance to a corresponding Remove...Listener() method (e.g.,
reference->RemoveValueListener(my_listener);,
auth->RemoveAuthStateListener(my_auth_listener);).
This overview provides a general understanding. Always refer to the specific
header files in firebase/app/client/cpp/include/firebase/ and
firebase/product_name/client/cpp/include/firebase/product_name/ for detailed
API documentation.
- Firebase C++ Style Guide: For specific C++ API design and coding
conventions relevant to this SDK, refer to the
STYLE_GUIDE.md.
- Google C++ Style Guide: Adhere to the
Google C++ Style Guide
as mentioned in CONTRIBUTING.md.
- Formatting: Use python3 scripts/format_code.py -git_diff -verbose to
format your code before committing.
- Naming Precision for Dynamic Systems: Function names should precisely
reflect their behavior, especially in systems with dynamic or asynchronous
interactions. For example, a function that processes a list of items should
be named differently from one that operates on a single, specific item
captured asynchronously. Regularly re-evaluate function names as
requirements evolve to maintain clarity.
- Write clear and concise comments where necessary to explain complex logic or
non-obvious behavior.
- Avoid overly verbose comments: Do not state the obvious. The code should
be as self-documenting as possible.
- Follow existing comment styles within the module you are working on.
- "Avoid adding comments next to #include directives merely to explain why
the include is necessary; the code usage should make this clear, or it can
be part of a broader comment block if truly non-obvious for a section of
code."
- "Do not include comments that narrate the AI agent's iterative development
process (e.g., 'Removed old logic here', 'Changed variable name from X to
Y because...', 'Attempted Z but it did not work'). Comments should focus on
explaining the current state of the code for future maintainers, not its
development history or the AI's thought process."
- Check Future status and errors: Always check future.status() and
future.error() before attempting to use future.result().
- A common success code is 0 (e.g.,
firebase::auth::kAuthErrorNone,
firebase::database::kErrorNone). Other specific error codes are
defined per module (e.g.,
firebase::auth::kAuthErrorUserNotFound).
- Callback error parameters: When using listeners or other callbacks,
always check the provided error code and message before processing the
data.
- Provide meaningful error messages if your code introduces new error
conditions.
- firebase::Future: Future objects manage their own resources.
Future::Release() can be called, but it's often handled by RAII when
futures go out of scope. Be mindful of Future lifetimes if they are
stored as members or passed around.
- ListenerRegistrations: When a listener is no longer needed, call
ListenerRegistration::Remove() to detach it. Failure to do so can lead
to memory leaks and unnecessary network/CPU usage.
- Pointers: Standard C++ smart pointers (std::unique_ptr,
std::shared_ptr) should be used where appropriate for managing
dynamically allocated memory.
- Future Lifecycle: Ensure Future objects returned from API calls are
properly managed. While Futures handle their own internal memory for the
result, the asynchronous operations they represent need to complete to
reliably free all associated operational resources or to ensure actions
(like writes to a database) are definitely finalized. Abandoning a Future
(letting it go out of scope without checking its result, attaching an
OnCompletion callback, or explicitly Wait()ing for it) can sometimes
lead to operations not completing as expected or resources not being
cleaned up promptly by the underlying services, especially if the Future
is the only handle to that operation. Prefer using OnCompletion or
otherwise ensuring the Future completes its course, particularly for
operations with side effects or those that allocate significant backend
resources.
- Lifecycle of Queued Callbacks/Blocks: If blocks or callbacks are queued
to be run upon an asynchronous event (e.g., an App Delegate class being set
or a Future completing), clearly define and document their lifecycle.
Determine if they are one-shot (cleared after first execution) or
persistent (intended to run for multiple or future events). This impacts
how associated data and the blocks themselves are stored and cleared,
preventing memory leaks or unexpected multiple executions.
- Be aware that some objects, like firebase::firestore::Query, are
immutable. Methods that appear to modify them (e.g., query.Where(...))
actually return a new instance with the modification.
- Firebase C++ SDK supports multiple platforms (Android, iOS, tvOS, desktop -
Windows, macOS, Linux).
- Platform-specific code is typically organized into subdirectories:
- android/ (for Java/JNI related code)
- ios/ (for Objective-C/Swift interoperability code)
- desktop/ (for Windows, macOS, Linux specific implementations)
- common/ (for C++ code shared across all platforms)
- Use preprocessor directives (e.g., #if FIREBASE_PLATFORM_ANDROID,
#if FIREBASE_PLATFORM_IOS) to conditionally compile platform-specific
sections when necessary, but prefer separate implementation files where
possible for better organization.
Platform-Specific Considerations
- Realtime Database (Desktop): The C++ SDK for Realtime Database on
desktop platforms (Windows, macOS, Linux) uses a REST-based
implementation. This means that any queries involving
Query::OrderByChild() require corresponding indexes to be defined in your
Firebase project's Realtime Database rules. Without these indexes, queries
may fail or not return expected results.
- iOS Method Swizzling: Be aware that some Firebase products on iOS
(e.g., Cloud Messaging) use method swizzling to
automatically attach handlers to your AppDelegate. While this simplifies
integration, it can occasionally be a factor to consider when debugging app
delegate behavior or integrating with other libraries that also perform
swizzling.
When implementing or interacting with swizzling, especially for App Delegate
methods like [UIApplication setDelegate:]:
* Be highly aware that setDelegate: can be called multiple times
with different delegate class instances, including proxy classes
from other libraries (e.g., GUL - Google Utilities). Swizzling
logic must be robust against being invoked multiple times for the
same effective method on the same class or on classes in a
hierarchy. An idempotency check (i.e., if the method's current IMP
is already the target swizzled IMP, do nothing more for that
specific swizzle attempt) in any swizzling utility can prevent
issues like recursion.
* When tracking unique App Delegate classes (e.g., for applying hooks
or callbacks via swizzling), consider the class hierarchy. If a
superclass has already been processed, processing a subclass for
the same inherited methods might be redundant or problematic. A
strategy to check if a newly set delegate is a subclass of an
already processed delegate can prevent such issues.
* For code that runs very early in the application lifecycle on
iOS/macOS (e.g., +load methods, static initializers involved in
swizzling), prefer using NSLog directly over custom logging
frameworks if there's any uncertainty about whether the custom
framework is fully initialized, to avoid crashes during logging
itself.
- Follow the existing pattern of internal and common classes within each
Firebase library (e.g., firestore/src/common, firestore/src/main,
firestore/src/android).
- Public headers defining the API are typically in
src/include/firebase/product_name/.
- Internal implementation classes often use the Internal suffix (e.g.,
DocumentReferenceInternal).
Pimpl (Pointer to Implementation) Idiom
- Many public API classes (e.g., firebase::storage::StorageReference,
firebase::storage::Metadata) use the Pimpl idiom.
- They hold a pointer to an internal implementation class (e.g.,
StorageReferenceInternal, MetadataInternal).
- This pattern helps decouple the public interface from its implementation,
reducing compilation dependencies and hiding internal details.
- When working with these classes, you will primarily interact with the public
interface. Modifications to the underlying implementation are done in the
*Internal classes.
A common convention for this Pimpl pattern in the codebase (e.g., as seen in
firebase::storage::Metadata) is that the public class owns the raw pointer to
its internal implementation (internal_). This requires careful manual memory
management:
- Creation: The internal_ object is typically allocated with new in
the public class's constructor(s). For instance, the default constructor
might do internal_ = new ClassNameInternal(...);, and a copy constructor
would do internal_ = new ClassNameInternal(*other.internal_); for a
deep copy.
- Deletion: The internal_ object is deleted in the public class's
destructor (e.g., delete internal_;). It's good practice to set
internal_ = nullptr; immediately after deletion if the destructor isn't
the absolute last point of usage, or if helper delete functions are used
(as seen with MetadataInternalCommon::DeleteInternal which nullifies the
pointer in the public class instance before deleting).
- Copy Semantics:
- Copy Constructor: If supported, a deep copy is usually performed. A
new internal_ instance is created, and the contents from the source
object's internal_ are copied into this new instance.
- Copy Assignment Operator: If supported, it must also perform a deep
copy. This typically involves deleting the current internal_ object,
then creating a new internal_ instance and copying data from the
source's internal_ object. Standard self-assignment checks should be
present.
- Move Semantics:
- Move Constructor: If supported, ownership of the internal_ pointer
is transferred from the source object to the new object. The source
object's internal_ pointer is then set to nullptr to prevent
double deletion.
- Move Assignment Operator: Similar to the move constructor, it
involves deleting the current object's internal_, then taking
ownership of the source's internal_ pointer, and finally setting the
source's internal_ to nullptr.
- Cleanup Registration (Advanced): In some cases, like
firebase::storage::Metadata, there might be an additional registration
with a central cleanup mechanism (e.g., via StorageInternal). This acts
as a safeguard or part of a larger resource management strategy within the
module, but the fundamental responsibility for creation and deletion in
typical scenarios lies with the Pimpl class itself.
It's crucial to correctly implement all these aspects (constructors,
destructor, copy/move operators) when dealing with raw pointer Pimpls to
prevent memory leaks, dangling pointers, or double deletions.
- Code for each Firebase product is typically within its own namespace under
firebase.
- Example: firebase::firestore, firebase::auth,
firebase::database.
- Internal or platform-specific implementation details might be in nested
namespaces like firebase::firestore::internal or
firebase::firestore::android.
Futures for Asynchronous Operations
- As detailed in the API Surface section, firebase::Future<T> is the
standard way all asynchronous operations return their results.
- Familiarize yourself with Future::status(), Future::error(),
Future::error_message(), Future::result(), and
Future::OnCompletion().
Internal Classes and Helpers
- Each module often has a set of internal classes (often suffixed with
Internal or residing in an internal namespace) that manage the core
logic, platform-specific interactions, and communication with the Firebase
backend.
- Utility functions and helper classes are common within the common/ or
util/ subdirectories of a product.
Singleton Usage (Limited)
- The primary singleton is firebase::App::GetInstance().
- Service entry points like firebase::firestore::Firestore::GetInstance()
also provide singleton-like access to service instances (scoped to an App
instance).
- Beyond these entry points, direct creation or use of singletons for core
data objects or utility classes is not a dominant pattern. Dependencies are
generally passed explicitly.
- For operations that differ by platform, there's often a common C++
interface defined in common/ or main/, with specific implementations
in android/, ios/, and desktop/ directories.
- JNI is used extensively in android/ directories for C++ to Java
communication.
- Objective-C++ (.mm files) is used in ios/ directories for C++ to
Objective-C communication.
- The AddSnapshotListener/ListenerRegistration pattern is common for
features requiring real-time updates (e.g., Firestore, Realtime
Database).
Builder/Fluent Interface for Queries
- Classes like firebase::firestore::Query use a fluent interface (method
chaining) to construct complex queries by progressively adding filters,
ordering, and limits. Each call typically returns a new instance of the
query object.
This document is a living guide. As the Firebase C++ SDK evolves, new patterns
may emerge, or existing practices might change. If you introduce a new common
pattern, significantly alter a build process, or establish a new best practice
during your work, please take a moment to update this AGENTS.md file
accordingly.
Keeping this document current will greatly benefit future AI agents and human
developers working on this repository.
Recommended General Prompt Instruction
When working on this task, please consistently refer to the AGENTS.md guide
for all repository-specific conventions, including setup procedures, coding
style, common architectural patterns, and API usage. Pay close attention to the
testing strategies outlined, ensuring your implementation includes
comprehensive integration tests with detailed test cases in your plan. Implement
robust error handling for any new or modified public API methods, following the
patterns for firebase::Future error reporting. If the feature involves
platform-specific code, ensure the public API remains consistent across all
platforms, as discussed in AGENTS.md. Write clear, maintainable code,
adhering to the commenting guidelines, and if you need to add new third-party
dependencies, document the rationale and update build configurations according
to the established practices. Ensure your changes align with the overall best
practices detailed in AGENTS.md.
Key Directives for Jules AI
- Prioritize AGENTS.md: This document (AGENTS.md) contains
repository-specific guidelines. Prioritize this information when making
decisions about coding style, testing procedures, architectural patterns,
and API usage.
- Adherence to Patterns: Strive to follow the common patterns and best
practices outlined here. This ensures consistency across the codebase.
- Clarification for Deviations: If the existing patterns in AGENTS.md do
not seem suitable for a specific task, or if a deviation is necessary,
please explicitly state this in your plan or request clarification before
proceeding with implementation.
- Updating AGENTS.md: If you introduce a new, broadly applicable
pattern, or if a significant change to the build process or best practices
occurs as part of your task, please include a step in your plan to update
AGENTS.md to reflect these changes.
- Testing: Remember that integration tests are the primary method of
testing. Ensure new features are accompanied by corresponding integration
tests as described in the 'Testing' section of AGENTS.md.
- Commit Messages: Follow standard commit message guidelines. A brief
summary line, followed by a more detailed explanation if necessary.
- Tool Limitations & Path Specificity: If codebase search tools (like
grep or recursive ls) are limited or unavailable, and initial attempts
to locate files/modules based on common directory structures are
unsuccessful, explicitly ask for more specific paths rather than assuming a
module doesn't exist or contains no relevant code.
GitHub Code Review Comments -- IMPORTANT, JULES READ THIS SECTION
If the user asks you to look at GitHub code review comments, PR reviews, etc,
that means that you should run the following command:
python3 scripts/print_github_reviews.py --branch BRANCH_NAME_THAT_JULES_PUSHED_TO_GITHUB
(with the remote branch name that was actually pushed to GitHub substituted, and
if you aren't sure what it is or it returns an error, just ask the user, as they
may have renamed the branch before pushing) and then address the comments that
the output shows. If it succeeds, then subsequent times you run the script on
the same branch, include the --since parameter in accordance with the previous
script run's output to ensure you only fetch new comments.