Lazy-loading Claude Code skills

16 min read Original article ↗

Lazy-loading Claude Code skills

Yikes! We just learned Claude Code inlines every installed skill's name and description into the system prompt on every turn!

I have the 87 Google Workspace skills installed via the googleworkspace/cli. gws-gmail, gws-calendar-insert, recipe-save-email-attachments, persona-exec-assistant, and 83 more. They work great, this CLI is a treat.

What's already possible (and what isn't)

A couple of native knobs:

  • disable-model-invocation: true in skill frontmatter — does not save tokens. Skill still listed, just not auto-invoked.
  • /plugin disable — works, but only for skills installed via the plugin system. My gws skills come from a CLI, not a marketplace. This is also a pain to manage.
  • ENABLE_TOOL_SEARCH=true — deferred loading, but only for MCP tools. Doesn't apply to skills.
  • disabledSkills in settings.json — doesn't exist. Filed as #23522 and #43816 "SkillSearch", no ship date.

So there's no built-in way to hide a skill's metadata from the system prompt without uninstalling it.

An easy solution

Claude Code only discovers skills that have a SKILL.md at .claude/skills/<name>/SKILL.md. Move the file somewhere else and Claude Code stops listing it in the system prompt but the file is still readable by the agent.

The move

cd .claude
mkdir -p skills-lazy/gws
mv skills/gws-* skills/persona-* skills/recipe-* skills-lazy/gws/

87 folders out of the auto-discovered path. Before / after:

The stub

Write one new skill at .claude/skills/gws/SKILL.md. Its frontmatter description covers the whole group and the body is a compact index of each skill's name and one-line description. When the model decides gws is relevant, it reads the index, picks the right child, and does Read .claude/skills-lazy/gws/<name>/SKILL.md to get the real instructions.

Stub frontmatter

The stub's description is what the top-level model sees. It has to be broad enough to match any request that would have hit any of the child skills. For the gws stub:

---
name: gws
description: "Google Workspace toolkit (87 lazy-loaded skills): Gmail, Drive, Calendar, Docs, Sheets, Slides, Chat, Meet, Tasks, Forms, Keep, Classroom, Admin Reports, Events; cross-service workflow/recipe automations; workflow personas. Use whenever the user asks about Google Workspace, Gmail, Drive, Calendar, Docs, Sheets, Slides, Chat, Meet, Tasks, Forms, Keep, Classroom, or a persona/recipe workflow."
---

The description is keyword-heavy on purpose. The auto-trigger picks stubs by semantic match on descriptions; if it doesn't see "Calendar" or "Drive" or "Gmail" in there, a user asking "check my calendar" won't invoke the stub and won't discover the lazy skills.

Body structure

# Google Workspace lazy-load index

The 87 individual skills below live at `.claude/skills-lazy/gws/<name>/SKILL.md`.

## How to use
1. Find the matching skill in the index below.
2. Read `.claude/skills-lazy/gws/<skill-name>/SKILL.md`.
3. Follow that file's instructions.

## Index
### gws-* — Workspace service primitives
- `gws-gmail`: Gmail: Send, read, and manage email.
- `gws-calendar`: Google Calendar: Manage calendars and events.
- ...

### persona-* — Workflow personas
- `persona-exec-assistant`: Manage an executive's schedule, inbox, and comms.
- ...

### recipe-* — Cross-service automations
- `recipe-save-email-attachments`: Find Gmail messages with attachments → save to Drive.
- ...

The index mirrors the descriptions Claude Code would have put in the system prompt. Same signal, loaded lazily.

Numbers

System prompt listed all 87 gws/persona/recipe skills inline, at a conservative count 1.2k tokens of descriptions.

After: one gws entry (~100 tokens) in the system prompt. The index (~1.5k tokens) only loads when the stub fires.

Net savings: ~1k tokens per turn, on every turn, for the entire session. These would be cached after the first turn which costs ~10% of non-cached. So at 50 turns you've paid for 600 tokens instead of 7.2k.

This is only helpful when you're not using these skills in every conversation. Often used skills should be kept in the main .claude/skills folder, eg: gws-gmail.

