Skip to content

feat(policy): add --policy flag for user defined policies#18500

Open
allenhutchison wants to merge 2 commits intomainfrom
adh/feature/add-policy-flag
Open

feat(policy): add --policy flag for user defined policies#18500
allenhutchison wants to merge 2 commits intomainfrom
adh/feature/add-policy-flag

Conversation

@allenhutchison
Copy link
Collaborator

Summary

Add a --policy flag to the Gemini CLI to allow users to specify additional policy files or directories. These user-provided policies replace the standard user policy directory (~/.gemini/policies), giving users full control over the policy engine's rules for a specific session or setup.

Details

  • Added --policy flag to CLI arguments.
  • Updated PolicySettings and settings schema to include policyPaths.
  • Enhanced loadPoliciesFromToml to support individual file paths in addition to directories.
  • Modified createPolicyEngineConfig to prioritize policyPaths and exclude the default user policy directory when they are present.
  • Updated createNonInteractiveUI to output info, warning, and error messages to the console, enabling /policies list to work in headless mode.
  • Regenerated settings schema and documentation.

Related Issues

Closes #11301

How to Validate

  1. Create a policy file ls-deny.toml:
[[rule]]
toolName = "ls"
decision = "deny"
priority = 900
deny_message = "ls is blocked by this test policy."
  1. Run npm start -- --policy ls-deny.toml --prompt "/policies list".
  2. Verify that ls-deny.toml is listed under user policies and standard policies from ~/.gemini/policies are NOT present.
  3. Verify that the output is displayed in the terminal (headless mode).

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run

@allenhutchison allenhutchison requested review from a team as code owners February 7, 2026 01:15
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @allenhutchison, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the policy management capabilities of the Gemini CLI by introducing a --policy flag. This flag empowers users to define and load custom policy sets, overriding the default user policies for a given session. The changes include updates to the CLI argument parsing, policy engine configuration, and the underlying TOML policy loader to support both individual files and directories. Additionally, the non-interactive UI has been improved to ensure policy-related output is visible in headless mode, providing a more robust and controllable policy experience.

Highlights

  • New --policy CLI Flag: Introduced a new --policy command-line flag that allows users to specify custom policy files or directories. This provides greater flexibility in defining policy rules for specific sessions or setups.
  • Policy Override Mechanism: When the --policy flag is used, the user-provided policy paths explicitly replace the standard user policy directory (~/.gemini/policies), giving users full control over the policy engine's rules without merging with default user policies.
  • Flexible Policy Loading: The policy loading mechanism has been enhanced to support both individual policy files and directories containing policy files, rather than being limited to just directories.
  • Headless UI Output for Policies: The non-interactive UI now outputs info, warning, and error messages to the console, enabling commands like /policies list to function correctly and display relevant information in headless environments.
  • Configuration and Documentation Updates: The policyPaths setting has been added to the settings schema and documentation, allowing for persistent configuration of custom policy paths.
Changelog
  • docs/get-started/configuration.md
    • Added documentation for the new policyPaths setting, detailing its description, default value, and restart requirement.
  • packages/cli/src/config/config.test.ts
    • Added a test case to verify that user-provided policy paths from the --policy flag are correctly passed to the createPolicyEngineConfig function.
  • packages/cli/src/config/config.ts
    • Updated the CliArgs interface to include the new policy array.
    • Integrated the --policy option into the CLI argument parser (yargs), allowing multiple or comma-separated policy paths.
    • Mapped the parsed --policy arguments to the policyPaths setting in the CLI configuration.
  • packages/cli/src/config/policy.ts
    • Modified createPolicyEngineConfig to accept and utilize the policyPaths from the settings object.
  • packages/cli/src/config/settingsSchema.ts
    • Added the policyPaths property to the internal settings schema, defining it as an array of strings for additional policy files or directories.
  • packages/cli/src/gemini.test.tsx
    • Updated mock argv objects in tests to include the new policy property.
  • packages/cli/src/ui/noninteractive/nonInteractiveUi.ts
    • Enhanced the addItem function to output info, warning, and error messages to stdout or stderr respectively, improving visibility in non-interactive environments.
  • packages/core/src/policy/config.test.ts
    • Updated file system mocks (fs.stat, fs.readdir, fs.readFile) to support testing the new policy loading logic, including individual files and directories.
  • packages/core/src/policy/config.ts
    • Refactored createPolicyEngineConfig to prioritize policyPaths from settings, replacing the default user policy directory when custom paths are provided.
    • Adjusted the getPolicyTier logic within loadPoliciesFromToml to correctly assign USER_POLICY_TIER to user-provided policy paths that are not admin policies.
  • packages/core/src/policy/toml-loader.test.ts
    • Added a test case to confirm the successful loading of an individual policy file.
    • Added a test case to ensure non-existent policy paths are gracefully handled without errors.
    • Removed a test case related to readdir failing on a file, as the new toml-loader logic handles files directly.
  • packages/core/src/policy/toml-loader.ts
    • Refactored loadPoliciesFromToml to accept policyPaths (which can be files or directories) and use fs.stat to determine their type.
    • Implemented logic to load policies from individual .toml files directly, in addition to scanning directories.
    • Improved error handling to skip non-existent paths (ENOENT) without generating errors.
  • packages/core/src/policy/types.ts
    • Added policyPaths?: string[]; to the PolicySettings interface to accommodate the new configuration option.
  • schemas/settings.schema.json
    • Added the policyPaths definition to the JSON schema, aligning with the new configuration option and its properties.
