Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/cli/plan-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ implementation strategy.
- [How to use Plan Mode](#how-to-use-plan-mode)
- [Entering Plan Mode](#entering-plan-mode)
- [The Planning Workflow](#the-planning-workflow)
- [Customizing Planning with Skills](#customizing-planning-with-skills)
- [Exiting Plan Mode](#exiting-plan-mode)
- [Tool Restrictions](#tool-restrictions)

Expand Down Expand Up @@ -76,6 +77,26 @@ You can enter Plan Mode in three ways:
Auto-Edit or Default approval mode).
- **Iterate:** Provide feedback to refine the plan.

### Customizing Planning with Skills

You can leverage [Agent Skills](./skills.md) to customize how Gemini CLI
approaches planning for specific types of tasks. When a skill is activated
during Plan Mode, its specialized instructions and procedural workflows will
guide the research and design phases.

For example:

- A **"Database Migration"** skill could ensure the plan includes data safety
checks and rollback strategies.
- A **"Security Audit"** skill could prompt the agent to look for specific
vulnerabilities during codebase exploration.
- A **"Frontend Design"** skill could guide the agent to use specific UI
components and accessibility standards in its proposal.

To use a skill in Plan Mode, you can explicitly ask the agent to "use the
[skill-name] skill to plan..." or the agent may autonomously activate it based
on the task description.

### Exiting Plan Mode

To exit Plan Mode:
Expand All @@ -92,6 +113,8 @@ These are the only allowed tools:

- **FileSystem (Read):** [`read_file`], [`list_directory`], [`glob`]
- **Search:** [`grep_search`], [`google_web_search`]
- **Skills:** [`activate_skill`] (allows loading specialized instructions and
resources in a read-only manner)
- **Interaction:** `ask_user`
- **MCP Tools (Read):** Read-only [MCP tools] (e.g., `github_read_issue`,
`postgres_read_schema`) are allowed.
Expand All @@ -106,3 +129,4 @@ These are the only allowed tools:
[`google_web_search`]: /docs/tools/web-search.md
[`replace`]: /docs/tools/file-system.md#6-replace-edit
[MCP tools]: /docs/tools/mcp-server.md
[`activate_skill`]: /docs/cli/skills.md
4 changes: 2 additions & 2 deletions packages/core/src/policy/policies/plan.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
decision = "deny"
priority = 60
modes = ["plan"]
deny_message = "You are in Plan Mode - adjust your prompt to only use read and search tools."
deny_message = "You are in Plan Mode with access to read-only tools. Execution of scripts (including those from skills) is blocked."

# Explicitly Allow Read-Only Tools in Plan mode.

[[rule]]
toolName = ["glob", "grep_search", "list_directory", "read_file", "google_web_search"]
toolName = ["glob", "grep_search", "list_directory", "read_file", "google_web_search", "activate_skill"]
decision = "allow"
priority = 70
modes = ["plan"]
Expand Down
40 changes: 40 additions & 0 deletions packages/core/src/policy/policy-engine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2086,4 +2086,44 @@ describe('PolicyEngine', () => {
expect(result.decision).toBe(PolicyDecision.ALLOW);
});
});

describe('Plan Mode', () => {
it('should allow activate_skill but deny shell commands in Plan Mode', async () => {
const rules: PolicyRule[] = [
{
decision: PolicyDecision.DENY,
priority: 60,
modes: [ApprovalMode.PLAN],
denyMessage:
'You are in Plan Mode with access to read-only tools. Execution of scripts (including those from skills) is blocked.',
},
{
toolName: 'activate_skill',
decision: PolicyDecision.ALLOW,
priority: 70,
modes: [ApprovalMode.PLAN],
},
];

engine = new PolicyEngine({
rules,
approvalMode: ApprovalMode.PLAN,
});

const skillResult = await engine.check(
{ name: 'activate_skill', args: { name: 'test' } },
undefined,
);
expect(skillResult.decision).toBe(PolicyDecision.ALLOW);

const shellResult = await engine.check(
{ name: 'run_shell_command', args: { command: 'ls' } },
undefined,
);
expect(shellResult.decision).toBe(PolicyDecision.DENY);
expect(shellResult.rule?.denyMessage).toContain(
'Execution of scripts (including those from skills) is blocked',
);
});
});
});
1 change: 1 addition & 0 deletions packages/core/src/tools/tool-names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export const PLAN_MODE_TOOLS = [
LS_TOOL_NAME,
WEB_SEARCH_TOOL_NAME,
ASK_USER_TOOL_NAME,
ACTIVATE_SKILL_TOOL_NAME,
EXIT_PLAN_MODE_TOOL_NAME,
] as const;

Expand Down
Loading