Caveats

  • Reinstalls clobber the move. gws install (or any upstream tool that writes to .claude/skills/) will repopulate the top-level paths. Mitigation: a note in the stub body about where the originals came from and that new ones need to be moved back into skills-lazy/.
  • Groupings are judgment calls. I put gws/persona/recipe into a single stub because they share a mental model (Google Workspace). For domains that don't cluster, you'll end up with several stubs, each with its own keyword-heavy description.
  • Stub descriptions compete. If your stub description is too broad, it'll trigger on requests that don't actually need the lazy skills, wasting the index load. Too narrow and it never fires. Err broad; the cost of loading the index when not strictly needed is still less than the cost of 87 descriptions on every turn.
  • Two-hop resolution. The agent now has to invoke the stub, then Read a child SKILL.md. Extra tool call, extra token cost on that particular turn. Break-even is ~1 turn where the lazy group doesn't fire; in practice, most sessions never touch these skills at all.
  • No auto-trigger on child skills. When a child SKILL.md lives in skills-lazy/, Claude Code's skill auto-trigger cannot fire it directly. The model has to explicitly decide to read it. This hasn't been a problem for me in practice.

Actual before and after

This is a line from my JSONL file in the same dir, from sessions before and after the change:

Before (2,861 tokens)

{"parentUuid":"db46f367-e832-4b0e-8c4a-c45b1f4e3d08","isSidechain":false,"attachment":{"type":"skill_listing","content":"- update-config: Use this skill to configure the Claude Code harness via settings.json. Automated behaviors (\"from now on when X\", \"each time X\", \"whenever X\", \"before/after X\") require hooks configured in settings.json - the harness executes these, not Claude, so memory/preferences cannot fulfill them. Also use for: permissions (\"allow X\", \"add permission\", \"move permission to\"), env vars (\"set X=Y\"), hook troubleshooting, or any changes to settings.json/settings.local.json files. Examples: \"allow npm commands\", \"add bq permission to global settings\", \"move permission to user settings\", \"set DEBUG=true\", \"when claude stops show X\". For simple settings like theme/model, use Config tool.\n- keybindings-help: Use when the user wants to customize keyboard shortcuts, rebind keys, add chord bindings, or modify ~/.claude/keybindings.json. Examples: \"rebind ctrl+s\", \"add a chord shortcut\", \"change the submit key\", \"customize keybindings\".\n- simplify: Review changed code for reuse, quality, and efficiency, then fix any issues found.\n- loop: Run a prompt or slash command on a recurring interval (e.g. /loop 5m /foo). Omit the interval to let the model self-pace. - When the user wants to set up a recurring task, poll for status, or run something repeatedly on an interval (e.g. \"check the deploy every 5 minutes\", \"keep running /babysit-prs\"). Do NOT invoke for one-off tasks.\n- schedule: Create, update, list, or run scheduled remote agents (triggers) that execute on a cron schedule. - When the user wants to schedule a recurring remote agent, set up automated tasks, create a cron job for Claude Code, or manage their scheduled agents/triggers.\n- claude-api: Build, debug, and optimize Claude API / Anthropic SDK apps. Apps built with this skill should include prompt caching.\nTRIGGER when: code imports `anthropic`/`@anthropic-ai/sdk`; user asks to use the Claude API, Anthropic SDKs, or Managed Agents (`/v1/agents`, `/v1/sessions`); user asks to add, modify, debug, optimize, or improve a Claude feature (prompt caching, cache hit rate, adaptive thinking, compaction, code_execution, batch, files API, citations, memory tool) or a Claude model (Opus/Sonnet/Haiku) in a file; or user asks about prompt caching / cache hit rate / cache reads / cache creation in any project that uses the Anthropic SDK (even without mentioning Claude by name).\nDO NOT TRIGGER when: file imports `openai`/non-Anthropic SDK, filename signals another provider (`agent-openai.py`, `*-generic.py`), code is provider-neutral, or task is general programming/ML.\n- asc-iap-attach: Attach in-app purchases and subscriptions to an app version for App Store review. Use when the user has IAPs or subscriptions in \"Ready to Submit\" state that need to be included with a first-time version submission. Works for both first-time and subsequent submissions.\n- asc-team-key-create: Create a new App Store Connect Team API Key with Admin permissions, download the one-time .p8 private key, and store it in ~/.blitz. Use when the user needs a new ASC API key for CLI auth, CI/CD, or external tooling.\n- skill-creator: Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.\n- macos-mail-reader: Query the macOS Mail.app Envelope Index SQLite database with sqlite3 to search, count, and export email metadata. Use when the user wants to read, search, or analyze their local Apple Mail without AppleScript, MCP servers, or third-party tools.\n- asc-privacy-nutrition-labels: Set up App Store privacy nutrition labels (data collection declarations) for an app. Use when the user needs to declare what data their app collects, how it's used, and whether it's linked to the user. Handles both \"no data collected\" and full data collection declarations.\n- review-counsel: Multi-agent code review with specialist reviewers and judge validation\n- gws-drive-upload: Google Drive: Upload a file with automatic metadata.\n- playwright-cli: Automates browser interactions for web testing, form filling, screenshots, and data extraction. Use when the user needs to navigate websites, interact with web pages, fill forms, take screenshots, test web applications, or extract information from web pages.\n- recipe-save-email-attachments: Find Gmail messages with attachments and save them to a Google Drive folder.\n- gws-gmail-triage: Gmail: Show unread inbox summary (sender, subject, date).\n- recipe-create-gmail-filter: Create a Gmail filter to automatically label, star, or categorize incoming messages.\n- recipe-label-and-archive-emails: Apply Gmail labels to matching messages and archive them to keep your inbox clean.\n- gws-gmail-watch: Gmail: Watch for new emails and stream them as NDJSON.\n- tavily-search: AI-powered web search via Tavily API. Returns an AI answer plus extracted page content. Use when the user asks to search the web, research a topic, or find information online.\n- gws-admin-reports: Google Workspace Admin SDK: Audit logs and usage reports.\n- gws-workflow: Google Workflow: Cross-service productivity workflows.\n- recipe-send-team-announcement: Send a team announcement via both Gmail and a Google Chat space.\n- gws-docs: Read and write Google Docs.\n- recipe-share-event-materials: Share Google Drive files with all attendees of a Google Calendar event.\n- recipe-schedule-recurring-event: Create a recurring Google Calendar event with attendees.\n- recipe-reschedule-meeting: Move a Google Calendar event to a new time and automatically notify all attendees.\n- recipe-sync-contacts-to-sheet: Export Google Contacts directory to a Google Sheets spreadsheet.\n- gws-workflow-email-to-task: Google Workflow: Convert a Gmail message into a Google Tasks entry.\n- recipe-collect-form-responses: Retrieve and review responses from a Google Form.\n- recipe-post-mortem-setup: Create a Google Docs post-mortem, schedule a Google Calendar review, and notify via Chat.\n- persona-event-coordinator: Plan and manage events — scheduling, invitations, and logistics.\n- gws-meet: Manage Google Meet conferences.\n- persona-sales-ops: Manage sales workflows — track deals, schedule calls, client comms.\n- recipe-create-meet-space: Create a Google Meet meeting space and share the join link.\n- google-search: Search Google using the Custom Search API and display formatted results. Use when the user asks to search the web, look something up, or find information online.\n- recipe-backup-sheet-as-csv: Export a Google Sheets spreadsheet as a CSV file for local backup or processing.\n- recipe-share-doc-and-notify: Share a Google Docs document with edit access and email collaborators the link.\n- gws-sheets-read: Google Sheets: Read values from a spreadsheet.\n- gws-calendar-insert: Google Calendar: Create a new event.\n- gws-gmail: Gmail: Send, read, and manage email.\n- recipe-forward-labeled-emails: Find Gmail messages with a specific label and forward them to another address.\n- persona-researcher: Organize research — manage references, notes, and collaboration.\n- recipe-bulk-download-folder: List and download all files from a Google Drive folder.\n- gws-workflow-weekly-digest: Google Workflow: Weekly summary: this week's meetings + unread email count.\n- recipe-find-free-time: Query Google Calendar free/busy status for multiple users to find a meeting slot.\n- persona-exec-assistant: Manage an executive's schedule, inbox, and communications.\n- recipe-create-presentation: Create a new Google Slides presentation and add initial slides.\n- gws-chat: Google Chat: Manage Chat spaces and messages.\n- recipe-create-doc-from-template: Copy a Google Docs template, fill in content, and share with collaborators.\n- gws-keep: Manage Google Keep notes.\n- gws-classroom: Google Classroom: Manage classes, rosters, and coursework.\n- gws-chat-send: Google Chat: Send a message to a space.\n- gws-events: Subscribe to Google Workspace events.\n- recipe-save-email-to-doc: Save a Gmail message body into a Google Doc for archival or reference.\n- gws-workflow-file-announce: Google Workflow: Announce a Drive file in a Chat space.\n- recipe-create-shared-drive: Create a Google Shared Drive and add members with appropriate roles.\n- gws-drive: Google Drive: Manage files, folders, and shared drives.\n- recipe-watch-drive-changes: Subscribe to change notifications on a Google Drive file or folder.\n- gws-events-subscribe: Google Workspace Events: Subscribe to Workspace events and stream them as NDJSON.\n- gws-forms: Read and write Google Forms.\n- gws-workflow-standup-report: Google Workflow: Today's meetings + open tasks as a standup summary.\n- recipe-create-feedback-form: Create a Google Form for feedback and share it via Gmail.\n- recipe-share-folder-with-team: Share a Google Drive folder and all its contents with a list of collaborators.\n- recipe-draft-email-from-doc: Read content from a Google Doc and use it as the body of a Gmail message.\n- recipe-plan-weekly-schedule: Review your Google Calendar week, identify gaps, and add events to fill them.\n- recipe-create-vacation-responder: Enable a Gmail out-of-office auto-reply with a custom message and date range.\n- recipe-create-expense-tracker: Set up a Google Sheets spreadsheet for tracking expenses with headers and initial entries.\n- recipe-log-deal-update: Append a deal status update to a Google Sheets sales tracking spreadsheet.\n- recipe-review-overdue-tasks: Find Google Tasks that are past due and need attention.\n- gws-calendar: Google Calendar: Manage calendars and events.\n- gws-sheets: Google Sheets: Read and write spreadsheets.\n- gws-docs-write: Google Docs: Append text to a document.\n- recipe-review-meet-participants: Review who attended a Google Meet conference and for how long.\n- persona-content-creator: Create, organize, and distribute content across Workspace.\n- recipe-copy-sheet-for-new-month: Duplicate a Google Sheets template tab for a new month of tracking.\n- recipe-generate-report-from-sheet: Read data from a Google Sheet and create a formatted Google Docs report.\n- gws-tasks: Google Tasks: Manage task lists and tasks.\n- gws-workflow-meeting-prep: Google Workflow: Prepare for your next meeting: agenda, attendees, and linked docs.\n- recipe-create-task-list: Set up a new Google Tasks list with initial tasks.\n- recipe-compare-sheet-tabs: Read data from two tabs in a Google Sheet to compare and identify differences.\n- gws-slides: Google Slides: Read and write presentations.\n- recipe-email-drive-link: Share a Google Drive file and email the link with a message to recipients.\n- gws-sheets-append: Google Sheets: Append a row to a spreadsheet.\n- gws-calendar-agenda: Google Calendar: Show upcoming events across all calendars.\n- persona-it-admin: Administer IT — monitor security and configure Workspace.\n- persona-customer-support: Manage customer support — track tickets, respond, escalate issues.\n- persona-team-lead: Lead a team — run standups, coordinate tasks, and communicate.\n- persona-project-manager: Coordinate projects — track tasks, schedule meetings, and share docs.\n- recipe-create-classroom-course: Create a Google Classroom course and invite students.\n- recipe-create-events-from-sheet: Read event data from a Google Sheets spreadsheet and create Google Calendar entries for each row.\n- persona-hr-coordinator: Handle HR workflows — onboarding, announcements, and employee comms.\n- gws-events-renew: Google Workspace Events: Renew/reactivate Workspace Events subscriptions.\n- gws-gmail-read: Gmail: Read a message and extract its body or headers.\n- recipe-organize-drive-folder: Create a Google Drive folder structure and move files into the right locations.\n- recipe-find-large-files: Identify large Google Drive files consuming storage quota.\n- recipe-batch-invite-to-event: Add a list of attendees to an existing Google Calendar event and send notifications.\n- recipe-block-focus-time: Create recurring focus time blocks on Google Calendar to protect deep work hours.","skillCount":98,"isInitial":true},"type":"attachment","uuid":"d050f190-3b46-4e1e-b9ed-fd0bbc03dc70","timestamp":"2026-04-13T22:19:24.392Z","userType":"external","entrypoint":"cli","cwd":"/Users/pdenya/Code/Linda","sessionId":"6d6efa59-a0f5-4cd8-88e1-cbb8242cea35","version":"2.1.105","gitBranch":"HEAD"}