Activity
  • The author, allenhutchison, has implemented the feature to add a --policy flag for user-defined policies.
  • Documentation in docs/get-started/configuration.md was updated to reflect the new policyPaths setting.
  • New and updated tests were added across packages/cli/src/config/config.test.ts, packages/core/src/policy/config.test.ts, and packages/core/src/policy/toml-loader.test.ts to cover the new functionality and policy loading logic.
  • The changes have been validated on MacOS using npm run.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a valuable --policy flag, allowing users to specify custom policy files and directories. The implementation is well-structured, with updates to argument parsing, settings schemas, and the core policy loading logic. The ability to handle both individual files and directories in the toml-loader is a great enhancement.

I've found one critical issue in packages/core/src/policy/toml-loader.ts related to an uninitialized variable that could lead to a crash, along with an inconsistency in file handling. My review comment provides a detailed explanation and a suggested fix.

Once that is addressed, this will be a solid feature addition to the CLI.

Comment on lines 229 to +245
let filesToLoad: string[];
let baseDir: string;

try {
const dirEntries = await fs.readdir(dir, { withFileTypes: true });
filesToLoad = dirEntries
.filter((entry) => entry.isFile() && entry.name.endsWith('.toml'))
.map((entry) => entry.name);
const stats = await fs.stat(p);
if (stats.isDirectory()) {
baseDir = p;
const dirEntries = await fs.readdir(p, { withFileTypes: true });
filesToLoad = dirEntries
.filter((entry) => entry.isFile() && entry.name.endsWith('.toml'))
.map((entry) => entry.name);
} else if (stats.isFile()) {
baseDir = path.dirname(p);
filesToLoad = [path.basename(p)];
} else {
continue;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

There's a critical bug here that can cause the application to crash. The filesToLoad variable is declared but not initialized. If fs.stat(p) fails with an error (e.g., permission denied), or if the path p is not a file or directory (e.g., a symlink), one of the continue statements will be executed. This leaves filesToLoad as undefined, causing a TypeError on line 263 when the code attempts to iterate over it.

Additionally, there's an inconsistency in how files are handled. When scanning a directory, only files ending with .toml are processed, while others are silently ignored. However, when an individual file path is provided, it's processed regardless of its extension, which will lead to a parsing error if it's not a TOML file. For consistent behavior, individual files should also be filtered to only include .toml files.

Both issues can be resolved by initializing filesToLoad and adding a check for the .toml extension for individual files.

    let filesToLoad: string[] = [];
    let baseDir = '';

    try {
      const stats = await fs.stat(p);
      if (stats.isDirectory()) {
        baseDir = p;
        const dirEntries = await fs.readdir(p, { withFileTypes: true });
        filesToLoad = dirEntries
          .filter((entry) => entry.isFile() && entry.name.endsWith('.toml'))
          .map((entry) => entry.name);
      } else if (stats.isFile() && p.endsWith('.toml')) {
        baseDir = path.dirname(p);
        filesToLoad = [path.basename(p)];
      }
      // Other file types or non-toml files are silently ignored for consistency.

@github-actions
Copy link

github-actions bot commented Feb 7, 2026

Size Change: +2.04 kB (+0.01%)

Total Size: 23.8 MB

Filename Size Change
./bundle/gemini.js 23.8 MB +2.04 kB (+0.01%)
ℹ️ View Unchanged
Filename Size
./bundle/sandbox-macos-permissive-closed.sb 1.03 kB
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-closed.sb 3.29 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB

compressed-size-action

@gemini-cli gemini-cli bot added the 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. label Feb 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔒 maintainer only ⛔ Do not contribute. Internal roadmap item.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add --policy flag for user defined policy

1 participant