agentleFS
Aias00Aias00/agent-skills/chrome-extension-dev/SKILL.md

chrome-extension-dev

Skill2 starsChanged 8 months agoApache-2.0View on GitHub

Expert Chrome extension development with Manifest V3. Use when creating, building, debugging, or publishing Chrome extensions or browser add-ons. Covers architecture, APIs, security, performance, and best practices. Triggers include Chrome extension, browser extension, browser plugin, Chrome add-on, Manifest V3, content script, background script, extension popup.

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

24 rules. About 0 are common, 11 are distinctive, and 13 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈11

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 13

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill as the primary entry point for extension architecture, implementation, debugging, and local packaging.

    line 12
  2. Distinctive:

    When work reaches release tasks, use companion skills through a single automated publish pipeline:

    line 14
  3. Very specific:

    Use $chrome-extension-publish for Chrome Web Store submission workflow, CWS form answers, permission rationale, privacy-policy decisions, …

    line 16
  4. Very specific:

    Use $chrome-webstore-image-generator for generating and validating store listing images (icon, screenshots, small promo, optional marquee).

    line 17
  5. Very specific:

    Run one-command release pipeline from $chrome-extension-publish:

    line 22
  6. Very specific:

    Only if needed, fine-tune assets and CWS wording manually with $chrome-webstore-image-generator and references/cws-publish-templates.md.

    line 31
  7. Distinctive:

    No remote code execution

    line 89
  8. Very specific:

    Use activeTab instead of broad host permissions

    line 255
  9. Distinctive:

    Use template from assets/templates/

    line 351
  10. Distinctive:

    Add background service worker

    line 374
  11. Distinctive:

    Test on target websites

    line 381
  12. Very specific:

    Prefer deterministic script packaging via $chrome-extension-publish:

    line 387
  13. Distinctive:

    Run one-command full pipeline:

    line 396
  14. Very specific:

    If needed, refine assets with $chrome-webstore-image-generator and adjust wording with …

    line 405
  15. Very specific:

    Use chrome.storage.local for large data (10MB)

    line 425
  16. Very specific:

    Use chrome.storage.sync for settings (100KB limit)

    line 426
  17. Very specific:

    Use chrome.storage.session for temporary data

    line 427
  18. Distinctive:

    Don't rely on global state

    line 432
  19. Very specific:

    Use chrome.storage for persistence

    line 433
  20. Very specific:

    "Could not load extension": Check manifest.json syntax

    line 439
  21. Distinctive:

    "Permission denied": Verify permissions in manifest

    line 441
  22. Distinctive:

    Service worker not running: Check for errors in DevTools Console

    line 445
  23. Very specific:

    Content script not loading: Verify matches patterns in manifest

    line 447
  24. Distinctive:

    Always start with clear requirements, choose minimal permissions, generate custom icons, and test thoroughly before publishing.

    line 472

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Chrome Extension Development

Expert guide for building Chrome extensions using Manifest V3.

Skill Coordination (Full Automation Integration)

Use this skill as the primary entry point for extension architecture, implementation, debugging, and local packaging.

When work reaches release tasks, use companion skills through a single automated publish pipeline:

  • Use $chrome-extension-publish for Chrome Web Store submission workflow, CWS form answers, permission rationale, privacy-policy decisions, and release checklist output.
  • Use $chrome-webstore-image-generator for generating and validating store listing images (icon, screenshots, small promo, optional marquee).

Recommended handoff sequence for end-to-end requests:

  1. Build and verify extension behavior in this skill.
  2. Run one-command release pipeline from $chrome-extension-publish:
python3 scripts/run_full_release_pipeline.py \
  --root /abs/path/to/extension \
  --capture-screenshots \
  --icon-source /abs/path/to/icon.png \
  --include-marquee \
  --headless
  1. Only if needed, fine-tune assets and CWS wording manually with $chrome-webstore-image-generator and references/cws-publish-templates.md.

Quick Start

1. Create Project Structure

my-extension/
├── manifest.json
├── background.js
├── popup.html
├── popup.js
├── content.js
├── content.css
└── icons/
    ├── icon16.png
    ├── icon48.png
    └── icon128.png