After (1,363 tokens)

{"parentUuid":"7f9ed23d-6dc2-4e31-ae80-8671c4a1776c","isSidechain":false,"attachment":{"type":"skill_listing","content":"- update-config: Use this skill to configure the Claude Code harness via settings.json. Automated behaviors (\"from now on when X\", \"each time X\", \"whenever X\", \"before/after X\") require hooks configured in settings.json - the harness executes these, not Claude, so memory/preferences cannot fulfill them. Also use for: permissions (\"allow X\", \"add permission\", \"move permission to\"), env vars (\"set X=Y\"), hook troubleshooting, or any changes to settings.json/settings.local.json files. Examples: \"allow npm commands\", \"add bq permission to global settings\", \"move permission to user settings\", \"set DEBUG=true\", \"when claude stops show X\". For simple settings like theme/model, use Config tool.\n- keybindings-help: Use when the user wants to customize keyboard shortcuts, rebind keys, add chord bindings, or modify ~/.claude/keybindings.json. Examples: \"rebind ctrl+s\", \"add a chord shortcut\", \"change the submit key\", \"customize keybindings\".\n- simplify: Review changed code for reuse, quality, and efficiency, then fix any issues found.\n- loop: Run a prompt or slash command on a recurring interval (e.g. /loop 5m /foo). Omit the interval to let the model self-pace. - When the user wants to set up a recurring task, poll for status, or run something repeatedly on an interval (e.g. \"check the deploy every 5 minutes\", \"keep running /babysit-prs\"). Do NOT invoke for one-off tasks.\n- schedule: Create, update, list, or run scheduled remote agents (triggers) that execute on a cron schedule. - When the user wants to schedule a recurring remote agent, set up automated tasks, create a cron job for Claude Code, or manage their scheduled agents/triggers.\n- claude-api: Build, debug, and optimize Claude API / Anthropic SDK apps. Apps built with this skill should include prompt caching.\nTRIGGER when: code imports `anthropic`/`@anthropic-ai/sdk`; user asks for the Claude API, Anthropic SDK, or Managed Agents; user adds/modifies/tunes a Claude feature (caching, thinking, compaction, tool use, batch, files, citations, memory) or model (Opus/Sonnet/Haiku) in a file; questions about prompt caching / cache hit rate in an Anthropic SDK project.\nSKIP: file imports `openai`/other-provider SDK, filename like `*-openai.py`/`*-generic.py`, provider-neutral code, general programming/ML.\n- asc-iap-attach: Attach in-app purchases and subscriptions to an app version for App Store review. Use when the user has IAPs or subscriptions in \"Ready to Submit\" state that need to be included with a first-time version submission. Works for both first-time and subsequent submissions.\n- asc-team-key-create: Create a new App Store Connect Team API Key with Admin permissions, download the one-time .p8 private key, and store it in ~/.blitz. Use when the user needs a new ASC API key for CLI auth, CI/CD, or external tooling.\n- skill-creator: Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.\n- reddit-search: Query Reddit via its public `.json` endpoints (unauthenticated, no API key). Use for post/comment search, thread fetch, subreddit listings, and user history. Includes a `site:reddit.com` fallback through the `google-search` skill when native relevance is insufficient.\n- macos-mail-reader: Query the macOS Mail.app Envelope Index SQLite database with sqlite3 to search, count, and export email metadata. Use when the user wants to read, search, or analyze their local Apple Mail without AppleScript, MCP servers, or third-party tools.\n- asc-privacy-nutrition-labels: Set up App Store privacy nutrition labels (data collection declarations) for an app. Use when the user needs to declare what data their app collects, how it's used, and whether it's linked to the user. Handles both \"no data collected\" and full data collection declarations.\n- review-counsel: Multi-agent code review with specialist reviewers and judge validation\n- playwright-cli: Automates browser interactions for web testing, form filling, screenshots, and data extraction. Use when the user needs to navigate websites, interact with web pages, fill forms, take screenshots, test web applications, or extract information from web pages.\n- tavily-search: AI-powered web search via Tavily API. Returns an AI answer plus extracted page content. Use when the user asks to search the web, research a topic, or find information online.\n- google-search: Search Google using the Custom Search API and display formatted results. Use when the user asks to search the web, look something up, or find information online.\n- gws: Google Workspace toolkit (83 lazy-loaded skills): Gmail, Drive, Calendar, Docs, Sheets, Slides, Chat, Meet, Tasks, Forms, Keep, Classroom, Admin Reports, Events; cross-service workflow/recipe automations (email→task, post-mortem setup, share folder, plan week, backup sheet, etc.); workflow personas (exec-assistant, event-coordinator, sales-ops, researcher, team-lead, project-manager, hr-coordinator, it-admin, customer-support, content-creator). Use whenever the user asks about Google Workspace, Gmail, Drive, Calendar, Docs, Sheets, Slides, Chat, Meet, Tasks, Forms, Keep, Classroom, or a persona/recipe workflow.\n- web-research: Pick and combine web search tools / skills for thorough web research","skillCount":24,"isInitial":true},"type":"attachment","uuid":"91a7712e-a017-4339-be62-b7ad95a98446","timestamp":"2026-04-15T16:15:40.630Z","userType":"external","entrypoint":"cli","cwd":"/Users/pdenya/Code/Linda","sessionId":"508ce92e-6430-4413-819a-00d3ece37879","version":"2.1.109","gitBranch":"HEAD"}