The templates in assets/templates/ follow this flat file layout.

2. Basic manifest.json

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0.0",
  "description": "What your extension does",
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "48": "icons/icon48.png"
    }
  },
  "permissions": ["storage", "activeTab", "scripting"]
}

3. Load Unpacked

  1. Open chrome://extensions/
  2. Enable "Developer mode" (top right)
  3. Click "Load unpacked"
  4. Select your extension folder

Core Components

Manifest V3

Required fields:

  • manifest_version: 3
  • name: Extension name
  • version: Version string (e.g., "1.0.0")

Key changes from V2:

  • Service workers replace background pages
  • No remote code execution
  • Enhanced security with CSP
  • New permissions model

Background Service Worker

// background.js
chrome.runtime.onInstalled.addListener(() => {
  console.log('Extension installed');
});

chrome.action.onClicked.addListener((tab) => {
  chrome.tabs.sendMessage(tab.id, {action: 'toggle'});
});

Content Scripts

// content.js
console.log('Content script loaded');

document.querySelectorAll('a').forEach(link => {
  link.style.color = 'red';
});

// Listen for messages
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'toggle') {
    document.body.classList.toggle('dark-mode');
    sendResponse({success: true});
  }
  return true;
});

Popup UI

<!-- popup.html -->
<!DOCTYPE html>
<html>
<head>
  <style>
    body { width: 300px; padding: 16px; }
    button { width: 100%; padding: 8px; }
  </style>
</head>
<body>
  <h2>My Extension</h2>
  <button id="toggle">Toggle Dark Mode</button>
  <script src="popup.js"></script>
</body>
</html>
// popup.js
document.getElementById('toggle').addEventListener('click', async () => {
  const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
  await chrome.tabs.sendMessage(tab.id, {action: 'toggle'});
  window.close();
});

Key APIs

Storage

// Save data
await chrome.storage.local.set({key: 'value'});

// Get data
const result = await chrome.storage.local.get(['key']);
console.log(result.key);

// Listen for changes
chrome.storage.onChanged.addListener((changes, areaName) => {
  console.log('Storage changed:', changes);
});

Tabs

// Query active tab
const [tab] = await chrome.tabs.query({active: true, currentWindow: true});

// Create new tab
await chrome.tabs.create({url: 'https://example.com'});

// Send message to tab
await chrome.tabs.sendMessage(tab.id, {data: 'hello'});

Messaging

One-time message:

// Send
const response = await chrome.runtime.sendMessage({action: 'getData'});

// Receive (background.js)
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'getData') {
    sendResponse({data: 'Hello from background'});
  }
  return true; // Keep channel open for async
});

Long-lived connection:

// Content script
const port = chrome.runtime.connect({name: 'myPort'});
port.postMessage({message: 'Hello'});
port.onMessage.addListener((msg) => console.log(msg));

// Background
chrome.runtime.onConnect.addListener((port) => {
  port.onMessage.addListener((msg) => {
    port.postMessage({response: 'Hi back'});
  });
});

Context Menus

// Create menu
chrome.contextMenus.create({
  id: 'myMenu',
  title: 'My Menu Item',
  contexts: ['selection']
});

// Handle click
chrome.contextMenus.onClicked.addListener((info, tab) => {
  console.log('Selected text:', info.selectionText);
});

Permissions

Common Permissions

{
  "permissions": [
    "storage",
    "activeTab",
    "tabs",
    "contextMenus",
    "alarms",
    "notifications"
  ],
  "host_permissions": [
    "https://*.example.com/*"
  ]
}

Permission Best Practices

  • Use activeTab instead of broad host permissions
  • Request optional permissions at runtime
  • Explain why permissions are needed
// Request at runtime
chrome.permissions.request({
  permissions: ['history'],
  origins: ['https://*.example.com/*']
}, (granted) => {
  if (granted) {
    console.log('Permission granted');
  }
});

Security

Content Security Policy

{
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  }
}

Avoid Inline Scripts

❌ Don't:

<button onclick="doSomething()">Click</button>

✅ Do:

<button id="myButton">Click</button>
<script src="popup.js"></script>
// popup.js
document.getElementById('myButton').addEventListener('click', doSomething);

Sanitize User Input

// Safe
element.textContent = userInput;

// Dangerous - don't use
element.innerHTML = userInput;

Debugging

Background Service Worker

chrome://extensions/ → Click "Service Worker" link → DevTools opens

Content Scripts

Page DevTools → Console (content script logs appear here)

Popup

Right-click extension icon → "Inspect popup"

Storage

DevTools → Application → Storage → Chrome Extension Storage

Common Patterns

See references/patterns.md for 15+ complete patterns including:

  • Page modifier
  • Context menu actions
  • Dynamic content injection
  • Cross-origin API requests
  • OAuth authentication
  • Keyboard shortcuts
  • Badge counter
  • Side panel

Development Workflow

1. Plan Extension

  • Define core functionality
  • Identify required APIs
  • Choose components (popup, content script, background)

2. Create Structure

Use template from assets/templates/

3. Generate Extension Icons

Don't use placeholder icons! Generate professional icons based on your extension's functionality.

See references/icon-generation.md for complete guide including:

  • AI-powered icon generation
  • Design principles for extension icons
  • Prompt templates for different extension types
  • Icon optimization tips

Quick example:

# Generate icon for a "dark mode" extension
infsh app run falai/flux-dev-lora --input '{
  "prompt": "simple icon of a crescent moon on dark background, minimalist design, clean vector style, app icon, professional, high contrast, centered composition, white moon on dark blue background"
}'

4. Implement

  • Start with manifest.json
  • Add background service worker
  • Implement content scripts
  • Build popup UI

5. Test

  • Load unpacked extension
  • Test on target websites
  • Check different scenarios
  • Verify permissions

6. Package

Prefer deterministic script packaging via $chrome-extension-publish:

python3 scripts/package_extension.py --root . --mode manifest --out release/chrome-webstore.zip

7. Publish

  • Pay $5 developer fee
  • Run one-command full pipeline:
python3 scripts/run_full_release_pipeline.py \
  --root /abs/path/to/extension \
  --capture-screenshots \
  --icon-source /abs/path/to/icon.png \
  --include-marquee \
  --headless
  • If needed, refine assets with $chrome-webstore-image-generator and adjust wording with $chrome-extension-publish/references/cws-publish-templates.md.
  • Upload to Chrome Web Store
  • Submit for review (1-3 days)

Performance Tips

Lazy Loading

// Inject only when needed
chrome.action.onClicked.addListener(async (tab) => {
  await chrome.scripting.executeScript({
    target: {tabId: tab.id},
    files: ['content.js']
  });
});

Efficient Storage

  • Use chrome.storage.local for large data (10MB)
  • Use chrome.storage.sync for settings (100KB limit)
  • Use chrome.storage.session for temporary data

Service Worker Lifecycle

  • Service workers wake up on events, then go dormant
  • Don't rely on global state
  • Use chrome.storage for persistence

Troubleshooting

Common Issues

"Could not load extension": Check manifest.json syntax

"Permission denied": Verify permissions in manifest

"Message channel closed": Return true from message listener for async responses

Service worker not running: Check for errors in DevTools Console

Content script not loading: Verify matches patterns in manifest

Resources

  • Manifest V3 Reference: references/manifest-v3.md
  • API Reference: references/api-reference.md
  • Common Patterns: references/patterns.md
  • Icon Generation Guide: references/icon-generation.md ⭐
  • Templates: assets/templates/

When to Use This Skill

Use when:

  • Creating new Chrome extensions
  • Migrating from Manifest V2 to V3
  • Debugging extension issues
  • Implementing Chrome APIs
  • Publishing to Chrome Web Store
  • Optimizing extension performance
  • Generating professional extension icons ⭐

Route to companion skills when needed:

  • $chrome-webstore-image-generator: deterministic CWS image generation/validation
  • $chrome-extension-publish: CWS submission text, policy alignment, and release gate checks

Always start with clear requirements, choose minimal permissions, generate custom icons, and test thoroughly before publishing.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.