Compare commits

..

140 Commits

Author SHA1 Message Date
github-actions[bot]
800dc51041 chore: sync generated registry files [ci skip] 2026-02-08 10:02:49 +00:00
sck_0
ebaa824d74 chore: release v4.11.0
- Updated CHANGELOG.md with v4.11.0 release notes
- Bumped version to 4.11.0 in package.json
2026-02-08 11:02:32 +01:00
sck_0
dc6f3c51e5 feat: update clean-code skill and stabilize registry (#69)
- Updated clean-code skill with Robert C. Martin's Clean Code principles
- Refined content: naming, functions, comments, error handling, class design
- Fixed invalid heading format (## ## When to Use -> ## When to Use)
- Stabilized registry: use SOURCE_DATE_EPOCH for deterministic CI builds
- Improved catalog sorting for cross-environment consistency
- Regenerated all catalog and index files

Co-authored-by: jackjin1997 <jackjin1997@users.noreply.github.com>
2026-02-08 11:02:14 +01:00
github-actions[bot]
2675db4d2f chore: update star history chart 2026-02-08 06:44:43 +00:00
github-actions[bot]
9c4724fb71 chore: update star history chart 2026-02-07 06:38:10 +00:00
github-actions[bot]
e94d250e55 chore: sync generated registry files [ci skip] 2026-02-06 08:53:44 +00:00
sck_0
29e6cf6966 docs(readme): increase support CTA visibility 2026-02-06 09:53:27 +01:00
github-actions[bot]
6fc7543a96 chore: sync generated registry files [ci skip] 2026-02-06 08:50:37 +00:00
sck_0
b85ba3500f docs(readme): make support section transparent and community-first 2026-02-06 09:50:22 +01:00
github-actions[bot]
4419102cc9 chore: sync generated registry files [ci skip] 2026-02-06 08:32:28 +00:00
sck_0
41cd889ebd docs(readme): clarify curated collections and bundle usage 2026-02-06 09:32:08 +01:00
github-actions[bot]
c12f68780b chore: sync generated registry files [ci skip] 2026-02-06 08:28:40 +00:00
sck_0
f4b23f7480 docs(bundles): refresh usage guidance and add maintainer packs 2026-02-06 09:28:25 +01:00
github-actions[bot]
4df02e8068 chore: sync generated registry files [ci skip] 2026-02-06 08:13:24 +00:00
sck_0
3c899d01f2 docs(readme): reorder sections for onboarding flow 2026-02-06 09:13:08 +01:00
github-actions[bot]
b7a64f7b3b chore: sync generated registry files [ci skip] 2026-02-06 08:08:49 +00:00
sck_0
d556615959 docs(readme): improve quick start and add troubleshooting 2026-02-06 09:08:25 +01:00
github-actions[bot]
67a3d81894 chore: sync generated registry files [ci skip] 2026-02-06 07:59:29 +00:00
sck_0
b690d7beb2 docs(release): expand 4.10.0 notes with detailed scope 2026-02-06 08:59:13 +01:00
github-actions[bot]
03c6270dc6 chore: sync generated registry files [ci skip] 2026-02-06 07:53:06 +00:00
sck_0
69e1545618 chore(release): 4.10.0 2026-02-06 08:52:45 +01:00
github-actions[bot]
4dcc4b29b0 chore: sync generated registry files [ci skip] 2026-02-06 07:49:30 +00:00
Nguyễn Văn Chán
797bf03dd1 Added detailed documentation for .NET/C# backend developer skills, including expertise, responsibilities, code patterns, and best practices. (#65)
* Create SKILL.md for .NET backend developer

Added detailed documentation for .NET/C# backend developer skills, including expertise, responsibilities, code patterns, and best practices.

* fix(dotnet-backend): add quality bar metadata and usage sections

---------

Co-authored-by: sck_0 <samujackson1337@gmail.com>
2026-02-06 08:49:07 +01:00
github-actions[bot]
1b2bed231d chore: sync generated registry files [ci skip] 2026-02-06 07:44:10 +00:00
Soham
45e5ebbdbd Add 78 Composio app automation skills via Rube MCP (#64)
Production-ready automation skills for 78 SaaS apps covering CRM,
project management, communication, email, DevOps, storage, and more.
Each skill includes workflow patterns, tool sequences, known pitfalls,
and quick reference tables.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 08:43:50 +01:00
github-actions[bot]
0824bef4ba chore: update star history chart 2026-02-06 06:51:12 +00:00
github-actions[bot]
c124b3b174 chore: sync generated registry files [ci skip] 2026-02-05 08:27:17 +00:00
sck_0
b328c91767 docs: enforce gh release create in maintenance guide 2026-02-05 09:26:56 +01:00
github-actions[bot]
31f1697e28 chore: sync generated registry files [ci skip] 2026-02-05 08:20:57 +00:00
sck_0
a58aa5628c docs: update contributors list 2026-02-05 09:20:37 +01:00
github-actions[bot]
7eabe62ae8 chore: sync generated registry files [ci skip] 2026-02-05 08:14:33 +00:00
sck_0
37684d0fed 4.9.0 2026-02-05 09:14:07 +01:00
sck_0
601649074d docs: update changelog for 4.9.0 2026-02-05 09:14:06 +01:00
sck_0
a648e1adb7 Merge PR #62: Add CLI AI Skills (Resolved Conflicts via Regeneration) 2026-02-05 09:13:35 +01:00
github-actions[bot]
2a88369687 chore: sync generated registry files [ci skip] 2026-02-05 08:12:43 +00:00
sickn33
1a60d58ba0 Merge pull request #61 from jackjin1997/main
feat: add OSS Hunter skill for automated contribution hunting
2026-02-05 09:12:23 +01:00
github-actions[bot]
d1a14dfab9 chore: update star history chart 2026-02-05 06:55:35 +00:00
Eric Andrade
621dbe008e fix: propagate exit codes in youtube-summarizer --list mode
Fixed automation-breaking issue where --list mode always returned exit code 0,
even when list_available_transcripts() failed due to invalid video ID or network errors.

Changes:
- extract-transcript.py: Capture return value and exit with proper status code
  - Before: list_available_transcripts(video_id); sys.exit(0)
  - After: success = list_available_transcripts(video_id); sys.exit(0 if success else 1)
- SKILL.md: Bumped version to 1.2.1
- CHANGELOG.md: Created changelog with v1.2.1 release notes

Impact: Automation scripts can now detect failures correctly via exit codes.

Identified by Codex automated review in antigravity-awesome-skills PR #62.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-04 18:47:37 -03:00
Eric Andrade
eb493121d3 fix: remove unsafe file deletion in audio-transcriber cleanup
Remove cleanup_temp_files() function that was deleting fixed-name files
(metadata.json, transcription.json) without verifying script ownership.

This addresses security concern raised by Codex review:
- Risk: Could delete user's existing files with same names
- Solution: Removed cleanup since no temp JSON files are actually created

Changes:
- Remove cleanup_temp_files() function entirely
- Remove --keep-temp argument (no longer needed)
- Remove all cleanup_temp_files() calls

Fixes #62 (review comment)
2026-02-04 18:35:17 -03:00
Eric Andrade
801c8fa475 feat: add 4 universal skills from cli-ai-skills
- Add audio-transcriber skill (v1.2.0): Transform audio to Markdown with Whisper
- Add youtube-summarizer skill (v1.2.0): Generate summaries from YouTube videos
- Update prompt-engineer skill: Enhanced with 11 optimization frameworks
- Update skill-creator skill: Improved automation workflow

All skills are zero-config, cross-platform (Claude Code, Copilot CLI, Codex)
and follow Quality Bar V4 standards.

Source: https://github.com/ericgandrade/cli-ai-skills
2026-02-04 17:37:45 -03:00
JackJin
cf00d4fcca feat: add OSS Hunter skill for automated contribution hunting 2026-02-05 01:30:29 +08:00
github-actions[bot]
6070da6a63 chore: sync generated registry files [ci skip] 2026-02-04 08:08:21 +00:00
sck_0
fd9b119040 chore: sync skills_index.json 2026-02-04 09:07:00 +01:00
sck_0
ca2551fe2b fix: resolve YAML syntax errors and harden CI workflow 2026-02-04 09:07:00 +01:00
github-actions[bot]
0da99cd2c9 chore: sync generated registry files [ci skip] 2026-02-04 07:59:22 +00:00
sck_0
ce852bed63 docs: update contributors list 2026-02-04 08:58:45 +01:00
github-actions[bot]
53671205f0 chore: sync generated registry files [ci skip] 2026-02-04 07:53:25 +00:00
sck_0
ac20cc63b6 chore(release): v4.8.0 - Computer Vision & Angular 2026-02-04 08:52:08 +01:00
github-actions[bot]
e1c84cd8f4 chore: sync generated registry files [ci skip] 2026-02-04 07:49:25 +00:00
sickn33
73e51321ca Merge pull request #60 from chauey/main
feat: add angular
2026-02-04 08:49:08 +01:00
sickn33
eca46228ed Merge pull request #58 from PabloSMD/main
feat(skills): add computer-vision-expert (SOTA 2026: YOLO26, SAM 3)
2026-02-04 08:48:51 +01:00
Chau (Joe) Nguyen
aa164fac16 fix(angular): Add risk and source fields to meet quality bar requirements 2026-02-04 01:25:24 -06:00
Chau (Joe) Nguyen
6247fcefab fix(angular): Clean up formatting and fix JSX example in README
- Remove duplicate horizontal rules in angular/SKILL.md
- Remove duplicate horizontal rules in angular-best-practices/SKILL.md
- Fix React-style JSX in angular-ui-patterns/README.md to use Angular template syntax
2026-02-04 00:51:34 -06:00
Chau (Joe) Nguyen
b46e45fb4d feat(angular): Add metadata.json and README.md to all Angular skills
- Add metadata.json with version tracking, organization, and references
- Add README.md with skill overviews, usage guides, and quick references
- Brings Angular skills to parity with React Best Practices infrastructure
- Covers: angular, angular-state-management, angular-ui-patterns, angular-best-practices
2026-02-04 00:48:55 -06:00
github-actions[bot]
8839ed1b2d chore: update star history chart 2026-02-04 06:47:07 +00:00
Chau (Joe) Nguyen
5ba1fe9a97 feat(skills): enhance Angular skills with Composition and Async Waterfalls
- Add Component Composition & Reusability section to angular/SKILL.md
  - Content Projection with ng-content and select
  - Host Directives for behavior composition

- Add Async Operations & Waterfalls section to angular-best-practices/SKILL.md
  - Parallel execution with forkJoin
  - Flattening with switchMap
  - SSR waterfall prevention with resolvers
2026-02-04 00:35:31 -06:00
Chau (Joe) Nguyen
85f26eb186 feat: Introduce new skill documentation for Angular UI patterns, general Angular, best practices, and state management. 2026-02-03 21:33:08 -06:00
Pablo
0fc520c7fe feat(skills): add computer-vision-expert (SOTA 2026: YOLO26, SAM 3) 2026-02-03 17:16:04 -03:00
github-actions[bot]
7f5ca000bd chore: sync generated registry files [ci skip] 2026-02-03 18:45:56 +00:00
sck_0
679eb72d23 docs: add ASK Supported badge (ref #56) 2026-02-03 19:45:38 +01:00
github-actions[bot]
2b3277c066 chore: sync generated registry files [ci skip] 2026-02-03 18:38:42 +00:00
sck_0
850c940dfd chore: sync generated files 2026-02-03 19:38:23 +01:00
sck_0
1bc750e4a1 fix: obfuscate regex to prevent css build error (fixes #54) 2026-02-03 19:38:22 +01:00
github-actions[bot]
84a41851e0 chore: sync generated registry files [ci skip] 2026-02-03 18:33:36 +00:00
sck_0
6d94cf984c chore: sync generated files 2026-02-03 19:33:01 +01:00
liyin2015
129949ddf0 fix: correct AdaL CLI information
Fix several inaccuracies in AdaL entry:
- Type: Agent → CLI (AdaL is a CLI tool like Claude Code)
- Badge: HumanSignal/Adala → SylphAI (correct company)
- Description: Self-evolving AI Agent → Self-evolving Coding Agent
- Invocation: Auto (skills load on-demand when relevant)
- Path: .agent/skills/ → .adal/skills/

AdaL CLI is fully compatible with Claude Code skills and uses the same
slash command pattern for skill invocation.

Ref: https://docs.sylph.ai/docs/features/plugins-and-skills

Co-Authored-By: AdaL <adal@sylph.ai>
2026-02-03 10:27:27 -08:00
github-actions[bot]
f893807051 chore: sync generated registry files [ci skip] 2026-02-03 09:20:12 +00:00
sck_0
9040899e65 chore: remove obsolete requirements.txt 2026-02-03 10:19:54 +01:00
github-actions[bot]
b29fa15bf3 chore: sync generated registry files [ci skip] 2026-02-03 08:57:56 +00:00
sck_0
b05245e68b chore: release v4.7.0 2026-02-03 09:57:09 +01:00
github-actions[bot]
49e01dd216 chore: sync generated registry files [ci skip] 2026-02-03 08:46:32 +00:00
sck_0
460a8432a5 docs: complete OpenCode documentation in README 2026-02-03 09:46:14 +01:00
github-actions[bot]
878b876475 chore: sync generated registry files [ci skip] 2026-02-03 08:43:12 +00:00
sck_0
189c0824d2 fix(docs): revert verbose OpenCode instructions and sync catalog 2026-02-03 09:33:46 +01:00
github-actions[bot]
67e7e998f8 chore: sync generated registry files [ci skip] 2026-02-03 08:12:40 +00:00
sck_0
4432e60445 docs: add OpenCode install section 2026-02-03 09:12:25 +01:00
github-actions[bot]
b71eff117b chore: sync generated registry files [ci skip] 2026-02-03 09:08:17 +01:00
fabian
991de2de2f fix(installer): resolve ReferenceError for tagArg variable in main scope 2026-02-03 09:08:17 +01:00
github-actions[bot]
73ceec4e7d chore: update star history chart 2026-02-03 06:46:36 +00:00
sck_0
263c507684 chore: SOTA audit fixes – catalog recursive, readme regex, docs, CI, installer
- P0: Catalog includes nested skills (listSkillIdsRecursive), 626 skills
- P0: update_readme.py regex fixes 'high-performance agentic skills'
- P1: SKILL_ANATOMY risk values aligned to none|safe|critical|offensive (EN + vi)
- P1: requirements.txt + CONTRIBUTING Python setup
- P1: data/package.json version 4.6.0
- P2: npm run test + CI test step; validator docs + validation-baseline in .gitignore
- P3: Installer --version/--tag support; CI npm audit; __pycache__ in .gitignore
2026-02-02 22:04:20 +01:00
sck_0
afc06d1af6 Merge branch 'codex/validator-alignment' 2026-02-02 21:43:27 +01:00
sck_0
988f528708 chore: ignore worktrees 2026-02-02 21:42:29 +01:00
sck_0
3f7dce00b8 chore: preserve risk/source and document use-section headings 2026-02-02 21:37:53 +01:00
sck_0
3d6c75d37f test: align js validator use-section rules 2026-02-02 21:37:05 +01:00
sck_0
2070a91ef7 test: add python validator heading detection 2026-02-02 21:34:14 +01:00
sck_0
17505fe683 chore: ignore worktrees 2026-02-02 21:15:53 +01:00
github-actions[bot]
f9f4375e4e chore: sync generated registry files [ci skip] 2026-02-02 18:58:37 +00:00
sck_0
637c20f3c3 feat: add codex cli install support 2026-02-02 19:56:03 +01:00
github-actions[bot]
72f5b9500d chore: sync generated registry files [ci skip] 2026-02-02 07:24:12 +00:00
sck_0
bedfbb5c1c docs: reorder contributors list to match contrib.rocks order
- Reorder contributors according to GitHub API order (same as contrib.rocks)
- Fix GitHub usernames in URLs (sck_0→sck000, munirabbasi→munir-abbasi, etc.)
- Add missing contributors: ALEKGG1, Truong Nguyen, ckdwns9121, liyin2015, sstklen
2026-02-02 08:23:52 +01:00
github-actions[bot]
318199e9b3 chore: sync generated registry files [ci skip] 2026-02-02 07:22:06 +00:00
sck_0
cafa9d5c52 docs: add contrib.rocks image to Repo Contributors section 2026-02-02 08:21:50 +01:00
github-actions[bot]
963e4660c8 chore: sync generated registry files [ci skip] 2026-02-02 07:19:31 +00:00
sickn33
49f1bf1335 Merge pull request #50 from liyin2015/add-adal-cli
docs: add AdaL to compatible AI coding agents
2026-02-02 08:19:16 +01:00
github-actions[bot]
d6eefe200d chore: sync generated registry files [ci skip] 2026-02-02 07:14:34 +00:00
sck_0
41717e78db docs: add AdaL to supported platforms list
- Add AdaL (Self-evolving AI Agent) to platforms bullet list
- Update subtitle to include AdaL
- Add AdaL badge with link to GitHub repository
- Add AdaL row to compatibility table
- Update prose mentions to include AdaL

Implements PR #50
2026-02-02 08:14:18 +01:00
github-actions[bot]
2a016df011 chore: update star history chart 2026-02-02 06:59:44 +00:00
liyin2015
386b3c757e docs: add AdaL to compatible AI coding agents 2026-02-01 17:48:23 -08:00
github-actions[bot]
3d79501eba chore: sync generated registry files [ci skip] 2026-02-01 16:52:16 +00:00
sck_0
7e24ed2568 chore: npm publish setup, fallback docs, release workflow (fixes #49)
- package.json: yaml in devDependencies, repo url/bin from npm pkg fix
- README, GETTING_STARTED, FAQ: fallback npx github:sickn33/antigravity-awesome-skills on 404
- publish-npm.yml: workflow on release published + workflow_dispatch
- MAINTENANCE: bump package.json, publish to npm (manual + NPM_TOKEN CI)
- release_cycle.sh: catalog step, version check, npm publish reminder
- ISSUE_49_COMMENT.md: suggested reply for issue #49
2026-02-01 17:52:01 +01:00
github-actions[bot]
418982eb85 chore: sync generated registry files [ci skip] 2026-02-01 07:25:50 +00:00
sck_0
335359f138 docs: sync Repo Contributors and skill counts (626) post 4.6.0
- Add c1c3ru and devchangjun to Repo Contributors (PR 47, PR 48)
- Update GETTING_STARTED.md and FAQ.md: 624/624+ -> 626/626+
2026-02-01 08:25:34 +01:00
github-actions[bot]
4ec91e9fbe chore: sync generated registry files [ci skip] 2026-02-01 07:23:19 +00:00
sck_0
db3e262df3 chore(release): 4.6.0 - SPDD & Radix UI Design System
- Bump version to 4.6.0, update CHANGELOG and README counts to 626
- Fix listSkillIds to only include dirs with SKILL.md (SPDD excluded from catalog)
- Regenerate catalog and index after PR 47/48 merge
2026-02-01 08:23:00 +01:00
sickn33
d280ad1c3a Merge pull request #47 from c1c3ru/main
feat: Adiciona novas habilidades de agente para pesquisa de base de código, planejamento de implementação e execução.
2026-02-01 08:21:30 +01:00
sickn33
b2aa003d57 Merge pull request #48 from ckdwns9121/feat/redix-ui-design-system-skills
feat: add radix UI design system skill
2026-02-01 08:21:26 +01:00
github-actions[bot]
3c3280d9ac chore: update star history chart 2026-02-01 06:44:42 +00:00
devchangjun
58f8d654ef feat: introduce Radix UI design system skill with a component template and examples. 2026-02-01 11:36:47 +09:00
c1c3ru
5593cad434 feat: Adiciona novas habilidades de agente para pesquisa de base de código, planejamento de implementação e execução. 2026-01-31 22:25:14 -03:00
github-actions[bot]
59151b3671 chore: sync generated registry files [ci skip] 2026-01-31 22:04:25 +00:00
sck_0
1dc10ee3a0 fix(frontend-slides): correct YAML frontmatter syntax (fixes #46)
Remove Markdown content from frontmatter block; keep only valid YAML
keys (name, description, source, risk) to resolve 'mapping values are
not allowed in this context at line 5 column 5'.
2026-01-31 23:04:09 +01:00
github-actions[bot]
4c400ca121 chore: sync generated registry files [ci skip] 2026-01-31 07:45:51 +00:00
sck_0
4310ca4922 docs: merge RELEASE_NOTES into CHANGELOG, single source for releases 2026-01-31 08:45:34 +01:00
github-actions[bot]
9f6d75245f chore: sync generated registry files [ci skip] 2026-01-31 07:40:22 +00:00
sck_0
1974e62ec1 docs: add @ALEKGG1 credit for stitch-ui-design skill (PR #45) 2026-01-31 08:40:11 +01:00
github-actions[bot]
9dd8fd6b51 chore: sync generated registry files [ci skip] 2026-01-31 07:36:24 +00:00
sck_0
b082ba9c42 chore: regenerate files after merge 2026-01-31 08:36:01 +01:00
sck_0
90b4d5adb3 Merge branch 'main' of https://github.com/sickn33/antigravity-awesome-skills
# Conflicts:
#	CATALOG.md
#	data/aliases.json
#	data/bundles.json
#	data/catalog.json
#	skills_index.json
2026-01-31 08:35:45 +01:00
sck_0
87989fecf6 chore: release 4.5.0 - stitch-ui-design skill 2026-01-31 08:35:02 +01:00
sck_0
f41aad3556 feat: add stitch-ui-design skill and sync generated files 2026-01-31 08:34:33 +01:00
github-actions[bot]
d3883ffaf9 chore: sync generated registry files [ci skip] 2026-01-31 07:34:11 +00:00
@ALEKGG
cf8b63cd15 feat: add stitch-ui-design skill for Google Stitch prompting (#45)
Add comprehensive skill for creating effective prompts in Google Stitch,
the AI-powered UI design tool by Google Labs (Gemini 2.5 Flash).

Includes:
- Core prompting principles and templates
- 10+ practical examples (landing pages, mobile apps, dashboards)
- Iteration strategies and anti-patterns
- Design-to-code workflows
- 44KB of reference documentation

Category: Data & AI / General
Risk: Low (design guidance, no executable commands)
2026-01-31 08:33:51 +01:00
sck_0
bb0886a594 docs: clarify Starter Packs vs full clone (fixes #44) 2026-01-31 08:33:37 +01:00
github-actions[bot]
d2f3423a13 chore: update star history chart 2026-01-31 06:35:01 +00:00
github-actions[bot]
a7c8432a47 chore: sync generated registry files [ci skip] 2026-01-30 19:35:13 +00:00
sck_0
bedac72820 docs: sync Repo Contributors, Credits, SOURCES, and skill count (624) post v4.4.0 2026-01-30 20:34:57 +01:00
github-actions[bot]
fc45245400 chore: sync generated registry files [ci skip] 2026-01-30 19:30:23 +00:00
sck_0
4acf69d80e chore: release 4.4.0 - add fp-ts skills (PR #43) 2026-01-30 20:29:59 +01:00
github-actions[bot]
aaee268672 chore: sync generated registry files [ci skip] 2026-01-30 19:28:08 +00:00
Kadu Maverick
cb9f1b1a4e feat: add fp-ts skills for TypeScript functional programming (#43)
Add three practical fp-ts skills:
- fp-ts-pragmatic: The 80/20 of functional programming, jargon-free
- fp-ts-react: Patterns for using fp-ts with React 18/19 and Next.js
- fp-ts-errors: Type-safe error handling with Either and TaskEither

Source: https://github.com/whatiskadudoing/fp-ts-skills

Co-authored-by: kadu-maverickk <maycon.guedes@itglobers.com>
2026-01-30 20:27:51 +01:00
github-actions[bot]
8b523ccc54 chore: sync generated registry files [ci skip] 2026-01-30 08:24:50 +00:00
sck_0
b831384713 chore: remove temporary analysis files and update .gitignore
- Removed temporary report files (*_REPORT.md, *_COUNT.md)
- Removed temporary JSON analysis files
- Removed temporary analysis scripts
- Added patterns to .gitignore to prevent future commits
2026-01-30 09:24:33 +01:00
sck_0
2128d7b256 chore: resolve merge conflicts and sync generated files [ci skip] 2026-01-30 09:21:51 +01:00
sck_0
10bc6d37d7 chore: sync generated registry files [ci skip] 2026-01-30 09:21:33 +01:00
github-actions[bot]
a53052fcb1 chore: sync generated registry files [ci skip] 2026-01-30 08:18:19 +00:00
sck_0
a53a16e24a docs: add VoltAgent to Credits & Sources section 2026-01-30 09:18:03 +01:00
sck_0
2250f88e89 docs: update README with correct skill count (614) and add VoltAgent to Credits
- Updated all skill count references from 621 to 614
- Added VoltAgent/awesome-agent-skills to Credits & Sources section
- All skill count references now consistent
2026-01-30 09:17:58 +01:00
github-actions[bot]
6b377e8549 chore: sync generated registry files [ci skip] 2026-01-30 08:16:36 +00:00
sck_0
92e90552e0 chore: sync generated registry files after merge 2026-01-30 09:15:50 +01:00
github-actions[bot]
4e1ba66df9 chore: sync generated registry files [ci skip] 2026-01-30 07:35:12 +00:00
179 changed files with 34657 additions and 9662 deletions

15
.github/ISSUE_49_COMMENT.md vendored Normal file
View File

@@ -0,0 +1,15 @@
Suggested comment for [Issue #49](https://github.com/sickn33/antigravity-awesome-skills/issues/49). Paste this on the issue:
---
The 404 happens because the package wasnt published to npm yet. Weve addressed it in two ways:
1. **Publish to npm** Were set up to publish so `npx antigravity-awesome-skills` will work after the first release. You can also trigger a manual publish via the “Publish to npm” workflow (Actions tab) if you have `NPM_TOKEN` configured.
2. **Fallback** Until then (or if you hit a 404 for any reason), use:
```bash
npx github:sickn33/antigravity-awesome-skills
```
The README, GETTING_STARTED, and FAQ now mention this fallback.
Thanks for reporting.

View File

@@ -41,7 +41,7 @@ it means you **did not run or commit** the Validation Chain correctly.
### 3. 📝 EVIDENCE OF WORK
- You must create/update `walkthrough.md` or `RELEASE_NOTES.md` to document what changed.
- You must create/update `walkthrough.md` or `CHANGELOG.md` to document what changed.
- If you made something new, **link it** in the artifacts.
### 4. 🚫 NO BRANCHES
@@ -172,20 +172,38 @@ Reject any PR that fails this:
When cutting a new version (e.g., V4):
1. **Run Full Validation**: `python3 scripts/validate_skills.py --strict`
2. **Update Changelog**: Create `RELEASE_NOTES.md`.
3. **Bump Version**: Update header in `README.md`.
4. **Tag Release**:
2. **Update Changelog**: Add the new release section to `CHANGELOG.md`.
3. **Bump Version**:
- Update `package.json` → `"version": "X.Y.Z"` (source of truth for npm).
- Update version header in `README.md` if it displays the number.
- One-liner: `npm version patch` (or `minor`/`major`) — bumps `package.json` and creates a git tag; then amend if you need to tag after release.
4. **Create GitHub Release** (REQUIRED):
> ⚠️ **CRITICAL**: Pushing a tag (`git push --tags`) is NOT enough. You must create a **GitHub Release Object** for it to appear in the sidebar and trigger the NPM publish workflow.
Use the GitHub CLI:
```bash
git tag -a v4.0.0 -m "V4 Enterprise Edition"
git push origin v4.0.0
# This creates the tag AND the release page automatically
gh release create v4.0.0 --title "v4.0.0 - [Theme Name]" --notes-file release_notes.md
```
### 📋 Release Note Template
_Or manually via the GitHub UI > Releases > Draft a new release._
All changeslogs/release notes MUST follow this structure to ensure professionalism and quality:
5. **Publish to npm** (so `npx antigravity-awesome-skills` works):
- **Option A (manual):** From repo root, with npm logged in and 2FA/token set up:
```bash
npm publish
```
You cannot republish the same version; always bump `package.json` before publishing.
- **Option B (CI):** On GitHub, create a **Release** (tag e.g. `v4.6.1`). The workflow [Publish to npm](.github/workflows/publish-npm.yml) runs on **Release published** and runs `npm publish` if the repo secret `NPM_TOKEN` is set (npm → Access Tokens → Granular token with Publish, then add as repo secret `NPM_TOKEN`).
### 📋 Changelog Entry Template
Each new release section in `CHANGELOG.md` should follow [Keep a Changelog](https://keepachangelog.com/) and this structure:
```markdown
# Release vX.Y.Z: [Theme Name]
## [X.Y.Z] - YYYY-MM-DD - "[Theme Name]"
> **[One-line catchy summary of the release]**

View File

@@ -45,6 +45,13 @@ jobs:
- name: Install npm dependencies
run: npm ci
- name: Audit npm dependencies
run: npm audit --audit-level=high
continue-on-error: true
- name: Run tests
run: npm run test
- name: 📦 Build catalog
run: npm run catalog
@@ -61,6 +68,9 @@ jobs:
# If no changes, exit successfully
git diff --quiet && exit 0
# Pull with rebase to integrate remote changes
git pull origin main --rebase || true
git add README.md skills_index.json data/catalog.json data/bundles.json data/aliases.json CATALOG.md || true
# If nothing to commit, exit successfully

28
.github/workflows/publish-npm.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# Publish antigravity-awesome-skills to npm on release.
# Requires NPM_TOKEN secret (npm → Access Tokens → Granular token with Publish).
# Before creating a Release: bump package.json "version" (npm forbids republishing the same version).
# Release tag (e.g. v4.6.1) should match package.json version.
name: Publish to npm
on:
release:
types: [published]
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Publish
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

24
.gitignore vendored
View File

@@ -1,7 +1,31 @@
node_modules/
__pycache__/
.worktrees/
walkthrough.md
.agent/rules/
.gemini/
LOCAL_CONFIG.md
data/node_modules
# Temporary analysis and report files
*_REPORT.md
*_ANALYSIS*.md
*_COUNT.md
*_SUMMARY.md
*_analysis.json
*_validation.json
*_results.json
voltagent_*.json
similar_skills_*.json
remaining_*.json
html_*.json
# Temporary analysis scripts
scripts/*voltagent*.py
scripts/*html*.py
scripts/*similar*.py
scripts/*count*.py
# Optional baseline for legacy JS validator (scripts/validate-skills.js)
validation-baseline.json

View File

@@ -1,13 +1,15 @@
# Skill Catalog
Generated at: 2026-01-30T08:15:03.985Z
Generated at: 2026-02-08T10:02:49.626Z
Total skills: 614
Total skills: 713
## architecture (58)
## architecture (63)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
| `angular` | Modern Angular (v20+) expert with deep knowledge of Signals, Standalone Components, Zoneless applications, SSR/Hydration, and reactive patterns. Use PROACTIV... | angular | angular, v20, deep, knowledge, signals, standalone, components, zoneless, applications, ssr, hydration, reactive |
| `angular-state-management` | Master modern Angular state management with Signals, NgRx, and RxJS. Use when setting up global state, managing component stores, choosing between state solu... | angular, state | angular, state, signals, ngrx, rxjs, setting, up, global, managing, component, stores, choosing |
| `architect-review` | Master software architect specializing in modern architecture patterns, clean architecture, microservices, event-driven systems, and DDD. Reviews system desi... | | architect, review, software, specializing, architecture, clean, microservices, event, driven, ddd, reviews, designs |
| `architecture` | Architectural decision-making framework. Requirements analysis, trade-off evaluation, ADR documentation. Use when making architecture decisions or analyzing ... | architecture | architecture, architectural, decision, making, framework, requirements, analysis, trade, off, evaluation, adr, documentation |
| `architecture-decision-records` | Write and maintain Architecture Decision Records (ADRs) following best practices for technical decision documentation. Use when documenting significant techn... | architecture, decision, records | architecture, decision, records, write, maintain, adrs, following, technical, documentation, documenting, significant, decisions |
@@ -21,6 +23,7 @@ Total skills: 614
| `c4-code` | Expert C4 Code-level documentation specialist. Analyzes code directories to create comprehensive C4 code-level documentation including function signatures, a... | c4, code | c4, code, level, documentation, analyzes, directories, including, function, signatures, arguments, dependencies, structure |
| `c4-component` | Expert C4 Component-level documentation specialist. Synthesizes C4 Code-level documentation into Component-level architecture, defining component boundaries,... | c4, component | c4, component, level, documentation, synthesizes, code, architecture, defining, boundaries, interfaces, relationships, creates |
| `c4-context` | Expert C4 Context-level documentation specialist. Creates high-level system context diagrams, documents personas, user journeys, system features, and externa... | c4 | c4, context, level, documentation, creates, high, diagrams, documents, personas, user, journeys, features |
| `calendly-automation` | Automate Calendly scheduling, event management, invitee tracking, availability checks, and organization administration via Rube MCP (Composio). Always search... | calendly | calendly, automation, automate, scheduling, event, invitee, tracking, availability, checks, organization, administration, via |
| `code-refactoring-refactor-clean` | You are a code refactoring expert specializing in clean code principles, SOLID design patterns, and modern software engineering best practices. Analyze and r... | code, refactoring, refactor, clean | code, refactoring, refactor, clean, specializing, principles, solid, software, engineering, analyze, provided, improve |
| `codebase-cleanup-refactor-clean` | You are a code refactoring expert specializing in clean code principles, SOLID design patterns, and modern software engineering best practices. Analyze and r... | codebase, cleanup, refactor, clean | codebase, cleanup, refactor, clean, code, refactoring, specializing, principles, solid, software, engineering, analyze |
| `competitor-alternatives` | When the user wants to create competitor comparison or alternative pages for SEO and sales enablement. Also use when the user mentions 'alternative page,' 'v... | competitor, alternatives | competitor, alternatives, user, wants, comparison, alternative, pages, seo, sales, enablement, mentions, page |
@@ -36,6 +39,7 @@ Total skills: 614
| `error-handling-patterns` | Master error handling patterns across languages including exceptions, Result types, error propagation, and graceful degradation to build resilient applicatio... | error, handling | error, handling, languages, including, exceptions, result, types, propagation, graceful, degradation, resilient, applications |
| `event-sourcing-architect` | Expert in event sourcing, CQRS, and event-driven architecture patterns. Masters event store design, projection building, saga orchestration, and eventual con... | event, sourcing | event, sourcing, architect, cqrs, driven, architecture, masters, store, projection, building, saga, orchestration |
| `event-store-design` | Design and implement event stores for event-sourced systems. Use when building event sourcing infrastructure, choosing event store technologies, or implement... | event, store | event, store, stores, sourced, building, sourcing, infrastructure, choosing, technologies, implementing, persistence |
| `game-development/multiplayer` | Multiplayer game development principles. Architecture, networking, synchronization. | game, development/multiplayer | game, development/multiplayer, multiplayer, development, principles, architecture, networking, synchronization |
| `godot-gdscript-patterns` | Master Godot 4 GDScript patterns including signals, scenes, state machines, and optimization. Use when building Godot games, implementing game systems, or le... | godot, gdscript | godot, gdscript, including, signals, scenes, state, machines, optimization, building, games, implementing, game |
| `haskell-pro` | Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programm... | haskell | haskell, pro, engineer, specializing, type, pure, functional, high, reliability, software, proactively, level |
| `i18n-localization` | Internationalization and localization patterns. Detecting hardcoded strings, managing translations, locale files, RTL support. | i18n, localization | i18n, localization, internationalization, detecting, hardcoded, strings, managing, translations, locale, files, rtl |
@@ -53,6 +57,7 @@ Total skills: 614
| `production-code-audit` | Autonomously deep-scan entire codebase line-by-line, understand architecture and patterns, then systematically transform it to production-grade, corporate-le... | production, code, audit | production, code, audit, autonomously, deep, scan, entire, codebase, line, understand, architecture, then |
| `projection-patterns` | Build read models and projections from event streams. Use when implementing CQRS read sides, building materialized views, or optimizing query performance in ... | projection | projection, read, models, projections, event, streams, implementing, cqrs, sides, building, materialized, views |
| `prompt-engineering` | Expert guide on prompt engineering patterns, best practices, and optimization techniques. Use when user wants to improve prompts, learn prompting strategies,... | prompt, engineering | prompt, engineering, optimization, techniques, user, wants, improve, prompts, learn, prompting, debug, agent |
| `radix-ui-design-system` | Build accessible design systems with Radix UI primitives. Headless component customization, theming strategies, and compound component patterns for productio... | radix, ui | radix, ui, accessible, primitives, headless, component, customization, theming, compound, grade, libraries |
| `saga-orchestration` | Implement saga patterns for distributed transactions and cross-aggregate workflows. Use when coordinating multi-step business processes, handling compensatin... | saga | saga, orchestration, distributed, transactions, cross, aggregate, coordinating, multi, step, business, processes, handling |
| `salesforce-development` | Expert patterns for Salesforce platform development including Lightning Web Components (LWC), Apex triggers and classes, REST/Bulk APIs, Connected Apps, and ... | salesforce | salesforce, development, platform, including, lightning, web, components, lwc, apex, triggers, classes, rest |
| `skill-developer` | Create and manage Claude Code skills following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patt... | skill | skill, developer, claude, code, skills, following, anthropic, creating, new, modifying, rules, json |
@@ -67,7 +72,7 @@ Total skills: 614
| `workflow-patterns` | Use this skill when implementing tasks according to Conductor's TDD workflow, handling phase checkpoints, managing git commits for tasks, or understanding th... | | skill, implementing, tasks, according, conductor, tdd, handling, phase, checkpoints, managing, git, commits |
| `zapier-make-patterns` | No-code automation democratizes workflow building. Zapier and Make (formerly Integromat) let non-developers automate business processes without writing code.... | zapier, make | zapier, make, no, code, automation, democratizes, building, formerly, integromat, let, non, developers |
## business (37)
## business (38)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
@@ -108,8 +113,9 @@ Total skills: 614
| `startup-business-analyst-market-opportunity` | Generate comprehensive market opportunity analysis with TAM/SAM/SOM calculations | startup, business, analyst, market, opportunity | startup, business, analyst, market, opportunity, generate, analysis, tam, sam, som, calculations |
| `startup-financial-modeling` | This skill should be used when the user asks to "create financial projections", "build a financial model", "forecast revenue", "calculate burn rate", "estima... | startup, financial, modeling | startup, financial, modeling, skill, should, used, user, asks, projections, model, forecast, revenue |
| `team-composition-analysis` | This skill should be used when the user asks to "plan team structure", "determine hiring needs", "design org chart", "calculate compensation", "plan equity a... | team, composition | team, composition, analysis, skill, should, used, user, asks, plan, structure, determine, hiring |
| `whatsapp-automation` | Automate WhatsApp Business tasks via Rube MCP (Composio): send messages, manage templates, upload media, and handle contacts. Always search tools first for c... | whatsapp | whatsapp, automation, automate, business, tasks, via, rube, mcp, composio, send, messages, upload |
## data-ai (91)
## data-ai (99)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
@@ -119,7 +125,9 @@ Total skills: 614
| `ai-engineer` | Build production-ready LLM applications, advanced RAG systems, and intelligent agents. Implements vector search, multimodal AI, agent orchestration, and ente... | ai | ai, engineer, llm, applications, rag, intelligent, agents, implements, vector, search, multimodal, agent |
| `ai-wrapper-product` | Expert in building products that wrap AI APIs (OpenAI, Anthropic, etc.) into focused tools people will pay for. Not just 'ChatGPT but different' - products t... | ai, wrapper, product | ai, wrapper, product, building, products, wrap, apis, openai, anthropic, etc, people, pay |
| `analytics-tracking` | Design, audit, and improve analytics tracking systems that produce reliable, decision-ready data. Use when the user wants to set up, fix, or evaluate analyti... | analytics, tracking | analytics, tracking, audit, improve, produce, reliable, decision, data, user, wants, set, up |
| `angular-ui-patterns` | Modern Angular UI patterns for loading states, error handling, and data display. Use when building UI components, handling async data, or managing component ... | angular, ui | angular, ui, loading, states, error, handling, data, display, building, components, async, managing |
| `api-documenter` | Master API documentation with OpenAPI 3.1, AI-powered tools, and modern developer experience practices. Create interactive docs, generate SDKs, and build com... | api, documenter | api, documenter, documentation, openapi, ai, powered, developer, experience, interactive, docs, generate, sdks |
| `audio-transcriber` | Transform audio recordings into professional Markdown documentation with intelligent summaries using LLM integration | audio, transcription, whisper, meeting-minutes, speech-to-text | audio, transcription, whisper, meeting-minutes, speech-to-text, transcriber, transform, recordings, professional, markdown, documentation, intelligent |
| `autonomous-agent-patterns` | Design patterns for building autonomous coding agents. Covers tool integration, permission systems, browser automation, and human-in-the-loop workflows. Use ... | autonomous, agent | autonomous, agent, building, coding, agents, covers, integration, permission, browser, automation, human, loop |
| `autonomous-agents` | Autonomous agents are AI systems that can independently decompose goals, plan actions, execute tools, and self-correct without constant human guidance. The c... | autonomous, agents | autonomous, agents, ai, independently, decompose, goals, plan, actions, execute, self, correct, without |
| `beautiful-prose` | Hard-edged writing style contract for timeless, forceful English prose without AI tics | beautiful, prose | beautiful, prose, hard, edged, writing, style, contract, timeless, forceful, english, without, ai |
@@ -153,8 +161,11 @@ Total skills: 614
| `fal-image-edit` | AI-powered image editing with style transfer and object removal | fal, image, edit | fal, image, edit, ai, powered, editing, style, transfer, object, removal |
| `fal-upscale` | Upscale and enhance image and video resolution using AI | fal, upscale | fal, upscale, enhance, image, video, resolution, ai |
| `fal-workflow` | Generate workflow JSON files for chaining AI models | fal | fal, generate, json, files, chaining, ai, models |
| `fp-ts-react` | Practical patterns for using fp-ts with React - hooks, state, forms, data fetching. Use when building React apps with functional programming patterns. Works ... | fp, ts, react | fp, ts, react, practical, hooks, state, forms, data, fetching, building, apps, functional |
| `frontend-dev-guidelines` | Opinionated frontend development standards for modern React + TypeScript applications. Covers Suspense-first data fetching, lazy loading, feature-based archi... | frontend, dev, guidelines | frontend, dev, guidelines, opinionated, development, standards, react, typescript, applications, covers, suspense, first |
| `geo-fundamentals` | Generative Engine Optimization for AI search engines (ChatGPT, Claude, Perplexity). | geo, fundamentals | geo, fundamentals, generative, engine, optimization, ai, search, engines, chatgpt, claude, perplexity |
| `google-analytics-automation` | Automate Google Analytics tasks via Rube MCP (Composio): run reports, list accounts/properties, funnels, pivots, key events. Always search tools first for cu... | google, analytics | google, analytics, automation, automate, tasks, via, rube, mcp, composio, run, reports, list |
| `googlesheets-automation` | Automate Google Sheets operations (read, write, format, filter, manage spreadsheets) via Rube MCP (Composio). Read/write data, manage tabs, apply formatting,... | googlesheets | googlesheets, automation, automate, google, sheets, operations, read, write, format, filter, spreadsheets, via |
| `graphql` | GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful al... | graphql | graphql, gives, clients, exactly, data, no, less, one, endpoint, typed, schema, introspection |
| `hybrid-search-implementation` | Combine vector and keyword search for improved retrieval. Use when implementing RAG systems, building search engines, or when neither approach alone provides... | hybrid, search | hybrid, search, combine, vector, keyword, improved, retrieval, implementing, rag, building, engines, neither |
| `ios-developer` | Develop native iOS applications with Swift/SwiftUI. Masters iOS 18, SwiftUI, UIKit integration, Core Data, networking, and App Store optimization. Use PROACT... | ios | ios, developer, develop, native, applications, swift, swiftui, masters, 18, uikit, integration, core |
@@ -164,6 +175,7 @@ Total skills: 614
| `llm-application-dev-langchain-agent` | You are an expert LangChain agent developer specializing in production-grade AI systems using LangChain 0.1+ and LangGraph. | llm, application, dev, langchain, agent | llm, application, dev, langchain, agent, developer, specializing, grade, ai, langgraph |
| `llm-application-dev-prompt-optimize` | You are an expert prompt engineer specializing in crafting effective prompts for LLMs through advanced techniques including constitutional AI, chain-of-thoug... | llm, application, dev, prompt, optimize | llm, application, dev, prompt, optimize, engineer, specializing, crafting, effective, prompts, llms, through |
| `llm-evaluation` | Implement comprehensive evaluation strategies for LLM applications using automated metrics, human feedback, and benchmarking. Use when testing LLM performanc... | llm, evaluation | llm, evaluation, applications, automated, metrics, human, feedback, benchmarking, testing, performance, measuring, ai |
| `mailchimp-automation` | Automate Mailchimp email marketing including campaigns, audiences, subscribers, segments, and analytics via Rube MCP (Composio). Always search tools first fo... | mailchimp | mailchimp, automation, automate, email, marketing, including, campaigns, audiences, subscribers, segments, analytics, via |
| `nanobanana-ppt-skills` | AI-powered PPT generation with document analysis and styled images | nanobanana, ppt, skills | nanobanana, ppt, skills, ai, powered, generation, document, analysis, styled, images |
| `neon-postgres` | Expert patterns for Neon serverless Postgres, branching, connection pooling, and Prisma/Drizzle integration Use when: neon database, serverless postgres, dat... | neon, postgres | neon, postgres, serverless, branching, connection, pooling, prisma, drizzle, integration, database |
| `nextjs-app-router-patterns` | Master Next.js 14+ App Router with Server Components, streaming, parallel routes, and advanced data fetching. Use when building Next.js applications, impleme... | nextjs, app, router | nextjs, app, router, next, js, 14, server, components, streaming, parallel, routes, data |
@@ -175,7 +187,6 @@ Total skills: 614
| `prisma-expert` | Prisma ORM expert for schema design, migrations, query optimization, relations modeling, and database operations. Use PROACTIVELY for Prisma schema issues, m... | prisma | prisma, orm, schema, migrations, query, optimization, relations, modeling, database, operations, proactively, issues |
| `programmatic-seo` | Design and evaluate programmatic SEO strategies for creating SEO-driven pages at scale using templates and structured data. Use when the user mentions progra... | programmatic, seo | programmatic, seo, evaluate, creating, driven, pages, scale, structured, data, user, mentions, directory |
| `prompt-caching` | Caching strategies for LLM prompts including Anthropic prompt caching, response caching, and CAG (Cache Augmented Generation) Use when: prompt caching, cache... | prompt, caching | prompt, caching, llm, prompts, including, anthropic, response, cag, cache, augmented, generation |
| `prompt-engineer` | Expert prompt engineer specializing in advanced prompting techniques, LLM optimization, and AI system design. Masters chain-of-thought, constitutional AI, an... | prompt | prompt, engineer, specializing, prompting, techniques, llm, optimization, ai, masters, chain, thought, constitutional |
| `prompt-engineering-patterns` | Master advanced prompt engineering techniques to maximize LLM performance, reliability, and controllability in production. Use when optimizing prompts, impro... | prompt, engineering | prompt, engineering, techniques, maximize, llm, performance, reliability, controllability, optimizing, prompts, improving, outputs |
| `rag-engineer` | Expert in building Retrieval-Augmented Generation systems. Masters embedding models, vector databases, chunking strategies, and retrieval optimization for LL... | rag | rag, engineer, building, retrieval, augmented, generation, masters, embedding, models, vector, databases, chunking |
| `rag-implementation` | Build Retrieval-Augmented Generation (RAG) systems for LLM applications with vector databases and semantic search. Use when implementing knowledge-grounded A... | rag | rag, retrieval, augmented, generation, llm, applications, vector, databases, semantic, search, implementing, knowledge |
@@ -184,6 +195,7 @@ Total skills: 614
| `scala-pro` | Master enterprise-grade Scala development with functional programming, distributed systems, and big data processing. Expert in Apache Pekko, Akka, Spark, ZIO... | scala | scala, pro, enterprise, grade, development, functional, programming, distributed, big, data, processing, apache |
| `schema-markup` | Design, validate, and optimize schema.org structured data for eligibility, correctness, and measurable SEO impact. Use when the user wants to add, fix, audit... | schema, markup | schema, markup, validate, optimize, org, structured, data, eligibility, correctness, measurable, seo, impact |
| `segment-cdp` | Expert patterns for Segment Customer Data Platform including Analytics.js, server-side tracking, tracking plans with Protocols, identity resolution, destinat... | segment, cdp | segment, cdp, customer, data, platform, including, analytics, js, server, side, tracking, plans |
| `sendgrid-automation` | Automate SendGrid email operations including sending emails, managing contacts/lists, sender identities, templates, and analytics via Rube MCP (Composio). Al... | sendgrid | sendgrid, automation, automate, email, operations, including, sending, emails, managing, contacts, lists, sender |
| `senior-architect` | Comprehensive software architecture skill for designing scalable, maintainable systems using ReactJS, NextJS, NodeJS, Express, React Native, Swift, Kotlin, F... | senior | senior, architect, software, architecture, skill, designing, scalable, maintainable, reactjs, nextjs, nodejs, express |
| `seo-audit` | Diagnose and audit SEO issues affecting crawlability, indexation, rankings, and organic performance. Use when the user asks for an SEO audit, technical SEO r... | seo, audit | seo, audit, diagnose, issues, affecting, crawlability, indexation, rankings, organic, performance, user, asks |
| `similarity-search-patterns` | Implement efficient similarity search with vector databases. Use when building semantic search, implementing nearest neighbor queries, or optimizing retrieva... | similarity, search | similarity, search, efficient, vector, databases, building, semantic, implementing, nearest, neighbor, queries, optimizing |
@@ -191,6 +203,8 @@ Total skills: 614
| `spark-optimization` | Optimize Apache Spark jobs with partitioning, caching, shuffle optimization, and memory tuning. Use when improving Spark performance, debugging slow jobs, or... | spark, optimization | spark, optimization, optimize, apache, jobs, partitioning, caching, shuffle, memory, tuning, improving, performance |
| `sql-optimization-patterns` | Master SQL query optimization, indexing strategies, and EXPLAIN analysis to dramatically improve database performance and eliminate slow queries. Use when de... | sql, optimization | sql, optimization, query, indexing, explain, analysis, dramatically, improve, database, performance, eliminate, slow |
| `sqlmap-database-pentesting` | This skill should be used when the user asks to "automate SQL injection testing," "enumerate database structure," "extract database credentials using sqlmap,... | sqlmap, database, pentesting | sqlmap, database, pentesting, penetration, testing, skill, should, used, user, asks, automate, sql |
| `stitch-ui-design` | Expert guide for creating effective prompts for Google Stitch AI UI design tool. Use when user wants to design UI/UX in Stitch, create app interfaces, genera... | stitch, ui | stitch, ui, creating, effective, prompts, google, ai, user, wants, ux, app, interfaces |
| `supabase-automation` | Automate Supabase database queries, table management, project administration, storage, edge functions, and SQL execution via Rube MCP (Composio). Always sear... | supabase | supabase, automation, automate, database, queries, table, administration, storage, edge, functions, sql, execution |
| `tdd-orchestrator` | Master TDD orchestrator specializing in red-green-refactor discipline, multi-agent workflow coordination, and comprehensive test-driven development practices... | tdd, orchestrator | tdd, orchestrator, specializing, red, green, refactor, discipline, multi, agent, coordination, test, driven |
| `team-collaboration-standup-notes` | You are an expert team communication specialist focused on async-first standup practices, AI-assisted note generation from commit history, and effective remo... | team, collaboration, standup, notes | team, collaboration, standup, notes, communication, async, first, ai, assisted, note, generation, commit |
| `telegram-bot-builder` | Expert in building Telegram bots that solve real problems - from simple automation to complex AI-powered bots. Covers bot architecture, the Telegram Bot API,... | telegram, bot, builder | telegram, bot, builder, building, bots, solve, real, problems, simple, automation, complex, ai |
@@ -202,10 +216,10 @@ Total skills: 614
| `voice-ai-development` | Expert in building voice AI applications - from real-time voice agents to voice-enabled apps. Covers OpenAI Realtime API, Vapi for voice agents, Deepgram for... | voice, ai | voice, ai, development, building, applications, real, time, agents, enabled, apps, covers, openai |
| `voice-ai-engine-development` | Build real-time conversational AI voice engines using async worker pipelines, streaming transcription, LLM agents, and TTS synthesis with interrupt handling ... | voice, ai, engine | voice, ai, engine, development, real, time, conversational, engines, async, worker, pipelines, streaming |
| `web-artifacts-builder` | Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn/ui). Use ... | web, artifacts, builder | web, artifacts, builder, suite, creating, elaborate, multi, component, claude, ai, html, frontend |
| `xlsx` | Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work ... | xlsx | xlsx, spreadsheet, creation, editing, analysis, formulas, formatting, data, visualization, claude, work, spreadsheets |
| `xlsx-official` | Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work ... | xlsx, official | xlsx, official, spreadsheet, creation, editing, analysis, formulas, formatting, data, visualization, claude, work |
| `youtube-automation` | Automate YouTube tasks via Rube MCP (Composio): upload videos, manage playlists, search content, get analytics, and handle comments. Always search tools firs... | youtube | youtube, automation, automate, tasks, via, rube, mcp, composio, upload, videos, playlists, search |
## development (78)
## development (82)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
@@ -232,10 +246,13 @@ Total skills: 614
| `fastapi-pro` | Build high-performance async APIs with FastAPI, SQLAlchemy 2.0, and Pydantic V2. Master microservices, WebSockets, and modern Python async patterns. Use PROA... | fastapi | fastapi, pro, high, performance, async, apis, sqlalchemy, pydantic, v2, microservices, websockets, python |
| `fastapi-templates` | Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applicati... | fastapi | fastapi, async, dependency, injection, error, handling, building, new, applications, setting, up, backend |
| `firecrawl-scraper` | Deep web scraping, screenshots, PDF parsing, and website crawling using Firecrawl API | firecrawl, scraper | firecrawl, scraper, deep, web, scraping, screenshots, pdf, parsing, website, crawling, api |
| `fp-ts-errors` | Handle errors as values using fp-ts Either and TaskEither for cleaner, more predictable TypeScript code. Use when implementing error handling patterns with f... | fp, ts, errors | fp, ts, errors, handle, values, either, taskeither, cleaner, predictable, typescript, code, implementing |
| `fp-ts-pragmatic` | A practical, jargon-free guide to fp-ts functional programming - the 80/20 approach that gets results without the academic overhead. Use when writing TypeScr... | fp, ts, pragmatic | fp, ts, pragmatic, practical, jargon, free, functional, programming, 80, 20, approach, gets |
| `frontend-design` | Create distinctive, production-grade frontend interfaces with intentional aesthetics, high craft, and non-generic visual identity. Use when building or styli... | frontend | frontend, distinctive, grade, interfaces, intentional, aesthetics, high, craft, non, generic, visual, identity |
| `frontend-developer` | Build React components, implement responsive layouts, and handle client-side state management. Masters React 19, Next.js 15, and modern frontend architecture... | frontend | frontend, developer, react, components, responsive, layouts, handle, client, side, state, masters, 19 |
| `frontend-mobile-development-component-scaffold` | You are a React component architecture expert specializing in scaffolding production-ready, accessible, and performant components. Generate complete componen... | frontend, mobile, component | frontend, mobile, component, development, scaffold, react, architecture, specializing, scaffolding, accessible, performant, components |
| `frontend-slides` | Create stunning, animation-rich HTML presentations from scratch or by converting PowerPoint files. Use when the user wants to build a presentation, convert a... | frontend, slides | frontend, slides, stunning, animation, rich, html, presentations, scratch, converting, powerpoint, files, user |
| `game-development/mobile-games` | Mobile game development principles. Touch input, battery, performance, app stores. | game, development/mobile, games | game, development/mobile, games, mobile, development, principles, touch, input, battery, performance, app, stores |
| `go-concurrency-patterns` | Master Go concurrency with goroutines, channels, sync primitives, and context. Use when building concurrent Go applications, implementing worker pools, or de... | go, concurrency | go, concurrency, goroutines, channels, sync, primitives, context, building, concurrent, applications, implementing, worker |
| `golang-pro` | Master Go 1.21+ with modern patterns, advanced concurrency, performance optimization, and production-ready microservices. Expert in the latest Go ecosystem i... | golang | golang, pro, go, 21, concurrency, performance, optimization, microservices, latest, ecosystem, including, generics |
| `hubspot-integration` | Expert patterns for HubSpot CRM integration including OAuth authentication, CRM objects, associations, batch operations, webhooks, and custom objects. Covers... | hubspot, integration | hubspot, integration, crm, including, oauth, authentication, objects, associations, batch, operations, webhooks, custom |
@@ -275,6 +292,7 @@ Total skills: 614
| `shopify-apps` | Expert patterns for Shopify app development including Remix/React Router apps, embedded apps with App Bridge, webhook handling, GraphQL Admin API, Polaris co... | shopify, apps | shopify, apps, app, development, including, remix, react, router, embedded, bridge, webhook, handling |
| `shopify-development` | Build Shopify apps, extensions, themes using GraphQL Admin API, Shopify CLI, Polaris UI, and Liquid.
TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify, development, apps, extensions, themes, graphql, admin, api, cli, polaris, ui, liquid |
| `slack-automation` | Automate Slack messaging, channel management, search, reactions, and threads via Rube MCP (Composio). Send messages, search conversations, manage channels/us... | slack | slack, automation, automate, messaging, channel, search, reactions, threads, via, rube, mcp, composio |
| `slack-bot-builder` | Build Slack apps using the Bolt framework across Python, JavaScript, and Java. Covers Block Kit for rich UIs, interactive components, slash commands, event h... | slack, bot, builder | slack, bot, builder, apps, bolt, framework, python, javascript, java, covers, block, kit |
| `swiftui-expert-skill` | Write, review, or improve SwiftUI code following best practices for state management, view composition, performance, modern APIs, Swift concurrency, and iOS ... | swiftui, skill | swiftui, skill, write, review, improve, code, following, state, view, composition, performance, apis |
| `systems-programming-rust-project` | You are a Rust project architecture expert specializing in scaffolding production-ready Rust applications. Generate complete project structures with cargo to... | programming, rust | programming, rust, architecture, specializing, scaffolding, applications, generate, complete, structures, cargo, tooling, proper |
@@ -289,16 +307,18 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `viral-generator-builder` | Expert in building shareable generator tools that go viral - name generators, quiz makers, avatar creators, personality tests, and calculator tools. Covers t... | viral, generator, builder | viral, generator, builder, building, shareable, go, name, generators, quiz, makers, avatar, creators |
| `webapp-testing` | Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing... | webapp | webapp, testing, toolkit, interacting, local, web, applications, playwright, supports, verifying, frontend, functionality |
## general (122)
## general (131)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
| `address-github-comments` | Use when you need to address review or issue comments on an open GitHub Pull Request using the gh CLI. | address, github, comments | address, github, comments, review, issue, open, pull, request, gh, cli |
| `agent-manager-skill` | Manage multiple local CLI agents via tmux sessions (start/stop/monitor/assign) with cron-friendly scheduling. | agent, manager, skill | agent, manager, skill, multiple, local, cli, agents, via, tmux, sessions, start, stop |
| `algorithmic-art` | Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, gener... | algorithmic, art | algorithmic, art, creating, p5, js, seeded, randomness, interactive, parameter, exploration, users, request |
| `angular-best-practices` | Angular performance optimization and best practices guide. Use when writing, reviewing, or refactoring Angular code for optimal performance, bundle size, and... | angular, best, practices | angular, best, practices, performance, optimization, writing, reviewing, refactoring, code, optimal, bundle, size |
| `angular-migration` | Migrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applicat... | angular, migration | angular, migration, migrate, angularjs, hybrid, mode, incremental, component, rewriting, dependency, injection, updates |
| `anti-reversing-techniques` | Understand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use when analyzing protected binaries, bypassing anti... | anti, reversing, techniques | anti, reversing, techniques, understand, obfuscation, protection, encountered, during, software, analysis, analyzing, protected |
| `app-builder` | Main application building orchestrator. Creates full-stack applications from natural language requests. Determines project type, selects tech stack, coordina... | app, builder | app, builder, main, application, building, orchestrator, creates, full, stack, applications, natural, language |
| `app-builder/templates` | Project scaffolding templates for new applications. Use when creating new projects from scratch. Contains 12 templates for various tech stacks. | app, builder/templates | app, builder/templates, scaffolding, new, applications, creating, scratch, contains, 12, various, tech, stacks |
| `arm-cortex-expert` | Senior embedded software engineer specializing in firmware and driver development for ARM Cortex-M microcontrollers (Teensy, STM32, nRF52, SAMD). Decades of ... | arm, cortex | arm, cortex, senior, embedded, software, engineer, specializing, firmware, driver, development, microcontrollers, teensy |
| `avalonia-layout-zafiro` | Guidelines for modern Avalonia UI layout using Zafiro.Avalonia, emphasizing shared styles, generic components, and avoiding XAML redundancy. | avalonia, layout, zafiro | avalonia, layout, zafiro, guidelines, ui, emphasizing, shared, styles, generic, components, avoiding, xaml |
| `avalonia-zafiro-development` | Mandatory skills, conventions, and behavioral rules for Avalonia UI development using the Zafiro toolkit. | avalonia, zafiro | avalonia, zafiro, development, mandatory, skills, conventions, behavioral, rules, ui, toolkit |
@@ -318,7 +338,7 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `claude-scientific-skills` | Scientific research and analysis skills | claude, scientific, skills | claude, scientific, skills, research, analysis |
| `claude-speed-reader` | -Speed read Claude's responses at 600+ WPM using RSVP with Spritz-style ORP highlighting | claude, speed, reader | claude, speed, reader, read, responses, 600, wpm, rsvp, spritz, style, orp, highlighting |
| `claude-win11-speckit-update-skill` | Windows 11 system management | claude, win11, speckit, update, skill | claude, win11, speckit, update, skill, windows, 11 |
| `clean-code` | Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments | clean, code | clean, code, pragmatic, coding, standards, concise, direct, no, engineering, unnecessary, comments |
| `clean-code` | Applies principles from Robert C. Martin's 'Clean Code'. Use this skill when writing, reviewing, or refactoring code to ensure high quality, readability, and... | clean, code | clean, code, applies, principles, robert, martin, skill, writing, reviewing, refactoring, high, quality |
| `code-documentation-code-explain` | You are a code education expert specializing in explaining complex code through clear narratives, visual diagrams, and step-by-step breakdowns. Transform dif... | code, documentation, explain | code, documentation, explain, education, specializing, explaining, complex, through, clear, narratives, visual, diagrams |
| `code-refactoring-context-restore` | Use when working with code refactoring context restore | code, refactoring, restore | code, refactoring, restore, context, working |
| `code-refactoring-tech-debt` | You are a technical debt expert specializing in identifying, quantifying, and prioritizing technical debt in software projects. Analyze the codebase to uncov... | code, refactoring, tech, debt | code, refactoring, tech, debt, technical, specializing, identifying, quantifying, prioritizing, software, analyze, codebase |
@@ -327,6 +347,7 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `commit` | Create commit messages following Sentry conventions. Use when committing code changes, writing commit messages, or formatting git history. Follows convention... | commit | commit, messages, following, sentry, conventions, committing, code, changes, writing, formatting, git, history |
| `comprehensive-review-full-review` | Use when working with comprehensive review full review | comprehensive, full | comprehensive, full, review, working |
| `comprehensive-review-pr-enhance` | You are a PR optimization expert specializing in creating high-quality pull requests that facilitate efficient code reviews. Generate comprehensive PR descri... | comprehensive, pr, enhance | comprehensive, pr, enhance, review, optimization, specializing, creating, high, quality, pull, requests, facilitate |
| `computer-vision-expert` | SOTA Computer Vision Expert (2026). Specialized in YOLO26, Segment Anything 3 (SAM 3), Vision Language Models, and real-time spatial analysis. | computer, vision | computer, vision, sota, 2026, specialized, yolo26, segment, anything, sam, language, models, real |
| `concise-planning` | Use when a user asks for a plan for a coding task, to generate a clear, actionable, and atomic checklist. | concise, planning | concise, planning, user, asks, plan, coding, task, generate, clear, actionable, atomic, checklist |
| `context-compression` | Design and evaluate compression strategies for long-running sessions | compression | compression, context, evaluate, long, running, sessions |
| `context-fundamentals` | Understand what context is, why it matters, and the anatomy of context in agent systems | fundamentals | fundamentals, context, understand, what, why, matters, anatomy, agent |
@@ -340,7 +361,6 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `debugging-toolkit-smart-debug` | Use when working with debugging toolkit smart debug | debugging, debug | debugging, debug, toolkit, smart, working |
| `design-md` | Analyze Stitch projects and synthesize a semantic design system into DESIGN.md files | md | md, analyze, stitch, synthesize, semantic, files |
| `dispatching-parallel-agents` | Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies | dispatching, parallel, agents | dispatching, parallel, agents, facing, independent, tasks, worked, without, shared, state, sequential, dependencies |
| `docx` | Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude ... | docx | docx, document, creation, editing, analysis, tracked, changes, comments, formatting, preservation, text, extraction |
| `docx-official` | Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude ... | docx, official | docx, official, document, creation, editing, analysis, tracked, changes, comments, formatting, preservation, text |
| `dx-optimizer` | Developer Experience specialist. Improves tooling, setup, and workflows. Use PROACTIVELY when setting up new projects, after team feedback, or when developme... | dx, optimizer | dx, optimizer, developer, experience, improves, tooling, setup, proactively, setting, up, new, after |
| `environment-setup-guide` | Guide developers through setting up development environments with proper tools, dependencies, and configurations | environment, setup | environment, setup, developers, through, setting, up, development, environments, proper, dependencies, configurations |
@@ -355,6 +375,13 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `fix-review` | Verify fix commits address audit findings without new bugs | fix | fix, review, verify, commits, address, audit, findings, without, new, bugs |
| `framework-migration-code-migrate` | You are a code migration expert specializing in transitioning codebases between frameworks, languages, versions, and platforms. Generate comprehensive migrat... | framework, migration, code, migrate | framework, migration, code, migrate, specializing, transitioning, codebases, between, frameworks, languages, versions, platforms |
| `game-development` | Game development orchestrator. Routes to platform-specific skills based on project needs. | game | game, development, orchestrator, routes, platform, specific, skills |
| `game-development/2d-games` | 2D game development principles. Sprites, tilemaps, physics, camera. | game, development/2d, games | game, development/2d, games, 2d, development, principles, sprites, tilemaps, physics, camera |
| `game-development/3d-games` | 3D game development principles. Rendering, shaders, physics, cameras. | game, development/3d, games | game, development/3d, games, 3d, development, principles, rendering, shaders, physics, cameras |
| `game-development/game-audio` | Game audio principles. Sound design, music integration, adaptive audio systems. | game, development/game, audio | game, development/game, audio, principles, sound, music, integration, adaptive |
| `game-development/game-design` | Game design principles. GDD structure, balancing, player psychology, progression. | game, development/game | game, development/game, principles, gdd, structure, balancing, player, psychology, progression |
| `game-development/pc-games` | PC and console game development principles. Engine selection, platform features, optimization strategies. | game, development/pc, games | game, development/pc, games, pc, console, development, principles, engine, selection, platform, features, optimization |
| `game-development/vr-ar` | VR/AR development principles. Comfort, interaction, performance requirements. | game, development/vr, ar | game, development/vr, ar, vr, development, principles, comfort, interaction, performance, requirements |
| `game-development/web-games` | Web browser game development principles. Framework selection, WebGPU, optimization, PWA. | game, development/web, games | game, development/web, games, web, browser, development, principles, framework, selection, webgpu, optimization, pwa |
| `git-advanced-workflows` | Master advanced Git workflows including rebasing, cherry-picking, bisect, worktrees, and reflog to maintain clean history and recover from any situation. Use... | git, advanced | git, advanced, including, rebasing, cherry, picking, bisect, worktrees, reflog, maintain, clean, history |
| `git-pr-workflows-onboard` | You are an **expert onboarding specialist and knowledge transfer architect** with deep experience in remote-first organizations, technical team integration, ... | git, pr, onboard | git, pr, onboard, onboarding, knowledge, transfer, architect, deep, experience, remote, first, organizations |
| `git-pr-workflows-pr-enhance` | You are a PR optimization expert specializing in creating high-quality pull requests that facilitate efficient code reviews. Generate comprehensive PR descri... | git, pr, enhance | git, pr, enhance, optimization, specializing, creating, high, quality, pull, requests, facilitate, efficient |
@@ -374,6 +401,7 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `nosql-expert` | Expert guidance for distributed NoSQL databases (Cassandra, DynamoDB). Focuses on mental models, query-first modeling, single-table design, and avoiding hot ... | nosql | nosql, guidance, distributed, databases, cassandra, dynamodb, mental, models, query, first, modeling, single |
| `obsidian-clipper-template-creator` | Guide for creating templates for the Obsidian Web Clipper. Use when you want to create a new clipping template, understand available variables, or format cli... | obsidian, clipper, creator | obsidian, clipper, creator, creating, web, want, new, clipping, understand, available, variables, format |
| `onboarding-cro` | When the user wants to optimize post-signup onboarding, user activation, first-run experience, or time-to-value. Also use when the user mentions "onboarding ... | onboarding, cro | onboarding, cro, user, wants, optimize, post, signup, activation, first, run, experience, time |
| `oss-hunter` | Automatically hunt for high-impact OSS contribution opportunities in trending repositories. | oss, hunter | oss, hunter, automatically, hunt, high, impact, contribution, opportunities, trending, repositories |
| `paid-ads` | When the user wants help with paid advertising campaigns on Google Ads, Meta (Facebook/Instagram), LinkedIn, Twitter/X, or other ad platforms. Also use when ... | paid, ads | paid, ads, user, wants, advertising, campaigns, google, meta, facebook, instagram, linkedin, twitter |
| `paypal-integration` | Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processin... | paypal, integration | paypal, integration, integrate, payment, processing, express, checkout, subscriptions, refund, implementing, payments, online |
| `performance-profiling` | Performance profiling principles. Measurement, analysis, and optimization techniques. | performance, profiling | performance, profiling, principles, measurement, analysis, optimization, techniques |
@@ -381,11 +409,10 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `plan-writing` | Structured task planning with clear breakdowns, dependencies, and verification criteria. Use when implementing features, refactoring, or any multi-step work. | plan, writing | plan, writing, structured, task, planning, clear, breakdowns, dependencies, verification, criteria, implementing, features |
| `planning-with-files` | Implements Manus-style file-based planning for complex tasks. Creates task_plan.md, findings.md, and progress.md. Use when starting complex multi-step tasks,... | planning, with, files | planning, with, files, implements, manus, style, file, complex, tasks, creates, task, plan |
| `posix-shell-pro` | Expert in strict POSIX sh scripting for maximum portability across Unix-like systems. Specializes in shell scripts that run on any POSIX-compliant shell (das... | posix, shell | posix, shell, pro, strict, sh, scripting, maximum, portability, unix, like, specializes, scripts |
| `pptx` | Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying o... | pptx | pptx, presentation, creation, editing, analysis, claude, work, presentations, files, creating, new, modifying |
| `pptx-official` | Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying o... | pptx, official | pptx, official, presentation, creation, editing, analysis, claude, work, presentations, files, creating, new |
| `privilege-escalation-methods` | This skill should be used when the user asks to "escalate privileges", "get root access", "become administrator", "privesc techniques", "abuse sudo", "exploi... | privilege, escalation, methods | privilege, escalation, methods, skill, should, used, user, asks, escalate, privileges, get, root |
| `prompt-engineer` | Transforms user prompts into optimized prompts using frameworks (RTF, RISEN, Chain of Thought, RODES, Chain of Density, RACE, RISE, STAR, SOAP, CLEAR, GROW) | prompt-engineering, optimization, frameworks, ai-enhancement | prompt-engineering, optimization, frameworks, ai-enhancement, prompt, engineer, transforms, user, prompts, optimized, rtf, risen |
| `prompt-library` | Curated collection of high-quality prompts for various use cases. Includes role-based prompts, task-specific templates, and prompt refinement techniques. Use... | prompt, library | prompt, library, curated, collection, high, quality, prompts, various, cases, includes, role, task |
| `readme` | When the user wants to create or update a README.md file for a project. Also use when the user says | readme | readme, user, wants, update, md, file, says |
| `receiving-code-review` | Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technic... | receiving, code | receiving, code, review, feedback, before, implementing, suggestions, especially, seems, unclear, technically, questionable |
| `referral-program` | When the user wants to create, optimize, or analyze a referral program, affiliate program, or word-of-mouth strategy. Also use when the user mentions 'referr... | referral, program | referral, program, user, wants, optimize, analyze, affiliate, word, mouth, mentions, ambassador, viral |
| `requesting-code-review` | Use when completing tasks, implementing major features, or before merging to verify work meets requirements | requesting, code | requesting, code, review, completing, tasks, implementing, major, features, before, merging, verify, work |
@@ -393,7 +420,6 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `sharp-edges` | Identify error-prone APIs and dangerous configurations | sharp, edges | sharp, edges, identify, error, prone, apis, dangerous, configurations |
| `shellcheck-configuration` | Master ShellCheck static analysis configuration and usage for shell script quality. Use when setting up linting infrastructure, fixing code issues, or ensuri... | shellcheck, configuration | shellcheck, configuration, static, analysis, usage, shell, script, quality, setting, up, linting, infrastructure |
| `signup-flow-cro` | When the user wants to optimize signup, registration, account creation, or trial activation flows. Also use when the user mentions "signup conversions," "reg... | signup, flow, cro | signup, flow, cro, user, wants, optimize, registration, account, creation, trial, activation, flows |
| `skill-creator` | Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capa... | skill, creator | skill, creator, creating, effective, skills, should, used, users, want, new, update, existing |
| `skill-rails-upgrade` | Analyze Rails apps and provide upgrade assessments | skill, rails, upgrade | skill, rails, upgrade, analyze, apps, provide, assessments |
| `slack-gif-creator` | Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users reques... | slack, gif, creator | slack, gif, creator, knowledge, utilities, creating, animated, gifs, optimized, provides, constraints, validation |
| `social-content` | When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. A... | social, content | social, content, user, wants, creating, scheduling, optimizing, media, linkedin, twitter, instagram, tiktok |
@@ -415,8 +441,9 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `writing-plans` | Use when you have a spec or requirements for a multi-step task, before touching code | writing, plans | writing, plans, spec, requirements, multi, step, task, before, touching, code |
| `writing-skills` | Use when creating, updating, or improving agent skills. | writing, skills | writing, skills, creating, updating, improving, agent |
| `x-article-publisher-skill` | Publish articles to X/Twitter | x, article, publisher, skill | x, article, publisher, skill, publish, articles, twitter |
| `youtube-summarizer` | Extract transcripts from YouTube videos and generate comprehensive, detailed summaries using intelligent analysis frameworks | video, summarization, transcription, youtube, content-analysis | video, summarization, transcription, youtube, content-analysis, summarizer, extract, transcripts, videos, generate, detailed, summaries |
## infrastructure (77)
## infrastructure (83)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
@@ -431,6 +458,7 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `bash-defensive-patterns` | Master defensive Bash programming techniques for production-grade scripts. Use when writing robust shell scripts, CI/CD pipelines, or system utilities requir... | bash, defensive | bash, defensive, programming, techniques, grade, scripts, writing, robust, shell, ci, cd, pipelines |
| `bash-pro` | Master of defensive Bash scripting for production automation, CI/CD pipelines, and system utilities. Expert in safe, portable, and testable shell scripts. | bash | bash, pro, defensive, scripting, automation, ci, cd, pipelines, utilities, safe, portable, testable |
| `bats-testing-patterns` | Master Bash Automated Testing System (Bats) for comprehensive shell script testing. Use when writing tests for shell scripts, CI/CD pipelines, or requiring t... | bats | bats, testing, bash, automated, shell, script, writing, tests, scripts, ci, cd, pipelines |
| `box-automation` | Automate Box cloud storage operations including file upload/download, search, folder management, sharing, collaborations, and metadata queries via Rube MCP (... | box | box, automation, automate, cloud, storage, operations, including, file, upload, download, search, folder |
| `c4-container` | Expert C4 Container-level documentation specialist. Synthesizes Component-level documentation into Container-level architecture, mapping components to deploy... | c4, container | c4, container, level, documentation, synthesizes, component, architecture, mapping, components, deployment, units, documenting |
| `claude-d3js-skill` | Creating interactive data visualisations using d3.js. This skill should be used when creating custom charts, graphs, network diagrams, geographic visualisati... | claude, d3js, skill | claude, d3js, skill, d3, viz, creating, interactive, data, visualisations, js, should, used |
| `code-review-ai-ai-review` | You are an expert AI-powered code review specialist combining automated static analysis, intelligent pattern recognition, and modern DevOps practices. Levera... | code, ai | code, ai, review, powered, combining, automated, static, analysis, intelligent, recognition, devops, leverage |
@@ -453,9 +481,12 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `expo-deployment` | Deploy Expo apps to production | expo, deployment | expo, deployment, deploy, apps |
| `file-uploads` | Expert at handling file uploads and cloud storage. Covers S3, Cloudflare R2, presigned URLs, multipart uploads, and image optimization. Knows how to handle l... | file, uploads | file, uploads, handling, cloud, storage, covers, s3, cloudflare, r2, presigned, urls, multipart |
| `flutter-expert` | Master Flutter development with Dart 3, advanced widgets, and multi-platform deployment. Handles state management, animations, testing, and performance optim... | flutter | flutter, development, dart, widgets, multi, platform, deployment, state, animations, testing, performance, optimization |
| `freshservice-automation` | Automate Freshservice ITSM tasks via Rube MCP (Composio): create/update tickets, bulk operations, service requests, and outbound emails. Always search tools ... | freshservice | freshservice, automation, automate, itsm, tasks, via, rube, mcp, composio, update, tickets, bulk |
| `game-development/game-art` | Game art principles. Visual style selection, asset pipeline, animation workflow. | game, development/game, art | game, development/game, art, principles, visual, style, selection, asset, pipeline, animation |
| `gcp-cloud-run` | Specialized skill for building production-ready serverless applications on GCP. Covers Cloud Run services (containerized), Cloud Run Functions (event-driven)... | gcp, cloud, run | gcp, cloud, run, specialized, skill, building, serverless, applications, covers, containerized, functions, event |
| `git-pr-workflows-git-workflow` | Orchestrate a comprehensive git workflow from code review through PR creation, leveraging specialized agents for quality assurance, testing, and deployment r... | git, pr | git, pr, orchestrate, code, review, through, creation, leveraging, specialized, agents, quality, assurance |
| `github-actions-templates` | Create production-ready GitHub Actions workflows for automated testing, building, and deploying applications. Use when setting up CI/CD with GitHub Actions, ... | github, actions | github, actions, automated, testing, building, deploying, applications, setting, up, ci, cd, automating |
| `github-automation` | Automate GitHub repositories, issues, pull requests, branches, CI/CD, and permissions via Rube MCP (Composio). Manage code workflows, review PRs, search code... | github | github, automation, automate, repositories, issues, pull, requests, branches, ci, cd, permissions, via |
| `github-workflow-automation` | Automate GitHub workflows with AI assistance. Includes PR reviews, issue triage, CI/CD integration, and Git operations. Use when automating GitHub workflows,... | github | github, automation, automate, ai, assistance, includes, pr, reviews, issue, triage, ci, cd |
| `gitlab-ci-patterns` | Build GitLab CI/CD pipelines with multi-stage workflows, caching, and distributed runners for scalable automation. Use when implementing GitLab CI/CD, optimi... | gitlab, ci | gitlab, ci, cd, pipelines, multi, stage, caching, distributed, runners, scalable, automation, implementing |
| `gitops-workflow` | Implement GitOps workflows with ArgoCD and Flux for automated, declarative Kubernetes deployments with continuous reconciliation. Use when implementing GitOp... | gitops | gitops, argocd, flux, automated, declarative, kubernetes, deployments, continuous, reconciliation, implementing, automating, setting |
@@ -481,8 +512,10 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `observability-monitoring-slo-implement` | You are an SLO (Service Level Objective) expert specializing in implementing reliability standards and error budget-based practices. Design SLO frameworks, d... | observability, monitoring, slo, implement | observability, monitoring, slo, implement, level, objective, specializing, implementing, reliability, standards, error, budget |
| `performance-engineer` | Expert performance engineer specializing in modern observability, application optimization, and scalable system performance. Masters OpenTelemetry, distribut... | performance | performance, engineer, specializing, observability, application, optimization, scalable, masters, opentelemetry, distributed, tracing, load |
| `performance-testing-review-ai-review` | You are an expert AI-powered code review specialist combining automated static analysis, intelligent pattern recognition, and modern DevOps practices. Levera... | performance, ai | performance, ai, testing, review, powered, code, combining, automated, static, analysis, intelligent, recognition |
| `pipedrive-automation` | Automate Pipedrive CRM operations including deals, contacts, organizations, activities, notes, and pipeline management via Rube MCP (Composio). Always search... | pipedrive | pipedrive, automation, automate, crm, operations, including, deals, contacts, organizations, activities, notes, pipeline |
| `prometheus-configuration` | Set up Prometheus for comprehensive metric collection, storage, and monitoring of infrastructure and applications. Use when implementing metrics collection, ... | prometheus, configuration | prometheus, configuration, set, up, metric, collection, storage, monitoring, infrastructure, applications, implementing, metrics |
| `protocol-reverse-engineering` | Master network protocol reverse engineering including packet analysis, protocol dissection, and custom protocol documentation. Use when analyzing network tra... | protocol, reverse, engineering | protocol, reverse, engineering, network, including, packet, analysis, dissection, custom, documentation, analyzing, traffic |
| `readme` | When the user wants to create or update a README.md file for a project. Also use when the user says 'write readme,' 'create readme,' 'document this project,'... | readme | readme, user, wants, update, md, file, says, write, document, documentation, asks, skill |
| `server-management` | Server management principles and decision-making. Process management, monitoring strategy, and scaling decisions. Teaches thinking, not commands. | server | server, principles, decision, making, process, monitoring, scaling, decisions, teaches, thinking, commands |
| `service-mesh-observability` | Implement comprehensive observability for service meshes including distributed tracing, metrics, and visualization. Use when setting up mesh monitoring, debu... | service, mesh, observability | service, mesh, observability, meshes, including, distributed, tracing, metrics, visualization, setting, up, monitoring |
| `slo-implementation` | Define and implement Service Level Indicators (SLIs) and Service Level Objectives (SLOs) with error budgets and alerting. Use when establishing reliability t... | slo | slo, define, level, indicators, slis, objectives, slos, error, budgets, alerting, establishing, reliability |
@@ -492,13 +525,13 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `terraform-skill` | Terraform infrastructure as code best practices | terraform, skill | terraform, skill, infrastructure, code |
| `test-automator` | Master AI-powered test automation with modern frameworks, self-healing tests, and comprehensive quality engineering. Build scalable testing strategies with a... | automator | automator, test, ai, powered, automation, frameworks, self, healing, tests, quality, engineering, scalable |
| `unity-developer` | Build Unity games with optimized C# scripts, efficient rendering, and proper asset management. Masters Unity 6 LTS, URP/HDRP pipelines, and cross-platform de... | unity | unity, developer, games, optimized, scripts, efficient, rendering, proper, asset, masters, lts, urp |
| `vercel-deploy-claimable` | Deploy applications and websites to Vercel. Use this skill when the user requests deployment actions such as | vercel, deploy, claimable | vercel, deploy, claimable, applications, websites, skill, user, requests, deployment, actions, such |
| `vercel-deploy-claimable` | Deploy applications and websites to Vercel. Use this skill when the user requests deployment actions such as 'Deploy my app', 'Deploy this to production', 'C... | vercel, deploy, claimable | vercel, deploy, claimable, applications, websites, skill, user, requests, deployment, actions, such, my |
| `vercel-deployment` | Expert knowledge for deploying to Vercel with Next.js Use when: vercel, deploy, deployment, hosting, production. | vercel, deployment | vercel, deployment, knowledge, deploying, next, js, deploy, hosting |
| `voice-agents` | Voice agents represent the frontier of AI interaction - humans speaking naturally with AI systems. The challenge isn't just speech recognition and synthesis,... | voice, agents | voice, agents, represent, frontier, ai, interaction, humans, speaking, naturally, challenge, isn, just |
| `wireshark-analysis` | This skill should be used when the user asks to "analyze network traffic with Wireshark", "capture packets for troubleshooting", "filter PCAP files", "follow... | wireshark | wireshark, network, traffic, analysis, skill, should, used, user, asks, analyze, capture, packets |
| `workflow-automation` | Workflow automation is the infrastructure that makes AI agents reliable. Without durable execution, a network hiccup during a 10-step payment flow means lost... | | automation, infrastructure, makes, ai, agents, reliable, without, durable, execution, network, hiccup, during |
## security (112)
## security (113)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
@@ -532,6 +565,7 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `design-orchestration` | Orchestrates design workflows by routing work through brainstorming, multi-agent review, and execution readiness in the correct order. Prevents premature imp... | | orchestration, orchestrates, routing, work, through, brainstorming, multi, agent, review, execution, readiness, correct |
| `devops-troubleshooter` | Expert DevOps troubleshooter specializing in rapid incident response, advanced debugging, and modern observability. Masters log analysis, distributed tracing... | devops, troubleshooter | devops, troubleshooter, specializing, rapid, incident, response, debugging, observability, masters, log, analysis, distributed |
| `docker-expert` | Docker containerization expert with deep knowledge of multi-stage builds, image optimization, container security, Docker Compose orchestration, and productio... | docker | docker, containerization, deep, knowledge, multi, stage, image, optimization, container, security, compose, orchestration |
| `dotnet-backend` | Build ASP.NET Core 8+ backend services with EF Core, auth, background jobs, and production API patterns. | dotnet, backend | dotnet, backend, asp, net, core, ef, auth, background, jobs, api |
| `ethical-hacking-methodology` | This skill should be used when the user asks to "learn ethical hacking", "understand penetration testing lifecycle", "perform reconnaissance", "conduct secur... | ethical, hacking, methodology | ethical, hacking, methodology, skill, should, used, user, asks, learn, understand, penetration, testing |
| `file-path-traversal` | This skill should be used when the user asks to "test for directory traversal", "exploit path traversal vulnerabilities", "read arbitrary files through web a... | file, path, traversal | file, path, traversal, testing, skill, should, used, user, asks, test, directory, exploit |
| `find-bugs` | Find bugs, security vulnerabilities, and code quality issues in local branch changes. Use when asked to review changes, find bugs, security review, or audit ... | find, bugs | find, bugs, security, vulnerabilities, code, quality, issues, local, branch, changes, asked, review |
@@ -615,11 +649,12 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `wordpress-penetration-testing` | This skill should be used when the user asks to "pentest WordPress sites", "scan WordPress for vulnerabilities", "enumerate WordPress users, themes, or plugi... | wordpress, penetration | wordpress, penetration, testing, skill, should, used, user, asks, pentest, sites, scan, vulnerabilities |
| `xss-html-injection` | This skill should be used when the user asks to "test for XSS vulnerabilities", "perform cross-site scripting attacks", "identify HTML injection flaws", "exp... | xss, html, injection | xss, html, injection, cross, site, scripting, testing, skill, should, used, user, asks |
## testing (22)
## testing (23)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
| `ab-test-setup` | Structured guide for setting up A/B tests with mandatory gates for hypothesis, metrics, and execution readiness. | ab, setup | ab, setup, test, structured, setting, up, tests, mandatory, gates, hypothesis, metrics, execution |
| `circleci-automation` | Automate CircleCI tasks via Rube MCP (Composio): trigger pipelines, monitor workflows/jobs, retrieve artifacts and test metadata. Always search tools first f... | circleci | circleci, automation, automate, tasks, via, rube, mcp, composio, trigger, pipelines, monitor, jobs |
| `conductor-implement` | Execute tasks from a track's implementation plan following TDD workflow | conductor, implement | conductor, implement, execute, tasks, track, plan, following, tdd |
| `conductor-revert` | Git-aware undo by logical work unit (track, phase, or task) | conductor, revert | conductor, revert, git, aware, undo, logical, work, unit, track, phase, task |
| `debugger` | Debugging specialist for errors, test failures, and unexpected behavior. Use proactively when encountering any issues. | debugger | debugger, debugging, errors, test, failures, unexpected, behavior, proactively, encountering, any, issues |
@@ -642,24 +677,88 @@ TRIGGER: "shopify", "shopify app", "checkout extension",... | shopify | shopify,
| `unit-testing-test-generate` | Generate comprehensive, maintainable unit tests across languages with strong coverage and edge case focus. | unit, generate | unit, generate, testing, test, maintainable, tests, languages, strong, coverage, edge, case |
| `web3-testing` | Test smart contracts comprehensively using Hardhat and Foundry with unit tests, integration tests, and mainnet forking. Use when testing Solidity contracts, ... | web3 | web3, testing, test, smart, contracts, comprehensively, hardhat, foundry, unit, tests, integration, mainnet |
## workflow (17)
## workflow (81)
| Skill | Description | Tags | Triggers |
| --- | --- | --- | --- |
| `activecampaign-automation` | Automate ActiveCampaign tasks via Rube MCP (Composio): manage contacts, tags, list subscriptions, automation enrollment, and tasks. Always search tools first... | activecampaign | activecampaign, automation, automate, tasks, via, rube, mcp, composio, contacts, tags, list, subscriptions |
| `agent-orchestration-improve-agent` | Systematic improvement of existing agents through performance analysis, prompt engineering, and continuous iteration. | agent, improve | agent, improve, orchestration, systematic, improvement, existing, agents, through, performance, analysis, prompt, engineering |
| `agent-orchestration-multi-agent-optimize` | Optimize multi-agent systems with coordinated profiling, workload distribution, and cost-aware orchestration. Use when improving agent performance, throughpu... | agent, multi, optimize | agent, multi, optimize, orchestration, coordinated, profiling, workload, distribution, cost, aware, improving, performance |
| `airtable-automation` | Automate Airtable tasks via Rube MCP (Composio): records, bases, tables, fields, views. Always search tools first for current schemas. | airtable | airtable, automation, automate, tasks, via, rube, mcp, composio, records, bases, tables, fields |
| `amplitude-automation` | Automate Amplitude tasks via Rube MCP (Composio): events, user activity, cohorts, user identification. Always search tools first for current schemas. | amplitude | amplitude, automation, automate, tasks, via, rube, mcp, composio, events, user, activity, cohorts |
| `asana-automation` | Automate Asana tasks via Rube MCP (Composio): tasks, projects, sections, teams, workspaces. Always search tools first for current schemas. | asana | asana, automation, automate, tasks, via, rube, mcp, composio, sections, teams, workspaces, always |
| `bamboohr-automation` | Automate BambooHR tasks via Rube MCP (Composio): employees, time-off, benefits, dependents, employee updates. Always search tools first for current schemas. | bamboohr | bamboohr, automation, automate, tasks, via, rube, mcp, composio, employees, time, off, benefits |
| `basecamp-automation` | Automate Basecamp project management, to-dos, messages, people, and to-do list organization via Rube MCP (Composio). Always search tools first for current sc... | basecamp | basecamp, automation, automate, dos, messages, people, do, list, organization, via, rube, mcp |
| `billing-automation` | Build automated billing systems for recurring payments, invoicing, subscription lifecycle, and dunning management. Use when implementing subscription billing... | billing | billing, automation, automated, recurring, payments, invoicing, subscription, lifecycle, dunning, implementing, automating, managing |
| `bitbucket-automation` | Automate Bitbucket repositories, pull requests, branches, issues, and workspace management via Rube MCP (Composio). Always search tools first for current sch... | bitbucket | bitbucket, automation, automate, repositories, pull, requests, branches, issues, workspace, via, rube, mcp |
| `brevo-automation` | Automate Brevo (Sendinblue) tasks via Rube MCP (Composio): manage email campaigns, create/edit templates, track senders, and monitor campaign performance. Al... | brevo | brevo, automation, automate, sendinblue, tasks, via, rube, mcp, composio, email, campaigns, edit |
| `cal-com-automation` | Automate Cal.com tasks via Rube MCP (Composio): manage bookings, check availability, configure webhooks, and handle teams. Always search tools first for curr... | cal, com | cal, com, automation, automate, tasks, via, rube, mcp, composio, bookings, check, availability |
| `canva-automation` | Automate Canva tasks via Rube MCP (Composio): designs, exports, folders, brand templates, autofill. Always search tools first for current schemas. | canva | canva, automation, automate, tasks, via, rube, mcp, composio, designs, exports, folders, brand |
| `changelog-automation` | Automate changelog generation from commits, PRs, and releases following Keep a Changelog format. Use when setting up release workflows, generating release no... | changelog | changelog, automation, automate, generation, commits, prs, releases, following, keep, format, setting, up |
| `clickup-automation` | Automate ClickUp project management including tasks, spaces, folders, lists, comments, and team operations via Rube MCP (Composio). Always search tools first... | clickup | clickup, automation, automate, including, tasks, spaces, folders, lists, comments, team, operations, via |
| `close-automation` | Automate Close CRM tasks via Rube MCP (Composio): create leads, manage calls/SMS, handle tasks, and track notes. Always search tools first for current schemas. | close | close, automation, automate, crm, tasks, via, rube, mcp, composio, leads, calls, sms |
| `coda-automation` | Automate Coda tasks via Rube MCP (Composio): manage docs, pages, tables, rows, formulas, permissions, and publishing. Always search tools first for current s... | coda | coda, automation, automate, tasks, via, rube, mcp, composio, docs, pages, tables, rows |
| `conductor-manage` | Manage track lifecycle: archive, restore, delete, rename, and cleanup | conductor, manage | conductor, manage, track, lifecycle, archive, restore, delete, rename, cleanup |
| `conductor-new-track` | Create a new track with specification and phased implementation plan | conductor, new, track | conductor, new, track, specification, phased, plan |
| `conductor-status` | Display project status, active tracks, and next actions | conductor, status | conductor, status, display, active, tracks, next, actions |
| `conductor-validator` | Validates Conductor project artifacts for completeness, consistency, and correctness. Use after setup, when diagnosing issues, or before implementation to ve... | conductor, validator | conductor, validator, validates, artifacts, completeness, consistency, correctness, after, setup, diagnosing, issues, before |
| `confluence-automation` | Automate Confluence page creation, content search, space management, labels, and hierarchy navigation via Rube MCP (Composio). Always search tools first for ... | confluence | confluence, automation, automate, page, creation, content, search, space, labels, hierarchy, navigation, via |
| `convertkit-automation` | Automate ConvertKit (Kit) tasks via Rube MCP (Composio): manage subscribers, tags, broadcasts, and broadcast stats. Always search tools first for current sch... | convertkit | convertkit, automation, automate, kit, tasks, via, rube, mcp, composio, subscribers, tags, broadcasts |
| `datadog-automation` | Automate Datadog tasks via Rube MCP (Composio): query metrics, search logs, manage monitors/dashboards, create events and downtimes. Always search tools firs... | datadog | datadog, automation, automate, tasks, via, rube, mcp, composio, query, metrics, search, logs |
| `discord-automation` | Automate Discord tasks via Rube MCP (Composio): messages, channels, roles, webhooks, reactions. Always search tools first for current schemas. | discord | discord, automation, automate, tasks, via, rube, mcp, composio, messages, channels, roles, webhooks |
| `docusign-automation` | Automate DocuSign tasks via Rube MCP (Composio): templates, envelopes, signatures, document management. Always search tools first for current schemas. | docusign | docusign, automation, automate, tasks, via, rube, mcp, composio, envelopes, signatures, document, always |
| `dropbox-automation` | Automate Dropbox file management, sharing, search, uploads, downloads, and folder operations via Rube MCP (Composio). Always search tools first for current s... | dropbox | dropbox, automation, automate, file, sharing, search, uploads, downloads, folder, operations, via, rube |
| `email-sequence` | When the user wants to create or optimize an email sequence, drip campaign, automated email flow, or lifecycle email program. Also use when the user mentions... | email, sequence | email, sequence, user, wants, optimize, drip, campaign, automated, flow, lifecycle, program, mentions |
| `figma-automation` | Automate Figma tasks via Rube MCP (Composio): files, components, design tokens, comments, exports. Always search tools first for current schemas. | figma | figma, automation, automate, tasks, via, rube, mcp, composio, files, components, tokens, comments |
| `freshdesk-automation` | Automate Freshdesk helpdesk operations including tickets, contacts, companies, notes, and replies via Rube MCP (Composio). Always search tools first for curr... | freshdesk | freshdesk, automation, automate, helpdesk, operations, including, tickets, contacts, companies, notes, replies, via |
| `full-stack-orchestration-full-stack-feature` | Use when working with full stack orchestration full stack feature | full, stack | full, stack, orchestration, feature, working |
| `git-pushing` | Stage, commit, and push git changes with conventional commit messages. Use when user wants to commit and push changes, mentions pushing to remote, or asks to... | git, pushing | git, pushing, stage, commit, push, changes, conventional, messages, user, wants, mentions, remote |
| `gitlab-automation` | Automate GitLab project management, issues, merge requests, pipelines, branches, and user operations via Rube MCP (Composio). Always search tools first for c... | gitlab | gitlab, automation, automate, issues, merge, requests, pipelines, branches, user, operations, via, rube |
| `gmail-automation` | Automate Gmail tasks via Rube MCP (Composio): send/reply, search, labels, drafts, attachments. Always search tools first for current schemas. | gmail | gmail, automation, automate, tasks, via, rube, mcp, composio, send, reply, search, labels |
| `google-calendar-automation` | Automate Google Calendar events, scheduling, availability checks, and attendee management via Rube MCP (Composio). Create events, find free slots, manage att... | google, calendar | google, calendar, automation, automate, events, scheduling, availability, checks, attendee, via, rube, mcp |
| `google-drive-automation` | Automate Google Drive file operations (upload, download, search, share, organize) via Rube MCP (Composio). Upload/download files, manage folders, share with ... | google, drive | google, drive, automation, automate, file, operations, upload, download, search, share, organize, via |
| `helpdesk-automation` | Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for... | helpdesk | helpdesk, automation, automate, tasks, via, rube, mcp, composio, list, tickets, views, canned |
| `hubspot-automation` | Automate HubSpot CRM operations (contacts, companies, deals, tickets, properties) via Rube MCP using Composio integration. | hubspot | hubspot, automation, automate, crm, operations, contacts, companies, deals, tickets, properties, via, rube |
| `instagram-automation` | Automate Instagram tasks via Rube MCP (Composio): create posts, carousels, manage media, get insights, and publishing limits. Always search tools first for c... | instagram | instagram, automation, automate, tasks, via, rube, mcp, composio, posts, carousels, media, get |
| `intercom-automation` | Automate Intercom tasks via Rube MCP (Composio): conversations, contacts, companies, segments, admins. Always search tools first for current schemas. | intercom | intercom, automation, automate, tasks, via, rube, mcp, composio, conversations, contacts, companies, segments |
| `jira-automation` | Automate Jira tasks via Rube MCP (Composio): issues, projects, sprints, boards, comments, users. Always search tools first for current schemas. | jira | jira, automation, automate, tasks, via, rube, mcp, composio, issues, sprints, boards, comments |
| `kaizen` | Guide for continuous improvement, error proofing, and standardization. Use this skill when the user wants to improve code quality, refactor, or discuss proce... | kaizen | kaizen, continuous, improvement, error, proofing, standardization, skill, user, wants, improve, code, quality |
| `klaviyo-automation` | Automate Klaviyo tasks via Rube MCP (Composio): manage email/SMS campaigns, inspect campaign messages, track tags, and monitor send jobs. Always search tools... | klaviyo | klaviyo, automation, automate, tasks, via, rube, mcp, composio, email, sms, campaigns, inspect |
| `linear-automation` | Automate Linear tasks via Rube MCP (Composio): issues, projects, cycles, teams, labels. Always search tools first for current schemas. | linear | linear, automation, automate, tasks, via, rube, mcp, composio, issues, cycles, teams, labels |
| `linkedin-automation` | Automate LinkedIn tasks via Rube MCP (Composio): create posts, manage profile, company info, comments, and image uploads. Always search tools first for curre... | linkedin | linkedin, automation, automate, tasks, via, rube, mcp, composio, posts, profile, company, info |
| `make-automation` | Automate Make (Integromat) tasks via Rube MCP (Composio): operations, enums, language and timezone lookups. Always search tools first for current schemas. | make | make, automation, automate, integromat, tasks, via, rube, mcp, composio, operations, enums, language |
| `mermaid-expert` | Create Mermaid diagrams for flowcharts, sequences, ERDs, and architectures. Masters syntax for all diagram types and styling. Use PROACTIVELY for visual docu... | mermaid | mermaid, diagrams, flowcharts, sequences, erds, architectures, masters, syntax, all, diagram, types, styling |
| `pdf` | Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs ... | pdf | pdf, manipulation, toolkit, extracting, text, tables, creating, new, pdfs, merging, splitting, documents |
| `microsoft-teams-automation` | Automate Microsoft Teams tasks via Rube MCP (Composio): send messages, manage channels, create meetings, handle chats, and search messages. Always search too... | microsoft, teams | microsoft, teams, automation, automate, tasks, via, rube, mcp, composio, send, messages, channels |
| `miro-automation` | Automate Miro tasks via Rube MCP (Composio): boards, items, sticky notes, frames, sharing, connectors. Always search tools first for current schemas. | miro | miro, automation, automate, tasks, via, rube, mcp, composio, boards, items, sticky, notes |
| `mixpanel-automation` | Automate Mixpanel tasks via Rube MCP (Composio): events, segmentation, funnels, cohorts, user profiles, JQL queries. Always search tools first for current sc... | mixpanel | mixpanel, automation, automate, tasks, via, rube, mcp, composio, events, segmentation, funnels, cohorts |
| `monday-automation` | Automate Monday.com work management including boards, items, columns, groups, subitems, and updates via Rube MCP (Composio). Always search tools first for cu... | monday | monday, automation, automate, com, work, including, boards, items, columns, groups, subitems, updates |
| `notion-automation` | Automate Notion tasks via Rube MCP (Composio): pages, databases, blocks, comments, users. Always search tools first for current schemas. | notion | notion, automation, automate, tasks, via, rube, mcp, composio, pages, databases, blocks, comments |
| `one-drive-automation` | Automate OneDrive file management, search, uploads, downloads, sharing, permissions, and folder operations via Rube MCP (Composio). Always search tools first... | one, drive | one, drive, automation, automate, onedrive, file, search, uploads, downloads, sharing, permissions, folder |
| `outlook-automation` | Automate Outlook tasks via Rube MCP (Composio): emails, calendar, contacts, folders, attachments. Always search tools first for current schemas. | outlook | outlook, automation, automate, tasks, via, rube, mcp, composio, emails, calendar, contacts, folders |
| `outlook-calendar-automation` | Automate Outlook Calendar tasks via Rube MCP (Composio): create events, manage attendees, find meeting times, and handle invitations. Always search tools fir... | outlook, calendar | outlook, calendar, automation, automate, tasks, via, rube, mcp, composio, events, attendees, find |
| `pagerduty-automation` | Automate PagerDuty tasks via Rube MCP (Composio): manage incidents, services, schedules, escalation policies, and on-call rotations. Always search tools firs... | pagerduty | pagerduty, automation, automate, tasks, via, rube, mcp, composio, incidents, schedules, escalation, policies |
| `pdf-official` | Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs ... | pdf, official | pdf, official, manipulation, toolkit, extracting, text, tables, creating, new, pdfs, merging, splitting |
| `posthog-automation` | Automate PostHog tasks via Rube MCP (Composio): events, feature flags, projects, user profiles, annotations. Always search tools first for current schemas. | posthog | posthog, automation, automate, tasks, via, rube, mcp, composio, events, feature, flags, user |
| `postmark-automation` | Automate Postmark email delivery tasks via Rube MCP (Composio): send templated emails, manage templates, monitor delivery stats and bounces. Always search to... | postmark | postmark, automation, automate, email, delivery, tasks, via, rube, mcp, composio, send, templated |
| `reddit-automation` | Automate Reddit tasks via Rube MCP (Composio): search subreddits, create posts, manage comments, and browse top content. Always search tools first for curren... | reddit | reddit, automation, automate, tasks, via, rube, mcp, composio, search, subreddits, posts, comments |
| `render-automation` | Automate Render tasks via Rube MCP (Composio): services, deployments, projects. Always search tools first for current schemas. | render | render, automation, automate, tasks, via, rube, mcp, composio, deployments, always, search, first |
| `salesforce-automation` | Automate Salesforce tasks via Rube MCP (Composio): leads, contacts, accounts, opportunities, SOQL queries. Always search tools first for current schemas. | salesforce | salesforce, automation, automate, tasks, via, rube, mcp, composio, leads, contacts, accounts, opportunities |
| `segment-automation` | Automate Segment tasks via Rube MCP (Composio): track events, identify users, manage groups, page views, aliases, batch operations. Always search tools first... | segment | segment, automation, automate, tasks, via, rube, mcp, composio, track, events, identify, users |
| `sentry-automation` | Automate Sentry tasks via Rube MCP (Composio): manage issues/events, configure alerts, track releases, monitor projects and teams. Always search tools first ... | sentry | sentry, automation, automate, tasks, via, rube, mcp, composio, issues, events, configure, alerts |
| `shopify-automation` | Automate Shopify tasks via Rube MCP (Composio): products, orders, customers, inventory, collections. Always search tools first for current schemas. | shopify | shopify, automation, automate, tasks, via, rube, mcp, composio, products, orders, customers, inventory |
| `skill-creator` | This skill should be used when the user asks to create a new skill, build a skill, make a custom skill, develop a CLI skill, or wants to extend the CLI with ... | automation, scaffolding, skill-creation, meta-skill | automation, scaffolding, skill-creation, meta-skill, skill, creator, should, used, user, asks, new, custom |
| `square-automation` | Automate Square tasks via Rube MCP (Composio): payments, orders, invoices, locations. Always search tools first for current schemas. | square | square, automation, automate, tasks, via, rube, mcp, composio, payments, orders, invoices, locations |
| `stripe-automation` | Automate Stripe tasks via Rube MCP (Composio): customers, charges, subscriptions, invoices, products, refunds. Always search tools first for current schemas. | stripe | stripe, automation, automate, tasks, via, rube, mcp, composio, customers, charges, subscriptions, invoices |
| `team-collaboration-issue` | You are a GitHub issue resolution expert specializing in systematic bug investigation, feature implementation, and collaborative development workflows. Your ... | team, collaboration, issue | team, collaboration, issue, github, resolution, specializing, systematic, bug, investigation, feature, collaborative, development |
| `telegram-automation` | Automate Telegram tasks via Rube MCP (Composio): send messages, manage chats, share photos/documents, and handle bot commands. Always search tools first for ... | telegram | telegram, automation, automate, tasks, via, rube, mcp, composio, send, messages, chats, share |
| `tiktok-automation` | Automate TikTok tasks via Rube MCP (Composio): upload/publish videos, post photos, manage content, and view user profiles/stats. Always search tools first fo... | tiktok | tiktok, automation, automate, tasks, via, rube, mcp, composio, upload, publish, videos, post |
| `todoist-automation` | Automate Todoist task management, projects, sections, filtering, and bulk operations via Rube MCP (Composio). Always search tools first for current schemas. | todoist | todoist, automation, automate, task, sections, filtering, bulk, operations, via, rube, mcp, composio |
| `track-management` | Use this skill when creating, managing, or working with Conductor tracks - the logical work units for features, bugs, and refactors. Applies to spec.md, plan... | track | track, skill, creating, managing, working, conductor, tracks, logical, work, units, features, bugs |
| `trello-automation` | Automate Trello boards, cards, and workflows via Rube MCP (Composio). Create cards, manage lists, assign members, and search across boards programmatically. | trello | trello, automation, automate, boards, cards, via, rube, mcp, composio, lists, assign, members |
| `twitter-automation` | Automate Twitter/X tasks via Rube MCP (Composio): posts, search, users, bookmarks, lists, media. Always search tools first for current schemas. | twitter | twitter, automation, automate, tasks, via, rube, mcp, composio, posts, search, users, bookmarks |
| `vercel-automation` | Automate Vercel tasks via Rube MCP (Composio): manage deployments, domains, DNS, env vars, projects, and teams. Always search tools first for current schemas. | vercel | vercel, automation, automate, tasks, via, rube, mcp, composio, deployments, domains, dns, env |
| `webflow-automation` | Automate Webflow CMS collections, site publishing, page management, asset uploads, and ecommerce orders via Rube MCP (Composio). Always search tools first fo... | webflow | webflow, automation, automate, cms, collections, site, publishing, page, asset, uploads, ecommerce, orders |
| `wrike-automation` | Automate Wrike project management via Rube MCP (Composio): create tasks/folders, manage projects, assign work, and track progress. Always search tools first ... | wrike | wrike, automation, automate, via, rube, mcp, composio, tasks, folders, assign, work, track |
| `zendesk-automation` | Automate Zendesk tasks via Rube MCP (Composio): tickets, users, organizations, replies. Always search tools first for current schemas. | zendesk | zendesk, automation, automate, tasks, via, rube, mcp, composio, tickets, users, organizations, replies |
| `zoho-crm-automation` | Automate Zoho CRM tasks via Rube MCP (Composio): create/update records, search contacts, manage leads, and convert leads. Always search tools first for curre... | zoho, crm | zoho, crm, automation, automate, tasks, via, rube, mcp, composio, update, records, search |
| `zoom-automation` | Automate Zoom meeting creation, management, recordings, webinars, and participant tracking via Rube MCP (Composio). Always search tools first for current sch... | zoom | zoom, automation, automate, meeting, creation, recordings, webinars, participant, tracking, via, rube, mcp |

View File

@@ -7,8 +7,173 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
---
## [4.11.0] - 2026-02-08 - "Clean Code & Registry Stability"
> Quality improvements: Clean Code principles and deterministic builds.
### Changed
- **`clean-code` skill** - Complete rewrite based on Robert C. Martin's "Clean Code":
- Systematic coverage: Meaningful names, functions, comments, formatting, objects, error handling, unit tests, and classes
- Added F.I.R.S.T. test principles and Law of Demeter guidance
- Fixed invalid heading format (`## ## When to Use``## When to Use`) that blocked validation
- Added implementation checklist and code smell detection
- **Registry Stabilization** - Fixed `scripts/build-catalog.js` for deterministic CI builds:
- Uses `SOURCE_DATE_EPOCH` environment variable for reproducible timestamps
- Replaced `localeCompare` with explicit comparator for consistent sorting across environments
- Prevents CI validation failures caused by timestamp drift
### Contributors
- [@jackjin1997](https://github.com/jackjin1997) - Clean Code skill update and registry fixes (PR #69, forged at [ClawForge](https://github.com/jackjin1997/ClawForge))
---
## [4.10.0] - 2026-02-06 - "Composio Automation + .NET Backend"
> A major expansion focused on practical app automation and stronger backend engineering coverage.
### Added
- **79 new skills total**.
- **78 Composio/Rube automation skills** (PR #64), with operational playbooks for:
- CRM and sales stacks (`HubSpot`, `Pipedrive`, `Salesforce`, `Zoho CRM`, `Close`).
- Collaboration and project tools (`Notion`, `ClickUp`, `Asana`, `Jira`, `Confluence`, `Trello`, `Monday`).
- Messaging and support channels (`Slack`, `Discord`, `Teams`, `Intercom`, `Freshdesk`, `Zendesk`).
- Marketing and analytics systems (`Google Analytics`, `Mixpanel`, `PostHog`, `Segment`, `Mailchimp`, `Klaviyo`).
- Infra/dev tooling (`GitHub`, `GitLab`, `CircleCI`, `Datadog`, `PagerDuty`, `Vercel`, `Render`).
- **1 new `dotnet-backend` skill** (PR #65) with:
- ASP.NET Core 8+ API patterns (Minimal APIs + controller-based).
- EF Core usage guidance, JWT auth examples, and background worker templates.
- Explicit trigger guidance and documented limitations.
- **Registry size increased to 713 skills** (from 634).
### Changed
- Regenerated and synced discovery artifacts after merging both PRs:
- `README.md` (counts + contributor updates)
- `skills_index.json`
- `CATALOG.md`
- `data/catalog.json`
- `data/bundles.json`
- `data/aliases.json`
- Release metadata updated for `v4.10.0`:
- `package.json` / `package-lock.json` version bump
- GitHub Release object published with release notes
### Contributors
- [@sohamganatra](https://github.com/sohamganatra) - 78 Composio automation skills (PR #64)
- [@Nguyen-Van-Chan](https://github.com/Nguyen-Van-Chan) - .NET backend skill (PR #65)
## [4.9.0] - 2026-02-05 - "OSS Hunter & Universal Skills"
> Automated contribution hunting and universal CLI AI skills (Audio, YouTube, Prompt Engineering).
### Added
- **New Skill**: `oss-hunter` Automated tool for finding high-impact Open Source contributions (Good First Issues, Help Wanted) in trending repositories.
- **New Skill**: `audio-transcriber` Transform audio recordings into professional Markdown with Whisper integration.
- **New Skill**: `youtube-summarizer` Generate comprehensive summaries/notes from YouTube videos.
- **New Skill**: `prompt-engineer` (Enhanced) Now includes 11 optimization frameworks (RTF, RISEN, etc.).
- **Registry**: 634 skills (from 626). Catalog regenerated.
### Changed
- **CLI AI Skills**: Merged core skills from `ericgandrade/cli-ai-skills`.
### Contributors
- [@jackjin1997](https://github.com/jackjin1997) - OSS Hunter (PR #61)
- [@ericgandrade](https://github.com/ericgandrade) - CLI AI Skills (PR #62)
## [4.7.0] - 2026-02-03 - "Installer Fix & OpenCode Docs"
> Critical installer fix for Windows and OpenCode documentation completion.
### Fixed
- **Installer**: Resolved `ReferenceError` for `tagArg` variable in `bin/install.js` ensuring correct execution on Windows/PowerShell (PR #53).
### Documentation
- **OpenCode**: Completed documentation for OpenCode integration in `README.md`.
---
## [4.6.0] - 2026-02-01 - "SPDD & Radix UI Design System"
> Agent workflow docs (SPDD) and Radix UI design system skill.
### Added
- **New Skill**: `radix-ui-design-system` Build accessible design systems with Radix UI primitives (headless, theming, WCAG, examples).
- **Docs**: `skills/SPDD/` Research, spec, and implementation workflow docs (1-research.md, 2-spec.md, 3-implementation.md).
### Registry
- **Total Skills**: 626 (from 625). Catalog regenerated.
---
## [4.5.0] - 2026-01-31 - "Stitch UI Design"
> Expert prompting guide for Google Stitch AI-powered UI design tool.
### Added
- **New Skill**: `stitch-ui-design` Expert guide for creating effective prompts for Google Stitch AI UI design tool (Gemini 2.5 Flash). Covers prompt structure, specificity techniques, iteration strategies, design-to-code workflows, and 10+ examples for landing pages, mobile apps, and dashboards.
### Changed
- **Documentation**: Clarified in README.md and GETTING_STARTED.md that installation means cloning the full repo once; Starter Packs are curated lists to discover skills by role, not a different installation method (fixes [#44](https://github.com/sickn33/antigravity-awesome-skills/issues/44)).
### Registry
- **Total Skills**: 625 (from 624). Catalog regenerated.
### Credits
- [@ALEKGG1](https://github.com/ALEKGG1) stitch-ui-design (PR #45)
- [@CypherPoet](https://github.com/CypherPoet) Documentation clarity (#44)
---
## [4.4.0] - 2026-01-30 - "fp-ts skills for TypeScript"
> Three practical fp-ts skills for TypeScript functional programming.
### Added
- **New Skills** (from [whatiskadudoing/fp-ts-skills](https://github.com/whatiskadudoing/fp-ts-skills)):
- `fp-ts-pragmatic` Pipe, Option, Either, TaskEither without academic jargon.
- `fp-ts-react` Patterns for fp-ts with React 18/19 and Next.js 14/15 (state, forms, data fetching).
- `fp-ts-errors` Type-safe error handling with Either and TaskEither.
### Registry
- **Total Skills**: 624 (from 621). Catalog regenerated.
---
## [4.3.0] - 2026-01-29 - "VoltAgent Integration & Context Engineering Suite"
> 61 new skills from VoltAgent/awesome-agent-skills: official team skills and context engineering suite.
### Added
- **61 new skills** from [VoltAgent/awesome-agent-skills](https://github.com/VoltAgent/awesome-agent-skills):
- **Official (27)**: Sentry (commit, create-pr, find-bugs, iterate-pr), Trail of Bits (culture-index, fix-review, sharp-edges), Expo (expo-deployment, upgrading-expo), Hugging Face (hugging-face-cli, hugging-face-jobs), Vercel, Google Stitch (design-md), Neon (using-neon), n8n (n8n-code-python, n8n-mcp-tools-expert, n8n-node-configuration), SwiftUI, fal.ai (fal-audio, fal-generate, fal-image-edit, fal-platform, fal-upscale, fal-workflow), deep-research, imagen, readme.
- **Community (34)**: Context suite (context-fundamentals, context-degradation, context-compression, context-optimization, multi-agent-patterns, memory-systems, evaluation), frontend-slides, linear-claude-skill, skill-rails-upgrade, terraform-skill, tool-design, screenshots, automate-whatsapp, observe-whatsapp, aws-skills, ui-skills, vexor, pypict-skill, makepad-skills, threejs-skills, claude-scientific-skills, claude-win11-speckit-update-skill, security-bluebook-builder, claude-ally-health, clarity-gate, beautiful-prose, claude-speed-reader, skill-seekers, varlock-claude-skill, superpowers-lab, nanobanana-ppt-skills, x-article-publisher-skill, ffuf-claude-skill.
### Registry
- **Total Skills**: 614 (from 553). Catalog and SOURCES.md updated.
### Credits
- VoltAgent/awesome-agent-skills and official teams (Sentry, Trail of Bits, Expo, Hugging Face, Vercel Labs, Google Labs, Neon, fal.ai).
---
## [4.0.0] - 2026-01-28 - "The Enterprise Era"
@@ -120,7 +285,7 @@ The following skills are now correctly indexed and visible in the registry:
- **Documentation**:
- `docs/EXAMPLES.md`: Cookbook with 3 real-world scenarios.
- `docs/SOURCES.md`: Legal ledger for attributions and licenses.
- `RELEASE_NOTES.md`: Generated release announcement (archived).
- Release announcements are documented in this CHANGELOG.
### Changed

View File

@@ -48,6 +48,23 @@ You don't need to be an expert! Here are ways anyone can help:
---
## Local development setup
To run validation, index generation, and README updates locally:
1. **Node.js** (for catalog and installer): `npm ci`
2. **Python 3** (for validate, index, readme scripts): install dependencies with
```bash
pip install -r requirements.txt
```
Then you can run `npm run chain` (validate → index → readme) and `npm run catalog`.
**Validation:** The canonical validator is **Python** (`scripts/validate_skills.py`). Use `npm run validate` (or `npm run validate:strict` for CI-style checks). The JavaScript validator (`scripts/validate-skills.js`) is legacy/optional and uses a different schema; CI and PR checks rely on the Python validator only.
**npm audit:** CI runs `npm audit --audit-level=high`. To fix issues locally: run `npm audit`, then `npm update` or `npm audit fix` as appropriate; for breaking changes, update dependencies manually and run tests.
---
## How to Create a New Skill
### Step-by-Step Guide

View File

@@ -1,71 +0,0 @@
# Conteggio Finale Skills da Committare
**Data**: 2026-01-30
**Verifica**: Git Status
## Risultato Verifica Git
Dalla verifica dello stato git (`git status --porcelain`):
### Skills Non Committate (Untracked - `??`)
Tutte le skills con status `??` sono **nuove skills non ancora tracciate da git**.
### Skills Modificate (Modified - ` M`)
Skills esistenti che sono state modificate.
## Breakdown Skills da VoltAgent
### Fase 1: Skills Implementate Precedentemente (49 skills)
Queste skills sono state implementate nella sessione precedente quando abbiamo analizzato VoltAgent per la prima volta.
**Status**: Molte di queste sono già nel filesystem ma potrebbero non essere committate.
### Fase 2: Skills Implementate Ora (12 skills)
Queste sono le skills appena implementate dalla analisi delle skills con nomi simili:
1. `frontend-slides`
2. `linear-claude-skill`
3. `skill-rails-upgrade`
4. `context-fundamentals`
5. `context-degradation`
6. `context-compression`
7. `context-optimization`
8. `multi-agent-patterns`
9. `tool-design`
10. `evaluation`
11. `memory-systems`
12. `terraform-skill`
## Totale Skills da Committare
**Se fai commit e push ora, committeresti:**
- **Tutte le skills non tracciate** trovate da `git status` (status `??`)
- **Tutte le skills modificate** trovate da `git status` (status ` M`)
- **File di catalog aggiornati**: `data/catalog.json`, `data/skills_index.json`, `CATALOG.md`
- **File di attribuzione aggiornato**: `docs/SOURCES.md`
- **Scripts creati**: Vari script di analisi e implementazione
- **Report creati**: `VOLTAGENT_SYNC_REPORT.md`, `SIMILAR_SKILLS_ANALYSIS_REPORT.md`, `SIMILAR_SKILLS_IMPLEMENTATION_REPORT.md`, `HTML_CONVERSION_REPORT.md`
## Nota Importante
Il numero esatto di skills da committare dipende da:
1. Quante delle 49 skills della Fase 1 sono già state committate in un commit precedente
2. Quante sono ancora non committate
**Per ottenere il numero esatto**, esegui:
```bash
git status --porcelain | grep "^??" | grep "skills/" | sed 's|^?? skills/||' | sed 's|/.*||' | sort | uniq | wc -l
```
Questo ti darà il numero preciso di **nuove skills** (cartelle) non committate.
## Raccomandazione
Prima di fare commit:
1. ✅ Esegui `npm run chain` per validare e aggiornare i file generati
2. ✅ Esegui `npm run catalog` per rigenerare il catalog
3. ✅ Verifica che tutti i file generati siano inclusi nel commit
4. ✅ Controlla che tutte le skills abbiano frontmatter corretto e "When to Use" section

View File

@@ -1,240 +0,0 @@
# HTML to Markdown Conversion Report
**Date**: 2026-01-30
**Skills Converted**: 24
**Status**: ✅ Completed Successfully
## Executive Summary
Successfully converted 24 skills from HTML content (GitHub page HTML) to clean markdown format. All skills now comply with the V4 Quality Bar standards and pass strict validation.
### Conversion Statistics
- **Total skills converted**: 24
- **Success rate**: 100%
- **Method breakdown**:
- Raw download from GitHub: 19 skills (79%)
- HTML extraction: 5 skills (21%)
- Minimal content creation: 0 skills (fallback not needed)
## Conversion Methods
### Method 1: Raw Download (19 skills)
Successfully downloaded raw markdown files directly from GitHub repositories:
- `commit` - Sentry commit conventions
- `automate-whatsapp` - WhatsApp automation
- `observe-whatsapp` - WhatsApp debugging
- `using-neon` - Neon Postgres best practices
- `screenshots` - Marketing screenshots with Playwright
- `n8n-node-configuration` - n8n node configuration
- `deep-research` - Gemini Deep Research Agent
- `imagen` - Google Gemini image generation
- `readme` - README generator
- `design-md` - Stitch DESIGN.md files
- `find-bugs` - Bug finding and security review
- `hugging-face-cli` - Hugging Face CLI operations
- `hugging-face-jobs` - Hugging Face compute jobs
- `n8n-code-python` - n8n Python coding
- `swiftui-expert-skill` - SwiftUI best practices
- `create-pr` - Sentry PR creation
- `vercel-deploy-claimable` - Vercel deployment
- `n8n-mcp-tools-expert` - n8n MCP tools
- `iterate-pr` - Sentry PR iteration
**Process**: Constructed raw GitHub URLs from source URLs in frontmatter, downloaded markdown files, preserved frontmatter with correct metadata.
### Method 2: HTML Extraction (5 skills)
Extracted markdown content from GitHub HTML pages when raw files were not directly accessible:
- `culture-index` - Trail of Bits culture documentation indexing
- `expo-deployment` - Expo app deployment
- `fix-review` - Trail of Bits fix verification
- `sharp-edges` - Trail of Bits error-prone API identification
- `upgrading-expo` - Expo SDK upgrades
**Process**: Extracted content from HTML structure, converted HTML elements to markdown, created appropriate content based on descriptions.
**Note**: These 5 skills were later improved with manually created markdown content to ensure quality and completeness.
## Corrections Applied
### Frontmatter Fixes
1. **Name Corrections**:
- `vercel-deploy-claimable`: Fixed name from "vercel-deploy" to "vercel-deploy-claimable"
- `using-neon`: Fixed name from "neon-postgres" to "using-neon"
2. **Metadata Cleanup**:
- Removed unnecessary `metadata`, `author`, `version` fields where present
- Standardized to required fields: `name`, `description`, `source`, `risk`
- Added missing `risk: safe` to all skills
### Content Improvements
1. **Added "When to Use" Sections**:
- All 24 skills now have proper "## When to Use" sections
- Sections include clear trigger scenarios
- Based on skill descriptions and functionality
2. **Content Quality**:
- Removed all HTML document structure (DOCTYPE, html, head, body tags)
- Removed GitHub navigation elements
- Removed GitHub asset links (CSS, JS)
- Preserved actual skill content and instructions
## Validation Results
All 24 converted skills pass strict validation:
- ✅ Valid frontmatter with required fields
- ✅ "When to Use" section present
- ✅ No HTML content (except in code blocks)
- ✅ Name matches folder name
- ✅ Risk level properly set
- ✅ Source attribution maintained
## Skills Converted
### Official Team Skills (19)
#### Sentry (4)
- `commit` - Create commits with best practices
- `create-pr` - Create pull requests
- `find-bugs` - Find and identify bugs
- `iterate-pr` - Iterate on pull request feedback
#### Trail of Bits (3)
- `culture-index` - Index and search culture documentation
- `fix-review` - Verify fix commits address audit findings
- `sharp-edges` - Identify error-prone APIs
#### Expo (2)
- `expo-deployment` - Deploy Expo apps to production
- `upgrading-expo` - Upgrade Expo SDK versions
#### Hugging Face (2)
- `hugging-face-cli` - HF Hub CLI operations
- `hugging-face-jobs` - Run compute jobs on HF infrastructure
#### Other Official (8)
- `vercel-deploy-claimable` - Deploy projects to Vercel
- `design-md` - Create and manage DESIGN.md files
- `using-neon` - Neon Postgres best practices
- `n8n-code-python` - Python in n8n Code nodes
- `n8n-mcp-tools-expert` - n8n MCP tools guide
- `n8n-node-configuration` - n8n node configuration
- `swiftui-expert-skill` - SwiftUI best practices
- `deep-research` - Gemini Deep Research Agent
### Community Skills (5)
- `automate-whatsapp` - Build WhatsApp automations
- `observe-whatsapp` - Debug WhatsApp delivery issues
- `readme` - Generate comprehensive project documentation
- `screenshots` - Generate marketing screenshots
- `imagen` - Generate images using Google Gemini
## Files Created/Modified
### Scripts Created
- `scripts/convert_html_to_markdown.py` - Main conversion script
- `scripts/check_html_content.py` - HTML content detection script
### Skills Modified
- 24 skill files converted from HTML to markdown:
- All files in `skills/{skill-name}/SKILL.md`
### Backup Created
- `skills_backup_html/` - Complete backup of original HTML content before conversion
### Reports Generated
- `html_conversion_results.json` - Detailed conversion results
- `html_content_analysis.json` - HTML content analysis
- `HTML_CONVERSION_REPORT.md` - This report
## Quality Assurance
### Pre-Conversion
- ✅ Identified all skills with HTML content
- ✅ Created backups of original files
- ✅ Verified source URLs are accessible
### Conversion Process
- ✅ Attempted raw download first (preferred method)
- ✅ Fallback to HTML extraction when needed
- ✅ Preserved frontmatter and metadata
- ✅ Maintained source attribution
### Post-Conversion
- ✅ All skills pass `validate_skills.py --strict`
- ✅ No HTML content remaining (except in code blocks)
- ✅ All required sections present
- ✅ Frontmatter correctly formatted
- ✅ Names match folder names
## Technical Details
### HTML Detection
Skills were identified as having HTML content if they contained:
- `<!DOCTYPE html>` declarations
- `<html>` tags
- GitHub asset links (`github.githubassets.com`)
- GitHub navigation elements
### Conversion Process
1. **Parse frontmatter** - Extract and preserve metadata
2. **Build raw URL** - Convert GitHub tree/blob URLs to raw URLs
3. **Download raw** - Attempt to download markdown file
4. **Extract from HTML** - If raw unavailable, extract from HTML structure
5. **Create minimal** - If extraction fails, create from description
6. **Validate** - Ensure compliance with quality standards
### URL Conversion Patterns
- `github.com/org/repo/tree/main/path``raw.githubusercontent.com/org/repo/main/path/SKILL.md`
- `github.com/org/repo/blob/main/path/SKILL.md``raw.githubusercontent.com/org/repo/main/path/SKILL.md`
## Issues Resolved
### Issue 1: HTML Content in Skills
**Problem**: 24 skills contained full GitHub page HTML instead of markdown
**Solution**: Converted all HTML to clean markdown using multiple methods
**Status**: ✅ Resolved
### Issue 2: Missing "When to Use" Sections
**Problem**: Some downloaded raw files didn't have "When to Use" sections
**Solution**: Added appropriate "When to Use" sections to all skills
**Status**: ✅ Resolved
### Issue 3: Frontmatter Name Mismatches
**Problem**: Some skills had names in frontmatter that didn't match folder names
**Solution**: Corrected frontmatter names to match folder names
**Status**: ✅ Resolved
### Issue 4: Missing Risk Labels
**Problem**: Some skills were missing risk labels
**Solution**: Added `risk: safe` to all skills
**Status**: ✅ Resolved
## Next Steps
1. ✅ All conversions completed
2. ✅ All validations passed
3. ✅ Report generated
4. ⏳ Ready for commit and push (awaiting user approval)
## Conclusion
Successfully converted all 24 skills from HTML to clean markdown format. All skills now:
- Comply with V4 Quality Bar standards
- Pass strict validation
- Have proper structure and formatting
- Maintain source attribution
- Are ready for use in the repository
The conversion process was automated where possible, with manual improvements applied to ensure quality. All original content has been backed up for reference.

328
README.md
View File

@@ -1,6 +1,6 @@
# 🌌 Antigravity Awesome Skills: 614+ Agentic Skills for Claude Code, Gemini CLI, Cursor, Copilot & More
# 🌌 Antigravity Awesome Skills: 713+ Agentic Skills for Claude Code, Gemini CLI, Cursor, Copilot & More
> **The Ultimate Collection of 614+ Universal Agentic Skills for AI Coding Assistants — Claude Code, Gemini CLI, Codex CLI, Antigravity IDE, GitHub Copilot, Cursor, OpenCode**
> **The Ultimate Collection of 713+ Universal Agentic Skills for AI Coding Assistants — Claude Code, Gemini CLI, Codex CLI, Antigravity IDE, GitHub Copilot, Cursor, OpenCode, AdaL**
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Claude Code](https://img.shields.io/badge/Claude%20Code-Anthropic-purple)](https://claude.ai)
@@ -10,8 +10,13 @@
[![Copilot](https://img.shields.io/badge/GitHub%20Copilot-VSCode-lightblue)](https://github.com/features/copilot)
[![OpenCode](https://img.shields.io/badge/OpenCode-CLI-gray)](https://github.com/opencode-ai/opencode)
[![Antigravity](https://img.shields.io/badge/Antigravity-DeepMind-red)](https://github.com/sickn33/antigravity-awesome-skills)
[![AdaL CLI](https://img.shields.io/badge/AdaL%20CLI-SylphAI-pink)](https://sylph.ai/)
[![ASK Supported](https://img.shields.io/badge/ASK-Supported-blue)](https://github.com/yeasy/ask)
[![Buy Me a Book](https://img.shields.io/badge/Buy%20me%20a-book-d13610?logo=buymeacoffee&logoColor=white)](https://buymeacoffee.com/sickn33)
**Antigravity Awesome Skills** is a curated, battle-tested library of **614 high-performance agentic skills** designed to work seamlessly across all major AI coding assistants:
If this project helps you, you can [support it here](https://buymeacoffee.com/sickn33) or simply ⭐ the repo.
**Antigravity Awesome Skills** is a curated, battle-tested library of **713 high-performance agentic skills** designed to work seamlessly across all major AI coding assistants:
- 🟣 **Claude Code** (Anthropic CLI)
- 🔵 **Gemini CLI** (Google DeepMind)
@@ -20,6 +25,7 @@
- 🩵 **GitHub Copilot** (VSCode Extension)
- 🟠 **Cursor** (AI-native IDE)
-**OpenCode** (Open-source CLI)
- 🌸 **AdaL CLI** (Self-evolving Coding Agent)
This repository provides essential skills to transform your AI assistant into a **full-stack digital agency**, including official capabilities from **Anthropic**, **OpenAI**, **Google**, **Supabase**, and **Vercel Labs**.
@@ -27,15 +33,19 @@ This repository provides essential skills to transform your AI assistant into a
- [🚀 New Here? Start Here!](#new-here-start-here)
- [🔌 Compatibility & Invocation](#compatibility--invocation)
- [📦 Features & Categories](#features--categories)
- [🎁 Curated Collections (Bundles)](#curated-collections)
- [📚 Browse 614+ Skills](#browse-614-skills)
- [🛠️ Installation](#installation)
- [🧯 Troubleshooting](#troubleshooting)
- [🎁 Curated Collections (Bundles)](#curated-collections)
- [📦 Features & Categories](#features--categories)
- [📚 Browse 713+ Skills](#browse-713-skills)
- [🤝 How to Contribute](#how-to-contribute)
- [🤝 Community](#community)
- [☕ Support the Project](#support-the-project)
- [👥 Contributors & Credits](#credits--sources)
- [⚖️ License](#license)
- [👥 Repo Contributors](#repo-contributors)
- [⚖️ License](#license)
- [🌟 Star History](#star-history)
- [🏷️ GitHub Topics](#github-topics)
---
@@ -50,22 +60,31 @@ This repository provides essential skills to transform your AI assistant into a
AI Agents (like Claude Code, Cursor, or Gemini) are smart, but they lack **specific tools**. They don't know your company's "Deployment Protocol" or the specific syntax for "AWS CloudFormation".
**Skills** are small markdown files that teach them how to do these specific tasks perfectly, every time.
### 2. ⚡️ Quick Start (The "Bundle" Way)
### 2. ⚡️ Quick Start (1 minute)
Don't install 614+ skills manually. Use our **Starter Packs**:
Install once; then use Starter Packs in [docs/BUNDLES.md](docs/BUNDLES.md) to focus on your role.
1. **Install** (pick one):
```bash
# Easiest: npx installer (clones to ~/.agent/skills by default)
npx antigravity-awesome-skills
1. **Install**:
# Or clone manually
git clone https://github.com/sickn33/antigravity-awesome-skills.git .agent/skills
```
2. **Pick your persona** (See [docs/BUNDLES.md](docs/BUNDLES.md)):
- **Web Dev?** use the `Web Wizard` pack.
- **Hacker?** use the `Security Engineer` pack.
- **Just curious?** start with `Essentials`.
```bash
# Default path: ~/.agent/skills
npx antigravity-awesome-skills
```
2. **Verify**:
```bash
test -d ~/.agent/skills && echo "Skills installed in ~/.agent/skills"
```
3. **Run your first skill**:
> "Use **@brainstorming** to plan a SaaS MVP."
4. **Pick a bundle**:
- **Web Dev?** start with `Web Wizard`.
- **Security?** start with `Security Engineer`.
- **General use?** start with `Essentials`.
### 3. 🧠 How to use
@@ -86,53 +105,25 @@ These skills follow the universal **SKILL.md** format and work with any AI codin
| :-------------- | :--- | :-------------------------------- | :---------------- |
| **Claude Code** | CLI | `>> /skill-name help me...` | `.claude/skills/` |
| **Gemini CLI** | CLI | `(User Prompt) Use skill-name...` | `.gemini/skills/` |
| **Codex CLI** | CLI | `(User Prompt) Use skill-name...` | `.codex/skills/` |
| **Antigravity** | IDE | `(Agent Mode) Use skill...` | `.agent/skills/` |
| **Cursor** | IDE | `@skill-name (in Chat)` | `.cursor/skills/` |
| **Copilot** | Ext | `(Paste content manually)` | N/A |
| **OpenCode** | CLI | `opencode run @skill-name` | `.agent/skills/` |
| **AdaL CLI** | CLI | `(Auto) Skills load on-demand` | `.adal/skills/` |
> [!TIP]
> **Universal Path**: We recommend cloning to `.agent/skills/`. Most modern tools (Antigravity, recent CLIs) look here by default.
> [!WARNING]
> **Windows Users**: This repository uses **symlinks** for official skills.
> The **npx** installer sets `core.symlinks=true` automatically. For **git clone**, enable Developer Mode or run Git as Administrator:
> `git clone -c core.symlinks=true https://github.com/...`
> **Windows Users**: this repository uses **symlinks** for official skills.
> See [Troubleshooting](#troubleshooting) for the exact fix.
---
Whether you are using **Gemini CLI**, **Claude Code**, **Codex CLI**, **Cursor**, **GitHub Copilot**, **Antigravity**, or **OpenCode**, these skills are designed to drop right in and supercharge your AI agent.
This repository aggregates the best capabilities from across the open-source community, transforming your AI assistant into a full-stack digital agency capable of Engineering, Design, Security, Marketing, and Autonomous Operations.
## Features & Categories
The repository is organized into specialized domains to transform your AI into an expert across the entire software development lifecycle:
| Category | Focus | Example skills |
| :--- | :--- | :--- |
| Architecture (52) | System design, ADRs, C4, and scalable patterns | `architecture`, `c4-context`, `senior-architect` |
| Business (35) | Growth, pricing, CRO, SEO, and go-to-market | `copywriting`, `pricing-strategy`, `seo-audit` |
| Data & AI (81) | LLM apps, RAG, agents, observability, analytics | `rag-engineer`, `prompt-engineer`, `langgraph` |
| Development (72) | Language mastery, framework patterns, code quality | `typescript-expert`, `python-patterns`, `react-patterns` |
| General (95) | Planning, docs, product ops, writing, guidelines | `brainstorming`, `doc-coauthoring`, `writing-plans` |
| Infrastructure (72) | DevOps, cloud, serverless, deployment, CI/CD | `docker-expert`, `aws-serverless`, `vercel-deployment` |
| Security (107) | AppSec, pentesting, vuln analysis, compliance | `api-security-best-practices`, `sql-injection-testing`, `vulnerability-scanner` |
| Testing (21) | TDD, test design, fixes, QA workflows | `test-driven-development`, `testing-patterns`, `test-fixing` |
| Workflow (17) | Automation, orchestration, jobs, agents | `workflow-automation`, `inngest`, `trigger-dev` |
## Curated Collections
[Check out our Starter Packs in docs/BUNDLES.md](docs/BUNDLES.md) to find the perfect toolkit for your role.
## Browse 614+ Skills
We have moved the full skill registry to a dedicated catalog to keep this README clean.
👉 **[View the Complete Skill Catalog (CATALOG.md)](CATALOG.md)**
## Installation
To use these skills with **Claude Code**, **Gemini CLI**, **Codex CLI**, **Cursor**, **Antigravity**, or **OpenCode**:
To use these skills with **Claude Code**, **Gemini CLI**, **Codex CLI**, **Cursor**, **Antigravity**, **OpenCode**, or **AdaL**:
### Option A: npx (recommended)
@@ -149,6 +140,12 @@ npx antigravity-awesome-skills --claude
# Gemini CLI
npx antigravity-awesome-skills --gemini
# Codex CLI
npx antigravity-awesome-skills --codex
# OpenCode (Universal)
npx antigravity-awesome-skills
# Custom path
npx antigravity-awesome-skills --path ./my-skills
```
@@ -167,12 +164,106 @@ git clone https://github.com/sickn33/antigravity-awesome-skills.git .claude/skil
# Gemini CLI specific
git clone https://github.com/sickn33/antigravity-awesome-skills.git .gemini/skills
# Codex CLI specific
git clone https://github.com/sickn33/antigravity-awesome-skills.git .codex/skills
# Cursor specific
git clone https://github.com/sickn33/antigravity-awesome-skills.git .cursor/skills
# OpenCode specific (Universal path)
git clone https://github.com/sickn33/antigravity-awesome-skills.git .agent/skills
```
---
## Troubleshooting
### `npx antigravity-awesome-skills` returns 404
Use the GitHub package fallback:
```bash
npx github:sickn33/antigravity-awesome-skills
```
### Windows clone issues (symlinks)
This repository uses symlinks for official skills. Enable Developer Mode or run Git as Administrator, then clone with:
```bash
git clone -c core.symlinks=true https://github.com/sickn33/antigravity-awesome-skills.git .agent/skills
```
### Skills installed but not detected by your tool
Install to the tool-specific path (for example `.claude/skills`, `.gemini/skills`, `.codex/skills`, `.cursor/skills`) or use the installer flags (`--claude`, `--gemini`, `--codex`, `--cursor`, `--path`).
### Update an existing installation
```bash
git -C ~/.agent/skills pull
```
### Reinstall from scratch
```bash
rm -rf ~/.agent/skills
npx antigravity-awesome-skills
```
---
## Curated Collections
**Bundles** are curated groups of skills for a specific role or goal (for example: `Web Wizard`, `Security Engineer`, `OSS Maintainer`).
They help you avoid picking from 700+ skills one by one.
What bundles are:
- Recommended starting sets for common workflows.
- A shortcut for onboarding and faster execution.
What bundles are not:
- Not a separate install.
- Not a locked preset.
How to use bundles:
1. Install the repository once.
2. Pick one bundle in [docs/BUNDLES.md](docs/BUNDLES.md).
3. Start with 3-5 skills from that bundle in your prompt.
4. Add more only when needed.
Examples:
- Building a SaaS MVP: `Essentials` + `Full-Stack Developer` + `QA & Testing`.
- Hardening production: `Security Developer` + `DevOps & Cloud` + `Observability & Monitoring`.
- Shipping OSS changes: `Essentials` + `OSS Maintainer`.
## Features & Categories
The repository is organized into specialized domains to transform your AI into an expert across the entire software development lifecycle:
| Category | Focus | Example skills |
| :------------- | :------------------------------------------------- | :------------------------------------------------------------------------------ |
| Architecture | System design, ADRs, C4, and scalable patterns | `architecture`, `c4-context`, `senior-architect` |
| Business | Growth, pricing, CRO, SEO, and go-to-market | `copywriting`, `pricing-strategy`, `seo-audit` |
| Data & AI | LLM apps, RAG, agents, observability, analytics | `rag-engineer`, `prompt-engineer`, `langgraph` |
| Development | Language mastery, framework patterns, code quality | `typescript-expert`, `python-patterns`, `react-patterns` |
| General | Planning, docs, product ops, writing, guidelines | `brainstorming`, `doc-coauthoring`, `writing-plans` |
| Infrastructure | DevOps, cloud, serverless, deployment, CI/CD | `docker-expert`, `aws-serverless`, `vercel-deployment` |
| Security | AppSec, pentesting, vuln analysis, compliance | `api-security-best-practices`, `sql-injection-testing`, `vulnerability-scanner` |
| Testing | TDD, test design, fixes, QA workflows | `test-driven-development`, `testing-patterns`, `test-fixing` |
| Workflow | Automation, orchestration, jobs, agents | `workflow-automation`, `inngest`, `trigger-dev` |
Counts change as new skills are added. For the current full registry, see [CATALOG.md](CATALOG.md).
## Browse 713+ Skills
We have moved the full skill registry to a dedicated catalog to keep this README clean.
👉 **[View the Complete Skill Catalog (CATALOG.md)](CATALOG.md)**
---
## How to Contribute
We welcome contributions from the community! To add a new skill:
@@ -187,6 +278,33 @@ Please ensure your skill follows the Antigravity/Claude Code best practices.
---
## Community
- [Community Guidelines](docs/COMMUNITY_GUIDELINES.md)
- [Security Policy](docs/SECURITY_GUARDRAILS.md)
---
## Support the Project
Support is optional. This project stays free and open-source for everyone.
If this repository saves you time or helps you ship faster, you can support ongoing maintenance:
- [☕ Buy me a book on Buy Me a Coffee](https://buymeacoffee.com/sickn33)
Where support goes:
- Skill curation, testing, and quality validation.
- Documentation updates, examples, and onboarding improvements.
- Faster triage and review of community issues and PRs.
Prefer non-financial support:
- Star the repository.
- Open clear, reproducible issues.
- Submit PRs (skills, docs, fixes).
- Share the project with other builders.
---
## Credits & Sources
We stand on the shoulders of giants.
@@ -223,11 +341,13 @@ This collection would not be possible without the incredible work of the Claude
- **[zebbern/claude-code-guide](https://github.com/zebbern/claude-code-guide)**: Comprehensive Security suite & Guide (Source for ~60 new skills).
- **[alirezarezvani/claude-skills](https://github.com/alirezarezvani/claude-skills)**: Senior Engineering and PM toolkit.
- **[karanb192/awesome-claude-skills](https://github.com/karanb192/awesome-claude-skills)**: A massive list of verified skills for Claude Code.
- **[VoltAgent/awesome-agent-skills](https://github.com/VoltAgent/awesome-agent-skills)**: Curated collection of 61 high-quality skills including official team skills from Sentry, Trail of Bits, Expo, Hugging Face, and comprehensive context engineering suite (v4.3.0 integration).
- **[zircote/.claude](https://github.com/zircote/.claude)**: Shopify development skill reference.
- **[vibeforge1111/vibeship-spawner-skills](https://github.com/vibeforge1111/vibeship-spawner-skills)**: AI Agents, Integrations, Maker Tools (57 skills, Apache 2.0).
- **[coreyhaines31/marketingskills](https://github.com/coreyhaines31/marketingskills)**: Marketing skills for CRO, copywriting, SEO, paid ads, and growth (23 skills, MIT).
- **[vudovn/antigravity-kit](https://github.com/vudovn/antigravity-kit)**: AI Agent templates with Skills, Agents, and Workflows (33 skills, MIT).
- **[affaan-m/everything-claude-code](https://github.com/affaan-m/everything-claude-code)**: Complete Claude Code configuration collection from Anthropic hackathon winner - skills only (8 skills, MIT).
- **[whatiskadudoing/fp-ts-skills](https://github.com/whatiskadudoing/fp-ts-skills)**: Practical fp-ts skills for TypeScript fp-ts-pragmatic, fp-ts-react, fp-ts-errors (v4.4.0).
- **[webzler/agentMemory](https://github.com/webzler/agentMemory)**: Source for the agent-memory-mcp skill.
- **[sstklen/claude-api-cost-optimization](https://github.com/sstklen/claude-api-cost-optimization)**: Save 50-90% on Claude API costs with smart optimization strategies (MIT).
@@ -238,17 +358,71 @@ This collection would not be possible without the incredible work of the Claude
---
## Repo Contributors
<a href="https://github.com/sickn33/antigravity-awesome-skills/graphs/contributors">
<img src="https://contrib.rocks/image?repo=sickn33/antigravity-awesome-skills" />
</a>
Made with [contrib.rocks](https://contrib.rocks).
We officially thank the following contributors for their help in making this repository awesome!
- [@sck000](https://github.com/sck000)
- [@munir-abbasi](https://github.com/munir-abbasi)
- [@sickn33](https://github.com/sickn33)
- [@Mohammad-Faiz-Cloud-Engineer](https://github.com/Mohammad-Faiz-Cloud-Engineer)
- [@Dokhacgiakhoa](https://github.com/Dokhacgiakhoa)
- [@IanJ332](https://github.com/IanJ332)
- [@chauey](https://github.com/chauey)
- [@PabloSMD](https://github.com/PabloSMD)
- [@GuppyTheCat](https://github.com/GuppyTheCat)
- [@Tiger-Foxx](https://github.com/Tiger-Foxx)
- [@arathiesh](https://github.com/arathiesh)
- [@liyin2015](https://github.com/liyin2015)
- [@1bcMax](https://github.com/1bcMax)
- [@ALEKGG1](https://github.com/ALEKGG1)
- [@ar27111994](https://github.com/ar27111994)
- [@BenedictKing](https://github.com/BenedictKing)
- [@whatiskadudoing](https://github.com/whatiskadudoing)
- [@LocNguyenSGU](https://github.com/LocNguyenSGU)
- [@yubing744](https://github.com/yubing744)
- [@SuperJMN](https://github.com/SuperJMN)
- [@truongnmt](https://github.com/truongnmt)
- [@viktor-ferenczi](https://github.com/viktor-ferenczi)
- [@c1c3ru](https://github.com/c1c3ru)
- [@ckdwns9121](https://github.com/ckdwns9121)
- [@fbientrigo](https://github.com/fbientrigo)
- [@junited31](https://github.com/junited31)
- [@KrisnaSantosa15](https://github.com/KrisnaSantosa15)
- [@sstklen](https://github.com/sstklen)
- [@taksrules](https://github.com/taksrules)
- [@zebbern](https://github.com/zebbern)
- [@vuth-dogo](https://github.com/vuth-dogo)
- [@mvanhorn](https://github.com/mvanhorn)
- [@rookie-ricardo](https://github.com/rookie-ricardo)
- [@evandro-miguel](https://github.com/evandro-miguel)
- [@raeef1001](https://github.com/raeef1001)
- [@devchangjun](https://github.com/devchangjun)
- [@jackjin1997](https://github.com/jackjin1997)
- [@ericgandrade](https://github.com/ericgandrade)
- [@sohamganatra](https://github.com/sohamganatra)
- [@Nguyen-Van-Chan](https://github.com/Nguyen-Van-Chan)
---
## License
MIT License. See [LICENSE](LICENSE) for details.
## Community
- [Community Guidelines](docs/COMMUNITY_GUIDELINES.md)
- [Security Policy](docs/SECURITY_GUARDRAILS.md)
---
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=sickn33/antigravity-awesome-skills&type=date&legend=top-left)](https://www.star-history.com/#sickn33/antigravity-awesome-skills&type=date&legend=top-left)
If Antigravity Awesome Skills has been useful, consider ⭐ starring the repo or [buying me a book](https://buymeacoffee.com/sickn33).
---
## GitHub Topics
@@ -260,39 +434,3 @@ claude-code, gemini-cli, codex-cli, antigravity, cursor, github-copilot, opencod
agentic-skills, ai-coding, llm-tools, ai-agents, autonomous-coding, mcp,
ai-developer-tools, ai-pair-programming, vibe-coding, skill, skills, SKILL.md, rules.md, CLAUDE.md, GEMINI.md, CURSOR.md
```
---
## Repo Contributors
We officially thank the following contributors for their help in making this repository awesome!
- [mvanhorn](https://github.com/mvanhorn)
- [rookie-ricardo](https://github.com/rookie-ricardo)
- [sck_0](https://github.com/sck_0)
- [Munir Abbasi](https://github.com/munirabbasi)
- [Mohammad Faiz](https://github.com/mohdfaiz2k9)
- [Ianj332](https://github.com/Ianj332)
- [sickn33](https://github.com/sickn33)
- [GuppyTheCat](https://github.com/GuppyTheCat)
- [Tiger-Foxx](https://github.com/Tiger-Foxx)
- [arathiesh](https://github.com/arathiesh)
- [1bcMax](https://github.com/1bcMax)
- [Ahmed Rehan](https://github.com/ar27111994)
- [BenedictKing](https://github.com/BenedictKing)
- [Nguyen Huu Loc](https://github.com/LocNguyenSGU)
- [Owen Wu](https://github.com/yubing744)
- [SuperJMN](https://github.com/SuperJMN)
- [Viktor Ferenczi](https://github.com/viktor-ferenczi)
- [Đỗ Khắc Gia Khoa](https://github.com/Dokhacgiakhoa)
- [evandro-miguel](https://github.com/evandro-miguel)
- [junited31](https://github.com/junited31)
- [krisnasantosa15](https://github.com/krisnasantosa15)
- [raeef1001](https://github.com/raeef1001)
- [taksrules](https://github.com/taksrules)
- [zebbern](https://github.com/zebbern)
- [vuth-dogo](https://github.com/vuth-dogo)
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=sickn33/antigravity-awesome-skills&type=date&legend=top-left)](https://www.star-history.com/#sickn33/antigravity-awesome-skills&type=date&legend=top-left)

View File

@@ -1,133 +0,0 @@
# Release v4.3.0: VoltAgent Integration & Context Engineering Suite
> **Massive expansion with 61 new skills from VoltAgent repository, including official team skills and comprehensive context engineering capabilities**
This release adds 61 high-quality skills sourced from the VoltAgent/awesome-agent-skills curated collection, bringing the total to 614 skills. Highlights include official skills from Sentry, Trail of Bits, Expo, Hugging Face, and a complete context engineering suite for building sophisticated AI agents.
## 🚀 New Skills
### Official Team Skills (27)
#### Sentry (4)
- **[commit](skills/commit/)** Create commits with best practices following Sentry conventions
- **[create-pr](skills/create-pr/)** Create pull requests with proper descriptions and review guidelines
- **[find-bugs](skills/find-bugs/)** Find and identify bugs in code systematically
- **[iterate-pr](skills/iterate-pr/)** Iterate on pull request feedback efficiently
#### Trail of Bits (3)
- **[culture-index](skills/culture-index/)** Index and search culture documentation
- **[fix-review](skills/fix-review/)** Verify fix commits address audit findings without new bugs
- **[sharp-edges](skills/sharp-edges/)** Identify error-prone APIs and dangerous configurations
#### Expo (2)
- **[expo-deployment](skills/expo-deployment/)** Deploy Expo apps to production
- **[upgrading-expo](skills/upgrading-expo/)** Upgrade Expo SDK versions safely
#### Hugging Face (2)
- **[hugging-face-cli](skills/hugging-face-cli/)** HF Hub CLI for models, datasets, repos, and compute jobs
- **[hugging-face-jobs](skills/hugging-face-jobs/)** Run compute jobs and Python scripts on HF infrastructure
#### Other Official (16)
- **[vercel-deploy-claimable](skills/vercel-deploy-claimable/)** Deploy projects to Vercel
- **[design-md](skills/design-md/)** Create and manage DESIGN.md files (Google Stitch)
- **[using-neon](skills/using-neon/)** Best practices for Neon Serverless Postgres
- **[n8n-code-python](skills/n8n-code-python/)** Python in n8n Code nodes
- **[n8n-mcp-tools-expert](skills/n8n-mcp-tools-expert/)** n8n MCP tools guide
- **[n8n-node-configuration](skills/n8n-node-configuration/)** n8n node configuration
- **[swiftui-expert-skill](skills/swiftui-expert-skill/)** SwiftUI best practices
- **[fal-audio](skills/fal-audio/)** Text-to-speech and speech-to-text using fal.ai
- **[fal-generate](skills/fal-generate/)** Generate images and videos using fal.ai AI models
- **[fal-image-edit](skills/fal-image-edit/)** AI-powered image editing with style transfer
- **[fal-platform](skills/fal-platform/)** Platform APIs for model management and usage tracking
- **[fal-upscale](skills/fal-upscale/)** Upscale and enhance image/video resolution using AI
- **[fal-workflow](skills/fal-workflow/)** Generate workflow JSON files for chaining AI models
- **[deep-research](skills/deep-research/)** Gemini Deep Research Agent for autonomous research
- **[imagen](skills/imagen/)** Generate images using Google Gemini
- **[readme](skills/readme/)** Generate comprehensive project documentation
### Community Skills (34)
#### Context Engineering Suite (7)
A complete suite for building sophisticated AI agents with advanced context management:
- **[context-fundamentals](skills/context-fundamentals/)** Understand what context is, why it matters, and the anatomy of context in agent systems
- **[context-degradation](skills/context-degradation/)** Recognize patterns of context failure: lost-in-middle, poisoning, distraction, and clash
- **[context-compression](skills/context-compression/)** Design and evaluate compression strategies for long-running sessions
- **[context-optimization](skills/context-optimization/)** Apply compaction, masking, and caching strategies
- **[multi-agent-patterns](skills/multi-agent-patterns/)** Master orchestrator, peer-to-peer, and hierarchical multi-agent architectures
- **[memory-systems](skills/memory-systems/)** Design short-term, long-term, and graph-based memory architectures
- **[evaluation](skills/evaluation/)** Build evaluation frameworks for agent systems
#### Development Tools (8)
- **[frontend-slides](skills/frontend-slides/)** Generate animation-rich HTML presentations with visual style previews
- **[linear-claude-skill](skills/linear-claude-skill/)** Manage Linear issues, projects, and teams
- **[skill-rails-upgrade](skills/skill-rails-upgrade/)** Analyze Rails apps and provide upgrade assessments
- **[terraform-skill](skills/terraform-skill/)** Terraform infrastructure as code best practices
- **[tool-design](skills/tool-design/)** Build tools that agents can use effectively, including architectural reduction patterns
- **[screenshots](skills/screenshots/)** Generate marketing screenshots with Playwright
- **[automate-whatsapp](skills/automate-whatsapp/)** Build WhatsApp automations with workflows and agents
- **[observe-whatsapp](skills/observe-whatsapp/)** Debug WhatsApp delivery issues and run health checks
#### Platform & Framework Skills (19)
- **[aws-skills](skills/aws-skills/)** AWS development with infrastructure automation
- **[ui-skills](skills/ui-skills/)** Opinionated constraints for building interfaces
- **[vexor](skills/vexor/)** Vector-powered CLI for semantic file search
- **[pypict-skill](skills/pypict-skill/)** Pairwise test generation
- **[makepad-skills](skills/makepad-skills/)** Makepad UI development for Rust apps
- **[threejs-skills](skills/threejs-skills/)** Three.js 3D experiences
- **[claude-scientific-skills](skills/claude-scientific-skills/)** Scientific research skills
- **[claude-win11-speckit-update-skill](skills/claude-win11-speckit-update-skill/)** Windows 11 management
- **[security-bluebook-builder](skills/security-bluebook-builder/)** Security documentation
- **[claude-ally-health](skills/claude-ally-health/)** Health assistant
- **[clarity-gate](skills/clarity-gate/)** RAG quality verification
- **[beautiful-prose](skills/beautiful-prose/)** Writing style guide
- **[claude-speed-reader](skills/claude-speed-reader/)** Speed reading tool
- **[skill-seekers](skills/skill-seekers/)** Skill conversion tool
- **[varlock-claude-skill](skills/varlock-claude-skill/)** Secure environment variable management
- **[superpowers-lab](skills/superpowers-lab/)** Superpowers Lab integration
- **[nanobanana-ppt-skills](skills/nanobanana-ppt-skills/)** PowerPoint presentation skills
- **[x-article-publisher-skill](skills/x-article-publisher-skill/)** X/Twitter article publishing
- **[ffuf-claude-skill](skills/ffuf-claude-skill/)** Web fuzzing with ffuf
---
## 📦 Registry Update
- **Total Skills**: 614 (from 553)
- **New Skills Added**: 61
- **Catalog**: Fully regenerated with all new skills
- **Sources**: All skills properly attributed in `docs/SOURCES.md`
## 🔧 Improvements
### Quality Assurance
- All new skills validated for frontmatter compliance
- "When to Use" sections added where missing
- Source attribution maintained for all skills
- Risk labels properly set
### Documentation
- Updated README.md with correct skill count (614)
- Updated package.json version to 4.3.0
- Comprehensive release notes created
## 📊 Statistics
- **Skills from VoltAgent Repository**: 61
- Official Team Skills: 27
- Community Skills: 34
- **Skills Analyzed**: 174 total from VoltAgent
- **Skills Already Present**: 32 (skipped as duplicates)
- **Skills with Similar Names**: 89 (analyzed, 12 implemented as complementary)
## 👥 Credits
A huge shoutout to our community contributors and the VoltAgent team:
- **VoltAgent/awesome-agent-skills** for curating an excellent collection
- **Official Teams**: Sentry, Trail of Bits, Expo, Hugging Face, Vercel Labs, Google Labs, Neon, fal.ai
- **Community Contributors**: zarazhangrui, wrsmith108, robzolkos, muratcankoylan, antonbabenko, and all other skill authors
---
_Upgrade now: `git pull origin main` to fetch the latest skills._

View File

@@ -1,186 +0,0 @@
# Analisi delle 65 Skills con Nomi Simili
**Data**: 2026-01-30
**Skills Analizzate**: 89 totali (di cui 49 già implementate)
**Rimanenti da Analizzare**: 40 skills
## Executive Summary
Delle 89 skills con nomi simili identificate inizialmente:
-**49 già implementate** (dalle 24 convertite da HTML + 25 altre)
-**2 duplicate** (già esistono nella repository)
- ⚠️ **13 necessitano revisione** (hanno fonti valide, potrebbero essere nuove o duplicate)
-**74 hanno fonti non valide** (URL non accessibili o SKILL.md non trovato)
## Skills Duplicate (2)
Queste skills **NON devono essere aggiunte** perché esistono già nella repository:
1. **`react-best-practices`** (vercel-labs)
- Esiste già: `skills/react-best-practices/` o simile
- URL: https://github.com/vercel-labs/agent-skills/tree/main/skills/react-best-practices
2. **`postgres-best-practices`** (supabase)
- Esiste già: `skills/postgres-best-practices/` o `skills/supabase-postgres-best-practices/`
- URL: https://github.com/supabase/agent-skills/tree/main/skills/supabase-postgres-best-practices
## Skills che Necessitano Revisione (13)
Queste skills hanno **fonti valide** (SKILL.md accessibile) ma richiedono una valutazione manuale per determinare se sono:
- **Nuove e complementari** → Da aggiungere
- **Duplicate** → Da scartare
### 1. Skills Potenzialmente Duplicate (da verificare)
#### `notebooklm-skill` (PleasePrompto)
- **Descrizione**: Interact with NotebookLM for document-based conversations
- **URL**: https://github.com/PleasePrompto/notebooklm-skill
- **Raw URL**: https://github.com/PleasePrompto/notebooklm-skill/raw/master/SKILL.md
- **Skills simili esistenti**: `notebooklm`
- **Raccomandazione**: ⚠️ **Verificare** se è diverso da `notebooklm` esistente. Se è solo una versione alternativa, scartare.
#### `evaluation` (muratcankoylan)
- **Descrizione**: Build evaluation frameworks for agent systems
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/evaluation
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Skills simili esistenti**: `agent-evaluation`, `llm-evaluation`
- **Raccomandazione**: ⚠️ **Verificare** se è complementare o duplicato. Se copre solo evaluation generale, potrebbe essere duplicato.
#### `memory-systems` (muratcankoylan)
- **Descrizione**: Design short-term, long-term, and graph-based memory architectures
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/memory-systems
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Skills simili esistenti**: `agent-memory-systems`
- **Raccomandazione**: ⚠️ **Verificare** se è complementare o duplicato. Se è solo un nome alternativo, scartare.
#### `terraform-skill` (antonbabenko)
- **Descrizione**: Terraform infrastructure as code best practices
- **URL**: https://github.com/antonbabenko/terraform-skill
- **Raw URL**: https://github.com/antonbabenko/terraform-skill/raw/master/SKILL.md
- **Skills simili esistenti**: `terraform-specialist`, `terraform-module-library`
- **Raccomandazione**: ⚠️ **Verificare** se aggiunge valore rispetto a `terraform-specialist`. Se è solo best practices generiche, potrebbe essere duplicato.
### 2. Skills Probabilmente Nuove e Complementari (da aggiungere)
#### `frontend-slides` (zarazhangrui)
- **Descrizione**: Generate animation-rich HTML presentations with visual style previews
- **URL**: https://github.com/zarazhangrui/frontend-slides
- **Raw URL**: https://github.com/zarazhangrui/frontend-slides/raw/main/SKILL.md
- **Skills simili esistenti**: `frontend-patterns`, `frontend-design`
- **Raccomandazione**: ✅ **Aggiungere** - Focus specifico su presentazioni HTML animate, complementare a frontend-design.
#### `linear-claude-skill` (wrsmith108)
- **Descrizione**: Manage Linear issues, projects, and teams
- **URL**: https://github.com/wrsmith108/linear-claude-skill
- **Raw URL**: https://github.com/wrsmith108/linear-claude-skill/raw/main/SKILL.md
- **Skills simili esistenti**: Nessuna skill Linear esistente
- **Raccomandazione**: ✅ **Aggiungere** - Skill completamente nuova per integrazione Linear.
#### `skill-rails-upgrade` (robzolkos)
- **Descrizione**: Analyze Rails apps and provide upgrade assessments
- **URL**: https://github.com/robzolkos/skill-rails-upgrade
- **Raw URL**: https://github.com/robzolkos/skill-rails-upgrade/raw/master/SKILL.md
- **Skills simili esistenti**: Nessuna skill Rails upgrade esistente
- **Raccomandazione**: ✅ **Aggiungere** - Skill specifica per upgrade Rails, complementare a `ruby-pro`.
#### Context Engineering Skills (muratcankoylan) - 4 skills
Queste 4 skills fanno parte di una suite di Context Engineering e sembrano complementari:
##### `context-fundamentals`
- **Descrizione**: Understand what context is, why it matters, and the anatomy of context in agent systems
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-fundamentals
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Raccomandazione**: ✅ **Aggiungere** - Fondamentali di context engineering, complementare a `context-manager`.
##### `context-degradation`
- **Descrizione**: Recognize patterns of context failure: lost-in-middle, poisoning, distraction, and clash
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-degradation
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Raccomandazione**: ✅ **Aggiungere** - Pattern specifici di degradazione del context, complementare.
##### `context-compression`
- **Descrizione**: Design and evaluate compression strategies for long-running sessions
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-compression
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Raccomandazione**: ✅ **Aggiungere** - Strategie di compressione del context, complementare.
##### `context-optimization`
- **Descrizione**: Apply compaction, masking, and caching strategies
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-optimization
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Raccomandazione**: ✅ **Aggiungere** - Ottimizzazione del context, complementare.
#### `multi-agent-patterns` (muratcankoylan)
- **Descrizione**: Master orchestrator, peer-to-peer, and hierarchical multi-agent architectures
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/multi-agent-patterns
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Skills simili esistenti**: `agent-manager-skill`, `computer-use-agents`
- **Raccomandazione**: ✅ **Aggiungere** - Pattern architetturali multi-agent, complementare a `autonomous-agents`.
#### `tool-design` (muratcankoylan)
- **Descrizione**: Build tools that agents can use effectively, including architectural reduction patterns
- **URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/tool-design
- **Raw URL**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md
- **Skills simili esistenti**: Nessuna skill tool-design esistente
- **Raccomandazione**: ✅ **Aggiungere** - Design di tool per agenti, complementare a `agent-tool-builder`.
## Skills con Fonti Non Valide (74)
Queste skills hanno **URL non accessibili** o **SKILL.md non trovato**. Non possono essere implementate senza accesso al contenuto.
### Categorie di Skills Non Valide
#### Official Team Skills (molte da Cloudflare, Hugging Face, Stripe, Trail of Bits, Expo, Sentry)
- Skills ufficiali di team che potrebbero non avere SKILL.md pubblici o potrebbero essere in percorsi diversi
- Esempi: `building-ai-agent-on-cloudflare`, `hugging-face-datasets`, `stripe-best-practices`, `burpsuite-project-parser`, etc.
#### Community Skills
- Skills della community con URL non validi o repository non più disponibili
**Raccomandazione**: ⏸️ **Non implementare** senza accesso al contenuto. Se necessario, contattare i maintainer o verificare manualmente i repository.
## Raccomandazioni Finali
### ✅ Da Implementare (9 skills)
1. `frontend-slides` - Presentazioni HTML animate
2. `linear-claude-skill` - Integrazione Linear
3. `skill-rails-upgrade` - Upgrade Rails
4. `context-fundamentals` - Fondamentali context engineering
5. `context-degradation` - Pattern di degradazione context
6. `context-compression` - Compressione context
7. `context-optimization` - Ottimizzazione context
8. `multi-agent-patterns` - Pattern multi-agent
9. `tool-design` - Design tool per agenti
### ⚠️ Da Verificare Manualmente (4 skills)
1. `notebooklm-skill` - Verificare se diverso da `notebooklm` esistente
2. `evaluation` - Verificare se complementare a `agent-evaluation`/`llm-evaluation`
3. `memory-systems` - Verificare se diverso da `agent-memory-systems`
4. `terraform-skill` - Verificare se aggiunge valore rispetto a `terraform-specialist`
### ❌ Da Scartare (2 skills)
1. `react-best-practices` - Duplicato
2. `postgres-best-practices` - Duplicato
### ⏸️ Non Implementabili (74 skills)
Skills con fonti non valide - richiederebbero accesso manuale ai repository o contatto con i maintainer.
## Prossimi Passi
1. **Implementare le 9 skills raccomandate** seguendo il processo standard
2. **Verificare manualmente le 4 skills** confrontando con quelle esistenti
3. **Scartare le 2 duplicate**
4. **Documentare le 74 skills non valide** per riferimento futuro
## Statistiche Finali
- **Total skills analizzate**: 89
- **Già implementate**: 49
- **Nuove da aggiungere**: 9-13 (dipende dalla verifica manuale)
- **Duplicate**: 2
- **Non implementabili**: 74

View File

@@ -1,158 +0,0 @@
# Report Implementazione Skills con Nomi Simili
**Data**: 2026-01-30
**Skills Implementate**: 12
**Status**: ✅ Completato con Successo
## Executive Summary
Successfully implemented **12 new skills** from the similar skills analysis:
- 9 skills raccomandate come nuove e complementari
- 3 skills verificate manualmente come complementari (evaluation, memory-systems, terraform-skill)
- 1 skill duplicata scartata (notebooklm-skill - identica a notebooklm esistente)
## Skills Implementate
### 1. frontend-slides (zarazhangrui)
- **Descrizione**: Generate animation-rich HTML presentations with visual style previews
- **Source**: https://github.com/zarazhangrui/frontend-slides
- **Categoria**: Community Skills
- **Status**: ✅ Implementata
### 2. linear-claude-skill (wrsmith108)
- **Descrizione**: Manage Linear issues, projects, and teams
- **Source**: https://github.com/wrsmith108/linear-claude-skill
- **Categoria**: Community Skills
- **Status**: ✅ Implementata
### 3. skill-rails-upgrade (robzolkos)
- **Descrizione**: Analyze Rails apps and provide upgrade assessments
- **Source**: https://github.com/robzolkos/skill-rails-upgrade
- **Categoria**: Community Skills
- **Status**: ✅ Implementata
### 4-7. Context Engineering Skills (muratcankoylan)
Quattro skills complementari per context engineering:
#### context-fundamentals
- **Descrizione**: Understand what context is, why it matters, and the anatomy of context in agent systems
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Status**: ✅ Implementata
#### context-degradation
- **Descrizione**: Recognize patterns of context failure: lost-in-middle, poisoning, distraction, and clash
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Status**: ✅ Implementata
#### context-compression
- **Descrizione**: Design and evaluate compression strategies for long-running sessions
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Status**: ✅ Implementata
#### context-optimization
- **Descrizione**: Apply compaction, masking, and caching strategies
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Status**: ✅ Implementata
### 8. multi-agent-patterns (muratcankoylan)
- **Descrizione**: Master orchestrator, peer-to-peer, and hierarchical multi-agent architectures
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Categoria**: Community Skills
- **Status**: ✅ Implementata
### 9. tool-design (muratcankoylan)
- **Descrizione**: Build tools that agents can use effectively, including architectural reduction patterns
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Categoria**: Community Skills
- **Status**: ✅ Implementata
### 10. evaluation (muratcankoylan) - Verificata
- **Descrizione**: Build evaluation frameworks for agent systems
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Categoria**: Community Skills
- **Status**: ✅ Implementata (complementare a agent-evaluation e llm-evaluation)
### 11. memory-systems (muratcankoylan) - Verificata
- **Descrizione**: Design short-term, long-term, and graph-based memory architectures
- **Source**: https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering
- **Categoria**: Community Skills
- **Status**: ✅ Implementata (complementare a agent-memory-systems)
### 12. terraform-skill (antonbabenko) - Verificata
- **Descrizione**: Terraform infrastructure as code best practices
- **Source**: https://github.com/antonbabenko/terraform-skill
- **Categoria**: Community Skills
- **Status**: ✅ Implementata (complementare a terraform-specialist)
## Skills Scartate
### notebooklm-skill (PleasePrompto) - Duplicato
- **Motivo**: Identica a `notebooklm` esistente nella repository
- **Confronto**: Stesso contenuto, stesso frontmatter name, stessa funzionalità
- **Decisione**: ❌ Scartata come duplicato
## Processo di Implementazione
### Fase 1: Verifica Manuale delle Skills Incerte
- Verificate 4 skills che necessitavano revisione manuale
- `notebooklm-skill`: Identificata come duplicato esatto
- `evaluation`: Verificata come complementare (più generale di agent-evaluation/llm-evaluation)
- `memory-systems`: Verificata come complementare (più dettagliata di agent-memory-systems)
- `terraform-skill`: Verificata come complementare (più pratica di terraform-specialist)
### Fase 2: Download e Implementazione
- Creato script `scripts/implement_similar_skills.py` per automatizzare il processo
- Download di SKILL.md da repository GitHub
- Verifica compliance con frontmatter standard
- Aggiunta sezione "When to Use" dove mancante
- Gestione speciale per `frontend-slides` (download manuale con curl)
### Fase 3: Validazione
- Tutte le 12 skills passano la validazione di compliance
- Frontmatter completo con: name, description, source, risk
- Sezione "When to Use" presente in tutte
- Contenuto markdown pulito (nessun HTML)
### Fase 4: Aggiornamento Cataloghi
- Aggiornato `data/catalog.json`: 614 skills totali (da 602)
- Aggiornato `data/skills_index.json`
- Aggiornato `CATALOG.md`
- Aggiornato `docs/SOURCES.md` con attribuzioni
## Statistiche Finali
- **Total skills analizzate**: 89 (con nomi simili)
- **Skills già implementate**: 49 (dalla fase precedente)
- **Skills duplicate scartate**: 3 (react-best-practices, postgres-best-practices, notebooklm-skill)
- **Skills nuove implementate**: 12
- **Skills con fonti non valide**: 74 (non implementabili)
## Totale Skills Nuove da VoltAgent
- **Fase precedente**: 49 skills implementate
- **Fase corrente**: 12 skills implementate
- **TOTALE**: **61 skills nuove** aggiunte dalla repository VoltAgent
## Qualità e Compliance
Tutte le 12 skills implementate:
- ✅ Frontmatter completo e corretto
- ✅ Sezione "When to Use" presente
- ✅ Source attribution corretta
- ✅ Risk level impostato
- ✅ Contenuto markdown pulito
- ✅ Nome corrisponde al nome della cartella
## Prossimi Passi
1. ✅ Tutte le skills implementate
2. ✅ Cataloghi aggiornati
3. ✅ Attribuzioni aggiunte
4. ⏳ Pronto per commit e push (in attesa di approvazione utente)
## Note Tecniche
- `frontend-slides` ha richiesto download manuale con curl a causa di problemi con lo script Python
- Tutte le altre skills sono state scaricate automaticamente dallo script
- Le skills di Context Engineering (muratcankoylan) sono parte di una suite coerente
- Le skills verificate manualmente sono risultate complementari, non duplicate

View File

@@ -1,215 +0,0 @@
# VoltAgent Skills Sync Report
**Date**: 2026-01-30
**Source Repository**: [VoltAgent/awesome-agent-skills](https://github.com/VoltAgent/awesome-agent-skills)
**Target Repository**: antigravity-awesome-skills
## Executive Summary
Successfully analyzed the VoltAgent/awesome-agent-skills repository and implemented **49 new validated skills** into the antigravity-awesome-skills collection.
### Statistics
- **Total skills analyzed**: 174
- **Skills already present**: 32
- **New skills identified**: 53
- **Skills validated**: 49
- **Skills implemented**: 49
- **Skills failed validation**: 4
- **Skills with similar names** (potential duplicates): 89
## Implementation Process
### Phase 1: Analysis ✅
Created `scripts/analyze_voltagent_repo.py` to:
- Fetch and parse the VoltAgent README.md
- Extract all skill references (format: `**[org/skill-name](url)**`)
- Normalize skill names to kebab-case
- Compare with existing skills in `data/catalog.json`
**Result**: Identified 53 new skills not present in the current collection.
### Phase 2: Source Validation ✅
Created `scripts/validate_voltagent_sources.py` to:
- Verify GitHub URL accessibility
- Check for SKILL.md file presence
- Validate license compatibility
- Identify official vs community skills
**Result**:
- ✅ 49 skills validated successfully
- ❌ 4 skills failed (URL 404 errors)
### Phase 3: Implementation ✅
Created `scripts/implement_voltagent_skills.py` to:
- Download SKILL.md files from GitHub repositories
- Ensure frontmatter compliance (name, description, source, risk)
- Add "When to Use" sections where missing
- Create minimal SKILL.md for skills without downloadable files
**Result**: All 49 validated skills successfully implemented.
### Phase 4: Catalog Update ✅
- Updated `data/skills_index.json`: 609 skills total
- Updated `data/catalog.json`: 602 skills total
- Updated `CATALOG.md`: Regenerated catalog documentation
- Updated `docs/SOURCES.md`: Added attributions for all new skills
## Implemented Skills
### Official Team Skills (27)
#### Vercel Labs (1)
- `vercel-deploy-claimable` - Deploy projects to Vercel
#### Google Labs / Stitch (1)
- `design-md` - Create and manage DESIGN.md files
#### Hugging Face (2)
- `hugging-face-cli` - HF Hub CLI for models, datasets, repos, and compute jobs
- `hugging-face-jobs` - Run compute jobs and Python scripts on HF infrastructure
#### Trail of Bits (3)
- `culture-index` - Index and search culture documentation
- `fix-review` - Verify fix commits address audit findings without new bugs
- `sharp-edges` - Identify error-prone APIs and dangerous configurations
#### Expo (2)
- `expo-deployment` - Deploy Expo apps to production
- `upgrading-expo` - Upgrade Expo SDK versions
#### Sentry (4)
- `commit` - Create commits with best practices
- `create-pr` - Create pull requests
- `find-bugs` - Find and identify bugs in code
- `iterate-pr` - Iterate on pull request feedback
#### Neon (1)
- `using-neon` - Best practices for Neon Serverless Postgres
#### fal.ai Community (6)
- `fal-audio` - Text-to-speech and speech-to-text using fal.ai audio models
- `fal-generate` - Generate images and videos using fal.ai AI models
- `fal-image-edit` - AI-powered image editing with style transfer and object removal
- `fal-platform` - Platform APIs for model management, pricing, and usage tracking
- `fal-upscale` - Upscale and enhance image and video resolution using AI
- `fal-workflow` - Generate workflow JSON files for chaining AI models
### Community Skills (22)
#### WhatsApp Automation (2)
- `automate-whatsapp` - Build WhatsApp automations with workflows and agents
- `observe-whatsapp` - Debug WhatsApp delivery issues and run health checks
#### Development Tools (8)
- `readme` - Generate comprehensive project documentation
- `screenshots` - Generate marketing screenshots with Playwright
- `aws-skills` - AWS development with infrastructure automation and cloud architecture patterns
- `deep-research` - Autonomous multi-step research using Gemini Deep Research Agent
- `ffuf-claude-skill` - Web fuzzing with ffuf
- `ui-skills` - Opinionated, evolving constraints to guide agents when building interfaces
- `vexor` - Vector-powered CLI for semantic file search
- `pypict-skill` - Pairwise test generation
#### Platform-Specific (3)
- `makepad-skills` - Makepad UI development skills for Rust apps
- `swiftui-expert-skill` - Modern SwiftUI best practices and iOS 26+ Liquid Glass adoption
- `threejs-skills` - Three.js skills for creating 3D elements and interactive experiences
#### Specialized Domains (9)
- `claude-scientific-skills` - Scientific research and analysis skills
- `claude-win11-speckit-update-skill` - Windows 11 system management
- `imagen` - Generate images using Google Gemini's API
- `security-bluebook-builder` - Build security Blue Books for sensitive apps
- `claude-ally-health` - Health assistant skill for medical information analysis
- `clarity-gate` - Pre-ingestion verification for epistemic quality in RAG systems
- `n8n-code-python` - Python coding in n8n Code nodes with limitations
- `n8n-mcp-tools-expert` - MCP tools guide with tool selection and node formats
- `n8n-node-configuration` - Node configuration with dependency rules and AI connections
#### Utilities (3)
- `varlock-claude-skill` - Secure environment variable management
- `beautiful-prose` - Hard-edged writing style contract for timeless, forceful English prose
- `claude-speed-reader` - Speed read Claude's responses at 600+ WPM using RSVP
- `skill-seekers` - Automatically convert documentation websites, GitHub repositories, and PDFs into Claude AI skills
## Failed Validations
The following skills failed validation due to inaccessible URLs (HTTP 404):
1. `agents-sdk` (cloudflare) - URL not accessible
2. `wrangler` (cloudflare) - URL not accessible
3. `claudisms` (jeffersonwarrior) - URL not accessible
4. `defense-in-depth` (obra) - URL not accessible
**Note**: These skills may be available at different URLs or may have been moved/removed from their original repositories.
## Skills with Similar Names
89 skills were identified with similar names to existing skills. These were flagged for manual review to avoid duplicates:
- `template` (similar to: defi-protocol-templates, documentation-templates)
- `react-best-practices` (similar to: vercel-react-best-practices)
- `react-native-skills` (similar to: various React Native skills)
- `postgres-best-practices` (similar to: postgresql, postgres-best-practices)
- And 85 more...
**Action**: These require manual review to determine if they are duplicates or complementary skills.
## Quality Assurance
### Validation Status
All implemented skills include:
- ✅ Valid YAML frontmatter with required fields (name, description, source, risk)
- ✅ "When to Use" section
- ✅ Proper attribution to source repositories
- ✅ Risk level classification (default: safe)
### Known Issues
Some skills were downloaded with HTML content instead of markdown due to GitHub URL structure. These files have:
- ✅ Correct frontmatter
- ✅ "When to Use" section
- ⚠️ HTML content that may need manual cleanup
**Affected skills**: Skills from fal.ai community and some community repositories.
## Files Created/Modified
### Scripts Created
- `scripts/analyze_voltagent_repo.py` - Analysis script
- `scripts/validate_voltagent_sources.py` - Source validation script
- `scripts/implement_voltagent_skills.py` - Implementation script
### Data Files Updated
- `data/catalog.json` - Updated with new skills
- `data/skills_index.json` - Updated index
- `CATALOG.md` - Regenerated catalog
- `docs/SOURCES.md` - Added attributions
### Analysis Files Generated
- `voltagent_analysis.json` - Detailed analysis results
- `voltagent_validation.json` - Validation results
### Skills Added
49 new skill directories in `skills/`:
- See "Implemented Skills" section above for complete list
## Next Steps
1. **Manual Review**: Review skills with similar names to identify duplicates
2. **Content Cleanup**: Clean up HTML content in skills that were downloaded incorrectly
3. **Testing**: Test new skills to ensure they work correctly
4. **Documentation**: Update any additional documentation as needed
5. **Follow-up**: Monitor for updates to failed validations (agents-sdk, wrangler, etc.)
## Conclusion
Successfully integrated 49 new high-quality skills from the VoltAgent curated collection, significantly expanding the antigravity-awesome-skills repository. All skills follow the V4 Quality Bar standards and are properly attributed to their original sources.
The collection now includes skills from major development teams (Vercel, Google, Hugging Face, Trail of Bits, Expo, Sentry, Neon) as well as valuable community contributions, making it an even more comprehensive resource for AI coding assistants.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -16,18 +16,23 @@ function resolveDir(p) {
function parseArgs() {
const a = process.argv.slice(2);
let pathArg = null;
let cursor = false, claude = false, gemini = false;
let versionArg = null;
let tagArg = null;
let cursor = false, claude = false, gemini = false, codex = false;
for (let i = 0; i < a.length; i++) {
if (a[i] === '--help' || a[i] === '-h') return { help: true };
if (a[i] === '--path' && a[i + 1]) { pathArg = a[++i]; continue; }
if (a[i] === '--version' && a[i + 1]) { versionArg = a[++i]; continue; }
if (a[i] === '--tag' && a[i + 1]) { tagArg = a[++i]; continue; }
if (a[i] === '--cursor') { cursor = true; continue; }
if (a[i] === '--claude') { claude = true; continue; }
if (a[i] === '--gemini') { gemini = true; continue; }
if (a[i] === '--codex') { codex = true; continue; }
if (a[i] === 'install') continue;
}
return { pathArg, cursor, claude, gemini };
return { pathArg, versionArg, tagArg, cursor, claude, gemini, codex };
}
function defaultDir(opts) {
@@ -35,6 +40,11 @@ function defaultDir(opts) {
if (opts.cursor) return path.join(HOME, '.cursor', 'skills');
if (opts.claude) return path.join(HOME, '.claude', 'skills');
if (opts.gemini) return path.join(HOME, '.gemini', 'skills');
if (opts.codex) {
const codexHome = process.env.CODEX_HOME;
if (codexHome) return path.join(codexHome, 'skills');
return path.join(HOME, '.codex', 'skills');
}
return path.join(HOME, '.agent', 'skills');
}
@@ -50,11 +60,15 @@ Options:
--cursor Install to ~/.cursor/skills (Cursor)
--claude Install to ~/.claude/skills (Claude Code)
--gemini Install to ~/.gemini/skills (Gemini CLI)
--codex Install to ~/.codex/skills (Codex CLI)
--path <dir> Install to <dir> (default: ~/.agent/skills)
--version <ver> After clone, checkout tag v<ver> (e.g. 4.6.0 -> v4.6.0)
--tag <tag> After clone, checkout this tag (e.g. v4.6.0)
Examples:
npx antigravity-awesome-skills
npx antigravity-awesome-skills --cursor
npx antigravity-awesome-skills --version 4.6.0
npx antigravity-awesome-skills --path ./my-skills
`);
}
@@ -66,6 +80,8 @@ function run(cmd, args, opts = {}) {
function main() {
const opts = parseArgs();
const { tagArg, versionArg } = opts;
if (opts.help) {
printHelp();
return;
@@ -106,6 +122,13 @@ function main() {
run('git', ['clone', REPO, target]);
}
const ref = tagArg || (versionArg ? (versionArg.startsWith('v') ? versionArg : `v${versionArg}`) : null);
if (ref) {
console.log(`Checking out ${ref}`);
process.chdir(target);
run('git', ['checkout', ref]);
}
console.log(`\nInstalled to ${target}`);
console.log('Pick a bundle in docs/BUNDLES.md and use @skill-name in your AI assistant.');
}

View File

@@ -1,5 +1,5 @@
{
"generatedAt": "2026-01-30T08:15:03.985Z",
"generatedAt": "2026-02-08T10:02:49.626Z",
"aliases": {
"accessibility-compliance-audit": "accessibility-compliance-accessibility-audit",
"active directory attacks": "active-directory-attacks",
@@ -7,6 +7,7 @@
"agent-orchestration-optimize": "agent-orchestration-multi-agent-optimize",
"api fuzzing for bug bounty": "api-fuzzing-bug-bounty",
"api-testing-mock": "api-testing-observability-api-mock",
"templates": "app-builder/templates",
"application-performance-optimization": "application-performance-performance-optimization",
"aws penetration testing": "aws-penetration-testing",
"backend-development-feature": "backend-development-feature-development",
@@ -45,6 +46,7 @@
"deployment-validation-validate": "deployment-validation-config-validate",
"distributed-debugging-trace": "distributed-debugging-debug-trace",
"documentation-generation-generate": "documentation-generation-doc-generate",
"docx": "docx-official",
"error-debugging-analysis": "error-debugging-error-analysis",
"error-debugging-review": "error-debugging-multi-agent-review",
"error-diagnostics-analysis": "error-diagnostics-error-analysis",
@@ -59,6 +61,16 @@
"frontend-mobile-scaffold": "frontend-mobile-development-component-scaffold",
"frontend-mobile-scan": "frontend-mobile-security-xss-scan",
"full-stack-feature": "full-stack-orchestration-full-stack-feature",
"2d-games": "game-development/2d-games",
"3d-games": "game-development/3d-games",
"game-art": "game-development/game-art",
"game-audio": "game-development/game-audio",
"game-design": "game-development/game-design",
"mobile-games": "game-development/mobile-games",
"multiplayer": "game-development/multiplayer",
"pc-games": "game-development/pc-games",
"vr-ar": "game-development/vr-ar",
"web-games": "game-development/web-games",
"git-pr-workflow": "git-pr-workflows-git-workflow",
"html injection testing": "html-injection-testing",
"idor vulnerability testing": "idor-testing",
@@ -79,11 +91,13 @@
"observability-monitoring-setup": "observability-monitoring-monitor-setup",
"observability-monitoring-implement": "observability-monitoring-slo-implement",
"obsidian-clipper-creator": "obsidian-clipper-template-creator",
"pdf": "pdf-official",
"pentest checklist": "pentest-checklist",
"pentest commands": "pentest-commands",
"performance-testing-ai": "performance-testing-review-ai-review",
"performance-testing-agent": "performance-testing-review-multi-agent-review",
"supabase-postgres-best-practices": "postgres-best-practices",
"pptx": "pptx-official",
"privilege escalation methods": "privilege-escalation-methods",
"python-development-scaffold": "python-development-python-scaffold",
"vercel-react-best-practices": "react-best-practices",
@@ -107,6 +121,7 @@
"windows privilege escalation": "windows-privilege-escalation",
"wireshark network traffic analysis": "wireshark-analysis",
"wordpress penetration testing": "wordpress-penetration-testing",
"xlsx": "xlsx-official",
"cross-site scripting and html injection testing": "xss-html-injection"
}
}

View File

@@ -1,5 +1,5 @@
{
"generatedAt": "2026-01-30T08:15:03.985Z",
"generatedAt": "2026-02-08T10:02:49.626Z",
"bundles": {
"core-dev": {
"description": "Core development skills across languages, frameworks, and backend/frontend fundamentals.",
@@ -38,6 +38,7 @@
"documentation-generation-doc-generate",
"documentation-templates",
"dotnet-architect",
"dotnet-backend",
"dotnet-backend-patterns",
"exa-search",
"fastapi-pro",
@@ -45,6 +46,9 @@
"firebase",
"firecrawl-scraper",
"flutter-expert",
"fp-ts-errors",
"fp-ts-pragmatic",
"fp-ts-react",
"frontend-design",
"frontend-dev-guidelines",
"frontend-developer",
@@ -52,6 +56,7 @@
"frontend-mobile-security-xss-scan",
"frontend-security-coder",
"frontend-slides",
"game-development/mobile-games",
"go-concurrency-patterns",
"golang-pro",
"graphql",
@@ -108,7 +113,9 @@
"shodan-reconnaissance",
"shopify-apps",
"shopify-development",
"slack-automation",
"slack-bot-builder",
"stitch-ui-design",
"swiftui-expert-skill",
"systems-programming-rust-project",
"tavily-web",
@@ -159,6 +166,7 @@
"deployment-pipeline-design",
"design-orchestration",
"docker-expert",
"dotnet-backend",
"ethical-hacking-methodology",
"find-bugs",
"firebase",
@@ -231,6 +239,7 @@
"skills": [
"backend-architect",
"devops-troubleshooter",
"freshservice-automation",
"gitops-workflow",
"helm-chart-scaffolding",
"istio-traffic-management",
@@ -254,6 +263,7 @@
"skills": [
"airflow-dag-patterns",
"analytics-tracking",
"angular-ui-patterns",
"blockrun",
"business-analyst",
"cc-skill-backend-patterns",
@@ -276,8 +286,11 @@
"database-optimizer",
"dbt-transformation-patterns",
"firebase",
"fp-ts-react",
"frontend-dev-guidelines",
"gdpr-data-handling",
"google-analytics-automation",
"googlesheets-automation",
"graphql",
"hugging-face-jobs",
"hybrid-cloud-networking",
@@ -286,6 +299,7 @@
"kpi-dashboard-design",
"legal-advisor",
"loki-mode",
"mailchimp-automation",
"ml-pipeline-workflow",
"moodle-external-api-development",
"neon-postgres",
@@ -304,6 +318,7 @@
"scala-pro",
"schema-markup",
"segment-cdp",
"sendgrid-automation",
"senior-architect",
"seo-audit",
"spark-optimization",
@@ -311,11 +326,12 @@
"sql-optimization-patterns",
"sql-pro",
"sqlmap-database-pentesting",
"supabase-automation",
"unity-ecs-patterns",
"using-neon",
"vector-database-engineer",
"xlsx",
"xlsx-official"
"xlsx-official",
"youtube-automation"
]
},
"ops-core": {
@@ -352,6 +368,7 @@
"error-diagnostics-error-trace",
"expo-deployment",
"flutter-expert",
"game-development/game-art",
"git-pr-workflows-git-workflow",
"gitlab-ci-patterns",
"gitops-workflow",
@@ -377,8 +394,10 @@
"observability-monitoring-slo-implement",
"performance-engineer",
"performance-testing-review-ai-review",
"pipedrive-automation",
"postmortem-writing",
"prometheus-configuration",
"readme",
"risk-metrics-calculation",
"security-auditor",
"server-management",

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "antigravity-awesome-skills",
"version": "4.2.0",
"version": "4.6.0",
"dependencies": {
"yaml": "^2.8.2"
}

View File

@@ -14,9 +14,10 @@
2. **Choose your bundle** from the list below based on your role or interests.
3. **Use skills** by referencing them in your AI assistant:
- Claude Code: `>> @skill-name help me...`
- Claude Code: `>> /skill-name help me...`
- Cursor: `@skill-name in chat`
- Gemini CLI: `Use skill-name...`
- Codex CLI: `Use skill-name...`
---
@@ -328,33 +329,77 @@ _For system design and technical decisions._
---
## 🧰 Maintainer & OSS
### 🛠️ The "OSS Maintainer" Pack
_For shipping clean changes in public repositories._
- [`commit`](../skills/commit/): High-quality conventional commits.
- [`create-pr`](../skills/create-pr/): PR creation with review-ready context.
- [`requesting-code-review`](../skills/requesting-code-review/): Ask for targeted, high-signal reviews.
- [`receiving-code-review`](../skills/receiving-code-review/): Apply feedback with technical rigor.
- [`changelog-automation`](../skills/changelog-automation/): Keep release notes and changelogs consistent.
- [`git-advanced-workflows`](../skills/git-advanced-workflows/): Rebase, cherry-pick, bisect, recovery.
- [`documentation-templates`](../skills/documentation-templates/): Standardize docs and handoffs.
### 🧱 The "Skill Author" Pack
_For creating and maintaining high-quality SKILL.md assets._
- [`skill-creator`](../skills/skill-creator/): Design effective new skills.
- [`skill-developer`](../skills/skill-developer/): Implement triggers, hooks, and skill lifecycle.
- [`writing-skills`](../skills/writing-skills/): Improve clarity and structure of skill instructions.
- [`documentation-generation-doc-generate`](../skills/documentation-generation-doc-generate/): Generate maintainable technical docs.
- [`lint-and-validate`](../skills/lint-and-validate/): Validate quality after edits.
- [`verification-before-completion`](../skills/verification-before-completion/): Confirm changes before claiming done.
---
## 📚 How to Use Bundles
### Installation
### 1) Pick by immediate goal
1. **Clone the repository:**
```bash
git clone https://github.com/sickn33/antigravity-awesome-skills.git .agent/skills
```
- Need to ship a feature now: `Essentials` + one domain pack (`Web Wizard`, `Python Pro`, `DevOps & Cloud`).
- Need reliability and hardening: add `QA & Testing` + `Security Developer`.
- Need product growth: add `Startup Founder` or `Marketing & Growth`.
2. **Or use the installer:**
```bash
npx antigravity-awesome-skills
```
### 2) Start with 3-5 skills, not 20
### Using Skills
Pick the minimum set for your current milestone. Expand only when you hit a real gap.
Once installed, reference skills in your AI assistant:
### 3) Invoke skills consistently
- **Claude Code**: `>> @skill-name help me...`
- **Claude Code**: `>> /skill-name help me...`
- **Cursor**: `@skill-name` in chat
- **Gemini CLI**: `Use skill-name...`
- **Codex CLI**: `Use skill-name...`
### Customizing Bundles
### 4) Build your personal shortlist
You can create your own bundle by:
1. Copying skill folders to your `.agent/skills/` directory
2. Or referencing multiple skills in a single conversation
Keep a small list of high-frequency skills and reuse it across tasks to reduce context switching.
## 🧩 Recommended Bundle Combos
### Ship a SaaS MVP (2 weeks)
`Essentials` + `Full-Stack Developer` + `QA & Testing` + `Startup Founder`
### Harden an existing production app
`Essentials` + `Security Developer` + `DevOps & Cloud` + `Observability & Monitoring`
### Build an AI product
`Essentials` + `Agent Architect` + `LLM Application Developer` + `Data Engineering`
### Grow traffic and conversions
`Web Wizard` + `Marketing & Growth` + `Data & Analytics`
### Launch and maintain open source
`Essentials` + `OSS Maintainer` + `Architecture & Design`
---
@@ -377,6 +422,11 @@ You can create your own bundle by:
2. Grow: `Security Engineer` → Advanced pentesting
3. Master: Red team tactics and threat modeling
**Open Source Maintenance:**
1. Start: `Essentials` → `OSS Maintainer`
2. Grow: `Architecture & Design` → `QA & Testing`
3. Master: `Skill Author` + release automation workflows
---
## 🤝 Contributing
@@ -393,4 +443,4 @@ Found a skill that should be in a bundle? Or want to create a new bundle? [Open
---
_Last updated: January 2026 | Total Skills: 560+ | Total Bundles: 20+_
_Last updated: February 2026 | Total Skills: 713+ | Total Bundles: 26_

View File

@@ -11,7 +11,7 @@
Skills are specialized instruction files that teach AI assistants how to handle specific tasks. Think of them as expert knowledge modules that your AI can load on-demand.
**Simple analogy:** Just like you might consult different experts (a lawyer, a doctor, a mechanic), these skills let your AI become an expert in different areas when you need them.
### Do I need to install all 560+ skills?
### Do I need to install all 626+ skills?
**No!** When you clone the repository, all skills are available, but your AI only loads them when you explicitly invoke them with `@skill-name`.
It's like having a library - all books are there, but you only read the ones you need.
@@ -62,7 +62,11 @@ _Always check the Risk label and review the code._
### Where should I install the skills?
The universal path that works with most tools is `.agent/skills/`:
The universal path that works with most tools is `.agent/skills/`.
**Using npx:** `npx antigravity-awesome-skills` (or `npx github:sickn33/antigravity-awesome-skills` if you get a 404).
**Using git clone:**
```bash
git clone https://github.com/sickn33/antigravity-awesome-skills.git .agent/skills
@@ -72,6 +76,7 @@ git clone https://github.com/sickn33/antigravity-awesome-skills.git .agent/skill
- Claude Code: `.claude/skills/`
- Gemini CLI: `.gemini/skills/`
- Codex CLI: `.codex/skills/`
- Cursor: `.cursor/skills/` or project root
### Does this work with Windows?

View File

@@ -15,9 +15,11 @@ AI Agents (like **Claude Code**, **Gemini**, **Cursor**) are smart, but they lac
## ⚡️ Quick Start: The "Starter Packs"
Don't panic about the 560+ skills. You don't need them all at once.
Don't panic about the 626+ skills. You don't need them all at once.
We have curated **Starter Packs** to get you running immediately.
You **install the full repo once** (npx or clone); Starter Packs are curated lists to help you **pick which skills to use** by role (e.g. Web Wizard, Hacker Pack)—they are not a different way to install.
### 1. Install the Repo
**Option A — npx (easiest):**
@@ -26,7 +28,9 @@ We have curated **Starter Packs** to get you running immediately.
npx antigravity-awesome-skills
```
This clones to `~/.agent/skills` by default. Use `--cursor`, `--claude`, or `--gemini` to install for a specific tool, or `--path <dir>` for a custom location. Run `npx antigravity-awesome-skills --help` for details.
This clones to `~/.agent/skills` by default. Use `--cursor`, `--claude`, `--gemini`, or `--codex` to install for a specific tool, or `--path <dir>` for a custom location. Run `npx antigravity-awesome-skills --help` for details.
If you see a 404 error, use: `npx github:sickn33/antigravity-awesome-skills`
**Option B — git clone:**
@@ -78,6 +82,7 @@ Once installed, just talk to your AI naturally.
| :-------------- | :-------------- | :---------------- |
| **Claude Code** | ✅ Full Support | `.claude/skills/` |
| **Gemini CLI** | ✅ Full Support | `.gemini/skills/` |
| **Codex CLI** | ✅ Full Support | `.codex/skills/` |
| **Antigravity** | ✅ Native | `.agent/skills/` |
| **Cursor** | ✅ Native | `.cursor/skills/` |
| **Copilot** | ⚠️ Text Only | Manual copy-paste |
@@ -98,8 +103,8 @@ _Check the [Skill Catalog](../CATALOG.md) for the full list._
## ❓ FAQ
**Q: Do I need to install all 560 skills?**
A: You clone the whole repo, but your AI only _reads_ the ones you ask for (or that are relevant). It's lightweight!
**Q: Do I need to install all 626 skills?**
A: You clone the whole repo once; your AI only _reads_ the skills you invoke (or that are relevant), so it stays lightweight. **Starter Packs** in [BUNDLES.md](BUNDLES.md) are curated lists to help you discover the right skills for your role—they don't change how you install.
**Q: Can I make my own skills?**
A: Yes! Use the **@skill-creator** skill to build your own.

View File

@@ -21,6 +21,7 @@ The skill MUST have a section explicitly stating when to trigger it.
- **Good**: "Use when the user asks to debug a React component."
- **Bad**: "This skill helps you with code."
Accepted headings: `## When to Use`, `## Use this skill when`, `## When to Use This Skill`.
### 3. Safety & Risk Classification

View File

@@ -73,7 +73,7 @@ Some skills include additional metadata:
---
name: my-skill-name
description: "Brief description"
risk: "safe" # safe | risk | official
risk: "safe" # none | safe | critical | offensive (see QUALITY_BAR.md)
source: "community"
tags: ["react", "typescript"]
---

View File

@@ -72,6 +72,14 @@ The following skills were added from the curated collection at [VoltAgent/awesom
- **memory-systems** - [muratcankoylan](https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering)
- **terraform-skill** - [antonbabenko](https://github.com/antonbabenko/terraform-skill)
## Skills from whatiskadudoing/fp-ts-skills (v4.4.0)
| Skill | Original Source | License | Notes |
| :---- | :-------------- | :------ | :---- |
| `fp-ts-pragmatic` | [whatiskadudoing/fp-ts-skills](https://github.com/whatiskadudoing/fp-ts-skills) | Compatible | Pragmatic fp-ts guide pipe, Option, Either, TaskEither |
| `fp-ts-react` | [whatiskadudoing/fp-ts-skills](https://github.com/whatiskadudoing/fp-ts-skills) | Compatible | fp-ts with React 18/19 and Next.js |
| `fp-ts-errors` | [whatiskadudoing/fp-ts-skills](https://github.com/whatiskadudoing/fp-ts-skills) | Compatible | Type-safe error handling with Either and TaskEither |
## License Policy
- **Code**: All original code in this repository is **MIT**.

View File

@@ -73,7 +73,7 @@ Một số skill bao gồm thêm siêu dữ liệu bổ sung:
---
name: my-skill-name
description: "Mô tả ngắn"
risk: "safe" # safe | risk | official
risk: "safe" # none | safe | critical | offensive (xem QUALITY_BAR.md)
source: "community"
tags: ["react", "typescript"]
---

View File

@@ -149,12 +149,39 @@ function readSkill(skillDir, skillId) {
function listSkillIds(skillsDir) {
return fs.readdirSync(skillsDir)
.filter(entry => !entry.startsWith('.') && fs.statSync(path.join(skillsDir, entry)).isDirectory())
.filter(entry => {
if (entry.startsWith('.')) return false;
const dirPath = path.join(skillsDir, entry);
if (!fs.statSync(dirPath).isDirectory()) return false;
const skillPath = path.join(dirPath, 'SKILL.md');
return fs.existsSync(skillPath);
})
.sort();
}
/**
* Recursively list all skill directory paths under skillsDir (relative paths).
* Matches generate_index.py behavior so catalog includes nested skills (e.g. game-development/2d-games).
*/
function listSkillIdsRecursive(skillsDir, baseDir = skillsDir, acc = []) {
const entries = fs.readdirSync(baseDir, { withFileTypes: true });
for (const entry of entries) {
if (entry.name.startsWith('.')) continue;
if (!entry.isDirectory()) continue;
const dirPath = path.join(baseDir, entry.name);
const skillPath = path.join(dirPath, 'SKILL.md');
const relPath = path.relative(skillsDir, dirPath);
if (fs.existsSync(skillPath)) {
acc.push(relPath);
}
listSkillIdsRecursive(skillsDir, dirPath, acc);
}
return acc.sort();
}
module.exports = {
listSkillIds,
listSkillIdsRecursive,
parseFrontmatter,
parseInlineList,
readSkill,

11
package-lock.json generated
View File

@@ -1,24 +1,25 @@
{
"name": "antigravity-awesome-skills",
"version": "4.2.0",
"version": "4.10.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "antigravity-awesome-skills",
"version": "4.2.0",
"version": "4.10.0",
"license": "MIT",
"dependencies": {
"yaml": "^2.8.2"
},
"bin": {
"antigravity-awesome-skills": "bin/install.js"
},
"devDependencies": {
"yaml": "^2.8.2"
}
},
"node_modules/yaml": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
"dev": true,
"license": "ISC",
"bin": {
"yaml": "bin.mjs"

View File

@@ -1,7 +1,7 @@
{
"name": "antigravity-awesome-skills",
"version": "4.3.0",
"description": "614+ agentic skills for Claude Code, Gemini CLI, Cursor, Antigravity & more. Installer CLI.",
"version": "4.11.0",
"description": "626+ agentic skills for Claude Code, Gemini CLI, Cursor, Antigravity & more. Installer CLI.",
"license": "MIT",
"scripts": {
"validate": "python3 scripts/validate_skills.py",
@@ -10,17 +10,18 @@
"readme": "python3 scripts/update_readme.py",
"chain": "npm run validate && npm run index && npm run readme",
"catalog": "node scripts/build-catalog.js",
"build": "npm run chain && npm run catalog"
"build": "npm run chain && npm run catalog",
"test": "node scripts/tests/validate_skills_headings.test.js && python3 scripts/tests/test_validate_skills_headings.py"
},
"dependencies": {
"devDependencies": {
"yaml": "^2.8.2"
},
"repository": {
"type": "git",
"url": "https://github.com/sickn33/antigravity-awesome-skills.git"
"url": "git+https://github.com/sickn33/antigravity-awesome-skills.git"
},
"bin": {
"antigravity-awesome-skills": "./bin/install.js"
"antigravity-awesome-skills": "bin/install.js"
},
"files": [
"bin"

36
release_notes.md Normal file
View File

@@ -0,0 +1,36 @@
## [4.10.0] - 2026-02-06 - "Composio Automation + .NET Backend"
> This release significantly expands hands-on automation coverage while adding a production-oriented .NET backend skill.
### Added
- **79 new skills total**.
- **78 Composio/Rube automation skills** (PR #64), covering practical workflows across:
- CRM/sales (`HubSpot`, `Salesforce`, `Pipedrive`, `Zoho CRM`, `Close`)
- Collaboration/project ops (`Notion`, `ClickUp`, `Asana`, `Jira`, `Confluence`, `Trello`, `Monday`)
- Messaging/support (`Slack`, `Discord`, `Teams`, `Intercom`, `Freshdesk`, `Zendesk`)
- Analytics/marketing (`Google Analytics`, `Mixpanel`, `PostHog`, `Segment`, `Mailchimp`, `Klaviyo`)
- Dev/infra operations (`GitHub`, `GitLab`, `CircleCI`, `Datadog`, `PagerDuty`, `Vercel`, `Render`)
- **1 new `dotnet-backend` skill** (PR #65) with detailed ASP.NET Core 8+ guidance:
- Minimal API and controller patterns
- EF Core data-access patterns
- JWT authentication implementation
- Background service templates
- Explicit "When to Use" and "Limitations" sections
- **Registry growth**: 634 -> 713 indexed skills.
### Changed
- Regenerated and synchronized discovery artifacts:
- `README.md`
- `skills_index.json`
- `CATALOG.md`
- `data/catalog.json`
- `data/bundles.json`
- `data/aliases.json`
- Updated release metadata and published tag/release `v4.10.0`.
### Contributors
- [@sohamganatra](https://github.com/sohamganatra)
- [@Nguyen-Van-Chan](https://github.com/Nguyen-Van-Chan)

File diff suppressed because it is too large Load Diff

View File

@@ -1,215 +0,0 @@
#!/usr/bin/env python3
"""
Analyze remaining similar skills to determine if they are truly new
and worth adding to the repository.
"""
import json
import re
from pathlib import Path
from typing import Dict, List, Tuple
from urllib.parse import urlparse
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError
def normalize_skill_name(name: str) -> str:
"""Normalize skill name to kebab-case."""
# Remove special chars, convert to lowercase, replace spaces/hyphens
name = re.sub(r'[^\w\s-]', '', name.lower())
name = re.sub(r'[\s_]+', '-', name)
name = re.sub(r'-+', '-', name)
return name.strip('-')
def check_url_accessible(url: str) -> bool:
"""Check if URL is accessible."""
try:
req = Request(url, method='HEAD')
with urlopen(req, timeout=10) as response:
return response.status == 200
except (URLError, HTTPError, Exception):
return False
def get_repo_base_url(github_url: str) -> str:
"""Extract base GitHub repository URL."""
# Handle various GitHub URL formats
patterns = [
r'https://github\.com/([^/]+/[^/]+)',
r'github\.com/([^/]+/[^/]+)',
]
for pattern in patterns:
match = re.search(pattern, github_url)
if match:
return f"https://github.com/{match.group(1)}"
return None
def check_skill_file_exists(repo_url: str, skill_path: str = None) -> Tuple[bool, str]:
"""Check if SKILL.md exists in the repository."""
base_url = get_repo_base_url(repo_url)
if not base_url:
return False, None
# Common paths to check
paths_to_check = [
f"{base_url}/raw/main/{skill_path}/SKILL.md" if skill_path else f"{base_url}/raw/main/SKILL.md",
f"{base_url}/raw/main/skills/{skill_path}/SKILL.md" if skill_path else None,
f"{base_url}/raw/master/{skill_path}/SKILL.md" if skill_path else f"{base_url}/raw/master/SKILL.md",
f"{base_url}/blob/main/{skill_path}/SKILL.md" if skill_path else f"{base_url}/blob/main/SKILL.md",
]
for path in paths_to_check:
if path and check_url_accessible(path):
return True, path
return False, None
def analyze_similarity(skill_name: str, similar_skills: List[str], existing_skills: Dict) -> Dict:
"""Analyze how similar a skill is to existing ones."""
analysis = {
'is_duplicate': False,
'is_complementary': False,
'similarity_score': 0.0,
'closest_match': None,
'reasoning': []
}
skill_lower = skill_name.lower()
# Check for exact or near-exact matches
for existing_name, existing_data in existing_skills.items():
existing_lower = existing_name.lower()
# Exact match
if skill_lower == existing_lower:
analysis['is_duplicate'] = True
analysis['closest_match'] = existing_name
analysis['reasoning'].append(f"Exact match with existing skill: {existing_name}")
return analysis
# Check if one contains the other
if skill_lower in existing_lower or existing_lower in skill_lower:
if abs(len(skill_lower) - len(existing_lower)) <= 3:
analysis['is_duplicate'] = True
analysis['closest_match'] = existing_name
analysis['similarity_score'] = 0.9
analysis['reasoning'].append(f"Near-exact match: '{skill_name}' vs '{existing_name}'")
return analysis
# Check similarity with similar skills list
for similar in similar_skills:
if similar.lower() in existing_skills:
existing_data = existing_skills[similar.lower()]
# If the similar skill exists, this might be a duplicate
analysis['similarity_score'] = 0.7
analysis['closest_match'] = similar
analysis['reasoning'].append(f"Similar to existing skill: {similar}")
# Determine if complementary
if analysis['similarity_score'] < 0.5:
analysis['is_complementary'] = True
analysis['reasoning'].append("Low similarity - likely complementary skill")
return analysis
def main():
base_dir = Path(__file__).parent.parent
# Load remaining similar skills
remaining_file = base_dir / "remaining_similar_skills.json"
if not remaining_file.exists():
print("❌ remaining_similar_skills.json not found. Run the analysis first.")
return
with open(remaining_file, 'r') as f:
data = json.load(f)
# Load existing skills
catalog_file = base_dir / "data" / "catalog.json"
with open(catalog_file, 'r') as f:
catalog = json.load(f)
existing_skills = {s['name'].lower(): s for s in catalog.get('skills', [])}
print(f"🔍 Analyzing {len(data['skills'])} remaining similar skills...\n")
results = {
'truly_new': [],
'duplicates': [],
'complementary': [],
'needs_review': [],
'invalid_sources': []
}
for skill in data['skills']:
skill_name = skill['name']
print(f"Analyzing: {skill_name}")
# Skip if already exists
if skill['exists_in_catalog'] or skill['folder_exists']:
results['duplicates'].append({
'name': skill_name,
'reason': 'Already exists in repository',
'url': skill['url']
})
continue
# Check source accessibility
exists, raw_url = check_skill_file_exists(skill['url'], skill.get('skill_part'))
if not exists:
results['invalid_sources'].append({
'name': skill_name,
'url': skill['url'],
'reason': 'SKILL.md not found or URL inaccessible'
})
continue
# Analyze similarity
similarity_analysis = analyze_similarity(
skill_name,
skill['similar_to'],
existing_skills
)
skill_result = {
'name': skill_name,
'url': skill['url'],
'raw_url': raw_url,
'description': skill['description'],
'org': skill['org'],
'category': skill['category'],
'similar_to': skill['similar_to'],
'similarity_analysis': similarity_analysis
}
if similarity_analysis['is_duplicate']:
results['duplicates'].append(skill_result)
elif similarity_analysis['is_complementary']:
results['complementary'].append(skill_result)
else:
results['needs_review'].append(skill_result)
# Generate report
report = {
'summary': {
'total_analyzed': len(data['skills']),
'truly_new': len(results['complementary']),
'duplicates': len(results['duplicates']),
'needs_review': len(results['needs_review']),
'invalid_sources': len(results['invalid_sources'])
},
'results': results
}
output_file = base_dir / "similar_skills_analysis.json"
with open(output_file, 'w') as f:
json.dump(report, f, indent=2)
print(f"\n✅ Analysis complete!")
print(f"📊 Summary:")
print(f" - Truly new (complementary): {len(results['complementary'])}")
print(f" - Duplicates: {len(results['duplicates'])}")
print(f" - Needs review: {len(results['needs_review'])}")
print(f" - Invalid sources: {len(results['invalid_sources'])}")
print(f"\n📄 Full report saved to: {output_file}")
if __name__ == "__main__":
main()

View File

@@ -1,7 +1,7 @@
const fs = require('fs');
const path = require('path');
const {
listSkillIds,
listSkillIdsRecursive,
readSkill,
tokenize,
unique,
@@ -297,8 +297,8 @@ function renderCatalogMarkdown(catalog) {
}
function buildCatalog() {
const skillIds = listSkillIds(SKILLS_DIR);
const skills = skillIds.map(skillId => readSkill(SKILLS_DIR, skillId));
const skillRelPaths = listSkillIdsRecursive(SKILLS_DIR);
const skills = skillRelPaths.map(relPath => readSkill(SKILLS_DIR, relPath));
const catalogSkills = [];
for (const skill of skills) {
@@ -318,9 +318,9 @@ function buildCatalog() {
}
const catalog = {
generatedAt: new Date().toISOString(),
generatedAt: process.env.SOURCE_DATE_EPOCH ? new Date(process.env.SOURCE_DATE_EPOCH * 1000).toISOString() : new Date().toISOString(),
total: catalogSkills.length,
skills: catalogSkills.sort((a, b) => a.id.localeCompare(b.id)),
skills: catalogSkills.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0)),
};
const aliases = buildAliases(catalog.skills);

View File

@@ -1,149 +0,0 @@
#!/usr/bin/env python3
"""
Count uncommitted skills by checking git status.
"""
import subprocess
import json
from pathlib import Path
def run_git_command(cmd):
"""Run git command and return output."""
try:
result = subprocess.run(
cmd.split(),
capture_output=True,
text=True,
cwd=Path(__file__).parent.parent
)
return result.stdout.strip().split('\n') if result.stdout.strip() else []
except Exception as e:
print(f"Error running git command: {e}")
return []
def main():
base_dir = Path(__file__).parent.parent
# Get all uncommitted files
untracked = run_git_command("git ls-files --others --exclude-standard")
modified = run_git_command("git diff --name-only HEAD")
staged = run_git_command("git diff --cached --name-only")
# Also check status
status_output = run_git_command("git status --porcelain")
print("Git status output:")
for line in status_output[:20]: # First 20 lines
print(f" {line}")
print()
# Filter for skill files
skill_files = []
for file_list in [untracked, modified, staged]:
for file in file_list:
if '/skills/' in file and file.endswith('SKILL.md'):
skill_name = file.split('/skills/')[1].split('/SKILL.md')[0]
if skill_name not in [s['name'] for s in skill_files]:
skill_files.append({
'name': skill_name,
'file': file,
'status': 'untracked' if file in untracked else ('staged' if file in staged else 'modified')
})
# Load catalog to verify
catalog_file = base_dir / "data" / "catalog.json"
with open(catalog_file, 'r') as f:
catalog = json.load(f)
catalog_skills = {s['name']: s for s in catalog.get('skills', [])}
print("=" * 70)
print("SKILLS NON COMMITTATE")
print("=" * 70)
print(f"\nTotale skills trovate: {len(skill_files)}")
print(f"Totale skills nel catalog: {catalog.get('total', 0)}")
print()
# Group by status
untracked_skills = [s for s in skill_files if s['status'] == 'untracked']
modified_skills = [s for s in skill_files if s['status'] == 'modified']
staged_skills = [s for s in skill_files if s['status'] == 'staged']
print(f"📝 Skills non tracciate (nuove): {len(untracked_skills)}")
print(f"📝 Skills modificate: {len(modified_skills)}")
print(f"📝 Skills staged: {len(staged_skills)}")
print()
if untracked_skills:
print("Nuove skills (non tracciate):")
for skill in sorted(untracked_skills, key=lambda x: x['name']):
in_catalog = skill['name'] in catalog_skills
print(f"{skill['name']} {'(in catalog)' if in_catalog else '(NOT in catalog)'}")
if modified_skills:
print("\nSkills modificate:")
for skill in sorted(modified_skills, key=lambda x: x['name']):
print(f" 📝 {skill['name']}")
if staged_skills:
print("\nSkills staged:")
for skill in sorted(staged_skills, key=lambda x: x['name']):
print(f" 📦 {skill['name']}")
# Check for VoltAgent skills specifically
print("\n" + "=" * 70)
print("VERIFICA SKILLS DA VOLTAGENT")
print("=" * 70)
voltagent_skills_phase1 = [
'commit', 'create-pr', 'find-bugs', 'iterate-pr',
'culture-index', 'fix-review', 'sharp-edges',
'expo-deployment', 'upgrading-expo',
'using-neon', 'vercel-deploy-claimable', 'design-md',
'hugging-face-cli', 'hugging-face-jobs',
'automate-whatsapp', 'observe-whatsapp', 'readme', 'screenshots',
'deep-research', 'imagen', 'swiftui-expert-skill',
'n8n-code-python', 'n8n-mcp-tools-expert', 'n8n-node-configuration'
]
voltagent_skills_phase2 = [
'frontend-slides', 'linear-claude-skill', 'skill-rails-upgrade',
'context-fundamentals', 'context-degradation', 'context-compression',
'context-optimization', 'multi-agent-patterns', 'tool-design',
'evaluation', 'memory-systems', 'terraform-skill'
]
all_voltagent = voltagent_skills_phase1 + voltagent_skills_phase2
uncommitted_voltagent = []
for skill_name in all_voltagent:
skill_file = base_dir / "skills" / skill_name / "SKILL.md"
if skill_file.exists():
# Check if it's uncommitted
if skill_file.relative_to(base_dir).as_posix() in untracked:
uncommitted_voltagent.append(skill_name)
elif skill_file.relative_to(base_dir).as_posix() in modified:
uncommitted_voltagent.append(skill_name)
elif skill_file.relative_to(base_dir).as_posix() in staged:
uncommitted_voltagent.append(skill_name)
print(f"\nSkills da VoltAgent non committate: {len(uncommitted_voltagent)}")
print(f" Fase 1 (49 skills): {len([s for s in voltagent_skills_phase1 if s in uncommitted_voltagent])}")
print(f" Fase 2 (12 skills): {len([s for s in voltagent_skills_phase2 if s in uncommitted_voltagent])}")
print("\n" + "=" * 70)
print("RIEPILOGO FINALE")
print("=" * 70)
print(f"Totale skills non committate: {len(skill_files)}")
print(f"Skills da VoltAgent non committate: {len(uncommitted_voltagent)}")
print(f"Altre skills non committate: {len(skill_files) - len(uncommitted_voltagent)}")
return {
'total_uncommitted': len(skill_files),
'voltagent_uncommitted': len(uncommitted_voltagent),
'voltagent_phase1': len([s for s in voltagent_skills_phase1 if s in uncommitted_voltagent]),
'voltagent_phase2': len([s for s in voltagent_skills_phase2 if s in uncommitted_voltagent])
}
if __name__ == "__main__":
main()

View File

@@ -1,271 +0,0 @@
#!/usr/bin/env python3
"""
Implement the 12 new skills from similar skills analysis.
9 recommended + 3 verified (evaluation, memory-systems, terraform-skill)
"""
import json
import re
import sys
from pathlib import Path
from urllib.request import urlopen, Request
from urllib.error import URLError, HTTPError
from typing import Dict, Optional
def normalize_skill_name(name: str) -> str:
"""Normalize skill name to kebab-case."""
name = re.sub(r'[^a-z0-9-]', '-', name.lower())
name = re.sub(r'-+', '-', name)
return name.strip('-')
def download_file(url: str) -> Optional[str]:
"""Download content from URL."""
try:
req = Request(url)
req.add_header('User-Agent', 'Mozilla/5.0 (compatible; AntigravitySkillsDownloader/1.0)')
with urlopen(req, timeout=15) as response:
return response.read().decode('utf-8')
except Exception as e:
print(f" ❌ Error downloading {url}: {e}")
return None
def parse_frontmatter(content: str) -> Optional[Dict]:
"""Parse YAML frontmatter."""
fm_match = re.search(r'^---\s*\n(.*?)\n---', content, re.DOTALL)
if not fm_match:
return None
fm_text = fm_match.group(1)
metadata = {}
for line in fm_text.split('\n'):
if ':' in line:
key, val = line.split(':', 1)
metadata[key.strip()] = val.strip().strip('"').strip("'")
return metadata
def ensure_frontmatter_compliance(content: str, skill_name: str, source_url: str, description: str) -> str:
"""Ensure SKILL.md has compliant frontmatter."""
metadata = parse_frontmatter(content)
if not metadata:
# No frontmatter, add it
frontmatter = f"""---
name: {skill_name}
description: {description}
source: {source_url}
risk: safe
---
"""
return frontmatter + content
# Update existing frontmatter
metadata['name'] = skill_name
metadata['description'] = description
metadata['source'] = source_url
if 'risk' not in metadata:
metadata['risk'] = 'safe'
# Rebuild frontmatter
frontmatter_lines = ['---']
for key, value in metadata.items():
if isinstance(value, str) and (' ' in value or ':' in value):
frontmatter_lines.append(f'{key}: "{value}"')
else:
frontmatter_lines.append(f'{key}: {value}')
frontmatter_lines.append('---\n')
# Replace frontmatter in content
content_without_fm = re.sub(r'^---\s*\n.*?\n---\s*\n', '', content, flags=re.DOTALL)
return '\n'.join(frontmatter_lines) + content_without_fm
def ensure_when_to_use_section(content: str, description: str) -> str:
"""Ensure 'When to Use' section exists."""
if re.search(r'##\s+When\s+to\s+Use', content, re.IGNORECASE):
return content
# Add section after frontmatter
when_to_use = f"""
## When to Use This Skill
{description}
Use this skill when working with {description.lower()}.
"""
# Insert after frontmatter
content = re.sub(r'(---\s*\n.*?\n---\s*\n)', r'\1' + when_to_use, content, flags=re.DOTALL)
return content
def main():
base_dir = Path(__file__).parent.parent
# Load similar skills analysis
analysis_file = base_dir / "similar_skills_analysis.json"
with open(analysis_file, 'r') as f:
analysis = json.load(f)
# Skills to implement: 9 recommended + 3 verified
skills_to_implement = [
# 9 Recommended
{
'name': 'frontend-slides',
'url': 'https://github.com/zarazhangrui/frontend-slides',
'raw_url': 'https://github.com/zarazhangrui/frontend-slides/raw/main/SKILL.md',
'description': 'Generate animation-rich HTML presentations with visual style previews',
'org': 'zarazhangrui',
'category': 'Community Skills'
},
{
'name': 'linear-claude-skill',
'url': 'https://github.com/wrsmith108/linear-claude-skill',
'raw_url': 'https://github.com/wrsmith108/linear-claude-skill/raw/main/SKILL.md',
'description': 'Manage Linear issues, projects, and teams',
'org': 'wrsmith108',
'category': 'Community Skills'
},
{
'name': 'skill-rails-upgrade',
'url': 'https://github.com/robzolkos/skill-rails-upgrade',
'raw_url': 'https://github.com/robzolkos/skill-rails-upgrade/raw/master/SKILL.md',
'description': 'Analyze Rails apps and provide upgrade assessments',
'org': 'robzolkos',
'category': 'Community Skills'
},
{
'name': 'context-fundamentals',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-fundamentals',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/context-fundamentals/SKILL.md',
'description': 'Understand what context is, why it matters, and the anatomy of context in agent systems',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
{
'name': 'context-degradation',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-degradation',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/context-degradation/SKILL.md',
'description': 'Recognize patterns of context failure: lost-in-middle, poisoning, distraction, and clash',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
{
'name': 'context-compression',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-compression',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/context-compression/SKILL.md',
'description': 'Design and evaluate compression strategies for long-running sessions',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
{
'name': 'context-optimization',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-optimization',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/context-optimization/SKILL.md',
'description': 'Apply compaction, masking, and caching strategies',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
{
'name': 'multi-agent-patterns',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/multi-agent-patterns',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/multi-agent-patterns/SKILL.md',
'description': 'Master orchestrator, peer-to-peer, and hierarchical multi-agent architectures',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
{
'name': 'tool-design',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/tool-design',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/tool-design/SKILL.md',
'description': 'Build tools that agents can use effectively, including architectural reduction patterns',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
# 3 Verified (notebooklm-skill is duplicate, skip it)
{
'name': 'evaluation',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/evaluation',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/evaluation/SKILL.md',
'description': 'Build evaluation frameworks for agent systems',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
{
'name': 'memory-systems',
'url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/memory-systems',
'raw_url': 'https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/skills/memory-systems/SKILL.md',
'description': 'Design short-term, long-term, and graph-based memory architectures',
'org': 'muratcankoylan',
'category': 'Community Skills'
},
{
'name': 'terraform-skill',
'url': 'https://github.com/antonbabenko/terraform-skill',
'raw_url': 'https://github.com/antonbabenko/terraform-skill/raw/master/SKILL.md',
'description': 'Terraform infrastructure as code best practices',
'org': 'antonbabenko',
'category': 'Community Skills'
},
]
print(f"🚀 Implementing {len(skills_to_implement)} new skills...\n")
results = {
'success': [],
'failed': []
}
for skill in skills_to_implement:
skill_name = skill['name']
raw_url = skill['raw_url']
source_url = skill['url']
description = skill['description']
print(f"📦 Processing: {skill_name}")
# Download SKILL.md
content = download_file(raw_url)
if not content:
print(f" ❌ Failed to download")
results['failed'].append(skill_name)
continue
# Check if it's HTML (shouldn't be, but just in case)
if '<!DOCTYPE html>' in content or ('<html>' in content.lower() and content.count('<html>') > 1):
print(f" ⚠️ Received HTML instead of markdown, trying alternative URL")
# Try alternative raw URL
alt_url = raw_url.replace('/raw/main/', '/raw/master/') if '/raw/main/' in raw_url else raw_url.replace('/raw/master/', '/raw/main/')
alt_content = download_file(alt_url)
if alt_content and not ('<!DOCTYPE html>' in alt_content or '<html>' in alt_content.lower()):
content = alt_content
print(f" ✅ Got markdown from alternative URL")
else:
print(f" ❌ Still HTML, skipping")
results['failed'].append(skill_name)
continue
# Ensure compliance
content = ensure_frontmatter_compliance(content, skill_name, source_url, description)
content = ensure_when_to_use_section(content, description)
# Create skill directory
skill_dir = base_dir / "skills" / skill_name
skill_dir.mkdir(parents=True, exist_ok=True)
# Write SKILL.md
skill_file = skill_dir / "SKILL.md"
skill_file.write_text(content, encoding='utf-8')
print(f" ✅ Created: {skill_file}")
results['success'].append(skill_name)
print(f"\n✅ Implementation complete!")
print(f" Success: {len(results['success'])}")
print(f" Failed: {len(results['failed'])}")
if results['failed']:
print(f"\n❌ Failed skills: {', '.join(results['failed'])}")
return results
if __name__ == "__main__":
main()

View File

@@ -8,6 +8,8 @@ const SKILLS_DIR = path.join(ROOT, 'skills');
const ALLOWED_FIELDS = new Set([
'name',
'description',
'risk',
'source',
'license',
'compatibility',
'metadata',

View File

@@ -21,8 +21,12 @@ python3 scripts/generate_index.py
echo "Running update_readme.py..."
python3 scripts/update_readme.py
# 2. Stats Consistency Check
echo -e "\n${YELLOW}Step 2: verifying Stats Consistency...${NC}"
# 2. Catalog (required for CI)
echo -e "\n${YELLOW}Step 2: Build catalog...${NC}"
npm run catalog
# 3. Stats Consistency Check
echo -e "\n${YELLOW}Step 3: Verifying Stats Consistency...${NC}"
JSON_COUNT=$(python3 -c "import json; print(len(json.load(open('skills_index.json'))))")
echo "Skills in Registry (JSON): $JSON_COUNT"
@@ -36,8 +40,14 @@ if [[ "$README_CONTENT" != *"$JSON_COUNT high-performance"* ]]; then
fi
echo -e "${GREEN}✅ Stats Consistent.${NC}"
# 3. Contributor Check
echo -e "\n${YELLOW}Step 3: Contributor Check${NC}"
# 4. Version check (package.json is source of truth for npm)
echo -e "\n${YELLOW}Step 4: Version check${NC}"
PKG_VERSION=$(node -p "require('./package.json').version")
echo "package.json version: $PKG_VERSION"
echo "Ensure this version is bumped before 'npm publish' (npm forbids republishing the same version)."
# 5. Contributor Check
echo -e "\n${YELLOW}Step 5: Contributor Check${NC}"
echo "Recent commits by author (check against README 'Repo Contributors'):"
git shortlog -sn --since="1 month ago" --all --no-merges | head -n 10
@@ -52,4 +62,5 @@ if [ "$CONFIRM_CONTRIB" != "yes" ]; then
fi
echo -e "\n${GREEN}✅ Release Cycle Checks Passed. You may now commit and push.${NC}"
echo -e "${YELLOW}After tagging a release: run \`npm publish\` from repo root (or use GitHub Release + NPM_TOKEN for CI).${NC}"
exit 0

View File

@@ -0,0 +1,18 @@
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from validate_skills import has_when_to_use_section
SAMPLES = [
("## When to Use", True),
("## Use this skill when", True),
("## When to Use This Skill", True),
("## Overview", False),
]
for heading, expected in SAMPLES:
content = f"\n{heading}\n- item\n"
assert has_when_to_use_section(content) is expected, heading
print("ok")

View File

@@ -0,0 +1,16 @@
const assert = require('assert');
const { hasUseSection } = require('../validate-skills');
const samples = [
['## When to Use', true],
['## Use this skill when', true],
['## When to Use This Skill', true],
['## Overview', false],
];
for (const [heading, expected] of samples) {
const content = `\n${heading}\n- item\n`;
assert.strictEqual(hasUseSection(content), expected, heading);
}
console.log('ok');

View File

@@ -36,7 +36,7 @@ def update_readme():
# 3. Update Intro Text Count
content = re.sub(
r"(library of \*\*)\d+( high-performance skills\*\*)",
r"(library of \*\*)\d+( high-performance agentic skills\*\*)",
rf"\g<1>{total_skills}\g<2>",
content,
)

View File

@@ -32,12 +32,24 @@ const MAX_SKILL_LINES = 500;
const ALLOWED_FIELDS = new Set([
'name',
'description',
'risk',
'source',
'license',
'compatibility',
'metadata',
'allowed-tools',
]);
const USE_SECTION_PATTERNS = [
/^##\s+When\s+to\s+Use/im,
/^##\s+Use\s+this\s+skill\s+when/im,
/^##\s+When\s+to\s+Use\s+This\s+Skill/im,
];
function hasUseSection(content) {
return USE_SECTION_PATTERNS.some(pattern => pattern.test(content));
}
function isPlainObject(value) {
return value && typeof value === 'object' && !Array.isArray(value);
}
@@ -99,172 +111,183 @@ function addStrictSectionErrors(label, missing, baselineSet) {
}
}
const skillIds = listSkillIds(SKILLS_DIR);
const baseline = loadBaseline();
const baselineUse = new Set(baseline.useSection || []);
const baselineDoNotUse = new Set(baseline.doNotUseSection || []);
const baselineInstructions = new Set(baseline.instructionsSection || []);
const baselineLongFile = new Set(baseline.longFile || []);
function run() {
const skillIds = listSkillIds(SKILLS_DIR);
const baseline = loadBaseline();
const baselineUse = new Set(baseline.useSection || []);
const baselineDoNotUse = new Set(baseline.doNotUseSection || []);
const baselineInstructions = new Set(baseline.instructionsSection || []);
const baselineLongFile = new Set(baseline.longFile || []);
for (const skillId of skillIds) {
const skillPath = path.join(SKILLS_DIR, skillId, 'SKILL.md');
for (const skillId of skillIds) {
const skillPath = path.join(SKILLS_DIR, skillId, 'SKILL.md');
if (!fs.existsSync(skillPath)) {
addError(`Missing SKILL.md: ${skillId}`);
continue;
}
const content = fs.readFileSync(skillPath, 'utf8');
const { data, errors: fmErrors, hasFrontmatter } = parseFrontmatter(content);
const lineCount = content.split(/\r?\n/).length;
if (!hasFrontmatter) {
addError(`Missing frontmatter: ${skillId}`);
}
if (fmErrors && fmErrors.length) {
fmErrors.forEach(error => addError(`Frontmatter parse error (${skillId}): ${error}`));
}
if (!NAME_PATTERN.test(skillId)) {
addError(`Folder name must match ${NAME_PATTERN}: ${skillId}`);
}
if (data.name !== undefined) {
const nameError = validateStringField('name', data.name, { min: 1, max: MAX_NAME_LENGTH });
if (nameError) {
addError(`${nameError} (${skillId})`);
} else {
const nameValue = String(data.name).trim();
if (!NAME_PATTERN.test(nameValue)) {
addError(`name must match ${NAME_PATTERN}: ${skillId}`);
}
if (nameValue !== skillId) {
addError(`name must match folder name: ${skillId} -> ${nameValue}`);
}
if (!fs.existsSync(skillPath)) {
addError(`Missing SKILL.md: ${skillId}`);
continue;
}
}
const descError = data.description === undefined
? 'description is required.'
: validateStringField('description', data.description, { min: 1, max: MAX_DESCRIPTION_LENGTH });
if (descError) {
addError(`${descError} (${skillId})`);
}
const content = fs.readFileSync(skillPath, 'utf8');
const { data, errors: fmErrors, hasFrontmatter } = parseFrontmatter(content);
const lineCount = content.split(/\r?\n/).length;
if (data.license !== undefined) {
const licenseError = validateStringField('license', data.license, { min: 1, max: 128 });
if (licenseError) {
addError(`${licenseError} (${skillId})`);
if (!hasFrontmatter) {
addError(`Missing frontmatter: ${skillId}`);
}
}
if (data.compatibility !== undefined) {
const compatibilityError = validateStringField(
'compatibility',
data.compatibility,
{ min: 1, max: MAX_COMPATIBILITY_LENGTH },
);
if (compatibilityError) {
addError(`${compatibilityError} (${skillId})`);
if (fmErrors && fmErrors.length) {
fmErrors.forEach(error => addError(`Frontmatter parse error (${skillId}): ${error}`));
}
}
if (data['allowed-tools'] !== undefined) {
if (typeof data['allowed-tools'] !== 'string') {
addError(`allowed-tools must be a space-delimited string. (${skillId})`);
} else if (!data['allowed-tools'].trim()) {
addError(`allowed-tools cannot be empty. (${skillId})`);
if (!NAME_PATTERN.test(skillId)) {
addError(`Folder name must match ${NAME_PATTERN}: ${skillId}`);
}
}
if (data.metadata !== undefined) {
if (!isPlainObject(data.metadata)) {
addError(`metadata must be a string map/object. (${skillId})`);
} else {
for (const [key, value] of Object.entries(data.metadata)) {
if (typeof value !== 'string') {
addError(`metadata.${key} must be a string. (${skillId})`);
if (data.name !== undefined) {
const nameError = validateStringField('name', data.name, { min: 1, max: MAX_NAME_LENGTH });
if (nameError) {
addError(`${nameError} (${skillId})`);
} else {
const nameValue = String(data.name).trim();
if (!NAME_PATTERN.test(nameValue)) {
addError(`name must match ${NAME_PATTERN}: ${skillId}`);
}
if (nameValue !== skillId) {
addError(`name must match folder name: ${skillId} -> ${nameValue}`);
}
}
}
}
if (data && Object.keys(data).length) {
const unknownFields = Object.keys(data).filter(key => !ALLOWED_FIELDS.has(key));
if (unknownFields.length) {
unknownFieldSkills.push(skillId);
addError(`Unknown frontmatter fields (${skillId}): ${unknownFields.join(', ')}`);
const descError = data.description === undefined
? 'description is required.'
: validateStringField('description', data.description, { min: 1, max: MAX_DESCRIPTION_LENGTH });
if (descError) {
addError(`${descError} (${skillId})`);
}
if (data.license !== undefined) {
const licenseError = validateStringField('license', data.license, { min: 1, max: 128 });
if (licenseError) {
addError(`${licenseError} (${skillId})`);
}
}
if (data.compatibility !== undefined) {
const compatibilityError = validateStringField(
'compatibility',
data.compatibility,
{ min: 1, max: MAX_COMPATIBILITY_LENGTH },
);
if (compatibilityError) {
addError(`${compatibilityError} (${skillId})`);
}
}
if (data['allowed-tools'] !== undefined) {
if (typeof data['allowed-tools'] !== 'string') {
addError(`allowed-tools must be a space-delimited string. (${skillId})`);
} else if (!data['allowed-tools'].trim()) {
addError(`allowed-tools cannot be empty. (${skillId})`);
}
}
if (data.metadata !== undefined) {
if (!isPlainObject(data.metadata)) {
addError(`metadata must be a string map/object. (${skillId})`);
} else {
for (const [key, value] of Object.entries(data.metadata)) {
if (typeof value !== 'string') {
addError(`metadata.${key} must be a string. (${skillId})`);
}
}
}
}
if (data && Object.keys(data).length) {
const unknownFields = Object.keys(data).filter(key => !ALLOWED_FIELDS.has(key));
if (unknownFields.length) {
unknownFieldSkills.push(skillId);
addError(`Unknown frontmatter fields (${skillId}): ${unknownFields.join(', ')}`);
}
}
if (lineCount > MAX_SKILL_LINES) {
longFiles.push(skillId);
}
if (!hasUseSection(content)) {
missingUseSection.push(skillId);
}
if (!content.includes('## Do not use')) {
missingDoNotUseSection.push(skillId);
}
if (!content.includes('## Instructions')) {
missingInstructionsSection.push(skillId);
}
}
if (lineCount > MAX_SKILL_LINES) {
longFiles.push(skillId);
if (missingUseSection.length) {
addWarning(`Missing "Use this skill when" section: ${missingUseSection.length} skills (examples: ${missingUseSection.slice(0, 5).join(', ')})`);
}
if (!content.includes('## Use this skill when')) {
missingUseSection.push(skillId);
if (missingDoNotUseSection.length) {
addWarning(`Missing "Do not use" section: ${missingDoNotUseSection.length} skills (examples: ${missingDoNotUseSection.slice(0, 5).join(', ')})`);
}
if (!content.includes('## Do not use')) {
missingDoNotUseSection.push(skillId);
if (missingInstructionsSection.length) {
addWarning(`Missing "Instructions" section: ${missingInstructionsSection.length} skills (examples: ${missingInstructionsSection.slice(0, 5).join(', ')})`);
}
if (!content.includes('## Instructions')) {
missingInstructionsSection.push(skillId);
if (longFiles.length) {
addWarning(`SKILL.md over ${MAX_SKILL_LINES} lines: ${longFiles.length} skills (examples: ${longFiles.slice(0, 5).join(', ')})`);
}
}
if (missingUseSection.length) {
addWarning(`Missing "Use this skill when" section: ${missingUseSection.length} skills (examples: ${missingUseSection.slice(0, 5).join(', ')})`);
}
if (missingDoNotUseSection.length) {
addWarning(`Missing "Do not use" section: ${missingDoNotUseSection.length} skills (examples: ${missingDoNotUseSection.slice(0, 5).join(', ')})`);
}
if (missingInstructionsSection.length) {
addWarning(`Missing "Instructions" section: ${missingInstructionsSection.length} skills (examples: ${missingInstructionsSection.slice(0, 5).join(', ')})`);
}
if (longFiles.length) {
addWarning(`SKILL.md over ${MAX_SKILL_LINES} lines: ${longFiles.length} skills (examples: ${longFiles.slice(0, 5).join(', ')})`);
}
if (unknownFieldSkills.length) {
addWarning(`Unknown frontmatter fields detected: ${unknownFieldSkills.length} skills (examples: ${unknownFieldSkills.slice(0, 5).join(', ')})`);
}
addStrictSectionErrors('Use this skill when', missingUseSection, baselineUse);
addStrictSectionErrors('Do not use', missingDoNotUseSection, baselineDoNotUse);
addStrictSectionErrors('Instructions', missingInstructionsSection, baselineInstructions);
addStrictSectionErrors(`SKILL.md line count <= ${MAX_SKILL_LINES}`, longFiles, baselineLongFile);
if (writeBaseline) {
const baselineData = {
generatedAt: new Date().toISOString(),
useSection: [...missingUseSection].sort(),
doNotUseSection: [...missingDoNotUseSection].sort(),
instructionsSection: [...missingInstructionsSection].sort(),
longFile: [...longFiles].sort(),
};
fs.writeFileSync(BASELINE_PATH, JSON.stringify(baselineData, null, 2));
console.log(`Baseline written to ${BASELINE_PATH}`);
}
if (warnings.length) {
console.warn('Warnings:');
for (const warning of warnings) {
console.warn(`- ${warning}`);
if (unknownFieldSkills.length) {
addWarning(`Unknown frontmatter fields detected: ${unknownFieldSkills.length} skills (examples: ${unknownFieldSkills.slice(0, 5).join(', ')})`);
}
}
if (errors.length) {
console.error('\nErrors:');
for (const error of errors) {
console.error(`- ${error}`);
addStrictSectionErrors('Use this skill when', missingUseSection, baselineUse);
addStrictSectionErrors('Do not use', missingDoNotUseSection, baselineDoNotUse);
addStrictSectionErrors('Instructions', missingInstructionsSection, baselineInstructions);
addStrictSectionErrors(`SKILL.md line count <= ${MAX_SKILL_LINES}`, longFiles, baselineLongFile);
if (writeBaseline) {
const baselineData = {
generatedAt: new Date().toISOString(),
useSection: [...missingUseSection].sort(),
doNotUseSection: [...missingDoNotUseSection].sort(),
instructionsSection: [...missingInstructionsSection].sort(),
longFile: [...longFiles].sort(),
};
fs.writeFileSync(BASELINE_PATH, JSON.stringify(baselineData, null, 2));
console.log(`Baseline written to ${BASELINE_PATH}`);
}
process.exit(1);
if (warnings.length) {
console.warn('Warnings:');
for (const warning of warnings) {
console.warn(`- ${warning}`);
}
}
if (errors.length) {
console.error('\nErrors:');
for (const error of errors) {
console.error(`- ${error}`);
}
process.exit(1);
}
console.log(`Validation passed for ${skillIds.length} skills.`);
}
console.log(`Validation passed for ${skillIds.length} skills.`);
if (require.main === module) {
run();
}
module.exports = {
hasUseSection,
run,
};

View File

@@ -3,6 +3,15 @@ import re
import argparse
import sys
WHEN_TO_USE_PATTERNS = [
re.compile(r"^##\s+When\s+to\s+Use", re.MULTILINE | re.IGNORECASE),
re.compile(r"^##\s+Use\s+this\s+skill\s+when", re.MULTILINE | re.IGNORECASE),
re.compile(r"^##\s+When\s+to\s+Use\s+This\s+Skill", re.MULTILINE | re.IGNORECASE),
]
def has_when_to_use_section(content):
return any(pattern.search(content) for pattern in WHEN_TO_USE_PATTERNS)
def parse_frontmatter(content):
"""
Simple frontmatter parser using regex to avoid external dependencies.
@@ -30,7 +39,6 @@ def validate_skills(skills_dir, strict_mode=False):
# Pre-compiled regex
security_disclaimer_pattern = re.compile(r"AUTHORIZED USE ONLY", re.IGNORECASE)
trigger_section_pattern = re.compile(r"^##\s+When to Use", re.MULTILINE | re.IGNORECASE)
valid_risk_levels = ["none", "safe", "critical", "offensive"]
@@ -80,7 +88,7 @@ def validate_skills(skills_dir, strict_mode=False):
else: warnings.append(msg)
# 3. Content Checks (Triggers)
if not trigger_section_pattern.search(content):
if not has_when_to_use_section(content):
msg = f"⚠️ {rel_path}: Missing '## When to Use' section"
if strict_mode: errors.append(msg.replace("⚠️", ""))
else: warnings.append(msg)

View File

@@ -1,703 +0,0 @@
{
"summary": {
"total_analyzed": 89,
"truly_new": 0,
"duplicates": 2,
"needs_review": 13,
"invalid_sources": 74
},
"results": {
"truly_new": [],
"duplicates": [
{
"name": "react-best-practices",
"reason": "Already exists in repository",
"url": "https://github.com/vercel-labs/agent-skills/tree/main/skills/react-best-practices"
},
{
"name": "postgres-best-practices",
"reason": "Already exists in repository",
"url": "https://github.com/supabase/agent-skills/tree/main/skills/supabase-postgres-best-practices"
}
],
"complementary": [],
"needs_review": [
{
"name": "frontend-slides",
"url": "https://github.com/zarazhangrui/frontend-slides",
"raw_url": "https://github.com/zarazhangrui/frontend-slides/raw/main/SKILL.md",
"description": "Generate animation-rich HTML presentations with visual style previews",
"org": "zarazhangrui",
"category": "Community Skills",
"similar_to": [
"frontend-patterns",
"frontend-design"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "frontend-design",
"reasoning": [
"Similar to existing skill: frontend-patterns",
"Similar to existing skill: frontend-design"
]
}
},
{
"name": "notebooklm-skill",
"url": "https://github.com/PleasePrompto/notebooklm-skill",
"raw_url": "https://github.com/PleasePrompto/notebooklm-skill/raw/master/SKILL.md",
"description": "Interact with NotebookLM for document-based conversations",
"org": "PleasePrompto",
"category": "Community Skills",
"similar_to": [
"notebooklm",
"slo-implementation"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "slo-implementation",
"reasoning": [
"Similar to existing skill: notebooklm",
"Similar to existing skill: slo-implementation"
]
}
},
{
"name": "linear-claude-skill",
"url": "https://github.com/wrsmith108/linear-claude-skill",
"raw_url": "https://github.com/wrsmith108/linear-claude-skill/raw/main/SKILL.md",
"description": "Manage Linear issues, projects, and teams",
"org": "wrsmith108",
"category": "Community Skills",
"similar_to": [
"api-design-principles",
"seo-content-auditor"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "seo-content-auditor",
"reasoning": [
"Similar to existing skill: api-design-principles",
"Similar to existing skill: seo-content-auditor"
]
}
},
{
"name": "skill-rails-upgrade",
"url": "https://github.com/robzolkos/skill-rails-upgrade",
"raw_url": "https://github.com/robzolkos/skill-rails-upgrade/raw/master/SKILL.md",
"description": "Analyze Rails apps and provide upgrade assessments",
"org": "robzolkos",
"category": "Community Skills",
"similar_to": [
"api-design-principles"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "api-design-principles",
"reasoning": [
"Similar to existing skill: api-design-principles"
]
}
},
{
"name": "terraform-skill",
"url": "https://github.com/antonbabenko/terraform-skill",
"raw_url": "https://github.com/antonbabenko/terraform-skill/raw/master/SKILL.md",
"description": "Terraform infrastructure as code best practices",
"org": "antonbabenko",
"category": "Community Skills",
"similar_to": [
"internal-comms",
"skill-creator",
"slack-gif-creator"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "slack-gif-creator",
"reasoning": [
"Similar to existing skill: internal-comms",
"Similar to existing skill: skill-creator",
"Similar to existing skill: slack-gif-creator"
]
}
},
{
"name": "context-fundamentals",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-fundamentals",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Understand what context is, why it matters, and the anatomy of context in agent systems",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"salesforce-development"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "salesforce-development",
"reasoning": [
"Similar to existing skill: salesforce-development"
]
}
},
{
"name": "context-degradation",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-degradation",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Recognize patterns of context failure: lost-in-middle, poisoning, distraction, and clash",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"design-orchestration",
"production-code-audit",
"react-modernization",
"saga-orchestration",
"screen-reader-testing",
"seo-content-auditor",
"vector-index-tuning"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "vector-index-tuning",
"reasoning": [
"Similar to existing skill: design-orchestration",
"Similar to existing skill: production-code-audit",
"Similar to existing skill: react-modernization",
"Similar to existing skill: saga-orchestration",
"Similar to existing skill: screen-reader-testing",
"Similar to existing skill: seo-content-auditor",
"Similar to existing skill: vector-index-tuning"
]
}
},
{
"name": "context-compression",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-compression",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Design and evaluate compression strategies for long-running sessions",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"incident-responder",
"monorepo-architect",
"postmortem-writing",
"projection-patterns",
"scroll-experience",
"service-mesh-expert"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "service-mesh-expert",
"reasoning": [
"Similar to existing skill: incident-responder",
"Similar to existing skill: monorepo-architect",
"Similar to existing skill: postmortem-writing",
"Similar to existing skill: projection-patterns",
"Similar to existing skill: scroll-experience",
"Similar to existing skill: service-mesh-expert"
]
}
},
{
"name": "context-optimization",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/context-optimization",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Apply compaction, masking, and caching strategies",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"app-store-optimization",
"monorepo-architect",
"react-modernization"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "react-modernization",
"reasoning": [
"Similar to existing skill: app-store-optimization",
"Similar to existing skill: monorepo-architect",
"Similar to existing skill: react-modernization"
]
}
},
{
"name": "multi-agent-patterns",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/multi-agent-patterns",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Master orchestrator, peer-to-peer, and hierarchical multi-agent architectures",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"agent-manager-skill",
"computer-use-agents",
"gitlab-ci-patterns",
"rag-implementation"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "rag-implementation",
"reasoning": [
"Similar to existing skill: agent-manager-skill",
"Similar to existing skill: computer-use-agents",
"Similar to existing skill: gitlab-ci-patterns",
"Similar to existing skill: rag-implementation"
]
}
},
{
"name": "memory-systems",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/memory-systems",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Design short-term, long-term, and graph-based memory architectures",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"agent-memory-systems"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "agent-memory-systems",
"reasoning": [
"Similar to existing skill: agent-memory-systems"
]
}
},
{
"name": "tool-design",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/tool-design",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Build tools that agents can use effectively, including architectural reduction patterns",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"mobile-design"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "mobile-design",
"reasoning": [
"Similar to existing skill: mobile-design"
]
}
},
{
"name": "evaluation",
"url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/skills/evaluation",
"raw_url": "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/raw/main/SKILL.md",
"description": "Build evaluation frameworks for agent systems",
"org": "muratcankoylan",
"category": "Community Skills",
"similar_to": [
"agent-evaluation",
"llm-evaluation"
],
"similarity_analysis": {
"is_duplicate": false,
"is_complementary": false,
"similarity_score": 0.7,
"closest_match": "llm-evaluation",
"reasoning": [
"Similar to existing skill: agent-evaluation",
"Similar to existing skill: llm-evaluation"
]
}
}
],
"invalid_sources": [
{
"name": "template",
"url": "https://github.com/anthropics/skills/tree/main/template",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "react-native-skills",
"url": "https://github.com/vercel-labs/agent-skills/tree/main/skills/react-native-skills",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "building-ai-agent-on-cloudflare",
"url": "https://github.com/cloudflare/skills/tree/main/building-ai-agent-on-cloudflare",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "building-mcp-server-on-cloudflare",
"url": "https://github.com/cloudflare/skills/tree/main/building-mcp-server-on-cloudflare",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "commands",
"url": "https://github.com/cloudflare/skills/tree/main/commands",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "durable-objects",
"url": "https://github.com/cloudflare/skills/tree/main/durable-objects",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "web-perf",
"url": "https://github.com/cloudflare/skills/tree/main/web-perf",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "react-components",
"url": "https://github.com/google-labs-code/stitch-skills/tree/main/skills/react-components",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "hugging-face-datasets",
"url": "https://github.com/huggingface/skills/tree/main/skills/hugging-face-datasets",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "hugging-face-evaluation",
"url": "https://github.com/huggingface/skills/tree/main/skills/hugging-face-evaluation",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "hugging-face-model-trainer",
"url": "https://github.com/huggingface/skills/tree/main/skills/hugging-face-model-trainer",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "hugging-face-paper-publisher",
"url": "https://github.com/huggingface/skills/tree/main/skills/hugging-face-paper-publisher",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "hugging-face-tool-builder",
"url": "https://github.com/huggingface/skills/tree/main/skills/hugging-face-tool-builder",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "hugging-face-trackio",
"url": "https://github.com/huggingface/skills/tree/main/skills/hugging-face-trackio",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "stripe-best-practices",
"url": "https://github.com/stripe/ai/tree/main/skills/stripe-best-practices",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "upgrade-stripe",
"url": "https://github.com/stripe/ai/tree/main/skills/upgrade-stripe",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "ask-questions-if-underspecified",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/ask-questions-if-underspecified",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "audit-context-building",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/audit-context-building",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "building-secure-contracts",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/building-secure-contracts",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "burpsuite-project-parser",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/burpsuite-project-parser",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "claude-in-chrome-troubleshooting",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/claude-in-chrome-troubleshooting",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "constant-time-analysis",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/constant-time-analysis",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "differential-review",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/differential-review",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "dwarf-expert",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/dwarf-expert",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "entry-point-analyzer",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/entry-point-analyzer",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "firebase-apk-scanner",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/firebase-apk-scanner",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "insecure-defaults",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/insecure-defaults",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "modern-python",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/modern-python",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "property-based-testing",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/property-based-testing",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "semgrep-rule-creator",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/semgrep-rule-creator",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "semgrep-rule-variant-creator",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/semgrep-rule-variant-creator",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "spec-to-code-compliance",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/spec-to-code-compliance",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "static-analysis",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/static-analysis",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "testing-handbook-skills",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/testing-handbook-skills",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "variant-analysis",
"url": "https://github.com/trailofbits/skills/tree/main/plugins/variant-analysis",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "expo-app-design",
"url": "https://github.com/expo/skills/tree/main/plugins/expo-app-design",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "agents-md",
"url": "https://github.com/getsentry/skills/tree/main/plugins/sentry-skills/skills/agents-md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "claude-settings-audit",
"url": "https://github.com/getsentry/skills/tree/main/plugins/sentry-skills/skills/claude-settings-audit",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "code-review",
"url": "https://github.com/getsentry/skills/tree/main/plugins/sentry-skills/skills/code-review",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "best-practices",
"url": "https://github.com/better-auth/skills/tree/main/better-auth/best-practices",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "commands",
"url": "https://github.com/better-auth/skills/tree/main/better-auth/commands",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "create-auth",
"url": "https://github.com/better-auth/skills/tree/main/better-auth/create-auth",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "tinybird-best-practices",
"url": "https://github.com/tinybirdco/tinybird-agent-skills/tree/main/skills/tinybird-best-practices",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "cloudflare-skill",
"url": "https://github.com/dmmulroy/cloudflare-skill/tree/main/skill/cloudflare",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "remotion",
"url": "https://github.com/remotion-dev/skills/tree/main/skills/remotion",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "marketingskills",
"url": "https://github.com/coreyhaines31/marketingskills",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "content-research-writer",
"url": "https://github.com/ComposioHQ/awesome-claude-skills/tree/master/content-research-writer",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "competitive-ads-extractor",
"url": "https://github.com/ComposioHQ/awesome-claude-skills/tree/master/competitive-ads-extractor",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "notion-skills-for-claude",
"url": "https://www.notion.so/notiondevs/Notion-Skills-for-Claude-28da4445d27180c7af1df7d8615723d0",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "integrate-whatsapp",
"url": "https://github.com/gokapso/agent-skills/tree/master/skills/integrate-whatsapp",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "sharing-skills",
"url": "https://github.com/obra/superpowers/blob/main/skills/sharing-skills/SKILL.md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "meeting-insights-analyzer",
"url": "https://github.com/ComposioHQ/awesome-claude-skills/tree/master/meeting-insights-analyzer",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "image-enhancer",
"url": "https://github.com/ComposioHQ/awesome-claude-skills/tree/master/image-enhancer",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "rootly-incident-responder",
"url": "https://github.com/Rootly-AI-Labs/Rootly-MCP-server/blob/main/examples/skills/rootly-incident-responder.md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "ios-simulator-skill",
"url": "https://github.com/conorluddy/ios-simulator-skill",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "postgres",
"url": "https://github.com/sanjay3290/ai-skills/tree/main/skills/postgres",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "ui-ux-pro-max-skill",
"url": "https://github.com/nextlevelbuilder/ui-ux-pro-max-skill",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "changelog-generator",
"url": "https://github.com/ComposioHQ/awesome-claude-skills/tree/master/changelog-generator",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "root-cause-tracing",
"url": "https://github.com/obra/superpowers/blob/main/skills/root-cause-tracing/SKILL.md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "testing-skills-with-subagents",
"url": "https://github.com/obra/superpowers/blob/main/skills/testing-skills-with-subagents/SKILL.md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "testing-anti-patterns",
"url": "https://github.com/obra/superpowers/blob/main/skills/testing-anti-patterns/SKILL.md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "condition-based-waiting",
"url": "https://github.com/obra/superpowers/blob/main/skills/condition-based-waiting/SKILL.md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "commands",
"url": "https://github.com/obra/superpowers/tree/main/skills/commands",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "dev-agent-skills",
"url": "https://github.com/fvadicamo/dev-agent-skills",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "claude-bootstrap",
"url": "https://github.com/alinaqi/claude-bootstrap",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "recursive-decomposition-skill",
"url": "https://github.com/massimodeluisa/recursive-decomposition-skill",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "react-native-best-practices",
"url": "https://github.com/callstackincubator/agent-skills/blob/main/skills/react-native-best-practices/SKILL.md",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "swift-patterns-skill",
"url": "https://github.com/efremidze/swift-patterns-skill/tree/main/swift-patterns",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "ai-research-skills",
"url": "https://github.com/zechenzhangAGI/AI-research-SKILLs",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "n8n-code-javascript",
"url": "https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-code-javascript",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "n8n-expression-syntax",
"url": "https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-expression-syntax",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "n8n-validation-expert",
"url": "https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-validation-expert",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "n8n-workflow-patterns",
"url": "https://github.com/czlonkowski/n8n-skills/tree/main/skills/n8n-workflow-patterns",
"reason": "SKILL.md not found or URL inaccessible"
},
{
"name": "materials-simulation-skills",
"url": "https://github.com/HeshamFS/materials-simulation-skills",
"reason": "SKILL.md not found or URL inaccessible"
}
]
}
}

22
skills/SPDD/1-research.md Normal file
View File

@@ -0,0 +1,22 @@
# ROLE: Codebase Research Agent
Sua única missão é documentar e explicar a base de código como ela existe hoje.
## CRITICAL RULES:
- NÃO sugira melhorias, refatorações ou mudanças arquiteturais.
- NÃO realize análise de causa raiz ou proponha melhorias futuras.
- APENAS descreva o que existe, onde existe e como os componentes interagem.
- Você é um cartógrafo técnico criando um mapa do sistema atual.
## STEPS TO FOLLOW:
1. **Initial Analysis:** Leia os arquivos mencionados pelo usuário integralmente (SEM limit/offset).
2. **Decomposition:** Decompunha a dúvida do usuário em áreas de pesquisa (ex: Rotas, Banco, UI).
3. **Execution:** - Localize onde os arquivos e componentes vivem.
- Analise COMO o código atual funciona (sem criticar).
- Encontre exemplos de padrões existentes para referência.
4. **Project State:**
- Se projeto NOVO: Pesquise e liste a melhor estrutura de pastas e bibliotecas padrão de mercado para a stack.
- Se projeto EXISTENTE: Identifique dívidas técnicas ou padrões que devem ser respeitados.
## OUTPUT:
- Gere o arquivo `docs/prds/prd_current_task.md` com YAML frontmatter (date, topic, tags, status).
- **Ação Obrigatória:** Termine com: "Pesquisa concluída. Por favor, dê um `/clear` e carregue `.agente/2-spec.md` para o planejamento."

20
skills/SPDD/2-spec.md Normal file
View File

@@ -0,0 +1,20 @@
# ROLE: Implementation Planning Agent
Você deve criar planos de implementação detalhados e ser cético quanto a requisitos vagos.
## CRITICAL RULES:
- Não escreva o plano de uma vez; valide a estrutura das fases com o usuário.
- Cada decisão técnica deve ser tomada antes de finalizar o plano.
- O plano deve ser acionável e completo, sem "perguntas abertas".
## STEPS TO FOLLOW:
1. **Context Check:** Leia o `docs/prds/prd_current_task.md` gerado anteriormente.
2. **Phasing:** Divida o trabalho em fases incrementais e testáveis.
3. **Detailing:** Para cada arquivo afetado, defina:
- **Path exato.**
- **Ação:** (CRIAR | MODIFICAR | DELETAR).
- **Lógica:** Snippets de pseudocódigo ou referências de implementação.
4. **Success Criteria:** Defina "Automated Verification" (scripts/testes) e "Manual Verification" (UI/UX).
## OUTPUT:
- Gere o arquivo `docs/specs/spec_current_task.md` seguindo o template de fases.
- **Ação Obrigatória:** Termine com: "Spec finalizada. Por favor, dê um `/clear` e carregue `.agente/3-implementation.md` para execução."

View File

@@ -0,0 +1,20 @@
# ROLE: Implementation Execution Agent
Você deve implementar um plano técnico aprovado com precisão cirúrgica.
## CRITICAL RULES:
- Siga a intenção do plano enquanto se adapta à realidade encontrada.
- Implemente uma fase COMPLETAMENTE antes de passar para a próxima.
- **STOP & THINK:** Se encontrar um erro na Spec ou um mismatch no código, PARE e reporte. Não tente adivinhar.
## STEPS TO FOLLOW:
1. **Sanity Check:** Leia a Spec e o Ticket original. Verifique se o ambiente está limpo.
2. **Execution:** Codifique seguindo os padrões de Clean Code e os snippets da Spec.
3. **Verification:**
- Após cada fase, execute os comandos de "Automated Verification" descritos na Spec.
- PAUSE para confirmação manual do usuário após cada fase concluída.
4. **Progress:** Atualize os checkboxes (- [x]) no arquivo de Spec conforme avança.
## OUTPUT:
- Código fonte implementado.
- Relatório de conclusão de fase com resultados de testes.
- **Ação Final:** Pergunte se o usuário deseja realizar testes de regressão ou seguir para a próxima task.

View File

@@ -0,0 +1,209 @@
---
name: activecampaign-automation
description: "Automate ActiveCampaign tasks via Rube MCP (Composio): manage contacts, tags, list subscriptions, automation enrollment, and tasks. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# ActiveCampaign Automation via Rube MCP
Automate ActiveCampaign CRM and marketing automation operations through Composio's ActiveCampaign toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active ActiveCampaign connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `active_campaign`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `active_campaign`
3. If connection is not ACTIVE, follow the returned auth link to complete ActiveCampaign authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Create and Find Contacts
**When to use**: User wants to create new contacts or look up existing ones
**Tool sequence**:
1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Search for an existing contact [Optional]
2. `ACTIVE_CAMPAIGN_CREATE_CONTACT` - Create a new contact [Required]
**Key parameters for find**:
- `email`: Search by email address
- `id`: Search by ActiveCampaign contact ID
- `phone`: Search by phone number
**Key parameters for create**:
- `email`: Contact email address (required)
- `first_name`: Contact first name
- `last_name`: Contact last name
- `phone`: Contact phone number
- `organization_name`: Contact's organization
- `job_title`: Contact's job title
- `tags`: Comma-separated list of tags to apply
**Pitfalls**:
- `email` is the only required field for contact creation
- Phone search uses a general search parameter internally; it may return partial matches
- When combining `email` and `phone` in FIND_CONTACT, results are filtered client-side
- Tags provided during creation are applied immediately
- Creating a contact with an existing email may update the existing contact
### 2. Manage Contact Tags
**When to use**: User wants to add or remove tags from contacts
**Tool sequence**:
1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Find contact by email or ID [Prerequisite]
2. `ACTIVE_CAMPAIGN_MANAGE_CONTACT_TAG` - Add or remove tags [Required]
**Key parameters**:
- `action`: 'Add' or 'Remove' (required)
- `tags`: Tag names as comma-separated string or array of strings (required)
- `contact_id`: Contact ID (provide this or contact_email)
- `contact_email`: Contact email address (alternative to contact_id)
**Pitfalls**:
- `action` values are capitalized: 'Add' or 'Remove' (not lowercase)
- Tags can be a comma-separated string ('tag1, tag2') or an array (['tag1', 'tag2'])
- Either `contact_id` or `contact_email` must be provided; `contact_id` takes precedence
- Adding a tag that does not exist creates it automatically
- Removing a non-existent tag is a no-op (does not error)
### 3. Manage List Subscriptions
**When to use**: User wants to subscribe or unsubscribe contacts from lists
**Tool sequence**:
1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Find the contact [Prerequisite]
2. `ACTIVE_CAMPAIGN_MANAGE_LIST_SUBSCRIPTION` - Subscribe or unsubscribe [Required]
**Key parameters**:
- `action`: 'subscribe' or 'unsubscribe' (required)
- `list_id`: Numeric list ID string (required)
- `email`: Contact email address (provide this or contact_id)
- `contact_id`: Numeric contact ID string (alternative to email)
**Pitfalls**:
- `action` values are lowercase: 'subscribe' or 'unsubscribe'
- `list_id` is a numeric string (e.g., '2'), not the list name
- List IDs can be retrieved via the GET /api/3/lists endpoint (not available as a Composio tool; use the ActiveCampaign UI)
- If both `email` and `contact_id` are provided, `contact_id` takes precedence
- Unsubscribing changes status to '2' (unsubscribed) but the relationship record persists
### 4. Add Contacts to Automations
**When to use**: User wants to enroll a contact in an automation workflow
**Tool sequence**:
1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Verify contact exists [Prerequisite]
2. `ACTIVE_CAMPAIGN_ADD_CONTACT_TO_AUTOMATION` - Enroll contact in automation [Required]
**Key parameters**:
- `contact_email`: Email of the contact to enroll (required)
- `automation_id`: ID of the target automation (required)
**Pitfalls**:
- The contact must already exist in ActiveCampaign
- Automations can only be created through the ActiveCampaign UI, not via API
- `automation_id` must reference an existing, active automation
- The tool performs a two-step process: lookup contact by email, then enroll
- Automation IDs can be found in the ActiveCampaign UI or via GET /api/3/automations
### 5. Create Contact Tasks
**When to use**: User wants to create follow-up tasks associated with contacts
**Tool sequence**:
1. `ACTIVE_CAMPAIGN_FIND_CONTACT` - Find the contact to associate the task with [Prerequisite]
2. `ACTIVE_CAMPAIGN_CREATE_CONTACT_TASK` - Create the task [Required]
**Key parameters**:
- `relid`: Contact ID to associate the task with (required)
- `duedate`: Due date in ISO 8601 format with timezone (required, e.g., '2025-01-15T14:30:00-05:00')
- `dealTasktype`: Task type ID based on available types (required)
- `title`: Task title
- `note`: Task description/content
- `assignee`: User ID to assign the task to
- `edate`: End date in ISO 8601 format (must be later than duedate)
- `status`: 0 for incomplete, 1 for complete
**Pitfalls**:
- `duedate` must be a valid ISO 8601 datetime with timezone offset; do NOT use placeholder values
- `edate` must be later than `duedate`
- `dealTasktype` is a string ID referencing task types configured in ActiveCampaign
- `relid` is the numeric contact ID, not the email address
- `assignee` is a user ID; resolve user names to IDs via the ActiveCampaign UI
## Common Patterns
### Contact Lookup Flow
```
1. Call ACTIVE_CAMPAIGN_FIND_CONTACT with email
2. If found, extract contact ID for subsequent operations
3. If not found, create contact with ACTIVE_CAMPAIGN_CREATE_CONTACT
4. Use contact ID for tags, subscriptions, or automations
```
### Bulk Contact Tagging
```
1. For each contact, call ACTIVE_CAMPAIGN_MANAGE_CONTACT_TAG
2. Use contact_email to avoid separate lookup calls
3. Batch with reasonable delays to respect rate limits
```
### ID Resolution
**Contact email -> Contact ID**:
```
1. Call ACTIVE_CAMPAIGN_FIND_CONTACT with email
2. Extract id from the response
```
## Known Pitfalls
**Action Capitalization**:
- Tag actions: 'Add', 'Remove' (capitalized)
- Subscription actions: 'subscribe', 'unsubscribe' (lowercase)
- Mixing up capitalization causes errors
**ID Types**:
- Contact IDs: numeric strings (e.g., '123')
- List IDs: numeric strings
- Automation IDs: numeric strings
- All IDs should be passed as strings, not integers
**Automations**:
- Automations cannot be created via API; only enrollment is possible
- Automation must be active to accept new contacts
- Enrolling a contact already in the automation may have no effect
**Rate Limits**:
- ActiveCampaign API has rate limits per account
- Implement backoff on 429 responses
- Batch operations should be spaced appropriately
**Response Parsing**:
- Response data may be nested under `data` or `data.data`
- Parse defensively with fallback patterns
- Contact search may return multiple results; match by email for accuracy
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Find contact | ACTIVE_CAMPAIGN_FIND_CONTACT | email, id, phone |
| Create contact | ACTIVE_CAMPAIGN_CREATE_CONTACT | email, first_name, last_name, tags |
| Add/remove tags | ACTIVE_CAMPAIGN_MANAGE_CONTACT_TAG | action, tags, contact_email |
| Subscribe/unsubscribe | ACTIVE_CAMPAIGN_MANAGE_LIST_SUBSCRIPTION | action, list_id, email |
| Add to automation | ACTIVE_CAMPAIGN_ADD_CONTACT_TO_AUTOMATION | contact_email, automation_id |
| Create task | ACTIVE_CAMPAIGN_CREATE_CONTACT_TASK | relid, duedate, dealTasktype, title |

View File

@@ -0,0 +1,170 @@
---
name: airtable-automation
description: "Automate Airtable tasks via Rube MCP (Composio): records, bases, tables, fields, views. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Airtable Automation via Rube MCP
Automate Airtable operations through Composio's Airtable toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Airtable connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `airtable`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `airtable`
3. If connection is not ACTIVE, follow the returned auth link to complete Airtable auth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Create and Manage Records
**When to use**: User wants to create, read, update, or delete records
**Tool sequence**:
1. `AIRTABLE_LIST_BASES` - Discover available bases [Prerequisite]
2. `AIRTABLE_GET_BASE_SCHEMA` - Inspect table structure [Prerequisite]
3. `AIRTABLE_LIST_RECORDS` - List/filter records [Optional]
4. `AIRTABLE_CREATE_RECORD` / `AIRTABLE_CREATE_RECORDS` - Create records [Optional]
5. `AIRTABLE_UPDATE_RECORD` / `AIRTABLE_UPDATE_MULTIPLE_RECORDS` - Update records [Optional]
6. `AIRTABLE_DELETE_RECORD` / `AIRTABLE_DELETE_MULTIPLE_RECORDS` - Delete records [Optional]
**Key parameters**:
- `baseId`: Base ID (starts with 'app', e.g., 'appXXXXXXXXXXXXXX')
- `tableIdOrName`: Table ID (starts with 'tbl') or table name
- `fields`: Object mapping field names to values
- `recordId`: Record ID (starts with 'rec') for updates/deletes
- `filterByFormula`: Airtable formula for filtering
- `typecast`: Set true for automatic type conversion
**Pitfalls**:
- pageSize capped at 100; uses offset pagination; changing filters between pages can skip/duplicate rows
- CREATE_RECORDS hard limit of 10 records per request; chunk larger imports
- Field names are CASE-SENSITIVE and must match schema exactly
- 422 UNKNOWN_FIELD_NAME when field names are wrong; 403 for permission issues
- INVALID_MULTIPLE_CHOICE_OPTIONS may require typecast=true
### 2. Search and Filter Records
**When to use**: User wants to find specific records using formulas
**Tool sequence**:
1. `AIRTABLE_GET_BASE_SCHEMA` - Verify field names and types [Prerequisite]
2. `AIRTABLE_LIST_RECORDS` - Query with filterByFormula [Required]
3. `AIRTABLE_GET_RECORD` - Get full record details [Optional]
**Key parameters**:
- `filterByFormula`: Airtable formula (e.g., `{Status}='Done'`)
- `sort`: Array of sort objects
- `fields`: Array of field names to return
- `maxRecords`: Max total records across all pages
- `offset`: Pagination cursor from previous response
**Pitfalls**:
- Field names in formulas must be wrapped in `{}` and match schema exactly
- String values must be quoted: `{Status}='Active'` not `{Status}=Active`
- 422 INVALID_FILTER_BY_FORMULA for bad syntax or non-existent fields
- Airtable rate limit: ~5 requests/second per base; handle 429 with Retry-After
### 3. Manage Fields and Schema
**When to use**: User wants to create or modify table fields
**Tool sequence**:
1. `AIRTABLE_GET_BASE_SCHEMA` - Inspect current schema [Prerequisite]
2. `AIRTABLE_CREATE_FIELD` - Create a new field [Optional]
3. `AIRTABLE_UPDATE_FIELD` - Rename/describe a field [Optional]
4. `AIRTABLE_UPDATE_TABLE` - Update table metadata [Optional]
**Key parameters**:
- `name`: Field name
- `type`: Field type (singleLineText, number, singleSelect, etc.)
- `options`: Type-specific options (choices for select, precision for number)
- `description`: Field description
**Pitfalls**:
- UPDATE_FIELD only changes name/description, NOT type/options; create a replacement field and migrate
- Computed fields (formula, rollup, lookup) cannot be created via API
- 422 when type options are missing or malformed
### 4. Manage Comments
**When to use**: User wants to view or add comments on records
**Tool sequence**:
1. `AIRTABLE_LIST_COMMENTS` - List comments on a record [Required]
**Key parameters**:
- `baseId`: Base ID
- `tableIdOrName`: Table identifier
- `recordId`: Record ID (17 chars, starts with 'rec')
- `pageSize`: Comments per page (max 100)
**Pitfalls**:
- Record IDs must be exactly 17 characters starting with 'rec'
## Common Patterns
### Airtable Formula Syntax
**Comparison**:
- `{Status}='Done'` - Equals
- `{Priority}>1` - Greater than
- `{Name}!=''` - Not empty
**Functions**:
- `AND({A}='x', {B}='y')` - Both conditions
- `OR({A}='x', {A}='y')` - Either condition
- `FIND('test', {Name})>0` - Contains text
- `IS_BEFORE({Due Date}, TODAY())` - Date comparison
**Escape rules**:
- Single quotes in values: double them (`{Name}='John''s Company'`)
### Pagination
- Set `pageSize` (max 100)
- Check response for `offset` string
- Pass `offset` to next request unchanged
- Keep filters/sorts/view stable between pages
## Known Pitfalls
**ID Formats**:
- Base IDs: `appXXXXXXXXXXXXXX` (17 chars)
- Table IDs: `tblXXXXXXXXXXXXXX` (17 chars)
- Record IDs: `recXXXXXXXXXXXXXX` (17 chars)
- Field IDs: `fldXXXXXXXXXXXXXX` (17 chars)
**Batch Limits**:
- CREATE_RECORDS: max 10 per request
- UPDATE_MULTIPLE_RECORDS: max 10 per request
- DELETE_MULTIPLE_RECORDS: max 10 per request
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List bases | AIRTABLE_LIST_BASES | (none) |
| Get schema | AIRTABLE_GET_BASE_SCHEMA | baseId |
| List records | AIRTABLE_LIST_RECORDS | baseId, tableIdOrName |
| Get record | AIRTABLE_GET_RECORD | baseId, tableIdOrName, recordId |
| Create record | AIRTABLE_CREATE_RECORD | baseId, tableIdOrName, fields |
| Create records | AIRTABLE_CREATE_RECORDS | baseId, tableIdOrName, records |
| Update record | AIRTABLE_UPDATE_RECORD | baseId, tableIdOrName, recordId, fields |
| Update records | AIRTABLE_UPDATE_MULTIPLE_RECORDS | baseId, tableIdOrName, records |
| Delete record | AIRTABLE_DELETE_RECORD | baseId, tableIdOrName, recordId |
| Create field | AIRTABLE_CREATE_FIELD | baseId, tableIdOrName, name, type |
| Update field | AIRTABLE_UPDATE_FIELD | baseId, tableIdOrName, fieldId |
| Update table | AIRTABLE_UPDATE_TABLE | baseId, tableIdOrName, name |
| List comments | AIRTABLE_LIST_COMMENTS | baseId, tableIdOrName, recordId |

View File

@@ -0,0 +1,216 @@
---
name: amplitude-automation
description: "Automate Amplitude tasks via Rube MCP (Composio): events, user activity, cohorts, user identification. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Amplitude Automation via Rube MCP
Automate Amplitude product analytics through Composio's Amplitude toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Amplitude connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `amplitude`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `amplitude`
3. If connection is not ACTIVE, follow the returned auth link to complete Amplitude authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Send Events
**When to use**: User wants to track events or send event data to Amplitude
**Tool sequence**:
1. `AMPLITUDE_SEND_EVENTS` - Send one or more events to Amplitude [Required]
**Key parameters**:
- `events`: Array of event objects, each containing:
- `event_type`: Name of the event (e.g., 'page_view', 'purchase')
- `user_id`: Unique user identifier (required if no `device_id`)
- `device_id`: Device identifier (required if no `user_id`)
- `event_properties`: Object with custom event properties
- `user_properties`: Object with user properties to set
- `time`: Event timestamp in milliseconds since epoch
**Pitfalls**:
- At least one of `user_id` or `device_id` is required per event
- `event_type` is required for every event; cannot be empty
- `time` must be in milliseconds (13-digit epoch), not seconds
- Batch limit applies; check schema for maximum events per request
- Events are processed asynchronously; successful API response does not mean data is immediately queryable
### 2. Get User Activity
**When to use**: User wants to view event history for a specific user
**Tool sequence**:
1. `AMPLITUDE_FIND_USER` - Find user by ID or property [Prerequisite]
2. `AMPLITUDE_GET_USER_ACTIVITY` - Retrieve user's event stream [Required]
**Key parameters**:
- `user`: Amplitude internal user ID (from FIND_USER)
- `offset`: Pagination offset for event list
- `limit`: Maximum number of events to return
**Pitfalls**:
- `user` parameter requires Amplitude's internal user ID, NOT your application's user_id
- Must call FIND_USER first to resolve your user_id to Amplitude's internal ID
- Activity is returned in reverse chronological order by default
- Large activity histories require pagination via `offset`
### 3. Find and Identify Users
**When to use**: User wants to look up users or set user properties
**Tool sequence**:
1. `AMPLITUDE_FIND_USER` - Search for a user by various identifiers [Required]
2. `AMPLITUDE_IDENTIFY` - Set or update user properties [Optional]
**Key parameters**:
- For FIND_USER:
- `user`: Search term (user_id, email, or Amplitude ID)
- For IDENTIFY:
- `user_id`: Your application's user identifier
- `device_id`: Device identifier (alternative to user_id)
- `user_properties`: Object with `$set`, `$unset`, `$add`, `$append` operations
**Pitfalls**:
- FIND_USER searches across user_id, device_id, and Amplitude ID
- IDENTIFY uses special property operations (`$set`, `$unset`, `$add`, `$append`)
- `$set` overwrites existing values; `$setOnce` only sets if not already set
- At least one of `user_id` or `device_id` is required for IDENTIFY
- User property changes are eventually consistent; not immediate
### 4. Manage Cohorts
**When to use**: User wants to list cohorts, view cohort details, or update cohort membership
**Tool sequence**:
1. `AMPLITUDE_LIST_COHORTS` - List all saved cohorts [Required]
2. `AMPLITUDE_GET_COHORT` - Get detailed cohort information [Optional]
3. `AMPLITUDE_UPDATE_COHORT_MEMBERSHIP` - Add/remove users from a cohort [Optional]
4. `AMPLITUDE_CHECK_COHORT_STATUS` - Check async cohort operation status [Optional]
**Key parameters**:
- For LIST_COHORTS: No required parameters
- For GET_COHORT: `cohort_id` (from list results)
- For UPDATE_COHORT_MEMBERSHIP:
- `cohort_id`: Target cohort ID
- `memberships`: Object with `add` and/or `remove` arrays of user IDs
- For CHECK_COHORT_STATUS: `request_id` from update response
**Pitfalls**:
- Cohort IDs are required for all cohort-specific operations
- UPDATE_COHORT_MEMBERSHIP is asynchronous; use CHECK_COHORT_STATUS to verify
- `request_id` from the update response is needed for status checking
- Maximum membership changes per request may be limited; chunk large updates
- Only behavioral cohorts support API membership updates
### 5. Browse Event Categories
**When to use**: User wants to discover available event types and categories in Amplitude
**Tool sequence**:
1. `AMPLITUDE_GET_EVENT_CATEGORIES` - List all event categories [Required]
**Key parameters**:
- No required parameters; returns all configured event categories
**Pitfalls**:
- Categories are configured in Amplitude UI; API provides read access
- Event names within categories are case-sensitive
- Use these categories to validate event_type values before sending events
## Common Patterns
### ID Resolution
**Application user_id -> Amplitude internal ID**:
```
1. Call AMPLITUDE_FIND_USER with user=your_user_id
2. Extract Amplitude's internal user ID from response
3. Use internal ID for GET_USER_ACTIVITY
```
**Cohort name -> Cohort ID**:
```
1. Call AMPLITUDE_LIST_COHORTS
2. Find cohort by name in results
3. Extract id for cohort operations
```
### User Property Operations
Amplitude IDENTIFY supports these property operations:
- `$set`: Set property value (overwrites existing)
- `$setOnce`: Set only if property not already set
- `$add`: Increment numeric property
- `$append`: Append to list property
- `$unset`: Remove property entirely
Example structure:
```json
{
"user_properties": {
"$set": {"plan": "premium", "company": "Acme"},
"$add": {"login_count": 1}
}
}
```
### Async Operation Pattern
For cohort membership updates:
```
1. Call AMPLITUDE_UPDATE_COHORT_MEMBERSHIP -> get request_id
2. Call AMPLITUDE_CHECK_COHORT_STATUS with request_id
3. Repeat step 2 until status is 'complete' or 'error'
```
## Known Pitfalls
**User IDs**:
- Amplitude has its own internal user IDs separate from your application's
- FIND_USER resolves your IDs to Amplitude's internal IDs
- GET_USER_ACTIVITY requires Amplitude's internal ID, not your user_id
**Event Timestamps**:
- Must be in milliseconds since epoch (13 digits)
- Seconds (10 digits) will be interpreted as very old dates
- Omitting timestamp uses server receive time
**Rate Limits**:
- Event ingestion has throughput limits per project
- Batch events where possible to reduce API calls
- Cohort membership updates have async processing limits
**Response Parsing**:
- Response data may be nested under `data` key
- User activity returns events in reverse chronological order
- Cohort lists may include archived cohorts; check status field
- Parse defensively with fallbacks for optional fields
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Send events | AMPLITUDE_SEND_EVENTS | events (array) |
| Find user | AMPLITUDE_FIND_USER | user |
| Get user activity | AMPLITUDE_GET_USER_ACTIVITY | user, offset, limit |
| Identify user | AMPLITUDE_IDENTIFY | user_id, user_properties |
| List cohorts | AMPLITUDE_LIST_COHORTS | (none) |
| Get cohort | AMPLITUDE_GET_COHORT | cohort_id |
| Update cohort members | AMPLITUDE_UPDATE_COHORT_MEMBERSHIP | cohort_id, memberships |
| Check cohort status | AMPLITUDE_CHECK_COHORT_STATUS | request_id |
| List event categories | AMPLITUDE_GET_EVENT_CATEGORIES | (none) |

View File

@@ -0,0 +1,58 @@
# Angular Best Practices
Performance optimization and best practices for Angular applications optimized for AI agents and LLMs.
## Overview
This skill provides prioritized performance guidelines across:
- **Change Detection** - OnPush strategy, Signals, Zoneless apps
- **Async Operations** - Avoiding waterfalls, SSR preloading
- **Bundle Optimization** - Lazy loading, `@defer`, tree-shaking
- **Rendering Performance** - TrackBy, virtual scrolling, CDK
- **SSR & Hydration** - Server-side rendering patterns
- **Template Optimization** - Structural directives, pipe memoization
- **State Management** - Efficient reactivity patterns
- **Memory Management** - Subscription cleanup, detached refs
## Structure
The `SKILL.md` file is organized by priority:
1. **Critical Priority** - Largest performance gains (change detection, async)
2. **High Priority** - Significant impact (bundles, rendering)
3. **Medium Priority** - Noticeable improvements (SSR, templates)
4. **Low Priority** - Incremental gains (memory, cleanup)
Each rule includes:
-**WRONG** - What not to do
-**CORRECT** - Recommended pattern
- 📝 **Why** - Explanation of the impact
## Quick Reference Checklist
**For New Components:**
- [ ] Using `ChangeDetectionStrategy.OnPush`
- [ ] Using Signals for reactive state
- [ ] Using `@defer` for non-critical content
- [ ] Using `trackBy` for `*ngFor` loops
- [ ] No subscriptions without cleanup
**For Performance Reviews:**
- [ ] No async waterfalls (parallel data fetching)
- [ ] Routes lazy-loaded
- [ ] Large libraries code-split
- [ ] Images use `NgOptimizedImage`
## Version
Current version: 1.0.0 (February 2026)
## References
- [Angular Performance](https://angular.dev/guide/performance)
- [Zoneless Angular](https://angular.dev/guide/zoneless)
- [Angular SSR](https://angular.dev/guide/ssr)

View File

@@ -0,0 +1,559 @@
---
name: angular-best-practices
description: Angular performance optimization and best practices guide. Use when writing, reviewing, or refactoring Angular code for optimal performance, bundle size, and rendering efficiency.
risk: safe
source: self
---
# Angular Best Practices
Comprehensive performance optimization guide for Angular applications. Contains prioritized rules for eliminating performance bottlenecks, optimizing bundles, and improving rendering.
## When to Apply
Reference these guidelines when:
- Writing new Angular components or pages
- Implementing data fetching patterns
- Reviewing code for performance issues
- Refactoring existing Angular code
- Optimizing bundle size or load times
- Configuring SSR/hydration
---
## Rule Categories by Priority
| Priority | Category | Impact | Focus |
| -------- | --------------------- | ---------- | ------------------------------- |
| 1 | Change Detection | CRITICAL | Signals, OnPush, Zoneless |
| 2 | Async Waterfalls | CRITICAL | RxJS patterns, SSR preloading |
| 3 | Bundle Optimization | CRITICAL | Lazy loading, tree shaking |
| 4 | Rendering Performance | HIGH | @defer, trackBy, virtualization |
| 5 | Server-Side Rendering | HIGH | Hydration, prerendering |
| 6 | Template Optimization | MEDIUM | Control flow, pipes |
| 7 | State Management | MEDIUM | Signal patterns, selectors |
| 8 | Memory Management | LOW-MEDIUM | Cleanup, subscriptions |
---
## 1. Change Detection (CRITICAL)
### Use OnPush Change Detection
```typescript
// CORRECT - OnPush with Signals
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
template: `<div>{{ count() }}</div>`,
})
export class CounterComponent {
count = signal(0);
}
// WRONG - Default change detection
@Component({
template: `<div>{{ count }}</div>`, // Checked every cycle
})
export class CounterComponent {
count = 0;
}
```
### Prefer Signals Over Mutable Properties
```typescript
// CORRECT - Signals trigger precise updates
@Component({
template: `
<h1>{{ title() }}</h1>
<p>Count: {{ count() }}</p>
`,
})
export class DashboardComponent {
title = signal("Dashboard");
count = signal(0);
}
// WRONG - Mutable properties require zone.js checks
@Component({
template: `
<h1>{{ title }}</h1>
<p>Count: {{ count }}</p>
`,
})
export class DashboardComponent {
title = "Dashboard";
count = 0;
}
```
### Enable Zoneless for New Projects
```typescript
// main.ts - Zoneless Angular (v20+)
bootstrapApplication(AppComponent, {
providers: [provideZonelessChangeDetection()],
});
```
**Benefits:**
- No zone.js patches on async APIs
- Smaller bundle (~15KB savings)
- Clean stack traces for debugging
- Better micro-frontend compatibility
---
## 2. Async Operations & Waterfalls (CRITICAL)
### Eliminate Sequential Data Fetching
```typescript
// WRONG - Nested subscriptions create waterfalls
this.route.params.subscribe((params) => {
// 1. Wait for params
this.userService.getUser(params.id).subscribe((user) => {
// 2. Wait for user
this.postsService.getPosts(user.id).subscribe((posts) => {
// 3. Wait for posts
});
});
});
// CORRECT - Parallel execution with forkJoin
forkJoin({
user: this.userService.getUser(id),
posts: this.postsService.getPosts(id),
}).subscribe((data) => {
// Fetched in parallel
});
// CORRECT - Flatten dependent calls with switchMap
this.route.params
.pipe(
map((p) => p.id),
switchMap((id) => this.userService.getUser(id)),
)
.subscribe();
```
### Avoid Client-Side Waterfalls in SSR
```typescript
// CORRECT - Use resolvers or blocking hydration for critical data
export const route: Route = {
path: "profile/:id",
resolve: { data: profileResolver }, // Fetched on server before navigation
component: ProfileComponent,
};
// WRONG - Component fetches data on init
class ProfileComponent implements OnInit {
ngOnInit() {
// Starts ONLY after JS loads and component renders
this.http.get("/api/profile").subscribe();
}
}
```
---
## 3. Bundle Optimization (CRITICAL)
### Lazy Load Routes
```typescript
// CORRECT - Lazy load feature routes
export const routes: Routes = [
{
path: "admin",
loadChildren: () =>
import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES),
},
{
path: "dashboard",
loadComponent: () =>
import("./dashboard/dashboard.component").then(
(m) => m.DashboardComponent,
),
},
];
// WRONG - Eager loading everything
import { AdminModule } from "./admin/admin.module";
export const routes: Routes = [
{ path: "admin", component: AdminComponent }, // In main bundle
];
```
### Use @defer for Heavy Components
```html
<!-- CORRECT - Heavy component loads on demand -->
@defer (on viewport) {
<app-analytics-chart [data]="data()" />
} @placeholder {
<div class="chart-skeleton"></div>
}
<!-- WRONG - Heavy component in initial bundle -->
<app-analytics-chart [data]="data()" />
```
### Avoid Barrel File Re-exports
```typescript
// WRONG - Imports entire barrel, breaks tree-shaking
import { Button, Modal, Table } from "@shared/components";
// CORRECT - Direct imports
import { Button } from "@shared/components/button/button.component";
import { Modal } from "@shared/components/modal/modal.component";
```
### Dynamic Import Third-Party Libraries
```typescript
// CORRECT - Load heavy library on demand
async loadChart() {
const { Chart } = await import('chart.js');
this.chart = new Chart(this.canvas, config);
}
// WRONG - Bundle Chart.js in main chunk
import { Chart } from 'chart.js';
```
---
## 4. Rendering Performance (HIGH)
### Always Use trackBy with @for
```html
<!-- CORRECT - Efficient DOM updates -->
@for (item of items(); track item.id) {
<app-item-card [item]="item" />
}
<!-- WRONG - Entire list re-renders on any change -->
@for (item of items(); track $index) {
<app-item-card [item]="item" />
}
```
### Use Virtual Scrolling for Large Lists
```typescript
import { CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll } from '@angular/cdk/scrolling';
@Component({
imports: [CdkVirtualScrollViewport, CdkFixedSizeVirtualScroll],
template: `
<cdk-virtual-scroll-viewport itemSize="50" class="viewport">
<div *cdkVirtualFor="let item of items" class="item">
{{ item.name }}
</div>
</cdk-virtual-scroll-viewport>
`
})
```
### Prefer Pure Pipes Over Methods
```typescript
// CORRECT - Pure pipe, memoized
@Pipe({ name: 'filterActive', standalone: true, pure: true })
export class FilterActivePipe implements PipeTransform {
transform(items: Item[]): Item[] {
return items.filter(i => i.active);
}
}
// Template
@for (item of items() | filterActive; track item.id) { ... }
// WRONG - Method called every change detection
@for (item of getActiveItems(); track item.id) { ... }
```
### Use computed() for Derived Data
```typescript
// CORRECT - Computed, cached until dependencies change
export class ProductStore {
products = signal<Product[]>([]);
filter = signal('');
filteredProducts = computed(() => {
const f = this.filter().toLowerCase();
return this.products().filter(p =>
p.name.toLowerCase().includes(f)
);
});
}
// WRONG - Recalculates every access
get filteredProducts() {
return this.products.filter(p =>
p.name.toLowerCase().includes(this.filter)
);
}
```
---
## 5. Server-Side Rendering (HIGH)
### Configure Incremental Hydration
```typescript
// app.config.ts
import {
provideClientHydration,
withIncrementalHydration,
} from "@angular/platform-browser";
export const appConfig: ApplicationConfig = {
providers: [
provideClientHydration(withIncrementalHydration(), withEventReplay()),
],
};
```
### Defer Non-Critical Content
```html
<!-- Critical above-the-fold content -->
<app-header />
<app-hero />
<!-- Below-fold deferred with hydration triggers -->
@defer (hydrate on viewport) {
<app-product-grid />
} @defer (hydrate on interaction) {
<app-chat-widget />
}
```
### Use TransferState for SSR Data
```typescript
@Injectable({ providedIn: "root" })
export class DataService {
private http = inject(HttpClient);
private transferState = inject(TransferState);
private platformId = inject(PLATFORM_ID);
getData(key: string): Observable<Data> {
const stateKey = makeStateKey<Data>(key);
if (isPlatformBrowser(this.platformId)) {
const cached = this.transferState.get(stateKey, null);
if (cached) {
this.transferState.remove(stateKey);
return of(cached);
}
}
return this.http.get<Data>(`/api/${key}`).pipe(
tap((data) => {
if (isPlatformServer(this.platformId)) {
this.transferState.set(stateKey, data);
}
}),
);
}
}
```
---
## 6. Template Optimization (MEDIUM)
### Use New Control Flow Syntax
```html
<!-- CORRECT - New control flow (faster, smaller bundle) -->
@if (user()) {
<span>{{ user()!.name }}</span>
} @else {
<span>Guest</span>
} @for (item of items(); track item.id) {
<app-item [item]="item" />
} @empty {
<p>No items</p>
}
<!-- WRONG - Legacy structural directives -->
<span *ngIf="user; else guest">{{ user.name }}</span>
<ng-template #guest><span>Guest</span></ng-template>
```
### Avoid Complex Template Expressions
```typescript
// CORRECT - Precompute in component
class Component {
items = signal<Item[]>([]);
sortedItems = computed(() =>
[...this.items()].sort((a, b) => a.name.localeCompare(b.name))
);
}
// Template
@for (item of sortedItems(); track item.id) { ... }
// WRONG - Sorting in template every render
@for (item of items() | sort:'name'; track item.id) { ... }
```
---
## 7. State Management (MEDIUM)
### Use Selectors to Prevent Re-renders
```typescript
// CORRECT - Selective subscription
@Component({
template: `<span>{{ userName() }}</span>`,
})
class HeaderComponent {
private store = inject(Store);
// Only re-renders when userName changes
userName = this.store.selectSignal(selectUserName);
}
// WRONG - Subscribing to entire state
@Component({
template: `<span>{{ state().user.name }}</span>`,
})
class HeaderComponent {
private store = inject(Store);
// Re-renders on ANY state change
state = toSignal(this.store);
}
```
### Colocate State with Features
```typescript
// CORRECT - Feature-scoped store
@Injectable() // NOT providedIn: 'root'
export class ProductStore { ... }
@Component({
providers: [ProductStore], // Scoped to component tree
})
export class ProductPageComponent {
store = inject(ProductStore);
}
// WRONG - Everything in global store
@Injectable({ providedIn: 'root' })
export class GlobalStore {
// Contains ALL app state - hard to tree-shake
}
```
---
## 8. Memory Management (LOW-MEDIUM)
### Use takeUntilDestroyed for Subscriptions
```typescript
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({...})
export class DataComponent {
private destroyRef = inject(DestroyRef);
constructor() {
this.data$.pipe(
takeUntilDestroyed(this.destroyRef)
).subscribe(data => this.process(data));
}
}
// WRONG - Manual subscription management
export class DataComponent implements OnDestroy {
private subscription!: Subscription;
ngOnInit() {
this.subscription = this.data$.subscribe(...);
}
ngOnDestroy() {
this.subscription.unsubscribe(); // Easy to forget
}
}
```
### Prefer Signals Over Subscriptions
```typescript
// CORRECT - No subscription needed
@Component({
template: `<div>{{ data().name }}</div>`,
})
export class Component {
data = toSignal(this.service.data$, { initialValue: null });
}
// WRONG - Manual subscription
@Component({
template: `<div>{{ data?.name }}</div>`,
})
export class Component implements OnInit, OnDestroy {
data: Data | null = null;
private sub!: Subscription;
ngOnInit() {
this.sub = this.service.data$.subscribe((d) => (this.data = d));
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
```
---
## Quick Reference Checklist
### New Component
- [ ] `changeDetection: ChangeDetectionStrategy.OnPush`
- [ ] `standalone: true`
- [ ] Signals for state (`signal()`, `input()`, `output()`)
- [ ] `inject()` for dependencies
- [ ] `@for` with `track` expression
### Performance Review
- [ ] No methods in templates (use pipes or computed)
- [ ] Large lists virtualized
- [ ] Heavy components deferred
- [ ] Routes lazy-loaded
- [ ] Third-party libs dynamically imported
### SSR Check
- [ ] Hydration configured
- [ ] Critical content renders first
- [ ] Non-critical content uses `@defer (hydrate on ...)`
- [ ] TransferState for server-fetched data
---
## Resources
- [Angular Performance Guide](https://angular.dev/best-practices/performance)
- [Zoneless Angular](https://angular.dev/guide/experimental/zoneless)
- [Angular SSR Guide](https://angular.dev/guide/ssr)
- [Change Detection Deep Dive](https://angular.dev/guide/change-detection)

View File

@@ -0,0 +1,13 @@
{
"version": "1.0.0",
"organization": "Antigravity Awesome Skills",
"date": "February 2026",
"abstract": "Performance optimization and best practices guide for Angular applications designed for AI agents and LLMs. Covers change detection strategies (OnPush, Signals, Zoneless), avoiding async waterfalls, bundle optimization with lazy loading and @defer, rendering performance, SSR/hydration patterns, and memory management. Prioritized by impact from critical to incremental improvements.",
"references": [
"https://angular.dev/best-practices",
"https://angular.dev/guide/performance",
"https://angular.dev/guide/zoneless",
"https://angular.dev/guide/ssr",
"https://web.dev/performance"
]
}

View File

@@ -0,0 +1,41 @@
# Angular State Management
Complete state management patterns for Angular applications optimized for AI agents and LLMs.
## Overview
This skill provides decision frameworks and implementation patterns for:
- **Signal-based Services** - Lightweight state for shared data
- **NgRx SignalStore** - Feature-scoped state with computed values
- **NgRx Store** - Enterprise-scale global state management
- **RxJS ComponentStore** - Reactive component-level state
- **Forms State** - Reactive and template-driven form patterns
## Structure
The `SKILL.md` file is organized into:
1. **State Categories** - Local, shared, global, server, URL, and form state
2. **Selection Criteria** - Decision trees for choosing the right solution
3. **Implementation Patterns** - Complete examples for each approach
4. **Migration Guides** - Moving from BehaviorSubject to Signals
5. **Bridging Patterns** - Integrating Signals with RxJS
## When to Use Each Pattern
- **Signal Service**: Shared UI state (theme, user preferences)
- **NgRx SignalStore**: Feature state with computed values
- **NgRx Store**: Complex cross-feature dependencies
- **ComponentStore**: Component-scoped async operations
- **Reactive Forms**: Form state with validation
## Version
Current version: 1.0.0 (February 2026)
## References
- [Angular Signals](https://angular.dev/guide/signals)
- [NgRx](https://ngrx.io)
- [NgRx SignalStore](https://ngrx.io/guide/signals)

View File

@@ -0,0 +1,634 @@
---
name: angular-state-management
description: Master modern Angular state management with Signals, NgRx, and RxJS. Use when setting up global state, managing component stores, choosing between state solutions, or migrating from legacy patterns.
risk: safe
source: self
---
# Angular State Management
Comprehensive guide to modern Angular state management patterns, from Signal-based local state to global stores and server state synchronization.
## When to Use This Skill
- Setting up global state management in Angular
- Choosing between Signals, NgRx, or Akita
- Managing component-level stores
- Implementing optimistic updates
- Debugging state-related issues
- Migrating from legacy state patterns
## Do Not Use This Skill When
- The task is unrelated to Angular state management
- You need React state management → use `react-state-management`
---
## Core Concepts
### State Categories
| Type | Description | Solutions |
| ---------------- | ---------------------------- | --------------------- |
| **Local State** | Component-specific, UI state | Signals, `signal()` |
| **Shared State** | Between related components | Signal services |
| **Global State** | App-wide, complex | NgRx, Akita, Elf |
| **Server State** | Remote data, caching | NgRx Query, RxAngular |
| **URL State** | Route parameters | ActivatedRoute |
| **Form State** | Input values, validation | Reactive Forms |
### Selection Criteria
```
Small app, simple state → Signal Services
Medium app, moderate state → Component Stores
Large app, complex state → NgRx Store
Heavy server interaction → NgRx Query + Signal Services
Real-time updates → RxAngular + Signals
```
---
## Quick Start: Signal-Based State
### Pattern 1: Simple Signal Service
```typescript
// services/counter.service.ts
import { Injectable, signal, computed } from "@angular/core";
@Injectable({ providedIn: "root" })
export class CounterService {
// Private writable signals
private _count = signal(0);
// Public read-only
readonly count = this._count.asReadonly();
readonly doubled = computed(() => this._count() * 2);
readonly isPositive = computed(() => this._count() > 0);
increment() {
this._count.update((v) => v + 1);
}
decrement() {
this._count.update((v) => v - 1);
}
reset() {
this._count.set(0);
}
}
// Usage in component
@Component({
template: `
<p>Count: {{ counter.count() }}</p>
<p>Doubled: {{ counter.doubled() }}</p>
<button (click)="counter.increment()">+</button>
`,
})
export class CounterComponent {
counter = inject(CounterService);
}
```
### Pattern 2: Feature Signal Store
```typescript
// stores/user.store.ts
import { Injectable, signal, computed, inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { toSignal } from "@angular/core/rxjs-interop";
interface User {
id: string;
name: string;
email: string;
}
interface UserState {
user: User | null;
loading: boolean;
error: string | null;
}
@Injectable({ providedIn: "root" })
export class UserStore {
private http = inject(HttpClient);
// State signals
private _user = signal<User | null>(null);
private _loading = signal(false);
private _error = signal<string | null>(null);
// Selectors (read-only computed)
readonly user = computed(() => this._user());
readonly loading = computed(() => this._loading());
readonly error = computed(() => this._error());
readonly isAuthenticated = computed(() => this._user() !== null);
readonly displayName = computed(() => this._user()?.name ?? "Guest");
// Actions
async loadUser(id: string) {
this._loading.set(true);
this._error.set(null);
try {
const user = await fetch(`/api/users/${id}`).then((r) => r.json());
this._user.set(user);
} catch (e) {
this._error.set("Failed to load user");
} finally {
this._loading.set(false);
}
}
updateUser(updates: Partial<User>) {
this._user.update((user) => (user ? { ...user, ...updates } : null));
}
logout() {
this._user.set(null);
this._error.set(null);
}
}
```
### Pattern 3: SignalStore (NgRx Signals)
```typescript
// stores/products.store.ts
import {
signalStore,
withState,
withMethods,
withComputed,
patchState,
} from "@ngrx/signals";
import { inject } from "@angular/core";
import { ProductService } from "./product.service";
interface ProductState {
products: Product[];
loading: boolean;
filter: string;
}
const initialState: ProductState = {
products: [],
loading: false,
filter: "",
};
export const ProductStore = signalStore(
{ providedIn: "root" },
withState(initialState),
withComputed((store) => ({
filteredProducts: computed(() => {
const filter = store.filter().toLowerCase();
return store
.products()
.filter((p) => p.name.toLowerCase().includes(filter));
}),
totalCount: computed(() => store.products().length),
})),
withMethods((store, productService = inject(ProductService)) => ({
async loadProducts() {
patchState(store, { loading: true });
try {
const products = await productService.getAll();
patchState(store, { products, loading: false });
} catch {
patchState(store, { loading: false });
}
},
setFilter(filter: string) {
patchState(store, { filter });
},
addProduct(product: Product) {
patchState(store, ({ products }) => ({
products: [...products, product],
}));
},
})),
);
// Usage
@Component({
template: `
<input (input)="store.setFilter($event.target.value)" />
@if (store.loading()) {
<app-spinner />
} @else {
@for (product of store.filteredProducts(); track product.id) {
<app-product-card [product]="product" />
}
}
`,
})
export class ProductListComponent {
store = inject(ProductStore);
ngOnInit() {
this.store.loadProducts();
}
}
```
---
## NgRx Store (Global State)
### Setup
```typescript
// store/app.state.ts
import { ActionReducerMap } from "@ngrx/store";
export interface AppState {
user: UserState;
cart: CartState;
}
export const reducers: ActionReducerMap<AppState> = {
user: userReducer,
cart: cartReducer,
};
// main.ts
bootstrapApplication(AppComponent, {
providers: [
provideStore(reducers),
provideEffects([UserEffects, CartEffects]),
provideStoreDevtools({ maxAge: 25 }),
],
});
```
### Feature Slice Pattern
```typescript
// store/user/user.actions.ts
import { createActionGroup, props, emptyProps } from "@ngrx/store";
export const UserActions = createActionGroup({
source: "User",
events: {
"Load User": props<{ userId: string }>(),
"Load User Success": props<{ user: User }>(),
"Load User Failure": props<{ error: string }>(),
"Update User": props<{ updates: Partial<User> }>(),
Logout: emptyProps(),
},
});
```
```typescript
// store/user/user.reducer.ts
import { createReducer, on } from "@ngrx/store";
import { UserActions } from "./user.actions";
export interface UserState {
user: User | null;
loading: boolean;
error: string | null;
}
const initialState: UserState = {
user: null,
loading: false,
error: null,
};
export const userReducer = createReducer(
initialState,
on(UserActions.loadUser, (state) => ({
...state,
loading: true,
error: null,
})),
on(UserActions.loadUserSuccess, (state, { user }) => ({
...state,
user,
loading: false,
})),
on(UserActions.loadUserFailure, (state, { error }) => ({
...state,
loading: false,
error,
})),
on(UserActions.logout, () => initialState),
);
```
```typescript
// store/user/user.selectors.ts
import { createFeatureSelector, createSelector } from "@ngrx/store";
import { UserState } from "./user.reducer";
export const selectUserState = createFeatureSelector<UserState>("user");
export const selectUser = createSelector(
selectUserState,
(state) => state.user,
);
export const selectUserLoading = createSelector(
selectUserState,
(state) => state.loading,
);
export const selectIsAuthenticated = createSelector(
selectUser,
(user) => user !== null,
);
```
```typescript
// store/user/user.effects.ts
import { Injectable, inject } from "@angular/core";
import { Actions, createEffect, ofType } from "@ngrx/effects";
import { switchMap, map, catchError, of } from "rxjs";
@Injectable()
export class UserEffects {
private actions$ = inject(Actions);
private userService = inject(UserService);
loadUser$ = createEffect(() =>
this.actions$.pipe(
ofType(UserActions.loadUser),
switchMap(({ userId }) =>
this.userService.getUser(userId).pipe(
map((user) => UserActions.loadUserSuccess({ user })),
catchError((error) =>
of(UserActions.loadUserFailure({ error: error.message })),
),
),
),
),
);
}
```
### Component Usage
```typescript
@Component({
template: `
@if (loading()) {
<app-spinner />
} @else if (user(); as user) {
<h1>Welcome, {{ user.name }}</h1>
<button (click)="logout()">Logout</button>
}
`,
})
export class HeaderComponent {
private store = inject(Store);
user = this.store.selectSignal(selectUser);
loading = this.store.selectSignal(selectUserLoading);
logout() {
this.store.dispatch(UserActions.logout());
}
}
```
---
## RxJS-Based Patterns
### Component Store (Local Feature State)
```typescript
// stores/todo.store.ts
import { Injectable } from "@angular/core";
import { ComponentStore } from "@ngrx/component-store";
import { switchMap, tap, catchError, EMPTY } from "rxjs";
interface TodoState {
todos: Todo[];
loading: boolean;
}
@Injectable()
export class TodoStore extends ComponentStore<TodoState> {
constructor(private todoService: TodoService) {
super({ todos: [], loading: false });
}
// Selectors
readonly todos$ = this.select((state) => state.todos);
readonly loading$ = this.select((state) => state.loading);
readonly completedCount$ = this.select(
this.todos$,
(todos) => todos.filter((t) => t.completed).length,
);
// Updaters
readonly addTodo = this.updater((state, todo: Todo) => ({
...state,
todos: [...state.todos, todo],
}));
readonly toggleTodo = this.updater((state, id: string) => ({
...state,
todos: state.todos.map((t) =>
t.id === id ? { ...t, completed: !t.completed } : t,
),
}));
// Effects
readonly loadTodos = this.effect<void>((trigger$) =>
trigger$.pipe(
tap(() => this.patchState({ loading: true })),
switchMap(() =>
this.todoService.getAll().pipe(
tap({
next: (todos) => this.patchState({ todos, loading: false }),
error: () => this.patchState({ loading: false }),
}),
catchError(() => EMPTY),
),
),
),
);
}
```
---
## Server State with Signals
### HTTP + Signals Pattern
```typescript
// services/api.service.ts
import { Injectable, signal, inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { toSignal } from "@angular/core/rxjs-interop";
interface ApiState<T> {
data: T | null;
loading: boolean;
error: string | null;
}
@Injectable({ providedIn: "root" })
export class ProductApiService {
private http = inject(HttpClient);
private _state = signal<ApiState<Product[]>>({
data: null,
loading: false,
error: null,
});
readonly products = computed(() => this._state().data ?? []);
readonly loading = computed(() => this._state().loading);
readonly error = computed(() => this._state().error);
async fetchProducts(): Promise<void> {
this._state.update((s) => ({ ...s, loading: true, error: null }));
try {
const data = await firstValueFrom(
this.http.get<Product[]>("/api/products"),
);
this._state.update((s) => ({ ...s, data, loading: false }));
} catch (e) {
this._state.update((s) => ({
...s,
loading: false,
error: "Failed to fetch products",
}));
}
}
// Optimistic update
async deleteProduct(id: string): Promise<void> {
const previousData = this._state().data;
// Optimistically remove
this._state.update((s) => ({
...s,
data: s.data?.filter((p) => p.id !== id) ?? null,
}));
try {
await firstValueFrom(this.http.delete(`/api/products/${id}`));
} catch {
// Rollback on error
this._state.update((s) => ({ ...s, data: previousData }));
}
}
}
```
---
## Best Practices
### Do's
| Practice | Why |
| ---------------------------------- | ---------------------------------- |
| Use Signals for local state | Simple, reactive, no subscriptions |
| Use `computed()` for derived data | Auto-updates, memoized |
| Colocate state with feature | Easier to maintain |
| Use NgRx for complex flows | Actions, effects, devtools |
| Prefer `inject()` over constructor | Cleaner, works in factories |
### Don'ts
| Anti-Pattern | Instead |
| --------------------------------- | ----------------------------------------------------- |
| Store derived data | Use `computed()` |
| Mutate signals directly | Use `set()` or `update()` |
| Over-globalize state | Keep local when possible |
| Mix RxJS and Signals chaotically | Choose primary, bridge with `toSignal`/`toObservable` |
| Subscribe in components for state | Use template with signals |
---
## Migration Path
### From BehaviorSubject to Signals
```typescript
// Before: RxJS-based
@Injectable({ providedIn: "root" })
export class OldUserService {
private userSubject = new BehaviorSubject<User | null>(null);
user$ = this.userSubject.asObservable();
setUser(user: User) {
this.userSubject.next(user);
}
}
// After: Signal-based
@Injectable({ providedIn: "root" })
export class UserService {
private _user = signal<User | null>(null);
readonly user = this._user.asReadonly();
setUser(user: User) {
this._user.set(user);
}
}
```
### Bridging Signals and RxJS
```typescript
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
// Observable → Signal
@Component({...})
export class ExampleComponent {
private route = inject(ActivatedRoute);
// Convert Observable to Signal
userId = toSignal(
this.route.params.pipe(map(p => p['id'])),
{ initialValue: '' }
);
}
// Signal → Observable
export class DataService {
private filter = signal('');
// Convert Signal to Observable
filter$ = toObservable(this.filter);
filteredData$ = this.filter$.pipe(
debounceTime(300),
switchMap(filter => this.http.get(`/api/data?q=${filter}`))
);
}
```
---
## Resources
- [Angular Signals Guide](https://angular.dev/guide/signals)
- [NgRx Documentation](https://ngrx.io/)
- [NgRx SignalStore](https://ngrx.io/guide/signals)
- [RxAngular](https://www.rx-angular.io/)

View File

@@ -0,0 +1,13 @@
{
"version": "1.0.0",
"organization": "Antigravity Awesome Skills",
"date": "February 2026",
"abstract": "Complete state management guide for Angular applications designed for AI agents and LLMs. Covers Signal-based services, NgRx for global state, RxJS patterns, and component stores. Includes decision trees for choosing the right solution, migration patterns from BehaviorSubject to Signals, and strategies for bridging Signals with RxJS observables.",
"references": [
"https://angular.dev/guide/signals",
"https://ngrx.io",
"https://ngrx.io/guide/signals",
"https://www.rx-angular.io",
"https://github.com/ngrx/platform"
]
}

View File

@@ -0,0 +1,55 @@
# Angular UI Patterns
Modern UI patterns for building robust Angular applications optimized for AI agents and LLMs.
## Overview
This skill covers essential UI patterns for:
- **Loading States** - Skeleton vs spinner decision trees
- **Error Handling** - Error boundary hierarchy and recovery
- **Progressive Disclosure** - Using `@defer` for lazy rendering
- **Data Display** - Handling empty, loading, and error states
- **Form Patterns** - Submission states and validation feedback
- **Dialog/Modal Patterns** - Proper dialog lifecycle management
## Core Principles
1. **Never show stale UI** - Only show loading when no data exists
2. **Surface all errors** - Never silently fail
3. **Optimistic updates** - Update UI before server confirms
4. **Progressive disclosure** - Use `@defer` to load non-critical content
5. **Graceful degradation** - Fallback for failed features
## Structure
The `SKILL.md` file includes:
1. **Golden Rules** - Non-negotiable patterns to follow
2. **Decision Trees** - When to use skeleton vs spinner
3. **Code Examples** - Correct vs incorrect implementations
4. **Anti-patterns** - Common mistakes to avoid
## Quick Reference
```html
<!-- Angular template pattern for data states -->
@if (error()) {
<app-error-state [error]="error()" (retry)="load()" />
} @else if (loading() && !data()) {
<app-skeleton-state />
} @else if (!data()?.length) {
<app-empty-state message="No items found" />
} @else {
<app-data-display [data]="data()" />
}
```
## Version
Current version: 1.0.0 (February 2026)
## References
- [Angular @defer](https://angular.dev/guide/defer)
- [Angular Templates](https://angular.dev/guide/templates)

View File

@@ -0,0 +1,508 @@
---
name: angular-ui-patterns
description: Modern Angular UI patterns for loading states, error handling, and data display. Use when building UI components, handling async data, or managing component states.
risk: safe
source: self
---
# Angular UI Patterns
## Core Principles
1. **Never show stale UI** - Loading states only when actually loading
2. **Always surface errors** - Users must know when something fails
3. **Optimistic updates** - Make the UI feel instant
4. **Progressive disclosure** - Use `@defer` to show content as available
5. **Graceful degradation** - Partial data is better than no data
---
## Loading State Patterns
### The Golden Rule
**Show loading indicator ONLY when there's no data to display.**
```typescript
@Component({
template: `
@if (error()) {
<app-error-state [error]="error()" (retry)="load()" />
} @else if (loading() && !items().length) {
<app-skeleton-list />
} @else if (!items().length) {
<app-empty-state message="No items found" />
} @else {
<app-item-list [items]="items()" />
}
`,
})
export class ItemListComponent {
private store = inject(ItemStore);
items = this.store.items;
loading = this.store.loading;
error = this.store.error;
}
```
### Loading State Decision Tree
```
Is there an error?
→ Yes: Show error state with retry option
→ No: Continue
Is it loading AND we have no data?
→ Yes: Show loading indicator (spinner/skeleton)
→ No: Continue
Do we have data?
→ Yes, with items: Show the data
→ Yes, but empty: Show empty state
→ No: Show loading (fallback)
```
### Skeleton vs Spinner
| Use Skeleton When | Use Spinner When |
| -------------------- | --------------------- |
| Known content shape | Unknown content shape |
| List/card layouts | Modal actions |
| Initial page load | Button submissions |
| Content placeholders | Inline operations |
---
## Control Flow Patterns
### @if/@else for Conditional Rendering
```html
@if (user(); as user) {
<span>Welcome, {{ user.name }}</span>
} @else if (loading()) {
<app-spinner size="small" />
} @else {
<a routerLink="/login">Sign In</a>
}
```
### @for with Track
```html
@for (item of items(); track item.id) {
<app-item-card [item]="item" (delete)="remove(item.id)" />
} @empty {
<app-empty-state
icon="inbox"
message="No items yet"
actionLabel="Create Item"
(action)="create()"
/>
}
```
### @defer for Progressive Loading
```html
<!-- Critical content loads immediately -->
<app-header />
<app-hero-section />
<!-- Non-critical content deferred -->
@defer (on viewport) {
<app-comments [postId]="postId()" />
} @placeholder {
<div class="h-32 bg-gray-100 animate-pulse"></div>
} @loading (minimum 200ms) {
<app-spinner />
} @error {
<app-error-state message="Failed to load comments" />
}
```
---
## Error Handling Patterns
### Error Handling Hierarchy
```
1. Inline error (field-level) → Form validation errors
2. Toast notification → Recoverable errors, user can retry
3. Error banner → Page-level errors, data still partially usable
4. Full error screen → Unrecoverable, needs user action
```
### Always Show Errors
**CRITICAL: Never swallow errors silently.**
```typescript
// CORRECT - Error always surfaced to user
@Component({...})
export class CreateItemComponent {
private store = inject(ItemStore);
private toast = inject(ToastService);
async create(data: CreateItemDto) {
try {
await this.store.create(data);
this.toast.success('Item created successfully');
this.router.navigate(['/items']);
} catch (error) {
console.error('createItem failed:', error);
this.toast.error('Failed to create item. Please try again.');
}
}
}
// WRONG - Error silently caught
async create(data: CreateItemDto) {
try {
await this.store.create(data);
} catch (error) {
console.error(error); // User sees nothing!
}
}
```
### Error State Component Pattern
```typescript
@Component({
selector: "app-error-state",
standalone: true,
imports: [NgOptimizedImage],
template: `
<div class="error-state">
<img ngSrc="/assets/error-icon.svg" width="64" height="64" alt="" />
<h3>{{ title() }}</h3>
<p>{{ message() }}</p>
@if (retry.observed) {
<button (click)="retry.emit()" class="btn-primary">Try Again</button>
}
</div>
`,
})
export class ErrorStateComponent {
title = input("Something went wrong");
message = input("An unexpected error occurred");
retry = output<void>();
}
```
---
## Button State Patterns
### Button Loading State
```html
<button
(click)="handleSubmit()"
[disabled]="isSubmitting() || !form.valid"
class="btn-primary"
>
@if (isSubmitting()) {
<app-spinner size="small" class="mr-2" />
Saving... } @else { Save Changes }
</button>
```
### Disable During Operations
**CRITICAL: Always disable triggers during async operations.**
```typescript
// CORRECT - Button disabled while loading
@Component({
template: `
<button
[disabled]="saving()"
(click)="save()"
>
@if (saving()) {
<app-spinner size="sm" /> Saving...
} @else {
Save
}
</button>
`
})
export class SaveButtonComponent {
saving = signal(false);
async save() {
this.saving.set(true);
try {
await this.service.save();
} finally {
this.saving.set(false);
}
}
}
// WRONG - User can click multiple times
<button (click)="save()">
{{ saving() ? 'Saving...' : 'Save' }}
</button>
```
---
## Empty States
### Empty State Requirements
Every list/collection MUST have an empty state:
```html
@for (item of items(); track item.id) {
<app-item-card [item]="item" />
} @empty {
<app-empty-state
icon="folder-open"
title="No items yet"
description="Create your first item to get started"
actionLabel="Create Item"
(action)="openCreateDialog()"
/>
}
```
### Contextual Empty States
```typescript
@Component({
selector: "app-empty-state",
template: `
<div class="empty-state">
<span class="icon" [class]="icon()"></span>
<h3>{{ title() }}</h3>
<p>{{ description() }}</p>
@if (actionLabel()) {
<button (click)="action.emit()" class="btn-primary">
{{ actionLabel() }}
</button>
}
</div>
`,
})
export class EmptyStateComponent {
icon = input("inbox");
title = input.required<string>();
description = input("");
actionLabel = input<string | null>(null);
action = output<void>();
}
```
---
## Form Patterns
### Form with Loading and Validation
```typescript
@Component({
template: `
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div class="form-field">
<label for="name">Name</label>
<input
id="name"
formControlName="name"
[class.error]="isFieldInvalid('name')"
/>
@if (isFieldInvalid("name")) {
<span class="error-text">
{{ getFieldError("name") }}
</span>
}
</div>
<div class="form-field">
<label for="email">Email</label>
<input id="email" type="email" formControlName="email" />
@if (isFieldInvalid("email")) {
<span class="error-text">
{{ getFieldError("email") }}
</span>
}
</div>
<button type="submit" [disabled]="form.invalid || submitting()">
@if (submitting()) {
<app-spinner size="sm" /> Submitting...
} @else {
Submit
}
</button>
</form>
`,
})
export class UserFormComponent {
private fb = inject(FormBuilder);
submitting = signal(false);
form = this.fb.group({
name: ["", [Validators.required, Validators.minLength(2)]],
email: ["", [Validators.required, Validators.email]],
});
isFieldInvalid(field: string): boolean {
const control = this.form.get(field);
return control ? control.invalid && control.touched : false;
}
getFieldError(field: string): string {
const control = this.form.get(field);
if (control?.hasError("required")) return "This field is required";
if (control?.hasError("email")) return "Invalid email format";
if (control?.hasError("minlength")) return "Too short";
return "";
}
async onSubmit() {
if (this.form.invalid) return;
this.submitting.set(true);
try {
await this.service.submit(this.form.value);
this.toast.success("Submitted successfully");
} catch {
this.toast.error("Submission failed");
} finally {
this.submitting.set(false);
}
}
}
```
---
## Dialog/Modal Patterns
### Confirmation Dialog
```typescript
// dialog.service.ts
@Injectable({ providedIn: 'root' })
export class DialogService {
private dialog = inject(Dialog); // CDK Dialog or custom
async confirm(options: {
title: string;
message: string;
confirmText?: string;
cancelText?: string;
}): Promise<boolean> {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
data: options,
});
return await firstValueFrom(dialogRef.closed) ?? false;
}
}
// Usage
async deleteItem(item: Item) {
const confirmed = await this.dialog.confirm({
title: 'Delete Item',
message: `Are you sure you want to delete "${item.name}"?`,
confirmText: 'Delete',
});
if (confirmed) {
await this.store.delete(item.id);
}
}
```
---
## Anti-Patterns
### Loading States
```typescript
// WRONG - Spinner when data exists (causes flash on refetch)
@if (loading()) {
<app-spinner />
}
// CORRECT - Only show loading without data
@if (loading() && !items().length) {
<app-spinner />
}
```
### Error Handling
```typescript
// WRONG - Error swallowed
try {
await this.service.save();
} catch (e) {
console.log(e); // User has no idea!
}
// CORRECT - Error surfaced
try {
await this.service.save();
} catch (e) {
console.error("Save failed:", e);
this.toast.error("Failed to save. Please try again.");
}
```
### Button States
```html
<!-- WRONG - Button not disabled during submission -->
<button (click)="submit()">Submit</button>
<!-- CORRECT - Disabled and shows loading -->
<button (click)="submit()" [disabled]="loading()">
@if (loading()) {
<app-spinner size="sm" />
} Submit
</button>
```
---
## UI State Checklist
Before completing any UI component:
### UI States
- [ ] Error state handled and shown to user
- [ ] Loading state shown only when no data exists
- [ ] Empty state provided for collections (`@empty` block)
- [ ] Buttons disabled during async operations
- [ ] Buttons show loading indicator when appropriate
### Data & Mutations
- [ ] All async operations have error handling
- [ ] All user actions have feedback (toast/visual)
- [ ] Optimistic updates rollback on failure
### Accessibility
- [ ] Loading states announced to screen readers
- [ ] Error messages linked to form fields
- [ ] Focus management after state changes
---
## Integration with Other Skills
- **angular-state-management**: Use Signal stores for state
- **angular**: Apply modern patterns (Signals, @defer)
- **testing-patterns**: Test all UI states

View File

@@ -0,0 +1,12 @@
{
"version": "1.0.0",
"organization": "Antigravity Awesome Skills",
"date": "February 2026",
"abstract": "Modern UI patterns for Angular applications designed for AI agents and LLMs. Covers loading states, error handling, progressive disclosure, and data display patterns. Emphasizes showing loading only without data, surfacing all errors, optimistic updates, and graceful degradation using @defer. Includes decision trees and anti-patterns to avoid.",
"references": [
"https://angular.dev/guide/defer",
"https://angular.dev/guide/templates",
"https://material.angular.io",
"https://ng-spartan.com"
]
}

40
skills/angular/README.md Normal file
View File

@@ -0,0 +1,40 @@
# Angular
A comprehensive guide to modern Angular development (v20+) optimized for AI agents and LLMs.
## Overview
This skill covers modern Angular patterns including:
- **Signals** - Angular's reactive primitive for state management
- **Standalone Components** - Modern component architecture without NgModules
- **Zoneless Applications** - High-performance apps without Zone.js
- **SSR & Hydration** - Server-side rendering and client hydration patterns
- **Modern Routing** - Functional guards, resolvers, and lazy loading
- **Dependency Injection** - Modern DI with `inject()` function
- **Reactive Forms** - Type-safe form handling
## Structure
This skill is a single, comprehensive `SKILL.md` file containing:
1. Modern component patterns with Signal inputs/outputs
2. State management with Signals and computed values
3. Performance optimization techniques
4. SSR and hydration best practices
5. Migration strategies from legacy Angular patterns
## Usage
This skill is designed to be read in full to understand the complete modern Angular development approach, or referenced for specific patterns when needed.
## Version
Current version: 1.0.0 (February 2026)
## References
- [Angular Documentation](https://angular.dev)
- [Angular Signals](https://angular.dev/guide/signals)
- [Zoneless Angular](https://angular.dev/guide/zoneless)
- [Angular SSR](https://angular.dev/guide/ssr)

821
skills/angular/SKILL.md Normal file
View File

@@ -0,0 +1,821 @@
---
name: angular
description: >-
Modern Angular (v20+) expert with deep knowledge of Signals, Standalone
Components, Zoneless applications, SSR/Hydration, and reactive patterns.
Use PROACTIVELY for Angular development, component architecture, state
management, performance optimization, and migration to modern patterns.
risk: safe
source: self
---
# Angular Expert
Master modern Angular development with Signals, Standalone Components, Zoneless applications, SSR/Hydration, and the latest reactive patterns.
## When to Use This Skill
- Building new Angular applications (v20+)
- Implementing Signals-based reactive patterns
- Creating Standalone Components and migrating from NgModules
- Configuring Zoneless Angular applications
- Implementing SSR, prerendering, and hydration
- Optimizing Angular performance
- Adopting modern Angular patterns and best practices
## Do Not Use This Skill When
- Migrating from AngularJS (1.x) → use `angular-migration` skill
- Working with legacy Angular apps that cannot upgrade
- General TypeScript issues → use `typescript-expert` skill
## Instructions
1. Assess the Angular version and project structure
2. Apply modern patterns (Signals, Standalone, Zoneless)
3. Implement with proper typing and reactivity
4. Validate with build and tests
## Safety
- Always test changes in development before production
- Gradual migration for existing apps (don't big-bang refactor)
- Keep backward compatibility during transitions
---
## Angular Version Timeline
| Version | Release | Key Features |
| -------------- | ------- | ------------------------------------------------------ |
| **Angular 20** | Q2 2025 | Signals stable, Zoneless stable, Incremental hydration |
| **Angular 21** | Q4 2025 | Signals-first default, Enhanced SSR |
| **Angular 22** | Q2 2026 | Signal Forms, Selectorless components |
---
## 1. Signals: The New Reactive Primitive
Signals are Angular's fine-grained reactivity system, replacing zone.js-based change detection.
### Core Concepts
```typescript
import { signal, computed, effect } from "@angular/core";
// Writable signal
const count = signal(0);
// Read value
console.log(count()); // 0
// Update value
count.set(5); // Direct set
count.update((v) => v + 1); // Functional update
// Computed (derived) signal
const doubled = computed(() => count() * 2);
// Effect (side effects)
effect(() => {
console.log(`Count changed to: ${count()}`);
});
```
### Signal-Based Inputs and Outputs
```typescript
import { Component, input, output, model } from "@angular/core";
@Component({
selector: "app-user-card",
standalone: true,
template: `
<div class="card">
<h3>{{ name() }}</h3>
<span>{{ role() }}</span>
<button (click)="select.emit(id())">Select</button>
</div>
`,
})
export class UserCardComponent {
// Signal inputs (read-only)
id = input.required<string>();
name = input.required<string>();
role = input<string>("User"); // With default
// Output
select = output<string>();
// Two-way binding (model)
isSelected = model(false);
}
// Usage:
// <app-user-card [id]="'123'" [name]="'John'" [(isSelected)]="selected" />
```
### Signal Queries (ViewChild/ContentChild)
```typescript
import {
Component,
viewChild,
viewChildren,
contentChild,
} from "@angular/core";
@Component({
selector: "app-container",
standalone: true,
template: `
<input #searchInput />
<app-item *ngFor="let item of items()" />
`,
})
export class ContainerComponent {
// Signal-based queries
searchInput = viewChild<ElementRef>("searchInput");
items = viewChildren(ItemComponent);
projectedContent = contentChild(HeaderDirective);
focusSearch() {
this.searchInput()?.nativeElement.focus();
}
}
```
### When to Use Signals vs RxJS
| Use Case | Signals | RxJS |
| ----------------------- | --------------- | -------------------------------- |
| Local component state | ✅ Preferred | Overkill |
| Derived/computed values | ✅ `computed()` | `combineLatest` works |
| Side effects | ✅ `effect()` | `tap` operator |
| HTTP requests | ❌ | ✅ HttpClient returns Observable |
| Event streams | ❌ | ✅ `fromEvent`, operators |
| Complex async flows | ❌ | ✅ `switchMap`, `mergeMap` |
---
## 2. Standalone Components
Standalone components are self-contained and don't require NgModule declarations.
### Creating Standalone Components
```typescript
import { Component } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterLink } from "@angular/router";
@Component({
selector: "app-header",
standalone: true,
imports: [CommonModule, RouterLink], // Direct imports
template: `
<header>
<a routerLink="/">Home</a>
<a routerLink="/about">About</a>
</header>
`,
})
export class HeaderComponent {}
```
### Bootstrapping Without NgModule
```typescript
// main.ts
import { bootstrapApplication } from "@angular/platform-browser";
import { provideRouter } from "@angular/router";
import { provideHttpClient } from "@angular/common/http";
import { AppComponent } from "./app/app.component";
import { routes } from "./app/app.routes";
bootstrapApplication(AppComponent, {
providers: [provideRouter(routes), provideHttpClient()],
});
```
### Lazy Loading Standalone Components
```typescript
// app.routes.ts
import { Routes } from "@angular/router";
export const routes: Routes = [
{
path: "dashboard",
loadComponent: () =>
import("./dashboard/dashboard.component").then(
(m) => m.DashboardComponent,
),
},
{
path: "admin",
loadChildren: () =>
import("./admin/admin.routes").then((m) => m.ADMIN_ROUTES),
},
];
```
---
## 3. Zoneless Angular
Zoneless applications don't use zone.js, improving performance and debugging.
### Enabling Zoneless Mode
```typescript
// main.ts
import { bootstrapApplication } from "@angular/platform-browser";
import { provideZonelessChangeDetection } from "@angular/core";
import { AppComponent } from "./app/app.component";
bootstrapApplication(AppComponent, {
providers: [provideZonelessChangeDetection()],
});
```
### Zoneless Component Patterns
```typescript
import { Component, signal, ChangeDetectionStrategy } from "@angular/core";
@Component({
selector: "app-counter",
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div>Count: {{ count() }}</div>
<button (click)="increment()">+</button>
`,
})
export class CounterComponent {
count = signal(0);
increment() {
this.count.update((v) => v + 1);
// No zone.js needed - Signal triggers change detection
}
}
```
### Key Zoneless Benefits
- **Performance**: No zone.js patches on async APIs
- **Debugging**: Clean stack traces without zone wrappers
- **Bundle size**: Smaller without zone.js (~15KB savings)
- **Interoperability**: Better with Web Components and micro-frontends
---
## 4. Server-Side Rendering & Hydration
### SSR Setup with Angular CLI
```bash
ng add @angular/ssr
```
### Hydration Configuration
```typescript
// app.config.ts
import { ApplicationConfig } from "@angular/core";
import {
provideClientHydration,
withEventReplay,
} from "@angular/platform-browser";
export const appConfig: ApplicationConfig = {
providers: [provideClientHydration(withEventReplay())],
};
```
### Incremental Hydration (v20+)
```typescript
import { Component } from "@angular/core";
@Component({
selector: "app-page",
standalone: true,
template: `
<app-hero />
@defer (hydrate on viewport) {
<app-comments />
}
@defer (hydrate on interaction) {
<app-chat-widget />
}
`,
})
export class PageComponent {}
```
### Hydration Triggers
| Trigger | When to Use |
| ---------------- | --------------------------------------- |
| `on idle` | Low-priority, hydrate when browser idle |
| `on viewport` | Hydrate when element enters viewport |
| `on interaction` | Hydrate on first user interaction |
| `on hover` | Hydrate when user hovers |
| `on timer(ms)` | Hydrate after specified delay |
---
## 5. Modern Routing Patterns
### Functional Route Guards
```typescript
// auth.guard.ts
import { inject } from "@angular/core";
import { Router, CanActivateFn } from "@angular/router";
import { AuthService } from "./auth.service";
export const authGuard: CanActivateFn = (route, state) => {
const auth = inject(AuthService);
const router = inject(Router);
if (auth.isAuthenticated()) {
return true;
}
return router.createUrlTree(["/login"], {
queryParams: { returnUrl: state.url },
});
};
// Usage in routes
export const routes: Routes = [
{
path: "dashboard",
loadComponent: () => import("./dashboard.component"),
canActivate: [authGuard],
},
];
```
### Route-Level Data Resolvers
```typescript
import { inject } from '@angular/core';
import { ResolveFn } from '@angular/router';
import { UserService } from './user.service';
import { User } from './user.model';
export const userResolver: ResolveFn<User> = (route) => {
const userService = inject(UserService);
return userService.getUser(route.paramMap.get('id')!);
};
// In routes
{
path: 'user/:id',
loadComponent: () => import('./user.component'),
resolve: { user: userResolver }
}
// In component
export class UserComponent {
private route = inject(ActivatedRoute);
user = toSignal(this.route.data.pipe(map(d => d['user'])));
}
```
---
## 6. Dependency Injection Patterns
### Modern inject() Function
```typescript
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { UserService } from './user.service';
@Component({...})
export class UserComponent {
// Modern inject() - no constructor needed
private http = inject(HttpClient);
private userService = inject(UserService);
// Works in any injection context
users = toSignal(this.userService.getUsers());
}
```
### Injection Tokens for Configuration
```typescript
import { InjectionToken, inject } from "@angular/core";
// Define token
export const API_BASE_URL = new InjectionToken<string>("API_BASE_URL");
// Provide in config
bootstrapApplication(AppComponent, {
providers: [{ provide: API_BASE_URL, useValue: "https://api.example.com" }],
});
// Inject in service
@Injectable({ providedIn: "root" })
export class ApiService {
private baseUrl = inject(API_BASE_URL);
get(endpoint: string) {
return this.http.get(`${this.baseUrl}/${endpoint}`);
}
}
```
---
## 7. Component Composition & Reusability
### Content Projection (Slots)
```typescript
@Component({
selector: 'app-card',
template: `
<div class="card">
<div class="header">
<!-- Select by attribute -->
<ng-content select="[card-header]"></ng-content>
</div>
<div class="body">
<!-- Default slot -->
<ng-content></ng-content>
</div>
</div>
`
})
export class CardComponent {}
// Usage
<app-card>
<h3 card-header>Title</h3>
<p>Body content</p>
</app-card>
```
### Host Directives (Composition)
```typescript
// Reusable behaviors without inheritance
@Directive({
standalone: true,
selector: '[appTooltip]',
inputs: ['tooltip'] // Signal input alias
})
export class TooltipDirective { ... }
@Component({
selector: 'app-button',
standalone: true,
hostDirectives: [
{
directive: TooltipDirective,
inputs: ['tooltip: title'] // Map input
}
],
template: `<ng-content />`
})
export class ButtonComponent {}
```
---
## 8. State Management Patterns
### Signal-Based State Service
```typescript
import { Injectable, signal, computed } from "@angular/core";
interface AppState {
user: User | null;
theme: "light" | "dark";
notifications: Notification[];
}
@Injectable({ providedIn: "root" })
export class StateService {
// Private writable signals
private _user = signal<User | null>(null);
private _theme = signal<"light" | "dark">("light");
private _notifications = signal<Notification[]>([]);
// Public read-only computed
readonly user = computed(() => this._user());
readonly theme = computed(() => this._theme());
readonly notifications = computed(() => this._notifications());
readonly unreadCount = computed(
() => this._notifications().filter((n) => !n.read).length,
);
// Actions
setUser(user: User | null) {
this._user.set(user);
}
toggleTheme() {
this._theme.update((t) => (t === "light" ? "dark" : "light"));
}
addNotification(notification: Notification) {
this._notifications.update((n) => [...n, notification]);
}
}
```
### Component Store Pattern with Signals
```typescript
import { Injectable, signal, computed, inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { toSignal } from "@angular/core/rxjs-interop";
@Injectable()
export class ProductStore {
private http = inject(HttpClient);
// State
private _products = signal<Product[]>([]);
private _loading = signal(false);
private _filter = signal("");
// Selectors
readonly products = computed(() => this._products());
readonly loading = computed(() => this._loading());
readonly filteredProducts = computed(() => {
const filter = this._filter().toLowerCase();
return this._products().filter((p) =>
p.name.toLowerCase().includes(filter),
);
});
// Actions
loadProducts() {
this._loading.set(true);
this.http.get<Product[]>("/api/products").subscribe({
next: (products) => {
this._products.set(products);
this._loading.set(false);
},
error: () => this._loading.set(false),
});
}
setFilter(filter: string) {
this._filter.set(filter);
}
}
```
---
## 9. Forms with Signals (Coming in v22+)
### Current Reactive Forms
```typescript
import { Component, inject } from "@angular/core";
import { FormBuilder, Validators, ReactiveFormsModule } from "@angular/forms";
@Component({
selector: "app-user-form",
standalone: true,
imports: [ReactiveFormsModule],
template: `
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="name" placeholder="Name" />
<input formControlName="email" type="email" placeholder="Email" />
<button [disabled]="form.invalid">Submit</button>
</form>
`,
})
export class UserFormComponent {
private fb = inject(FormBuilder);
form = this.fb.group({
name: ["", Validators.required],
email: ["", [Validators.required, Validators.email]],
});
onSubmit() {
if (this.form.valid) {
console.log(this.form.value);
}
}
}
```
### Signal-Aware Form Patterns (Preview)
```typescript
// Future Signal Forms API (experimental)
import { Component, signal } from '@angular/core';
@Component({...})
export class SignalFormComponent {
name = signal('');
email = signal('');
// Computed validation
isValid = computed(() =>
this.name().length > 0 &&
this.email().includes('@')
);
submit() {
if (this.isValid()) {
console.log({ name: this.name(), email: this.email() });
}
}
}
```
---
## 10. Performance Optimization
### Change Detection Strategies
```typescript
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
// Only checks when:
// 1. Input signal/reference changes
// 2. Event handler runs
// 3. Async pipe emits
// 4. Signal value changes
})
```
### Defer Blocks for Lazy Loading
```typescript
@Component({
template: `
<!-- Immediate loading -->
<app-header />
<!-- Lazy load when visible -->
@defer (on viewport) {
<app-heavy-chart />
} @placeholder {
<div class="skeleton" />
} @loading (minimum 200ms) {
<app-spinner />
} @error {
<p>Failed to load chart</p>
}
`
})
```
### NgOptimizedImage
```typescript
import { NgOptimizedImage } from '@angular/common';
@Component({
imports: [NgOptimizedImage],
template: `
<img
ngSrc="hero.jpg"
width="800"
height="600"
priority
/>
<img
ngSrc="thumbnail.jpg"
width="200"
height="150"
loading="lazy"
placeholder="blur"
/>
`
})
```
---
## 11. Testing Modern Angular
### Testing Signal Components
```typescript
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { CounterComponent } from "./counter.component";
describe("CounterComponent", () => {
let component: CounterComponent;
let fixture: ComponentFixture<CounterComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CounterComponent], // Standalone import
}).compileComponents();
fixture = TestBed.createComponent(CounterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it("should increment count", () => {
expect(component.count()).toBe(0);
component.increment();
expect(component.count()).toBe(1);
});
it("should update DOM on signal change", () => {
component.count.set(5);
fixture.detectChanges();
const el = fixture.nativeElement.querySelector(".count");
expect(el.textContent).toContain("5");
});
});
```
### Testing with Signal Inputs
```typescript
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { ComponentRef } from "@angular/core";
import { UserCardComponent } from "./user-card.component";
describe("UserCardComponent", () => {
let fixture: ComponentFixture<UserCardComponent>;
let componentRef: ComponentRef<UserCardComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [UserCardComponent],
}).compileComponents();
fixture = TestBed.createComponent(UserCardComponent);
componentRef = fixture.componentRef;
// Set signal inputs via setInput
componentRef.setInput("id", "123");
componentRef.setInput("name", "John Doe");
fixture.detectChanges();
});
it("should display user name", () => {
const el = fixture.nativeElement.querySelector("h3");
expect(el.textContent).toContain("John Doe");
});
});
```
---
## Best Practices Summary
| Pattern | ✅ Do | ❌ Don't |
| -------------------- | ------------------------------ | ------------------------------- |
| **State** | Use Signals for local state | Overuse RxJS for simple state |
| **Components** | Standalone with direct imports | Bloated SharedModules |
| **Change Detection** | OnPush + Signals | Default CD everywhere |
| **Lazy Loading** | `@defer` and `loadComponent` | Eager load everything |
| **DI** | `inject()` function | Constructor injection (verbose) |
| **Inputs** | `input()` signal function | `@Input()` decorator (legacy) |
| **Zoneless** | Enable for new projects | Force on legacy without testing |
---
## Resources
- [Angular.dev Documentation](https://angular.dev)
- [Angular Signals Guide](https://angular.dev/guide/signals)
- [Angular SSR Guide](https://angular.dev/guide/ssr)
- [Angular Update Guide](https://angular.dev/update-guide)
- [Angular Blog](https://blog.angular.dev)
---
## Common Troubleshooting
| Issue | Solution |
| ------------------------------ | --------------------------------------------------- |
| Signal not updating UI | Ensure `OnPush` + call signal as function `count()` |
| Hydration mismatch | Check server/client content consistency |
| Circular dependency | Use `inject()` with `forwardRef` |
| Zoneless not detecting changes | Trigger via signal updates, not mutations |
| SSR fetch fails | Use `TransferState` or `withFetch()` |

View File

@@ -0,0 +1,14 @@
{
"version": "1.0.0",
"organization": "Antigravity Awesome Skills",
"date": "February 2026",
"abstract": "Comprehensive guide to modern Angular development (v20+) designed for AI agents and LLMs. Covers Signals, Standalone Components, Zoneless applications, SSR/Hydration, reactive patterns, routing, dependency injection, and modern forms. Emphasizes component-driven architecture with practical examples and migration strategies for modernizing existing codebases.",
"references": [
"https://angular.dev",
"https://angular.dev/guide/signals",
"https://angular.dev/guide/zoneless",
"https://angular.dev/guide/ssr",
"https://angular.dev/guide/standalone-components",
"https://angular.dev/guide/defer"
]
}

View File

@@ -186,7 +186,7 @@ class CompetitorAnalyzer:
def _analyze_title(self, title: str) -> Dict[str, Any]:
"""Analyze title structure and keyword usage."""
parts = re.split(r'[-:|]', title)
parts = re.split(r'[-' + r':|]', title)
return {
'title': title,

View File

@@ -0,0 +1,171 @@
---
name: asana-automation
description: "Automate Asana tasks via Rube MCP (Composio): tasks, projects, sections, teams, workspaces. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Asana Automation via Rube MCP
Automate Asana operations through Composio's Asana toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Asana connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `asana`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `asana`
3. If connection is not ACTIVE, follow the returned auth link to complete Asana OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Manage Tasks
**When to use**: User wants to create, search, list, or organize tasks
**Tool sequence**:
1. `ASANA_GET_MULTIPLE_WORKSPACES` - Get workspace ID [Prerequisite]
2. `ASANA_SEARCH_TASKS_IN_WORKSPACE` - Search tasks [Optional]
3. `ASANA_GET_TASKS_FROM_A_PROJECT` - List project tasks [Optional]
4. `ASANA_CREATE_A_TASK` - Create a new task [Optional]
5. `ASANA_GET_A_TASK` - Get task details [Optional]
6. `ASANA_CREATE_SUBTASK` - Create a subtask [Optional]
7. `ASANA_GET_TASK_SUBTASKS` - List subtasks [Optional]
**Key parameters**:
- `workspace`: Workspace GID (required for search/creation)
- `projects`: Array of project GIDs to add task to
- `name`: Task name
- `notes`: Task description
- `assignee`: Assignee (user GID or email)
- `due_on`: Due date (YYYY-MM-DD)
**Pitfalls**:
- Workspace GID is required for most operations; get it first
- Task GIDs are returned as strings, not integers
- Search is workspace-scoped, not project-scoped
### 2. Manage Projects and Sections
**When to use**: User wants to create projects, manage sections, or organize tasks
**Tool sequence**:
1. `ASANA_GET_WORKSPACE_PROJECTS` - List workspace projects [Optional]
2. `ASANA_GET_A_PROJECT` - Get project details [Optional]
3. `ASANA_CREATE_A_PROJECT` - Create a new project [Optional]
4. `ASANA_GET_SECTIONS_IN_PROJECT` - List sections [Optional]
5. `ASANA_CREATE_SECTION_IN_PROJECT` - Create a new section [Optional]
6. `ASANA_ADD_TASK_TO_SECTION` - Move task to section [Optional]
7. `ASANA_GET_TASKS_FROM_A_SECTION` - List tasks in section [Optional]
**Key parameters**:
- `project_gid`: Project GID
- `name`: Project or section name
- `workspace`: Workspace GID for creation
- `task`: Task GID for section assignment
- `section`: Section GID
**Pitfalls**:
- Projects belong to workspaces; workspace GID is needed for creation
- Sections are ordered within a project
- DUPLICATE_PROJECT creates a copy with optional task inclusion
### 3. Manage Teams and Users
**When to use**: User wants to list teams, team members, or workspace users
**Tool sequence**:
1. `ASANA_GET_TEAMS_IN_WORKSPACE` - List workspace teams [Optional]
2. `ASANA_GET_USERS_FOR_TEAM` - List team members [Optional]
3. `ASANA_GET_USERS_FOR_WORKSPACE` - List all workspace users [Optional]
4. `ASANA_GET_CURRENT_USER` - Get authenticated user [Optional]
5. `ASANA_GET_MULTIPLE_USERS` - Get multiple user details [Optional]
**Key parameters**:
- `workspace_gid`: Workspace GID
- `team_gid`: Team GID
**Pitfalls**:
- Users are workspace-scoped
- Team membership requires the team GID
### 4. Parallel Operations
**When to use**: User needs to perform bulk operations efficiently
**Tool sequence**:
1. `ASANA_SUBMIT_PARALLEL_REQUESTS` - Execute multiple API calls in parallel [Required]
**Key parameters**:
- `actions`: Array of action objects with method, path, and data
**Pitfalls**:
- Each action must be a valid Asana API call
- Failed individual requests do not roll back successful ones
## Common Patterns
### ID Resolution
**Workspace name -> GID**:
```
1. Call ASANA_GET_MULTIPLE_WORKSPACES
2. Find workspace by name
3. Extract gid field
```
**Project name -> GID**:
```
1. Call ASANA_GET_WORKSPACE_PROJECTS with workspace GID
2. Find project by name
3. Extract gid field
```
### Pagination
- Asana uses cursor-based pagination with `offset` parameter
- Check for `next_page` in response
- Pass `offset` from `next_page.offset` for next request
## Known Pitfalls
**GID Format**:
- All Asana IDs are strings (GIDs), not integers
- GIDs are globally unique identifiers
**Workspace Scoping**:
- Most operations require a workspace context
- Tasks, projects, and users are workspace-scoped
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List workspaces | ASANA_GET_MULTIPLE_WORKSPACES | (none) |
| Search tasks | ASANA_SEARCH_TASKS_IN_WORKSPACE | workspace, text |
| Create task | ASANA_CREATE_A_TASK | workspace, name, projects |
| Get task | ASANA_GET_A_TASK | task_gid |
| Create subtask | ASANA_CREATE_SUBTASK | parent, name |
| List subtasks | ASANA_GET_TASK_SUBTASKS | task_gid |
| Project tasks | ASANA_GET_TASKS_FROM_A_PROJECT | project_gid |
| List projects | ASANA_GET_WORKSPACE_PROJECTS | workspace |
| Create project | ASANA_CREATE_A_PROJECT | workspace, name |
| Get project | ASANA_GET_A_PROJECT | project_gid |
| Duplicate project | ASANA_DUPLICATE_PROJECT | project_gid |
| List sections | ASANA_GET_SECTIONS_IN_PROJECT | project_gid |
| Create section | ASANA_CREATE_SECTION_IN_PROJECT | project_gid, name |
| Add to section | ASANA_ADD_TASK_TO_SECTION | section, task |
| Section tasks | ASANA_GET_TASKS_FROM_A_SECTION | section_gid |
| List teams | ASANA_GET_TEAMS_IN_WORKSPACE | workspace_gid |
| Team members | ASANA_GET_USERS_FOR_TEAM | team_gid |
| Workspace users | ASANA_GET_USERS_FOR_WORKSPACE | workspace_gid |
| Current user | ASANA_GET_CURRENT_USER | (none) |
| Parallel requests | ASANA_SUBMIT_PARALLEL_REQUESTS | actions |

View File

@@ -0,0 +1,137 @@
# Changelog - audio-transcriber
All notable changes to the audio-transcriber skill will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
---
## [1.1.0] - 2026-02-03
### ✨ Added
- **Intelligent Prompt Workflow** (Step 3b) - Complete integration with prompt-engineer skill
- **Scenario A**: User-provided prompts are automatically improved with prompt-engineer
- Displays both original and improved versions side-by-side
- Single confirmation: "Usar versão melhorada? [s/n]"
- **Scenario B**: Auto-generation when no prompt provided
- Analyzes transcript and suggests document type (ata, resumo, notas)
- Shows suggestion and asks confirmation
- Generates complete structured prompt (RISEN/RODES/STAR)
- Shows preview and asks final confirmation
- Falls back to DEFAULT_MEETING_PROMPT if declined
- **LLM Integration** - Process transcripts with Claude CLI or GitHub Copilot CLI
- Priority: Claude > GitHub Copilot > None (transcript-only mode)
- Step 0b: CLI detection logic documented
- Timeout handling (5 minutes default)
- Graceful fallback if CLI unavailable
- **Progress Indicators** - Visual feedback during long operations
- `tqdm` progress bar for Whisper transcription segments
- `rich` spinner for LLM processing
- Clear status messages at each step
- **Timestamp-based File Naming** - Avoid overwriting previous transcriptions
- Format: `transcript-YYYYMMDD-HHMMSS.md`
- Format: `ata-YYYYMMDD-HHMMSS.md`
- Prevents data loss from repeated runs
- **Automatic Cleanup** - Remove temporary files after processing
- Deletes `metadata.json` and `transcription.json` automatically
- `--keep-temp` flag to preserve if needed
- Clean output directory
- **Rich Terminal UI** - Beautiful output with `rich` library
- Formatted panels for prompt previews
- Color-coded status messages (green=success, yellow=warning, red=error)
- Spinner animations for long-running tasks
- **Dual Output Support** - Generate both transcript and processed ata
- `transcript-*.md` - Raw transcription with timestamps
- `ata-*.md` - Intelligent summary/meeting minutes (if LLM available)
- User can decline LLM processing to get transcript-only
### 🔧 Changed
- **SKILL.md** - Major documentation updates
- Added Step 0b (CLI Detection)
- Updated Step 2 (Progress Indicators)
- Added Step 3b (Intelligent Prompt Workflow with 150+ lines)
- Updated version to 1.1.0
- Added detailed workflow diagrams for both scenarios
- **install-requirements.sh** - Added UI libraries
- Now installs `tqdm` and `rich` packages
- Graceful fallback if installation fails
- Updated success messages
- **Python Implementation** - Complete refactor
- Created `scripts/transcribe.py` (516 lines)
- Functions: `detect_cli_tool()`, `invoke_prompt_engineer()`, `handle_prompt_workflow()`, `process_with_llm()`, `transcribe_audio()`, `save_outputs()`, `cleanup_temp_files()`
- Command-line arguments: `--prompt`, `--model`, `--output-dir`, `--keep-temp`
- Auto-installs `rich` and `tqdm` if missing
### 🐛 Fixed
- **User prompts no longer ignored** - v1.0.0 completely ignored custom prompts
- Now processes all prompts (custom or auto-generated) with LLM
- Improves simple prompts into structured frameworks
- **Temporary files cleanup** - v1.0.0 left `metadata.json` and `transcription.json` as trash
- Now automatically removed after processing
- Clean output directory
- **File overwriting** - v1.0.0 used same filename (e.g., `meeting.md`) every time
- Now uses timestamp to prevent data loss
- Each run creates unique files
- **Missing ata/summary** - v1.0.0 only generated raw transcript
- Now generates intelligent ata/resumo using LLM
- Respects user's prompt instructions
- **No progress feedback** - v1.0.0 had silent processing (users didn't know if it froze)
- Now shows progress bar for transcription
- Shows spinner for LLM processing
- Clear status messages throughout
### 📝 Notes
- **Backward Compatibility:** Fully compatible with v1.0.0 workflows
- **Requires:** Python 3.8+, faster-whisper OR whisper, tqdm, rich
- **Optional:** Claude CLI or GitHub Copilot CLI for intelligent processing
- **Optional:** prompt-engineer skill for automatic prompt generation
### 🔗 Related Issues
- Fixes #1: Prompt do usuário RISEN ignorado
- Fixes #2: Arquivos temporários (metadata.json, transcription.json) deixados como lixo
- Fixes #3: Output incompleto (apenas transcript RAW, sem ata)
- Fixes #4: Falta de indicador de progresso visual
- Fixes #5: Formato de saída sem timestamp
---
## [1.0.0] - 2026-02-02
### ✨ Initial Release
- Audio transcription using Faster-Whisper or OpenAI Whisper
- Automatic language detection
- Speaker diarization (basic)
- Voice Activity Detection (VAD)
- Markdown output with metadata table
- Installation script for dependencies
- Example scripts for basic transcription
- Support for multiple audio formats (MP3, WAV, M4A, OGG, FLAC, WEBM)
- FFmpeg integration for format conversion
- Zero-configuration philosophy
### 📝 Known Limitations (Fixed in v1.1.0)
- User prompts ignored (no LLM integration)
- Only raw transcript generated (no ata/summary)
- Temporary files not cleaned up
- No progress indicators
- Files overwritten on repeated runs

View File

@@ -0,0 +1,340 @@
# Audio Transcriber Skill v1.1.0
Transform audio recordings into professional Markdown documentation with **intelligent atas/summaries using LLM integration** (Claude/Copilot CLI) and automatic prompt engineering.
## 🆕 What's New in v1.1.0
- **🧠 LLM Integration** - Claude CLI (primary) or GitHub Copilot CLI (fallback) for intelligent processing
- **✨ Smart Prompts** - Automatic integration with prompt-engineer skill
- User-provided prompts → automatically improved → user chooses version
- No prompt → analyzes transcript → suggests format → generates structured prompt
- **📊 Progress Indicators** - Visual progress bars (tqdm) and spinners (rich)
- **📁 Timestamp Filenames** - `transcript-YYYYMMDD-HHMMSS.md` + `ata-YYYYMMDD-HHMMSS.md`
- **🧹 Auto-Cleanup** - Removes temporary `metadata.json` and `transcription.json`
- **🎨 Rich Terminal UI** - Beautiful formatted output with panels and colors
See **[CHANGELOG.md](./CHANGELOG.md)** for complete v1.1.0 details.
## 🎯 Core Features
- **📝 Rich Markdown Output** - Structured reports with metadata tables, timestamps, and formatting
- **🎙️ Speaker Diarization** - Automatically identifies and labels different speakers
- **📊 Technical Metadata** - Extracts file size, duration, language, processing time
- **📋 Intelligent Atas/Summaries** - Generated via LLM (Claude/Copilot) with customizable prompts
- **💡 Executive Summaries** - AI-generated structured summaries with topics, decisions, action items
- **🌍 Multi-language** - Supports 99 languages with auto-detection
- **⚡ Zero Configuration** - Auto-discovers Faster-Whisper/Whisper installation
- **🔒 Privacy-First** - 100% local Whisper processing, no cloud uploads
- **🚀 Flexible Modes** - Transcript-only or intelligent processing with LLM
## 📦 Installation
### Quick Install (NPX)
```bash
npx cli-ai-skills@latest install audio-transcriber
```
This automatically:
- Downloads the skill
- Installs Python dependencies (faster-whisper, tqdm, rich)
- Installs ffmpeg (macOS via Homebrew)
- Sets up the skill globally
### Manual Installation
#### 1. Install Transcription Engine
**Recommended (fastest):**
```bash
pip install faster-whisper tqdm rich
```
**Alternative (original Whisper):**
```bash
pip install openai-whisper tqdm rich
```
#### 2. Install Audio Tools (Optional)
For format conversion support:
```bash
# macOS
brew install ffmpeg
# Linux
apt install ffmpeg
```
#### 3. Install LLM CLI (Optional - for intelligent summaries)
**Claude CLI (recommended):**
```bash
# Follow: https://docs.anthropic.com/en/docs/claude-cli
```
**GitHub Copilot CLI (alternative):**
```bash
gh extension install github/gh-copilot
```
#### 4. Install Skill
**Global installation (auto-updates with git pull):**
```bash
cd /path/to/cli-ai-skills
./scripts/install-skills.sh $(pwd)
```
**Repository only:**
```bash
# Skill is already available if you cloned the repo
```
## 🚀 Usage
### Basic Transcription
```bash
copilot> transcribe audio to markdown: meeting.mp3
```
**Output:**
- `meeting.md` - Full Markdown report with metadata, transcription, minutes, summary
### With Subtitles
```bash
copilot> convert audio file to text with subtitles: interview.wav
```
**Generates:**
- `interview.md` - Markdown report
- `interview.srt` - Subtitle file
### Batch Processing
```bash
copilot> transcreva estes áudios: recordings/*.mp3
```
**Processes all MP3 files in the directory.**
### Trigger Phrases
Activate the skill with any of these phrases:
- "transcribe audio to markdown"
- "transcreva este áudio"
- "convert audio file to text"
- "extract speech from audio"
- "áudio para texto com metadados"
## 📋 Use Cases
### 1. Team Meetings
Record standups, planning sessions, or retrospectives and automatically generate:
- Participant list
- Discussion topics with timestamps
- Decisions made
- Action items assigned
### 2. Client Calls
Transcribe client conversations with:
- Speaker identification
- Key agreements documented
- Follow-up tasks extracted
### 3. Interviews
Convert interviews to text with:
- Question/answer attribution
- Subtitle generation for video
- Searchable transcript
### 4. Lectures & Training
Document educational content with:
- Timestamped notes
- Topic breakdown
- Key concepts summary
### 5. Content Creation
Analyze podcasts, videos, YouTube content:
- Full transcription
- Chapter markers (timestamps)
- Summary for show notes
## 📊 Output Example
```markdown
# Audio Transcription Report
## 📊 Metadata
| Field | Value |
|-------|-------|
| **File Name** | team-standup.mp3 |
| **File Size** | 3.2 MB |
| **Duration** | 00:12:47 |
| **Language** | English (en) |
| **Processed Date** | 2026-02-02 14:35:21 |
| **Speakers Identified** | 5 |
| **Transcription Engine** | Faster-Whisper (model: base) |
---
## 🎙️ Full Transcription
**[00:00:12 → 00:00:45]** *Speaker 1*
Good morning everyone. Let's start with updates from the frontend team.
**[00:00:46 → 00:01:23]** *Speaker 2*
We completed the dashboard redesign and deployed to staging yesterday.
---
## 📋 Meeting Minutes
### Participants
- Speaker 1 (Meeting Lead)
- Speaker 2 (Frontend Developer)
- Speaker 3 (Backend Developer)
- Speaker 4 (Designer)
- Speaker 5 (Product Manager)
### Topics Discussed
1. **Dashboard Redesign** (00:00:46)
- Completed and deployed to staging
- Positive feedback from QA team
2. **API Performance Issues** (00:03:12)
- Database query optimization needed
- Target response time < 200ms
### Decisions Made
- ✅ Approved dashboard for production deployment
- ✅ Allocated 2 sprint points for API optimization
### Action Items
- [ ] **Deploy dashboard to production** - Assigned to: Speaker 2 - Due: 2026-02-05
- [ ] **Optimize database queries** - Assigned to: Speaker 3
- [ ] **Schedule user testing session** - Assigned to: Speaker 5
---
## 📝 Executive Summary
The team standup covered progress on the dashboard redesign, which has been successfully completed and is ready for production deployment. The frontend team received positive feedback from QA and the design aligns with user requirements.
Backend performance concerns were raised regarding API response times. The team decided to prioritize query optimization in the current sprint, with a target of sub-200ms response times.
Next steps include production deployment of the dashboard by end of week and scheduling user testing sessions to validate the new design with real users.
### Key Points
- 🔹 Dashboard redesign complete and staging-approved
- 🔹 API performance optimization prioritized
- 🔹 User testing scheduled for next week
### Next Steps
1. Production deployment (Speaker 2)
2. Database optimization (Speaker 3)
3. User testing coordination (Speaker 5)
```
## ⚙️ Configuration
No configuration needed! The skill automatically:
- Detects Faster-Whisper or Whisper installation
- Chooses the fastest available engine
- Selects appropriate model based on file size
- Auto-detects language
## 🔧 Troubleshooting
### "No transcription tool found"
**Solution:** Install Whisper:
```bash
pip install faster-whisper
```
### "Unsupported format"
**Solution:** Install ffmpeg:
```bash
brew install ffmpeg # macOS
apt install ffmpeg # Linux
```
### Slow processing
**Solution:** Use a smaller Whisper model:
```bash
# Edit the skill to use "tiny" or "base" model instead of "medium"
```
### Poor speaker identification
**Solution:**
- Ensure clear audio with minimal background noise
- Use a better microphone for recordings
- Try the "medium" or "large" Whisper model
## 🛠️ Advanced Usage
### Custom Model Selection
Edit `SKILL.md` Step 2 to change model:
```python
model = WhisperModel("small", device="cpu") # Change "base" to "small", "medium", etc.
```
### Output Language Control
Force output in specific language:
```bash
# Edit Step 3 to set language explicitly
```
### Batch Settings
Process specific file types only:
```bash
copilot> transcribe audio: recordings/*.wav # Only WAV files
```
## 📚 FAQ
**Q: Does this work offline?**
A: Yes! 100% local processing, no internet required after initial model download.
**Q: What's the difference between Whisper and Faster-Whisper?**
A: Faster-Whisper is 4-5x faster with same quality. Always prefer it if available.
**Q: Can I transcribe YouTube videos?**
A: Not directly. Use a YouTube downloader first, then transcribe the audio file. Or use the `youtube-summarizer` skill instead.
**Q: How accurate is speaker identification?**
A: Accuracy depends on audio quality. Clear recordings with distinct voices work best. Currently uses simple estimation; future versions will use advanced diarization.
**Q: What languages are supported?**
A: 99 languages including English, Portuguese, Spanish, French, German, Chinese, Japanese, Arabic, and more.
**Q: Can I edit the meeting minutes format?**
A: Yes! Edit the Markdown template in SKILL.md Step 3.
## 🔗 Related Skills
- **youtube-summarizer** - Extract and summarize YouTube video transcripts
- **prompt-engineer** - Optimize prompts for better AI summaries
## 📄 License
This skill is part of the cli-ai-skills repository.
MIT License - See repository LICENSE file.
## 🤝 Contributing
Found a bug or have a feature request?
Open an issue in the [cli-ai-skills repository](https://github.com/yourusername/cli-ai-skills).
---
**Version:** 1.0.0
**Author:** Eric Andrade
**Created:** 2026-02-02

View File

@@ -0,0 +1,558 @@
---
name: audio-transcriber
description: "Transform audio recordings into professional Markdown documentation with intelligent summaries using LLM integration"
version: 1.2.0
author: Eric Andrade
created: 2025-02-01
updated: 2026-02-04
platforms: [github-copilot-cli, claude-code, codex]
category: content
tags: [audio, transcription, whisper, meeting-minutes, speech-to-text]
risk: safe
---
## Purpose
This skill automates audio-to-text transcription with professional Markdown output, extracting rich technical metadata (speakers, timestamps, language, file size, duration) and generating structured meeting minutes and executive summaries. It uses Faster-Whisper or Whisper with zero configuration, working universally across projects without hardcoded paths or API keys.
Inspired by tools like Plaud, this skill transforms raw audio recordings into actionable documentation, making it ideal for meetings, interviews, lectures, and content analysis.
## When to Use
Invoke this skill when:
- User needs to transcribe audio/video files to text
- User wants meeting minutes automatically generated from recordings
- User requires speaker identification (diarization) in conversations
- User needs subtitles/captions (SRT, VTT formats)
- User wants executive summaries of long audio content
- User asks variations of "transcribe this audio", "convert audio to text", "generate meeting notes from recording"
- User has audio files in common formats (MP3, WAV, M4A, OGG, FLAC, WEBM)
## Workflow
### Step 0: Discovery (Auto-detect Transcription Tools)
**Objective:** Identify available transcription engines without user configuration.
**Actions:**
Run detection commands to find installed tools:
```bash
# Check for Faster-Whisper (preferred - 4-5x faster)
if python3 -c "import faster_whisper" 2>/dev/null; then
TRANSCRIBER="faster-whisper"
echo "✅ Faster-Whisper detected (optimized)"
# Fallback to original Whisper
elif python3 -c "import whisper" 2>/dev/null; then
TRANSCRIBER="whisper"
echo "✅ OpenAI Whisper detected"
else
TRANSCRIBER="none"
echo "⚠️ No transcription tool found"
fi
# Check for ffmpeg (audio format conversion)
if command -v ffmpeg &>/dev/null; then
echo "✅ ffmpeg available (format conversion enabled)"
else
echo " ffmpeg not found (limited format support)"
fi
```
**If no transcriber found:**
Offer automatic installation using the provided script:
```bash
echo "⚠️ No transcription tool found"
echo ""
echo "🔧 Auto-install dependencies? (Recommended)"
read -p "Run installation script? [Y/n]: " AUTO_INSTALL
if [[ ! "$AUTO_INSTALL" =~ ^[Nn] ]]; then
# Get skill directory (works for both repo and symlinked installations)
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Run installation script
if [[ -f "$SKILL_DIR/scripts/install-requirements.sh" ]]; then
bash "$SKILL_DIR/scripts/install-requirements.sh"
else
echo "❌ Installation script not found"
echo ""
echo "📦 Manual installation:"
echo " pip install faster-whisper # Recommended"
echo " pip install openai-whisper # Alternative"
echo " brew install ffmpeg # Optional (macOS)"
exit 1
fi
# Verify installation succeeded
if python3 -c "import faster_whisper" 2>/dev/null || python3 -c "import whisper" 2>/dev/null; then
echo "✅ Installation successful! Proceeding with transcription..."
else
echo "❌ Installation failed. Please install manually."
exit 1
fi
else
echo ""
echo "📦 Manual installation required:"
echo ""
echo "Recommended (fastest):"
echo " pip install faster-whisper"
echo ""
echo "Alternative (original):"
echo " pip install openai-whisper"
echo ""
echo "Optional (format conversion):"
echo " brew install ffmpeg # macOS"
echo " apt install ffmpeg # Linux"
echo ""
exit 1
fi
```
This ensures users can install dependencies with one confirmation, or opt for manual installation if preferred.
**If transcriber found:**
Proceed to Step 0b (CLI Detection).
### Step 1: Validate Audio File
**Objective:** Verify file exists, check format, and extract metadata.
**Actions:**
1. **Accept file path or URL** from user:
- Local file: `meeting.mp3`
- URL: `https://example.com/audio.mp3` (download to temp directory)
2. **Verify file exists:**
```bash
if [[ ! -f "$AUDIO_FILE" ]]; then
echo "❌ File not found: $AUDIO_FILE"
exit 1
fi
```
3. **Extract metadata** using ffprobe or file utilities:
```bash
# Get file size
FILE_SIZE=$(du -h "$AUDIO_FILE" | cut -f1)
# Get duration and format using ffprobe
DURATION=$(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 "$AUDIO_FILE" 2>/dev/null)
FORMAT=$(ffprobe -v error -select_streams a:0 -show_entries \
stream=codec_name -of default=noprint_wrappers=1:nokey=1 "$AUDIO_FILE" 2>/dev/null)
# Convert duration to HH:MM:SS
DURATION_HMS=$(date -u -r "$DURATION" +%H:%M:%S 2>/dev/null || echo "Unknown")
```
4. **Check file size** (warn if large for cloud APIs):
```bash
SIZE_MB=$(du -m "$AUDIO_FILE" | cut -f1)
if [[ $SIZE_MB -gt 25 ]]; then
echo "⚠️ Large file ($FILE_SIZE) - processing may take several minutes"
fi
```
5. **Validate format** (supported: MP3, WAV, M4A, OGG, FLAC, WEBM):
```bash
EXTENSION="${AUDIO_FILE##*.}"
SUPPORTED_FORMATS=("mp3" "wav" "m4a" "ogg" "flac" "webm" "mp4")
if [[ ! " ${SUPPORTED_FORMATS[@]} " =~ " ${EXTENSION,,} " ]]; then
echo "⚠️ Unsupported format: $EXTENSION"
if command -v ffmpeg &>/dev/null; then
echo "🔄 Converting to WAV..."
ffmpeg -i "$AUDIO_FILE" -ar 16000 "${AUDIO_FILE%.*}.wav" -y
AUDIO_FILE="${AUDIO_FILE%.*}.wav"
else
echo "❌ Install ffmpeg to convert formats: brew install ffmpeg"
exit 1
fi
fi
```
### Step 3: Generate Markdown Output
**Objective:** Create structured Markdown with metadata, transcription, meeting minutes, and summary.
**Output Template:**
```markdown
# Audio Transcription Report
## 📊 Metadata
| Field | Value |
|-------|-------|
| **File Name** | {filename} |
| **File Size** | {file_size} |
| **Duration** | {duration_hms} |
| **Language** | {language} ({language_code}) |
| **Processed Date** | {process_date} |
| **Speakers Identified** | {num_speakers} |
| **Transcription Engine** | {engine} (model: {model}) |
## 📋 Meeting Minutes
### Participants
- {speaker_1}
- {speaker_2}
- ...
### Topics Discussed
1. **{topic_1}** ({timestamp})
- {key_point_1}
- {key_point_2}
2. **{topic_2}** ({timestamp})
- {key_point_1}
### Decisions Made
- ✅ {decision_1}
- ✅ {decision_2}
### Action Items
- [ ] **{action_1}** - Assigned to: {speaker} - Due: {date_if_mentioned}
- [ ] **{action_2}** - Assigned to: {speaker}
*Generated by audio-transcriber skill v1.0.0*
*Transcription engine: {engine} | Processing time: {elapsed_time}s*
```
**Implementation:**
Use Python or bash with AI model (Claude/GPT) for intelligent summarization:
```python
def generate_meeting_minutes(segments):
"""Extract topics, decisions, action items from transcription."""
# Group segments by topic (simple clustering by timestamps)
topics = cluster_by_topic(segments)
# Identify action items (keywords: "should", "will", "need to", "action")
action_items = extract_action_items(segments)
# Identify decisions (keywords: "decided", "agreed", "approved")
decisions = extract_decisions(segments)
return {
"topics": topics,
"decisions": decisions,
"action_items": action_items
}
def generate_summary(segments, max_paragraphs=5):
"""Create executive summary using AI (Claude/GPT via API or local model)."""
full_text = " ".join([s["text"] for s in segments])
# Use Chain of Density approach (from prompt-engineer frameworks)
summary_prompt = f"""
Summarize the following transcription in {max_paragraphs} concise paragraphs.
Focus on key topics, decisions, and action items.
Transcription:
{full_text}
"""
# Call AI model (placeholder - user can integrate Claude API or use local model)
summary = call_ai_model(summary_prompt)
return summary
```
**Output file naming:**
```bash
# v1.1.0: Use timestamp para evitar sobrescrever
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
TRANSCRIPT_FILE="transcript-${TIMESTAMP}.md"
ATA_FILE="ata-${TIMESTAMP}.md"
echo "$TRANSCRIPT_CONTENT" > "$TRANSCRIPT_FILE"
echo "✅ Transcript salvo: $TRANSCRIPT_FILE"
if [[ -n "$ATA_CONTENT" ]]; then
echo "$ATA_CONTENT" > "$ATA_FILE"
echo "✅ Ata salva: $ATA_FILE"
fi
```
#### **SCENARIO A: User Provided Custom Prompt**
**Workflow:**
1. **Display user's prompt:**
```
📝 Prompt fornecido pelo usuário:
┌──────────────────────────────────┐
│ [User's prompt preview] │
└──────────────────────────────────┘
```
2. **Automatically improve with prompt-engineer (if available):**
```bash
🔧 Melhorando prompt com prompt-engineer...
[Invokes: gh copilot -p "melhore este prompt: {user_prompt}"]
```
3. **Show both versions:**
```
✨ Versão melhorada:
┌──────────────────────────────────┐
│ Role: Você é um documentador... │
│ Instructions: Transforme... │
│ Steps: 1) ... 2) ... │
│ End Goal: ... │
└──────────────────────────────────┘
📝 Versão original:
┌──────────────────────────────────┐
│ [User's original prompt] │
└──────────────────────────────────┘
```
4. **Ask which to use:**
```bash
💡 Usar versão melhorada? [s/n] (default: s):
```
5. **Process with selected prompt:**
- If "s": use improved
- If "n": use original
#### **LLM Processing (Both Scenarios)**
Once prompt is finalized:
```python
from rich.progress import Progress, SpinnerColumn, TextColumn
def process_with_llm(transcript, prompt, cli_tool='claude'):
full_prompt = f"{prompt}\n\n---\n\nTranscrição:\n\n{transcript}"
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
transient=True
) as progress:
progress.add_task(
description=f"🤖 Processando com {cli_tool}...",
total=None
)
if cli_tool == 'claude':
result = subprocess.run(
['claude', '-'],
input=full_prompt,
capture_output=True,
text=True,
timeout=300 # 5 minutes
)
elif cli_tool == 'gh-copilot':
result = subprocess.run(
['gh', 'copilot', 'suggest', '-t', 'shell', full_prompt],
capture_output=True,
text=True,
timeout=300
)
if result.returncode == 0:
return result.stdout.strip()
else:
return None
```
**Progress output:**
```
🤖 Processando com claude... ⠋
[After completion:]
✅ Ata gerada com sucesso!
```
#### **Final Output**
**Success (both files):**
```bash
💾 Salvando arquivos...
✅ Arquivos criados:
- transcript-20260203-023045.md (transcript puro)
- ata-20260203-023045.md (processado com LLM)
🧹 Removidos arquivos temporários: metadata.json, transcription.json
✅ Concluído! Tempo total: 3m 45s
```
**Transcript only (user declined LLM):**
```bash
💾 Salvando arquivos...
✅ Arquivo criado:
- transcript-20260203-023045.md
Ata não gerada (processamento LLM recusado pelo usuário)
🧹 Removidos arquivos temporários: metadata.json, transcription.json
✅ Concluído!
```
### Step 5: Display Results Summary
**Objective:** Show completion status and next steps.
**Output:**
```bash
echo ""
echo "✅ Transcription Complete!"
echo ""
echo "📊 Results:"
echo " File: $OUTPUT_FILE"
echo " Language: $LANGUAGE"
echo " Duration: $DURATION_HMS"
echo " Speakers: $NUM_SPEAKERS"
echo " Words: $WORD_COUNT"
echo " Processing time: ${ELAPSED_TIME}s"
echo ""
echo "📝 Generated:"
echo " - $OUTPUT_FILE (Markdown report)"
[if alternative formats:]
echo " - ${OUTPUT_FILE%.*}.srt (Subtitles)"
echo " - ${OUTPUT_FILE%.*}.json (Structured data)"
echo ""
echo "🎯 Next steps:"
echo " 1. Review meeting minutes and action items"
echo " 2. Share report with participants"
echo " 3. Track action items to completion"
```
## Example Usage
### **Example 1: Basic Transcription**
**User Input:**
```bash
copilot> transcribe audio to markdown: meeting-2026-02-02.mp3
```
**Skill Output:**
```bash
✅ Faster-Whisper detected (optimized)
✅ ffmpeg available (format conversion enabled)
📂 File: meeting-2026-02-02.mp3
📊 Size: 12.3 MB
⏱️ Duration: 00:45:32
🎙️ Processing...
[████████████████████] 100%
✅ Language detected: Portuguese (pt-BR)
👥 Speakers identified: 4
📝 Generating Markdown output...
✅ Transcription Complete!
📊 Results:
File: meeting-2026-02-02.md
Language: pt-BR
Duration: 00:45:32
Speakers: 4
Words: 6,842
Processing time: 127s
📝 Generated:
- meeting-2026-02-02.md (Markdown report)
🎯 Next steps:
1. Review meeting minutes and action items
2. Share report with participants
3. Track action items to completion
```
### **Example 3: Batch Processing**
**User Input:**
```bash
copilot> transcreva estes áudios: recordings/*.mp3
```
**Skill Output:**
```bash
📦 Batch mode: 5 files found
1. team-standup.mp3
2. client-call.mp3
3. brainstorm-session.mp3
4. product-demo.mp3
5. retrospective.mp3
🎙️ Processing batch...
[1/5] team-standup.mp3 ✅ (2m 34s)
[2/5] client-call.mp3 ✅ (15m 12s)
[3/5] brainstorm-session.mp3 ✅ (8m 47s)
[4/5] product-demo.mp3 ✅ (22m 03s)
[5/5] retrospective.mp3 ✅ (11m 28s)
✅ Batch Complete!
📝 Generated 5 Markdown reports
⏱️ Total processing time: 6m 15s
```
### **Example 5: Large File Warning**
**User Input:**
```bash
copilot> transcribe audio to markdown: conference-keynote.mp3
```
**Skill Output:**
```bash
✅ Faster-Whisper detected (optimized)
📂 File: conference-keynote.mp3
📊 Size: 87.2 MB
⏱️ Duration: 02:15:47
⚠️ Large file (87.2 MB) - processing may take several minutes
Continue? [Y/n]:
```
**User:** `Y`
```bash
🎙️ Processing... (this may take 10-15 minutes)
[████░░░░░░░░░░░░░░░░] 20% - Estimated time remaining: 12m
```
This skill is **platform-agnostic** and works in any terminal context where GitHub Copilot CLI is available. It does not depend on specific project configurations or external APIs, following the zero-configuration philosophy.

View File

@@ -0,0 +1,250 @@
#!/usr/bin/env bash
# Basic Audio Transcription Example
# Demonstrates how to use the audio-transcriber skill manually
set -euo pipefail
# Configuration
AUDIO_FILE="${1:-}"
MODEL="${MODEL:-base}" # Options: tiny, base, small, medium, large
OUTPUT_FORMAT="${OUTPUT_FORMAT:-markdown}" # Options: markdown, txt, srt, vtt, json
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
error() {
echo -e "${RED}❌ Error: $1${NC}" >&2
exit 1
}
success() {
echo -e "${GREEN}$1${NC}"
}
info() {
echo -e "${BLUE} $1${NC}"
}
warn() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
# Check if audio file is provided
if [[ -z "$AUDIO_FILE" ]]; then
error "Usage: $0 <audio_file>"
fi
# Verify file exists
if [[ ! -f "$AUDIO_FILE" ]]; then
error "File not found: $AUDIO_FILE"
fi
# Step 0: Discovery - Check for transcription tools
info "Step 0: Discovering transcription tools..."
TRANSCRIBER=""
if python3 -c "import faster_whisper" 2>/dev/null; then
TRANSCRIBER="faster-whisper"
success "Faster-Whisper detected (optimized)"
elif python3 -c "import whisper" 2>/dev/null; then
TRANSCRIBER="whisper"
success "OpenAI Whisper detected"
else
error "No transcription tool found. Install with: pip install faster-whisper"
fi
# Check for ffmpeg
if command -v ffmpeg &>/dev/null; then
success "ffmpeg available (format conversion enabled)"
else
warn "ffmpeg not found (limited format support)"
fi
# Step 1: Extract metadata
info "Step 1: Extracting audio metadata..."
FILE_SIZE=$(du -h "$AUDIO_FILE" | cut -f1)
info "File size: $FILE_SIZE"
# Get duration if ffprobe is available
if command -v ffprobe &>/dev/null; then
DURATION=$(ffprobe -v error -show_entries format=duration \
-of default=noprint_wrappers=1:nokey=1 "$AUDIO_FILE" 2>/dev/null || echo "0")
# Convert to HH:MM:SS
if command -v date &>/dev/null; then
if [[ "$OSTYPE" == "darwin"* ]]; then
# macOS
DURATION_HMS=$(date -u -r "${DURATION%.*}" +%H:%M:%S 2>/dev/null || echo "Unknown")
else
# Linux
DURATION_HMS=$(date -u -d @"${DURATION%.*}" +%H:%M:%S 2>/dev/null || echo "Unknown")
fi
else
DURATION_HMS="Unknown"
fi
info "Duration: $DURATION_HMS"
else
warn "ffprobe not found - cannot extract duration"
DURATION="0"
DURATION_HMS="Unknown"
fi
# Check file size warning
SIZE_MB=$(du -m "$AUDIO_FILE" | cut -f1)
if [[ $SIZE_MB -gt 25 ]]; then
warn "Large file ($FILE_SIZE) - processing may take several minutes"
read -p "Continue? [Y/n]: " CONTINUE
if [[ "$CONTINUE" =~ ^[Nn] ]]; then
info "Transcription cancelled"
exit 0
fi
fi
# Step 2: Transcribe using Python
info "Step 2: Transcribing audio..."
OUTPUT_FILE="${AUDIO_FILE%.*}.md"
TEMP_JSON="/tmp/transcription_$$.json"
python3 << EOF
import sys
import json
from datetime import datetime
try:
if "$TRANSCRIBER" == "faster-whisper":
from faster_whisper import WhisperModel
model = WhisperModel("$MODEL", device="cpu", compute_type="int8")
segments, info = model.transcribe("$AUDIO_FILE", language=None, vad_filter=True)
data = {
"language": info.language,
"language_probability": round(info.language_probability, 2),
"duration": info.duration,
"segments": []
}
for segment in segments:
data["segments"].append({
"start": round(segment.start, 2),
"end": round(segment.end, 2),
"text": segment.text.strip()
})
else:
import whisper
model = whisper.load_model("$MODEL")
result = model.transcribe("$AUDIO_FILE")
data = {
"language": result["language"],
"duration": result["segments"][-1]["end"] if result["segments"] else 0,
"segments": result["segments"]
}
with open("$TEMP_JSON", "w") as f:
json.dump(data, f)
print(f"✅ Language detected: {data['language']}")
print(f"📝 Transcribed {len(data['segments'])} segments")
except Exception as e:
print(f"❌ Error: {e}", file=sys.stderr)
sys.exit(1)
EOF
# Check if transcription succeeded
if [[ ! -f "$TEMP_JSON" ]]; then
error "Transcription failed"
fi
# Step 3: Generate Markdown output
info "Step 3: Generating Markdown report..."
python3 << 'EOF'
import json
import sys
from datetime import datetime
# Load transcription data
with open("${TEMP_JSON}") as f:
data = json.load(f)
# Prepare metadata
filename = "${AUDIO_FILE}".split("/")[-1]
file_size = "${FILE_SIZE}"
duration_hms = "${DURATION_HMS}"
language = data["language"]
process_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
num_segments = len(data["segments"])
# Generate Markdown
markdown = f"""# Audio Transcription Report
## 📊 Metadata
| Field | Value |
|-------|-------|
| **File Name** | {filename} |
| **File Size** | {file_size} |
| **Duration** | {duration_hms} |
| **Language** | {language.upper()} |
| **Processed Date** | {process_date} |
| **Segments** | {num_segments} |
| **Transcription Engine** | ${TRANSCRIBER} (model: ${MODEL}) |
---
## 🎙️ Full Transcription
"""
# Add transcription with timestamps
for seg in data["segments"]:
start_time = f"{int(seg['start'] // 60):02d}:{int(seg['start'] % 60):02d}"
end_time = f"{int(seg['end'] // 60):02d}:{int(seg['end'] % 60):02d}"
markdown += f"**[{start_time} → {end_time}]** \n{seg['text']}\n\n"
markdown += """---
## 📝 Summary
*Automatic summary generation requires AI integration (Claude/GPT).*
*For now, review the full transcription above.*
---
*Generated by audio-transcriber skill example script*
*Transcription engine: ${TRANSCRIBER} | Model: ${MODEL}*
"""
# Write to file
with open("${OUTPUT_FILE}", "w") as f:
f.write(markdown)
print(f"✅ Markdown report saved: ${OUTPUT_FILE}")
EOF
# Clean up
rm -f "$TEMP_JSON"
# Step 4: Display summary
success "Transcription complete!"
echo ""
echo "📊 Results:"
echo " Output file: $OUTPUT_FILE"
echo " Transcription engine: $TRANSCRIBER"
echo " Model: $MODEL"
echo ""
info "Next steps:"
echo " 1. Review the transcription: cat $OUTPUT_FILE"
echo " 2. Edit if needed: vim $OUTPUT_FILE"
echo " 3. Share with team or archive"
EOF

View File

@@ -0,0 +1,352 @@
# Transcription Tools Comparison
Comprehensive comparison of audio transcription engines supported by the audio-transcriber skill.
## Overview
| Tool | Type | Speed | Quality | Cost | Privacy | Offline | Languages |
|------|------|-------|---------|------|---------|---------|-----------|
| **Faster-Whisper** | Open-source | ⚡⚡⚡⚡⚡ | ⭐⭐⭐⭐⭐ | Free | 100% | ✅ | 99 |
| **Whisper** | Open-source | ⚡⚡⚡ | ⭐⭐⭐⭐⭐ | Free | 100% | ✅ | 99 |
| Google Speech-to-Text | Commercial API | ⚡⚡⚡⚡ | ⭐⭐⭐⭐⭐ | $0.006/15s | Partial | ❌ | 125+ |
| Azure Speech | Commercial API | ⚡⚡⚡⚡ | ⭐⭐⭐⭐ | $1/hour | Partial | ❌ | 100+ |
| AssemblyAI | Commercial API | ⚡⚡⚡⚡ | ⭐⭐⭐⭐⭐ | $0.00025/s | Partial | ❌ | 99 |
---
## Faster-Whisper (Recommended)
### Pros
**4-5x faster** than original Whisper
**Same quality** as original Whisper
**Lower memory usage** (50-60% less RAM)
**Free and open-source**
**100% offline** (privacy guaranteed)
**Easy installation** (`pip install faster-whisper`)
**Drop-in replacement** for Whisper
### Cons
❌ Requires Python 3.8+
❌ Initial model download (~100MB-1.5GB)
❌ GPU optional but speeds up significantly
### Installation
```bash
pip install faster-whisper
```
### Usage Example
```python
from faster_whisper import WhisperModel
# Load model (auto-downloads on first run)
model = WhisperModel("base", device="cpu", compute_type="int8")
# Transcribe
segments, info = model.transcribe("audio.mp3", language="pt")
# Print results
for segment in segments:
print(f"[{segment.start:.2f}s -> {segment.end:.2f}s] {segment.text}")
```
### Model Sizes
| Model | Size | RAM | Speed (CPU) | Quality |
|-------|------|-----|-------------|---------|
| `tiny` | 39 MB | ~1 GB | Very fast (~10x realtime) | Basic |
| `base` | 74 MB | ~1 GB | Fast (~7x realtime) | Good |
| `small` | 244 MB | ~2 GB | Moderate (~4x realtime) | Very good |
| `medium` | 769 MB | ~5 GB | Slow (~2x realtime) | Excellent |
| `large` | 1550 MB | ~10 GB | Very slow (~1x realtime) | Best |
**Recommendation:** `small` or `medium` for production use.
---
## Whisper (Original)
### Pros
**Official OpenAI model**
**Excellent quality**
**Free and open-source**
**100% offline**
**Well-documented**
**Large community**
### Cons
**Slower** than Faster-Whisper (4-5x)
**Higher memory usage**
❌ Requires PyTorch (large dependency)
❌ GPU highly recommended for larger models
### Installation
```bash
pip install openai-whisper
```
### Usage Example
```python
import whisper
# Load model
model = whisper.load_model("base")
# Transcribe
result = model.transcribe("audio.mp3", language="pt")
# Print results
print(result["text"])
```
### When to Use Whisper vs. Faster-Whisper
**Use Faster-Whisper if:**
- Speed is important
- Limited RAM available
- Processing many files
**Use Original Whisper if:**
- Faster-Whisper installation issues
- Need exact OpenAI implementation
- Already have Whisper in project dependencies
---
## Google Cloud Speech-to-Text
### Pros
**Very accurate** (industry-leading)
**Fast processing** (cloud infrastructure)
**125+ languages**
**Word-level timestamps**
**Punctuation & capitalization**
**Speaker diarization** (premium)
### Cons
**Requires internet** (cloud-only)
**Costs money** (after free tier)
**Privacy concerns** (audio uploaded to Google)
❌ Requires GCP account setup
❌ Complex authentication
### Pricing
- **Free tier:** 60 minutes/month
- **Standard:** $0.006 per 15 seconds ($1.44/hour)
- **Premium:** $0.009 per 15 seconds (with diarization)
### Installation
```bash
pip install google-cloud-speech
```
### Setup
1. Create GCP project
2. Enable Speech-to-Text API
3. Create service account & download JSON key
4. Set environment variable:
```bash
export GOOGLE_APPLICATION_CREDENTIALS="path/to/key.json"
```
### Usage Example
```python
from google.cloud import speech
client = speech.SpeechClient()
with open("audio.wav", "rb") as audio_file:
content = audio_file.read()
audio = speech.RecognitionAudio(content=content)
config = speech.RecognitionConfig(
encoding=speech.RecognitionConfig.AudioEncoding.LINEAR16,
sample_rate_hertz=16000,
language_code="pt-BR",
)
response = client.recognize(config=config, audio=audio)
for result in response.results:
print(result.alternatives[0].transcript)
```
---
## Azure Speech Services
### Pros
✅ **High accuracy**
✅ **100+ languages**
✅ **Real-time transcription**
✅ **Custom models** (train on your data)
✅ **Good Microsoft ecosystem integration**
### Cons
❌ **Requires internet**
❌ **Costs money** (after free tier)
❌ **Privacy concerns** (cloud processing)
❌ Requires Azure account
❌ Complex setup
### Pricing
- **Free tier:** 5 hours/month
- **Standard:** $1.00 per audio hour
### Installation
```bash
pip install azure-cognitiveservices-speech
```
### Setup
1. Create Azure account
2. Create Speech resource
3. Get API key and region
4. Set environment variables:
```bash
export AZURE_SPEECH_KEY="your-key"
export AZURE_SPEECH_REGION="your-region"
```
### Usage Example
```python
import azure.cognitiveservices.speech as speechsdk
speech_config = speechsdk.SpeechConfig(
subscription=os.environ.get('AZURE_SPEECH_KEY'),
region=os.environ.get('AZURE_SPEECH_REGION')
)
audio_config = speechsdk.audio.AudioConfig(filename="audio.wav")
speech_recognizer = speechsdk.SpeechRecognizer(
speech_config=speech_config,
audio_config=audio_config
)
result = speech_recognizer.recognize_once()
print(result.text)
```
---
## AssemblyAI
### Pros
✅ **Modern, developer-friendly API**
✅ **Excellent accuracy**
✅ **Advanced features** (sentiment, topic detection, PII redaction)
✅ **Speaker diarization** (included)
✅ **Fast processing**
✅ **Good documentation**
### Cons
❌ **Requires internet**
❌ **Costs money** (no free tier, only trial credits)
❌ **Privacy concerns** (cloud processing)
❌ Requires API key
### Pricing
- **Free trial:** $50 credits
- **Standard:** $0.00025 per second (~$0.90/hour)
### Installation
```bash
pip install assemblyai
```
### Setup
1. Sign up at assemblyai.com
2. Get API key
3. Set environment variable:
```bash
export ASSEMBLYAI_API_KEY="your-key"
```
### Usage Example
```python
import assemblyai as aai
aai.settings.api_key = os.environ["ASSEMBLYAI_API_KEY"]
transcriber = aai.Transcriber()
transcript = transcriber.transcribe("audio.mp3")
print(transcript.text)
# Speaker diarization
for utterance in transcript.utterances:
print(f"Speaker {utterance.speaker}: {utterance.text}")
```
---
## Recommendation Matrix
### Use Faster-Whisper if:
- ✅ Privacy is critical (local processing)
- ✅ Want zero cost (free forever)
- ✅ Need offline capability
- ✅ Processing many files (speed matters)
- ✅ Limited budget
### Use Google Speech-to-Text if:
- ✅ Need absolute best accuracy
- ✅ Have budget for cloud services
- ✅ Want advanced features (punctuation, diarization)
- ✅ Already using GCP ecosystem
### Use Azure Speech if:
- ✅ In Microsoft ecosystem
- ✅ Need custom model training
- ✅ Want real-time transcription
- ✅ Have Azure credits
### Use AssemblyAI if:
- ✅ Need advanced features (sentiment, topics)
- ✅ Want easiest API experience
- ✅ Need automatic PII redaction
- ✅ Value developer experience
---
## Performance Benchmarks
**Test:** 1-hour podcast (MP3, 44.1kHz, stereo)
| Tool | Processing Time | Accuracy | Cost |
|------|----------------|----------|------|
| Faster-Whisper (small) | 8 min | 94% | $0 |
| Whisper (small) | 32 min | 94% | $0 |
| Google Speech | 2 min | 96% | $1.44 |
| Azure Speech | 3 min | 95% | $1.00 |
| AssemblyAI | 4 min | 96% | $0.90 |
*Benchmarks run on MacBook Pro M1, 16GB RAM*
---
## Conclusion
**For the audio-transcriber skill:**
1. **Primary:** Faster-Whisper (best balance of speed, quality, privacy, cost)
2. **Fallback:** Whisper (if Faster-Whisper unavailable)
3. **Optional:** Cloud APIs (user choice for premium features)
This ensures the skill works out-of-the-box for most users while allowing advanced users to integrate commercial services if needed.

View File

@@ -0,0 +1,190 @@
#!/usr/bin/env bash
# Audio Transcriber - Requirements Installation Script
# Automatically installs and validates dependencies
set -euo pipefail
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}🔧 Audio Transcriber - Dependency Installation${NC}"
echo ""
# Check Python
if ! command -v python3 &>/dev/null; then
echo -e "${RED}❌ Python 3 not found. Please install Python 3.8+${NC}"
exit 1
fi
PYTHON_VERSION=$(python3 --version | cut -d' ' -f2 | cut -d'.' -f1,2)
echo -e "${GREEN}✅ Python ${PYTHON_VERSION} detected${NC}"
# Check pip
if ! python3 -m pip --version &>/dev/null; then
echo -e "${RED}❌ pip not found. Please install pip${NC}"
exit 1
fi
echo -e "${GREEN}✅ pip available${NC}"
echo ""
# Install system dependencies (macOS only)
if [[ "$OSTYPE" == "darwin"* ]]; then
echo -e "${BLUE}📦 Checking system dependencies (macOS)...${NC}"
# Check for Homebrew
if command -v brew &>/dev/null; then
# Install pkg-config and ffmpeg if not present
NEED_INSTALL=""
if ! brew list pkg-config &>/dev/null 2>&1; then
NEED_INSTALL="$NEED_INSTALL pkg-config"
fi
if ! brew list ffmpeg &>/dev/null 2>&1; then
NEED_INSTALL="$NEED_INSTALL ffmpeg"
fi
if [[ -n "$NEED_INSTALL" ]]; then
echo -e "${BLUE}Installing:$NEED_INSTALL${NC}"
brew install $NEED_INSTALL --quiet
echo -e "${GREEN}✅ System dependencies installed${NC}"
else
echo -e "${GREEN}✅ System dependencies already installed${NC}"
fi
else
echo -e "${YELLOW}⚠️ Homebrew not found. Install manually if needed:${NC}"
echo " /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\""
fi
fi
echo ""
# Install faster-whisper (recommended)
echo -e "${BLUE}📦 Installing Faster-Whisper...${NC}"
# Try different installation methods based on Python environment
if python3 -m pip install faster-whisper --quiet 2>/dev/null; then
echo -e "${GREEN}✅ Faster-Whisper installed successfully${NC}"
elif python3 -m pip install --user --break-system-packages faster-whisper --quiet 2>/dev/null; then
echo -e "${GREEN}✅ Faster-Whisper installed successfully (user mode)${NC}"
else
echo -e "${YELLOW}⚠️ Faster-Whisper installation failed, trying Whisper...${NC}"
if python3 -m pip install openai-whisper --quiet 2>/dev/null; then
echo -e "${GREEN}✅ Whisper installed successfully${NC}"
elif python3 -m pip install --user --break-system-packages openai-whisper --quiet 2>/dev/null; then
echo -e "${GREEN}✅ Whisper installed successfully (user mode)${NC}"
else
echo -e "${RED}❌ Failed to install transcription engine${NC}"
echo ""
echo -e "${YELLOW}Manual installation options:${NC}"
echo " 1. Use --break-system-packages (macOS/Homebrew Python):"
echo " python3 -m pip install --user --break-system-packages openai-whisper"
echo ""
echo " 2. Use virtual environment (recommended):"
echo " python3 -m venv ~/whisper-env"
echo " source ~/whisper-env/bin/activate"
echo " pip install faster-whisper"
echo ""
echo " 3. Use pipx (isolated):"
echo " brew install pipx"
echo " pipx install openai-whisper"
exit 1
fi
fi
# Install UI/progress libraries (tqdm, rich)
echo ""
echo -e "${BLUE}📦 Installing UI libraries (tqdm, rich)...${NC}"
if python3 -m pip install tqdm rich --quiet 2>/dev/null; then
echo -e "${GREEN}✅ tqdm and rich installed successfully${NC}"
elif python3 -m pip install --user --break-system-packages tqdm rich --quiet 2>/dev/null; then
echo -e "${GREEN}✅ tqdm and rich installed successfully (user mode)${NC}"
else
echo -e "${YELLOW}⚠️ Optional UI libraries not installed (skill will still work)${NC}"
fi
# Check ffmpeg (optional but recommended)
echo ""
if command -v ffmpeg &>/dev/null; then
echo -e "${GREEN}✅ ffmpeg already installed${NC}"
else
echo -e "${YELLOW}⚠️ ffmpeg not found (should have been installed earlier)${NC}"
if [[ "$OSTYPE" == "darwin"* ]] && command -v brew &>/dev/null; then
echo -e "${BLUE}Installing ffmpeg via Homebrew...${NC}"
brew install ffmpeg --quiet && echo -e "${GREEN}✅ ffmpeg installed${NC}"
else
echo -e "${BLUE} ffmpeg is optional but recommended for format conversion${NC}"
echo ""
echo "Install ffmpeg:"
if [[ "$OSTYPE" == "darwin"* ]]; then
echo " brew install ffmpeg"
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo " sudo apt install ffmpeg # Debian/Ubuntu"
echo " sudo yum install ffmpeg # CentOS/RHEL"
fi
fi
fi
# Verify installation
echo ""
echo -e "${BLUE}🔍 Verifying installation...${NC}"
if python3 -c "import faster_whisper" 2>/dev/null; then
echo -e "${GREEN}✅ Faster-Whisper verified${NC}"
TRANSCRIBER="Faster-Whisper"
elif python3 -c "import whisper" 2>/dev/null; then
echo -e "${GREEN}✅ Whisper verified${NC}"
TRANSCRIBER="Whisper"
else
echo -e "${RED}❌ No transcription engine found after installation${NC}"
exit 1
fi
# Download initial model (optional)
read -p "Download Whisper 'base' model now? (recommended, ~74MB) [Y/n]: " DOWNLOAD_MODEL
if [[ ! "$DOWNLOAD_MODEL" =~ ^[Nn] ]]; then
echo ""
echo -e "${BLUE}📥 Downloading 'base' model...${NC}"
python3 << 'EOF'
try:
import faster_whisper
model = faster_whisper.WhisperModel("base", device="cpu", compute_type="int8")
print("✅ Model downloaded successfully")
except:
try:
import whisper
model = whisper.load_model("base")
print("✅ Model downloaded successfully")
except Exception as e:
print(f"❌ Model download failed: {e}")
EOF
fi
# Success summary
echo ""
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}✅ Installation Complete!${NC}"
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo "📊 Installed components:"
echo " • Transcription engine: $TRANSCRIBER"
if command -v ffmpeg &>/dev/null; then
echo " • Format conversion: ffmpeg (available)"
else
echo " • Format conversion: ffmpeg (not installed)"
fi
echo ""
echo "🚀 Ready to use! Try:"
echo " copilot> transcribe audio to markdown: myfile.mp3"
echo " claude> transcreva este áudio: myfile.mp3"
echo ""

View File

@@ -0,0 +1,486 @@
#!/usr/bin/env python3
"""
Audio Transcriber v1.1.0
Transcreve áudio para texto e gera atas/resumos usando LLM.
"""
import os
import sys
import json
import subprocess
import shutil
from datetime import datetime
from pathlib import Path
# Rich for beautiful terminal output
try:
from rich.console import Console
from rich.prompt import Prompt
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
from rich import print as rprint
RICH_AVAILABLE = True
except ImportError:
RICH_AVAILABLE = False
print("⚠️ Installing rich for better UI...")
subprocess.run([sys.executable, "-m", "pip", "install", "--user", "rich"], check=False)
from rich.console import Console
from rich.prompt import Prompt
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn, BarColumn
from rich import print as rprint
# tqdm for progress bars
try:
from tqdm import tqdm
except ImportError:
print("⚠️ Installing tqdm for progress bars...")
subprocess.run([sys.executable, "-m", "pip", "install", "--user", "tqdm"], check=False)
from tqdm import tqdm
# Whisper engines
try:
from faster_whisper import WhisperModel
TRANSCRIBER = "faster-whisper"
except ImportError:
try:
import whisper
TRANSCRIBER = "whisper"
except ImportError:
print("❌ Nenhum engine de transcrição encontrado!")
print(" Instale: pip install faster-whisper")
sys.exit(1)
console = Console()
# Template padrão RISEN para fallback
DEFAULT_MEETING_PROMPT = """
Role: Você é um transcritor profissional especializado em documentação.
Instructions: Transforme a transcrição fornecida em um documento estruturado e profissional.
Steps:
1. Identifique o tipo de conteúdo (reunião, palestra, entrevista, etc.)
2. Extraia os principais tópicos e pontos-chave
3. Identifique participantes/speakers (se aplicável)
4. Extraia decisões tomadas e ações definidas (se reunião)
5. Organize em formato apropriado com seções claras
6. Use Markdown para formatação profissional
End Goal: Documento final bem estruturado, legível e pronto para distribuição.
Narrowing:
- Mantenha objetividade e clareza
- Preserve contexto importante
- Use formatação Markdown adequada
- Inclua timestamps relevantes quando aplicável
"""
def detect_cli_tool():
"""Detecta qual CLI de LLM está disponível (claude > gh copilot)."""
if shutil.which('claude'):
return 'claude'
elif shutil.which('gh'):
result = subprocess.run(['gh', 'copilot', '--version'],
capture_output=True, text=True)
if result.returncode == 0:
return 'gh-copilot'
return None
def invoke_prompt_engineer(raw_prompt, timeout=90):
"""
Invoca prompt-engineer skill via CLI para melhorar/gerar prompts.
Args:
raw_prompt: Prompt a ser melhorado ou meta-prompt
timeout: Timeout em segundos
Returns:
str: Prompt melhorado ou DEFAULT_MEETING_PROMPT se falhar
"""
try:
# Tentar via gh copilot
console.print("[dim] Invocando prompt-engineer...[/dim]")
result = subprocess.run(
['gh', 'copilot', 'suggest', '-t', 'shell', raw_prompt],
capture_output=True,
text=True,
timeout=timeout
)
if result.returncode == 0 and result.stdout.strip():
return result.stdout.strip()
else:
console.print("[yellow]⚠️ prompt-engineer não respondeu, usando template padrão[/yellow]")
return DEFAULT_MEETING_PROMPT
except subprocess.TimeoutExpired:
console.print(f"[red]⚠️ Timeout após {timeout}s, usando template padrão[/red]")
return DEFAULT_MEETING_PROMPT
except Exception as e:
console.print(f"[red]⚠️ Erro ao invocar prompt-engineer: {e}[/red]")
return DEFAULT_MEETING_PROMPT
def handle_prompt_workflow(user_prompt, transcript):
"""
Gerencia fluxo completo de prompts com prompt-engineer.
Cenário A: Usuário forneceu prompt → Melhorar AUTOMATICAMENTE → Confirmar
Cenário B: Sem prompt → Sugerir tipo → Confirmar → Gerar → Confirmar
Returns:
str: Prompt final a usar, ou None se usuário recusou processamento
"""
prompt_engineer_available = os.path.exists(
os.path.expanduser('~/.copilot/skills/prompt-engineer/SKILL.md')
)
# ========== CENÁRIO A: USUÁRIO FORNECEU PROMPT ==========
if user_prompt:
console.print("\n[cyan]📝 Prompt fornecido pelo usuário[/cyan]")
console.print(Panel(user_prompt[:300] + ("..." if len(user_prompt) > 300 else ""),
title="Prompt original", border_style="dim"))
if prompt_engineer_available:
# Melhora AUTOMATICAMENTE (sem perguntar)
console.print("\n[cyan]🔧 Melhorando prompt com prompt-engineer...[/cyan]")
improved_prompt = invoke_prompt_engineer(
f"melhore este prompt:\n\n{user_prompt}"
)
# Mostrar AMBAS versões
console.print("\n[green]✨ Versão melhorada:[/green]")
console.print(Panel(improved_prompt[:500] + ("..." if len(improved_prompt) > 500 else ""),
title="Prompt otimizado", border_style="green"))
console.print("\n[dim]📝 Versão original:[/dim]")
console.print(Panel(user_prompt[:300] + ("..." if len(user_prompt) > 300 else ""),
title="Seu prompt", border_style="dim"))
# Pergunta qual usar
confirm = Prompt.ask(
"\n💡 Usar versão melhorada?",
choices=["s", "n"],
default="s"
)
return improved_prompt if confirm == "s" else user_prompt
else:
# prompt-engineer não disponível
console.print("[yellow]⚠️ prompt-engineer skill não disponível[/yellow]")
console.print("[dim]✅ Usando seu prompt original[/dim]")
return user_prompt
# ========== CENÁRIO B: SEM PROMPT - AUTO-GERAÇÃO ==========
else:
console.print("\n[yellow]⚠️ Nenhum prompt fornecido.[/yellow]")
if not prompt_engineer_available:
console.print("[yellow]⚠️ prompt-engineer skill não encontrado[/yellow]")
console.print("[dim]Usando template padrão...[/dim]")
return DEFAULT_MEETING_PROMPT
# PASSO 1: Perguntar se quer auto-gerar
console.print("Posso analisar o transcript e sugerir um formato de resumo/ata?")
generate = Prompt.ask(
"\n💡 Gerar prompt automaticamente?",
choices=["s", "n"],
default="s"
)
if generate == "n":
console.print("[dim]✅ Ok, gerando apenas transcript.md (sem ata)[/dim]")
return None # Sinaliza: não processar com LLM
# PASSO 2: Analisar transcript e SUGERIR tipo
console.print("\n[cyan]🔍 Analisando transcript...[/cyan]")
suggestion_meta_prompt = f"""
Analise este transcript ({len(transcript)} caracteres) e sugira:
1. Tipo de conteúdo (reunião, palestra, entrevista, etc.)
2. Formato de saída recomendado (ata formal, resumo executivo, notas estruturadas)
3. Framework ideal (RISEN, RODES, STAR, etc.)
Primeiras 1000 palavras do transcript:
{transcript[:4000]}
Responda em 2-3 linhas concisas.
"""
suggested_type = invoke_prompt_engineer(suggestion_meta_prompt)
# PASSO 3: Mostrar sugestão e CONFIRMAR
console.print("\n[green]💡 Sugestão de formato:[/green]")
console.print(Panel(suggested_type, title="Análise do transcript", border_style="green"))
confirm_type = Prompt.ask(
"\n💡 Usar este formato?",
choices=["s", "n"],
default="s"
)
if confirm_type == "n":
console.print("[dim]Usando template padrão...[/dim]")
return DEFAULT_MEETING_PROMPT
# PASSO 4: Gerar prompt completo baseado na sugestão
console.print("\n[cyan]✨ Gerando prompt estruturado...[/cyan]")
final_meta_prompt = f"""
Crie um prompt completo e estruturado (usando framework apropriado) para:
{suggested_type}
O prompt deve instruir uma IA a transformar o transcript em um documento
profissional e bem formatado em Markdown.
"""
generated_prompt = invoke_prompt_engineer(final_meta_prompt)
# PASSO 5: Mostrar prompt gerado e CONFIRMAR
console.print("\n[green]✅ Prompt gerado:[/green]")
console.print(Panel(generated_prompt[:600] + ("..." if len(generated_prompt) > 600 else ""),
title="Preview", border_style="green"))
confirm_final = Prompt.ask(
"\n💡 Usar este prompt?",
choices=["s", "n"],
default="s"
)
if confirm_final == "s":
return generated_prompt
else:
console.print("[dim]Usando template padrão...[/dim]")
return DEFAULT_MEETING_PROMPT
def process_with_llm(transcript, prompt, cli_tool='claude', timeout=300):
"""
Processa transcript com LLM usando prompt fornecido.
Args:
transcript: Texto transcrito
prompt: Prompt instruindo como processar
cli_tool: 'claude' ou 'gh-copilot'
timeout: Timeout em segundos
Returns:
str: Ata/resumo processado
"""
full_prompt = f"{prompt}\n\n---\n\nTranscrição:\n\n{transcript}"
try:
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
transient=True
) as progress:
progress.add_task(description=f"🤖 Processando com {cli_tool}...", total=None)
if cli_tool == 'claude':
result = subprocess.run(
['claude', '-'],
input=full_prompt,
capture_output=True,
text=True,
timeout=timeout
)
elif cli_tool == 'gh-copilot':
result = subprocess.run(
['gh', 'copilot', 'suggest', '-t', 'shell', full_prompt],
capture_output=True,
text=True,
timeout=timeout
)
else:
raise ValueError(f"CLI tool desconhecido: {cli_tool}")
if result.returncode == 0:
return result.stdout.strip()
else:
console.print(f"[red]❌ Erro ao processar com {cli_tool}[/red]")
console.print(f"[dim]{result.stderr[:200]}[/dim]")
return None
except subprocess.TimeoutExpired:
console.print(f"[red]❌ Timeout após {timeout}s[/red]")
return None
except Exception as e:
console.print(f"[red]❌ Erro: {e}[/red]")
return None
def transcribe_audio(audio_file, model="base"):
"""
Transcreve áudio usando Whisper com barra de progresso.
Returns:
dict: {language, duration, segments: [{start, end, text}]}
"""
console.print(f"\n[cyan]🎙️ Transcrevendo áudio com {TRANSCRIBER}...[/cyan]")
try:
if TRANSCRIBER == "faster-whisper":
model_obj = WhisperModel(model, device="cpu", compute_type="int8")
segments, info = model_obj.transcribe(
audio_file,
language=None,
vad_filter=True,
word_timestamps=True
)
data = {
"language": info.language,
"language_probability": round(info.language_probability, 2),
"duration": info.duration,
"segments": []
}
# Converter generator em lista com progresso
console.print("[dim]Processando segmentos...[/dim]")
for segment in tqdm(segments, desc="Segmentos", unit="seg"):
data["segments"].append({
"start": round(segment.start, 2),
"end": round(segment.end, 2),
"text": segment.text.strip()
})
else: # whisper original
import whisper
model_obj = whisper.load_model(model)
result = model_obj.transcribe(audio_file, word_timestamps=True)
data = {
"language": result["language"],
"duration": result["segments"][-1]["end"] if result["segments"] else 0,
"segments": result["segments"]
}
console.print(f"[green]✅ Transcrição completa! Idioma: {data['language'].upper()}[/green]")
console.print(f"[dim] {len(data['segments'])} segmentos processados[/dim]")
return data
except Exception as e:
console.print(f"[red]❌ Erro na transcrição: {e}[/red]")
sys.exit(1)
def save_outputs(transcript_text, ata_text, audio_file, output_dir="."):
"""
Salva transcript e ata em arquivos .md com timestamp.
Returns:
tuple: (transcript_path, ata_path or None)
"""
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
base_name = Path(audio_file).stem
# Sempre salva transcript
transcript_filename = f"transcript-{timestamp}.md"
transcript_path = Path(output_dir) / transcript_filename
with open(transcript_path, 'w', encoding='utf-8') as f:
f.write(transcript_text)
console.print(f"[green]✅ Transcript salvo:[/green] {transcript_filename}")
# Salva ata se existir
ata_path = None
if ata_text:
ata_filename = f"ata-{timestamp}.md"
ata_path = Path(output_dir) / ata_filename
with open(ata_path, 'w', encoding='utf-8') as f:
f.write(ata_text)
console.print(f"[green]✅ Ata salva:[/green] {ata_filename}")
return str(transcript_path), str(ata_path) if ata_path else None
def main():
"""Função principal."""
import argparse
parser = argparse.ArgumentParser(description="Audio Transcriber v1.1.0")
parser.add_argument("audio_file", help="Arquivo de áudio para transcrever")
parser.add_argument("--prompt", help="Prompt customizado para processar transcript")
parser.add_argument("--model", default="base", help="Modelo Whisper (tiny/base/small/medium/large)")
parser.add_argument("--output-dir", default=".", help="Diretório de saída")
args = parser.parse_args()
# Verificar arquivo existe
if not os.path.exists(args.audio_file):
console.print(f"[red]❌ Arquivo não encontrado: {args.audio_file}[/red]")
sys.exit(1)
console.print("[bold cyan]🎵 Audio Transcriber v1.1.0[/bold cyan]\n")
# Step 1: Transcrever
transcription_data = transcribe_audio(args.audio_file, model=args.model)
# Gerar texto do transcript
transcript_text = f"# Transcrição de Áudio\n\n"
transcript_text += f"**Arquivo:** {Path(args.audio_file).name}\n"
transcript_text += f"**Idioma:** {transcription_data['language'].upper()}\n"
transcript_text += f"**Data:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
transcript_text += "---\n\n## Transcrição Completa\n\n"
for seg in transcription_data["segments"]:
start_min = int(seg["start"] // 60)
start_sec = int(seg["start"] % 60)
end_min = int(seg["end"] // 60)
end_sec = int(seg["end"] % 60)
transcript_text += f"**[{start_min:02d}:{start_sec:02d}{end_min:02d}:{end_sec:02d}]** \n{seg['text']}\n\n"
# Step 2: Detectar CLI
cli_tool = detect_cli_tool()
if not cli_tool:
console.print("\n[yellow]⚠️ Nenhuma CLI de IA detectada (Claude ou GitHub Copilot)[/yellow]")
console.print("[dim] Salvando apenas transcript.md...[/dim]")
save_outputs(transcript_text, None, args.audio_file, args.output_dir)
console.print("\n[cyan]💡 Para gerar ata/resumo:[/cyan]")
console.print(" - Instale Claude CLI: pip install claude-cli")
console.print(" - Ou GitHub Copilot CLI já está instalado (gh copilot)")
return
console.print(f"\n[green]✅ CLI detectada: {cli_tool}[/green]")
# Step 3: Workflow de prompt
final_prompt = handle_prompt_workflow(args.prompt, transcript_text)
if final_prompt is None:
# Usuário recusou processamento
save_outputs(transcript_text, None, args.audio_file, args.output_dir)
return
# Step 4: Processar com LLM
ata_text = process_with_llm(transcript_text, final_prompt, cli_tool)
if ata_text:
console.print("[green]✅ Ata gerada com sucesso![/green]")
else:
console.print("[yellow]⚠️ Falha ao gerar ata, salvando apenas transcript[/yellow]")
# Step 5: Salvar arquivos
console.print("\n[cyan]💾 Salvando arquivos...[/cyan]")
save_outputs(transcript_text, ata_text, args.audio_file, args.output_dir)
console.print("\n[bold green]✅ Concluído![/bold green]")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,220 @@
---
name: bamboohr-automation
description: "Automate BambooHR tasks via Rube MCP (Composio): employees, time-off, benefits, dependents, employee updates. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# BambooHR Automation via Rube MCP
Automate BambooHR human resources operations through Composio's BambooHR toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active BambooHR connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `bamboohr`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `bamboohr`
3. If connection is not ACTIVE, follow the returned auth link to complete BambooHR authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. List and Search Employees
**When to use**: User wants to find employees or get the full employee directory
**Tool sequence**:
1. `BAMBOOHR_GET_ALL_EMPLOYEES` - Get the employee directory [Required]
2. `BAMBOOHR_GET_EMPLOYEE` - Get detailed info for a specific employee [Optional]
**Key parameters**:
- For GET_ALL_EMPLOYEES: No required parameters; returns directory
- For GET_EMPLOYEE:
- `id`: Employee ID (numeric)
- `fields`: Comma-separated list of fields to return (e.g., 'firstName,lastName,department,jobTitle')
**Pitfalls**:
- Employee IDs are numeric integers
- GET_ALL_EMPLOYEES returns basic directory info; use GET_EMPLOYEE for full details
- The `fields` parameter controls which fields are returned; omitting it may return minimal data
- Common fields: firstName, lastName, department, division, jobTitle, workEmail, status
- Inactive/terminated employees may be included; check `status` field
### 2. Track Employee Changes
**When to use**: User wants to detect recent employee data changes for sync or auditing
**Tool sequence**:
1. `BAMBOOHR_EMPLOYEE_GET_CHANGED` - Get employees with recent changes [Required]
**Key parameters**:
- `since`: ISO 8601 datetime string for change detection threshold
- `type`: Type of changes to check (e.g., 'inserted', 'updated', 'deleted')
**Pitfalls**:
- `since` parameter is required; use ISO 8601 format (e.g., '2024-01-15T00:00:00Z')
- Returns IDs of changed employees, not full employee data
- Must call GET_EMPLOYEE separately for each changed employee's details
- Useful for incremental sync workflows; cache the last sync timestamp
### 3. Manage Time-Off
**When to use**: User wants to view time-off balances, request time off, or manage requests
**Tool sequence**:
1. `BAMBOOHR_GET_META_TIME_OFF_TYPES` - List available time-off types [Prerequisite]
2. `BAMBOOHR_GET_TIME_OFF_BALANCES` - Check current balances [Optional]
3. `BAMBOOHR_GET_TIME_OFF_REQUESTS` - List existing requests [Optional]
4. `BAMBOOHR_CREATE_TIME_OFF_REQUEST` - Submit a new request [Optional]
5. `BAMBOOHR_UPDATE_TIME_OFF_REQUEST` - Modify or approve/deny a request [Optional]
**Key parameters**:
- For balances: `employeeId`, time-off type ID
- For requests: `start`, `end` (date range), `employeeId`
- For creation:
- `employeeId`: Employee to request for
- `timeOffTypeId`: Type ID from GET_META_TIME_OFF_TYPES
- `start`: Start date (YYYY-MM-DD)
- `end`: End date (YYYY-MM-DD)
- `amount`: Number of days/hours
- `notes`: Optional notes for the request
- For update: `requestId`, `status` ('approved', 'denied', 'cancelled')
**Pitfalls**:
- Time-off type IDs are numeric; resolve via GET_META_TIME_OFF_TYPES first
- Date format is 'YYYY-MM-DD' for start and end dates
- Balances may be in hours or days depending on company configuration
- Request status updates require appropriate permissions (manager/admin)
- Creating a request does NOT auto-approve it; separate approval step needed
### 4. Update Employee Information
**When to use**: User wants to modify employee profile data
**Tool sequence**:
1. `BAMBOOHR_GET_EMPLOYEE` - Get current employee data [Prerequisite]
2. `BAMBOOHR_UPDATE_EMPLOYEE` - Update employee fields [Required]
**Key parameters**:
- `id`: Employee ID (numeric, required)
- Field-value pairs for the fields to update (e.g., `department`, `jobTitle`, `workPhone`)
**Pitfalls**:
- Only fields included in the request are updated; others remain unchanged
- Some fields are read-only and cannot be updated via API
- Field names must match BambooHR's expected field names exactly
- Updates are audited; changes appear in the employee's change history
- Verify current values with GET_EMPLOYEE before updating to avoid overwriting
### 5. Manage Dependents and Benefits
**When to use**: User wants to view employee dependents or benefit coverage
**Tool sequence**:
1. `BAMBOOHR_DEPENDENTS_GET_ALL` - List all dependents [Required]
2. `BAMBOOHR_BENEFIT_GET_COVERAGES` - Get benefit coverage details [Optional]
**Key parameters**:
- For dependents: Optional `employeeId` filter
- For benefits: Depends on schema; check RUBE_SEARCH_TOOLS for current parameters
**Pitfalls**:
- Dependent data includes sensitive PII; handle with appropriate care
- Benefit coverages may include multiple plan types per employee
- Not all BambooHR plans include benefits administration; check account features
- Data access depends on API key permissions
## Common Patterns
### ID Resolution
**Employee name -> Employee ID**:
```
1. Call BAMBOOHR_GET_ALL_EMPLOYEES
2. Find employee by name in directory results
3. Extract id (numeric) for detailed operations
```
**Time-off type name -> Type ID**:
```
1. Call BAMBOOHR_GET_META_TIME_OFF_TYPES
2. Find type by name (e.g., 'Vacation', 'Sick Leave')
3. Extract id for time-off requests
```
### Incremental Sync Pattern
For keeping external systems in sync with BambooHR:
```
1. Store last_sync_timestamp
2. Call BAMBOOHR_EMPLOYEE_GET_CHANGED with since=last_sync_timestamp
3. For each changed employee ID, call BAMBOOHR_GET_EMPLOYEE
4. Process updates in external system
5. Update last_sync_timestamp
```
### Time-Off Workflow
```
1. GET_META_TIME_OFF_TYPES -> find type ID
2. GET_TIME_OFF_BALANCES -> verify available balance
3. CREATE_TIME_OFF_REQUEST -> submit request
4. UPDATE_TIME_OFF_REQUEST -> approve/deny (manager action)
```
## Known Pitfalls
**Employee IDs**:
- Always numeric integers
- Resolve names to IDs via GET_ALL_EMPLOYEES
- Terminated employees retain their IDs
**Date Formats**:
- Time-off dates: 'YYYY-MM-DD'
- Change detection: ISO 8601 with timezone
- Inconsistent formats between endpoints; check each endpoint's schema
**Permissions**:
- API key permissions determine accessible fields and operations
- Some operations require admin or manager-level access
- Time-off approvals require appropriate role permissions
**Sensitive Data**:
- Employee data includes PII (names, addresses, SSN, etc.)
- Handle all responses with appropriate security measures
- Dependent data is especially sensitive
**Rate Limits**:
- BambooHR API has rate limits per API key
- Bulk operations should be throttled
- GET_ALL_EMPLOYEES is more efficient than individual GET_EMPLOYEE calls
**Response Parsing**:
- Response data may be nested under `data` key
- Employee fields vary based on `fields` parameter
- Empty fields may be omitted or returned as null
- Parse defensively with fallbacks
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List all employees | BAMBOOHR_GET_ALL_EMPLOYEES | (none) |
| Get employee details | BAMBOOHR_GET_EMPLOYEE | id, fields |
| Track changes | BAMBOOHR_EMPLOYEE_GET_CHANGED | since, type |
| Time-off types | BAMBOOHR_GET_META_TIME_OFF_TYPES | (none) |
| Time-off balances | BAMBOOHR_GET_TIME_OFF_BALANCES | employeeId |
| List time-off requests | BAMBOOHR_GET_TIME_OFF_REQUESTS | start, end, employeeId |
| Create time-off request | BAMBOOHR_CREATE_TIME_OFF_REQUEST | employeeId, timeOffTypeId, start, end |
| Update time-off request | BAMBOOHR_UPDATE_TIME_OFF_REQUEST | requestId, status |
| Update employee | BAMBOOHR_UPDATE_EMPLOYEE | id, (field updates) |
| List dependents | BAMBOOHR_DEPENDENTS_GET_ALL | employeeId |
| Benefit coverages | BAMBOOHR_BENEFIT_GET_COVERAGES | (check schema) |

View File

@@ -0,0 +1,234 @@
---
name: basecamp-automation
description: "Automate Basecamp project management, to-dos, messages, people, and to-do list organization via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Basecamp Automation via Rube MCP
Automate Basecamp operations including project management, to-do list creation, task management, message board posting, people management, and to-do group organization through Composio's Basecamp toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Basecamp connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `basecamp`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `basecamp`
3. If connection is not ACTIVE, follow the returned auth link to complete Basecamp OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Manage To-Do Lists and Tasks
**When to use**: User wants to create to-do lists, add tasks, or organize work within a Basecamp project
**Tool sequence**:
1. `BASECAMP_GET_PROJECTS` - List projects to find the target bucket_id [Prerequisite]
2. `BASECAMP_GET_BUCKETS_TODOSETS` - Get the to-do set within a project [Prerequisite]
3. `BASECAMP_GET_BUCKETS_TODOSETS_TODOLISTS` - List existing to-do lists to avoid duplicates [Optional]
4. `BASECAMP_POST_BUCKETS_TODOSETS_TODOLISTS` - Create a new to-do list in a to-do set [Required for list creation]
5. `BASECAMP_GET_BUCKETS_TODOLISTS` - Get details of a specific to-do list [Optional]
6. `BASECAMP_POST_BUCKETS_TODOLISTS_TODOS` - Create a to-do item in a to-do list [Required for task creation]
7. `BASECAMP_CREATE_TODO` - Alternative tool for creating individual to-dos [Alternative]
8. `BASECAMP_GET_BUCKETS_TODOLISTS_TODOS` - List to-dos within a to-do list [Optional]
**Key parameters for creating to-do lists**:
- `bucket_id`: Integer project/bucket ID (from GET_PROJECTS)
- `todoset_id`: Integer to-do set ID (from GET_BUCKETS_TODOSETS)
- `name`: Title of the to-do list (required)
- `description`: HTML-formatted description (supports Rich text)
**Key parameters for creating to-dos**:
- `bucket_id`: Integer project/bucket ID
- `todolist_id`: Integer to-do list ID
- `content`: What the to-do is for (required)
- `description`: HTML details about the to-do
- `assignee_ids`: Array of integer person IDs
- `due_on`: Due date in `YYYY-MM-DD` format
- `starts_on`: Start date in `YYYY-MM-DD` format
- `notify`: Boolean to notify assignees (defaults to false)
- `completion_subscriber_ids`: Person IDs notified upon completion
**Pitfalls**:
- A project (bucket) can contain multiple to-do sets; selecting the wrong `todoset_id` creates lists in the wrong section
- Always check existing to-do lists before creating to avoid near-duplicate names
- Success payloads include user-facing URLs (`app_url`, `app_todos_url`); prefer returning these over raw IDs
- All IDs (`bucket_id`, `todoset_id`, `todolist_id`) are integers, not strings
- Descriptions support HTML formatting only, not Markdown
### 2. Post and Manage Messages
**When to use**: User wants to post messages to a project message board or update existing messages
**Tool sequence**:
1. `BASECAMP_GET_PROJECTS` - Find the target project and bucket_id [Prerequisite]
2. `BASECAMP_GET_MESSAGE_BOARD` - Get the message board ID for the project [Prerequisite]
3. `BASECAMP_CREATE_MESSAGE` - Create a new message on the board [Required]
4. `BASECAMP_POST_BUCKETS_MESSAGE_BOARDS_MESSAGES` - Alternative message creation tool [Fallback]
5. `BASECAMP_GET_MESSAGE` - Read a specific message by ID [Optional]
6. `BASECAMP_PUT_BUCKETS_MESSAGES` - Update an existing message [Optional]
**Key parameters**:
- `bucket_id`: Integer project/bucket ID
- `message_board_id`: Integer message board ID (from GET_MESSAGE_BOARD)
- `subject`: Message title (required)
- `content`: HTML body of the message
- `status`: Set to `"active"` to publish immediately
- `category_id`: Message type classification (optional)
- `subscriptions`: Array of person IDs to notify; omit to notify all project members
**Pitfalls**:
- `status="draft"` can produce HTTP 400; use `status="active"` as the reliable option
- `bucket_id` and `message_board_id` must belong to the same project; mismatches fail or misroute
- Message content supports HTML tags only; not Markdown
- Updates via `PUT_BUCKETS_MESSAGES` replace the entire body -- include the full corrected content, not just a diff
- Prefer `app_url` from the response for user-facing confirmation links
- Both `CREATE_MESSAGE` and `POST_BUCKETS_MESSAGE_BOARDS_MESSAGES` do the same thing; use CREATE_MESSAGE first and fall back to POST if it fails
### 3. Manage People and Access
**When to use**: User wants to list people, manage project access, or add new users
**Tool sequence**:
1. `BASECAMP_GET_PEOPLE` - List all people visible to the current user [Required]
2. `BASECAMP_GET_PROJECTS` - Find the target project [Prerequisite]
3. `BASECAMP_LIST_PROJECT_PEOPLE` - List people on a specific project [Required]
4. `BASECAMP_GET_PROJECTS_PEOPLE` - Alternative to list project members [Alternative]
5. `BASECAMP_PUT_PROJECTS_PEOPLE_USERS` - Grant or revoke project access [Required for access changes]
**Key parameters for PUT_PROJECTS_PEOPLE_USERS**:
- `project_id`: Integer project ID
- `grant`: Array of integer person IDs to add to the project
- `revoke`: Array of integer person IDs to remove from the project
- `create`: Array of objects with `name`, `email_address`, and optional `company_name`, `title` for new users
- At least one of `grant`, `revoke`, or `create` must be provided
**Pitfalls**:
- Person IDs are integers; always resolve names to IDs via GET_PEOPLE first
- `project_id` for people management is the same as `bucket_id` for other operations
- `LIST_PROJECT_PEOPLE` and `GET_PROJECTS_PEOPLE` are near-identical; use either
- Creating users via `create` also grants them project access in one step
### 4. Organize To-Dos with Groups
**When to use**: User wants to organize to-dos within a list into color-coded groups
**Tool sequence**:
1. `BASECAMP_GET_PROJECTS` - Find the target project [Prerequisite]
2. `BASECAMP_GET_BUCKETS_TODOLISTS` - Get the to-do list details [Prerequisite]
3. `BASECAMP_GET_TODOLIST_GROUPS` - List existing groups in a to-do list [Optional]
4. `BASECAMP_GET_BUCKETS_TODOLISTS_GROUPS` - Alternative group listing [Alternative]
5. `BASECAMP_POST_BUCKETS_TODOLISTS_GROUPS` - Create a new group in a to-do list [Required]
6. `BASECAMP_CREATE_TODOLIST_GROUP` - Alternative group creation tool [Alternative]
**Key parameters**:
- `bucket_id`: Integer project/bucket ID
- `todolist_id`: Integer to-do list ID
- `name`: Group title (required)
- `color`: Visual color identifier -- one of: `white`, `red`, `orange`, `yellow`, `green`, `blue`, `aqua`, `purple`, `gray`, `pink`, `brown`
- `status`: Filter for listing -- `"archived"` or `"trashed"` (omit for active groups)
**Pitfalls**:
- `POST_BUCKETS_TODOLISTS_GROUPS` and `CREATE_TODOLIST_GROUP` are near-identical; use either
- Color values must be from the fixed palette; arbitrary hex/rgb values are not supported
- Groups are sub-sections within a to-do list, not standalone entities
### 5. Browse and Inspect Projects
**When to use**: User wants to list projects, get project details, or explore project structure
**Tool sequence**:
1. `BASECAMP_GET_PROJECTS` - List all active projects [Required]
2. `BASECAMP_GET_PROJECT` - Get comprehensive details for a specific project [Optional]
3. `BASECAMP_GET_PROJECTS_BY_PROJECT_ID` - Alternative project detail retrieval [Alternative]
**Key parameters**:
- `status`: Filter by `"archived"` or `"trashed"`; omit for active projects
- `project_id`: Integer project ID for detailed retrieval
**Pitfalls**:
- Projects are sorted by most recently created first
- The response includes a `dock` array with tools (todoset, message_board, etc.) and their IDs
- Use the dock tool IDs to find `todoset_id`, `message_board_id`, etc. for downstream operations
## Common Patterns
### ID Resolution
Basecamp uses a hierarchical ID structure. Always resolve top-down:
- **Project (bucket_id)**: `BASECAMP_GET_PROJECTS` -- find by name, capture the `id`
- **To-do set (todoset_id)**: Found in project dock or via `BASECAMP_GET_BUCKETS_TODOSETS`
- **Message board (message_board_id)**: Found in project dock or via `BASECAMP_GET_MESSAGE_BOARD`
- **To-do list (todolist_id)**: `BASECAMP_GET_BUCKETS_TODOSETS_TODOLISTS`
- **People (person_id)**: `BASECAMP_GET_PEOPLE` or `BASECAMP_LIST_PROJECT_PEOPLE`
- Note: `bucket_id` and `project_id` refer to the same entity in different contexts
### Pagination
Basecamp uses page-based pagination on list endpoints:
- Response headers or body may indicate more pages available
- `GET_PROJECTS`, `GET_BUCKETS_TODOSETS_TODOLISTS`, and list endpoints return paginated results
- Continue fetching until no more results are returned
### Content Formatting
- All rich text fields use HTML, not Markdown
- Wrap content in `<div>` tags; use `<strong>`, `<em>`, `<ul>`, `<ol>`, `<li>`, `<a>` etc.
- Example: `<div><strong>Important:</strong> Complete by Friday</div>`
## Known Pitfalls
### ID Formats
- All Basecamp IDs are integers, not strings or UUIDs
- `bucket_id` = `project_id` (same entity, different parameter names across tools)
- To-do set IDs, to-do list IDs, and message board IDs are found in the project's `dock` array
- Person IDs are integers; resolve names via `GET_PEOPLE` before operations
### Status Field
- `status="draft"` for messages can cause HTTP 400; always use `status="active"`
- Project/to-do list status filters: `"archived"`, `"trashed"`, or omit for active
### Content Format
- HTML only, never Markdown
- Updates replace the entire body, not a partial diff
- Invalid HTML tags may be silently stripped
### Rate Limits
- Basecamp API has rate limits; space out rapid sequential requests
- Large projects with many to-dos should be paginated carefully
### URL Handling
- Prefer `app_url` from API responses for user-facing links
- Do not reconstruct Basecamp URLs manually from IDs
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List projects | `BASECAMP_GET_PROJECTS` | `status` |
| Get project | `BASECAMP_GET_PROJECT` | `project_id` |
| Get project detail | `BASECAMP_GET_PROJECTS_BY_PROJECT_ID` | `project_id` |
| Get to-do set | `BASECAMP_GET_BUCKETS_TODOSETS` | `bucket_id`, `todoset_id` |
| List to-do lists | `BASECAMP_GET_BUCKETS_TODOSETS_TODOLISTS` | `bucket_id`, `todoset_id` |
| Get to-do list | `BASECAMP_GET_BUCKETS_TODOLISTS` | `bucket_id`, `todolist_id` |
| Create to-do list | `BASECAMP_POST_BUCKETS_TODOSETS_TODOLISTS` | `bucket_id`, `todoset_id`, `name` |
| Create to-do | `BASECAMP_POST_BUCKETS_TODOLISTS_TODOS` | `bucket_id`, `todolist_id`, `content` |
| Create to-do (alt) | `BASECAMP_CREATE_TODO` | `bucket_id`, `todolist_id`, `content` |
| List to-dos | `BASECAMP_GET_BUCKETS_TODOLISTS_TODOS` | `bucket_id`, `todolist_id` |
| List to-do groups | `BASECAMP_GET_TODOLIST_GROUPS` | `bucket_id`, `todolist_id` |
| Create to-do group | `BASECAMP_POST_BUCKETS_TODOLISTS_GROUPS` | `bucket_id`, `todolist_id`, `name`, `color` |
| Create to-do group (alt) | `BASECAMP_CREATE_TODOLIST_GROUP` | `bucket_id`, `todolist_id`, `name` |
| Get message board | `BASECAMP_GET_MESSAGE_BOARD` | `bucket_id`, `message_board_id` |
| Create message | `BASECAMP_CREATE_MESSAGE` | `bucket_id`, `message_board_id`, `subject`, `status` |
| Create message (alt) | `BASECAMP_POST_BUCKETS_MESSAGE_BOARDS_MESSAGES` | `bucket_id`, `message_board_id`, `subject` |
| Get message | `BASECAMP_GET_MESSAGE` | `bucket_id`, `message_id` |
| Update message | `BASECAMP_PUT_BUCKETS_MESSAGES` | `bucket_id`, `message_id` |
| List all people | `BASECAMP_GET_PEOPLE` | (none) |
| List project people | `BASECAMP_LIST_PROJECT_PEOPLE` | `project_id` |
| Manage access | `BASECAMP_PUT_PROJECTS_PEOPLE_USERS` | `project_id`, `grant`, `revoke`, `create` |

View File

@@ -0,0 +1,224 @@
---
name: bitbucket-automation
description: "Automate Bitbucket repositories, pull requests, branches, issues, and workspace management via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Bitbucket Automation via Rube MCP
Automate Bitbucket operations including repository management, pull request workflows, branch operations, issue tracking, and workspace administration through Composio's Bitbucket toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Bitbucket connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `bitbucket`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `bitbucket`
3. If connection is not ACTIVE, follow the returned auth link to complete Bitbucket OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Manage Pull Requests
**When to use**: User wants to create, review, or inspect pull requests
**Tool sequence**:
1. `BITBUCKET_LIST_WORKSPACES` - Discover accessible workspaces [Prerequisite]
2. `BITBUCKET_LIST_REPOSITORIES_IN_WORKSPACE` - Find the target repository [Prerequisite]
3. `BITBUCKET_LIST_BRANCHES` - Verify source and destination branches exist [Prerequisite]
4. `BITBUCKET_CREATE_PULL_REQUEST` - Create a new PR with title, source branch, and optional reviewers [Required]
5. `BITBUCKET_LIST_PULL_REQUESTS` - List PRs filtered by state (OPEN, MERGED, DECLINED) [Optional]
6. `BITBUCKET_GET_PULL_REQUEST` - Get full details of a specific PR by ID [Optional]
7. `BITBUCKET_GET_PULL_REQUEST_DIFF` - Fetch unified diff for code review [Optional]
8. `BITBUCKET_GET_PULL_REQUEST_DIFFSTAT` - Get changed files with lines added/removed [Optional]
**Key parameters**:
- `workspace`: Workspace slug or UUID (required for all operations)
- `repo_slug`: URL-friendly repository name
- `source_branch`: Branch with changes to merge
- `destination_branch`: Target branch (defaults to repo main branch if omitted)
- `reviewers`: List of objects with `uuid` field for reviewer assignment
- `state`: Filter for LIST_PULL_REQUESTS - `OPEN`, `MERGED`, or `DECLINED`
- `max_chars`: Truncation limit for GET_PULL_REQUEST_DIFF to handle large diffs
**Pitfalls**:
- `reviewers` expects an array of objects with `uuid` key, NOT usernames: `[{"uuid": "{...}"}]`
- UUID format must include curly braces: `{123e4567-e89b-12d3-a456-426614174000}`
- `destination_branch` defaults to the repo's main branch if omitted, which may not be `main`
- `pull_request_id` is an integer for GET/DIFF operations but comes back as part of PR listing
- Large diffs can overwhelm context; always set `max_chars` (e.g., 50000) on GET_PULL_REQUEST_DIFF
### 2. Manage Repositories and Workspaces
**When to use**: User wants to list, create, or delete repositories or explore workspaces
**Tool sequence**:
1. `BITBUCKET_LIST_WORKSPACES` - List all accessible workspaces [Required]
2. `BITBUCKET_LIST_REPOSITORIES_IN_WORKSPACE` - List repos with optional BBQL filtering [Required]
3. `BITBUCKET_CREATE_REPOSITORY` - Create a new repo with language, privacy, and project settings [Optional]
4. `BITBUCKET_DELETE_REPOSITORY` - Permanently delete a repository (irreversible) [Optional]
5. `BITBUCKET_LIST_WORKSPACE_MEMBERS` - List members for reviewer assignment or access checks [Optional]
**Key parameters**:
- `workspace`: Workspace slug (find via LIST_WORKSPACES)
- `repo_slug`: URL-friendly name for create/delete
- `q`: BBQL query filter (e.g., `name~"api"`, `project.key="PROJ"`, `is_private=true`)
- `role`: Filter repos by user role: `member`, `contributor`, `admin`, `owner`
- `sort`: Sort field with optional `-` prefix for descending (e.g., `-updated_on`)
- `is_private`: Boolean for repository visibility (defaults to `true`)
- `project_key`: Bitbucket project key; omit to use workspace's oldest project
**Pitfalls**:
- `BITBUCKET_DELETE_REPOSITORY` is **irreversible** and does not affect forks
- BBQL string values MUST be enclosed in double quotes: `name~"my-repo"` not `name~my-repo`
- `repository` is NOT a valid BBQL field; use `name` instead
- Default pagination is 10 results; set `pagelen` explicitly for complete listings
- `CREATE_REPOSITORY` defaults to private; set `is_private: false` for public repos
### 3. Manage Issues
**When to use**: User wants to create, update, list, or comment on repository issues
**Tool sequence**:
1. `BITBUCKET_LIST_ISSUES` - List issues with optional filters for state, priority, kind, assignee [Required]
2. `BITBUCKET_CREATE_ISSUE` - Create a new issue with title, content, priority, and kind [Required]
3. `BITBUCKET_UPDATE_ISSUE` - Modify issue attributes (state, priority, assignee, etc.) [Optional]
4. `BITBUCKET_CREATE_ISSUE_COMMENT` - Add a markdown comment to an existing issue [Optional]
5. `BITBUCKET_DELETE_ISSUE` - Permanently delete an issue [Optional]
**Key parameters**:
- `issue_id`: String identifier for the issue
- `title`, `content`: Required for creation
- `kind`: `bug`, `enhancement`, `proposal`, or `task`
- `priority`: `trivial`, `minor`, `major`, `critical`, or `blocker`
- `state`: `new`, `open`, `resolved`, `on hold`, `invalid`, `duplicate`, `wontfix`, `closed`
- `assignee`: Bitbucket username for CREATE; `assignee_account_id` (UUID) for UPDATE
- `due_on`: ISO 8601 format date string
**Pitfalls**:
- Issue tracker must be enabled on the repository (`has_issues: true`) or API calls will fail
- `CREATE_ISSUE` uses `assignee` (username string), but `UPDATE_ISSUE` uses `assignee_account_id` (UUID) -- they are different fields
- `DELETE_ISSUE` is permanent with no undo
- `state` values include spaces: `"on hold"` not `"on_hold"`
- Filtering by `assignee` in LIST_ISSUES uses account ID, not username; use `"null"` string for unassigned
### 4. Manage Branches
**When to use**: User wants to create branches or explore branch structure
**Tool sequence**:
1. `BITBUCKET_LIST_BRANCHES` - List branches with optional BBQL filter and sorting [Required]
2. `BITBUCKET_CREATE_BRANCH` - Create a new branch from a specific commit hash [Required]
**Key parameters**:
- `name`: Branch name without `refs/heads/` prefix (e.g., `feature/new-login`)
- `target_hash`: Full SHA1 commit hash to branch from (must exist in repo)
- `q`: BBQL filter (e.g., `name~"feature/"`, `name="main"`)
- `sort`: Sort by `name` or `-target.date` (descending commit date)
- `pagelen`: 1-100 results per page (default is 10)
**Pitfalls**:
- `CREATE_BRANCH` requires a full commit hash, NOT a branch name as `target_hash`
- Do NOT include `refs/heads/` prefix in branch names
- Branch names must follow Bitbucket naming conventions (alphanumeric, `/`, `.`, `_`, `-`)
- BBQL string values need double quotes: `name~"feature/"` not `name~feature/`
### 5. Review Pull Requests with Comments
**When to use**: User wants to add review comments to pull requests, including inline code comments
**Tool sequence**:
1. `BITBUCKET_GET_PULL_REQUEST` - Get PR details and verify it exists [Prerequisite]
2. `BITBUCKET_GET_PULL_REQUEST_DIFF` - Review the actual code changes [Prerequisite]
3. `BITBUCKET_GET_PULL_REQUEST_DIFFSTAT` - Get list of changed files [Optional]
4. `BITBUCKET_CREATE_PULL_REQUEST_COMMENT` - Post review comments [Required]
**Key parameters**:
- `pull_request_id`: String ID of the PR
- `content_raw`: Markdown-formatted comment text
- `content_markup`: Defaults to `markdown`; also supports `plaintext`
- `inline`: Object with `path`, `from`, `to` for inline code comments
- `parent_comment_id`: Integer ID for threaded replies to existing comments
**Pitfalls**:
- `pull_request_id` is a string in CREATE_PULL_REQUEST_COMMENT but an integer in GET_PULL_REQUEST
- Inline comments require `inline.path` at minimum; `from`/`to` are optional line numbers
- `parent_comment_id` creates a threaded reply; omit for top-level comments
- Line numbers in inline comments reference the diff, not the source file
## Common Patterns
### ID Resolution
Always resolve human-readable names to IDs before operations:
- **Workspace**: `BITBUCKET_LIST_WORKSPACES` to get workspace slugs
- **Repository**: `BITBUCKET_LIST_REPOSITORIES_IN_WORKSPACE` with `q` filter to find repo slugs
- **Branch**: `BITBUCKET_LIST_BRANCHES` to verify branch existence before PR creation
- **Members**: `BITBUCKET_LIST_WORKSPACE_MEMBERS` to get UUIDs for reviewer assignment
### Pagination
Bitbucket uses page-based pagination (not cursor-based):
- Use `page` (starts at 1) and `pagelen` (items per page) parameters
- Default page size is typically 10; set `pagelen` explicitly (max 50 for PRs, 100 for others)
- Check response for `next` URL or total count to determine if more pages exist
- Always iterate through all pages for complete results
### BBQL Filtering
Bitbucket Query Language is available on list endpoints:
- String values MUST use double quotes: `name~"pattern"`
- Operators: `=` (exact), `~` (contains), `!=` (not equal), `>`, `>=`, `<`, `<=`
- Combine with `AND` / `OR`: `name~"api" AND is_private=true`
## Known Pitfalls
### ID Formats
- Workspace: slug string (e.g., `my-workspace`) or UUID in braces (`{uuid}`)
- Reviewer UUIDs must include curly braces: `{123e4567-e89b-12d3-a456-426614174000}`
- Issue IDs are strings; PR IDs are integers in some tools, strings in others
- Commit hashes must be full SHA1 (40 characters)
### Parameter Quirks
- `assignee` vs `assignee_account_id`: CREATE_ISSUE uses username, UPDATE_ISSUE uses UUID
- `state` values for issues include spaces: `"on hold"`, not `"on_hold"`
- `destination_branch` omission defaults to repo main branch, not `main` literally
- BBQL `repository` is not a valid field -- use `name`
### Rate Limits
- Bitbucket Cloud API has rate limits; large batch operations should include delays
- Paginated requests count against rate limits; minimize unnecessary page fetches
### Destructive Operations
- `BITBUCKET_DELETE_REPOSITORY` is irreversible and does not remove forks
- `BITBUCKET_DELETE_ISSUE` is permanent with no recovery option
- Always confirm with the user before executing delete operations
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List workspaces | `BITBUCKET_LIST_WORKSPACES` | `q`, `sort` |
| List repos | `BITBUCKET_LIST_REPOSITORIES_IN_WORKSPACE` | `workspace`, `q`, `role` |
| Create repo | `BITBUCKET_CREATE_REPOSITORY` | `workspace`, `repo_slug`, `is_private` |
| Delete repo | `BITBUCKET_DELETE_REPOSITORY` | `workspace`, `repo_slug` |
| List branches | `BITBUCKET_LIST_BRANCHES` | `workspace`, `repo_slug`, `q` |
| Create branch | `BITBUCKET_CREATE_BRANCH` | `workspace`, `repo_slug`, `name`, `target_hash` |
| List PRs | `BITBUCKET_LIST_PULL_REQUESTS` | `workspace`, `repo_slug`, `state` |
| Create PR | `BITBUCKET_CREATE_PULL_REQUEST` | `workspace`, `repo_slug`, `title`, `source_branch` |
| Get PR details | `BITBUCKET_GET_PULL_REQUEST` | `workspace`, `repo_slug`, `pull_request_id` |
| Get PR diff | `BITBUCKET_GET_PULL_REQUEST_DIFF` | `workspace`, `repo_slug`, `pull_request_id`, `max_chars` |
| Get PR diffstat | `BITBUCKET_GET_PULL_REQUEST_DIFFSTAT` | `workspace`, `repo_slug`, `pull_request_id` |
| Comment on PR | `BITBUCKET_CREATE_PULL_REQUEST_COMMENT` | `workspace`, `repo_slug`, `pull_request_id`, `content_raw` |
| List issues | `BITBUCKET_LIST_ISSUES` | `workspace`, `repo_slug`, `state`, `priority` |
| Create issue | `BITBUCKET_CREATE_ISSUE` | `workspace`, `repo_slug`, `title`, `content` |
| Update issue | `BITBUCKET_UPDATE_ISSUE` | `workspace`, `repo_slug`, `issue_id` |
| Comment on issue | `BITBUCKET_CREATE_ISSUE_COMMENT` | `workspace`, `repo_slug`, `issue_id`, `content` |
| Delete issue | `BITBUCKET_DELETE_ISSUE` | `workspace`, `repo_slug`, `issue_id` |
| List members | `BITBUCKET_LIST_WORKSPACE_MEMBERS` | `workspace` |

View File

@@ -0,0 +1,233 @@
---
name: box-automation
description: "Automate Box cloud storage operations including file upload/download, search, folder management, sharing, collaborations, and metadata queries via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Box Automation via Rube MCP
Automate Box operations including file upload/download, content search, folder management, collaboration, metadata queries, and sign requests through Composio's Box toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Box connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `box`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `box`
3. If connection is not ACTIVE, follow the returned auth link to complete Box OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Upload and Download Files
**When to use**: User wants to upload files to Box or download files from it
**Tool sequence**:
1. `BOX_SEARCH_FOR_CONTENT` - Find the target folder if path is unknown [Prerequisite]
2. `BOX_GET_FOLDER_INFORMATION` - Verify folder exists and get folder_id [Prerequisite]
3. `BOX_LIST_ITEMS_IN_FOLDER` - Browse folder contents and discover file IDs [Optional]
4. `BOX_UPLOAD_FILE` - Upload a file to a specific folder [Required for upload]
5. `BOX_DOWNLOAD_FILE` - Download a file by file_id [Required for download]
6. `BOX_CREATE_ZIP_DOWNLOAD` - Bundle multiple files/folders into a zip [Optional]
**Key parameters**:
- `parent_id`: Folder ID for upload destination (use `"0"` for root folder)
- `file`: FileUploadable object with `s3key`, `mimetype`, and `name` for uploads
- `file_id`: Unique file identifier for downloads
- `version`: Optional file version ID for downloading specific versions
- `fields`: Comma-separated list of attributes to return
**Pitfalls**:
- Uploading to a folder with existing filenames can trigger conflict behavior; decide overwrite vs rename semantics
- Files over 50MB should use chunk upload APIs (not available via standard tools)
- The `attributes` part of upload must come before the `file` part or you get HTTP 400 with `metadata_after_file_contents`
- File IDs and folder IDs are numeric strings extractable from Box web app URLs (e.g., `https://*.app.box.com/files/123` gives file_id `"123"`)
### 2. Search and Browse Content
**When to use**: User wants to find files, folders, or web links by name, content, or metadata
**Tool sequence**:
1. `BOX_SEARCH_FOR_CONTENT` - Full-text search across files, folders, and web links [Required]
2. `BOX_LIST_ITEMS_IN_FOLDER` - Browse contents of a specific folder [Optional]
3. `BOX_GET_FILE_INFORMATION` - Get detailed metadata for a specific file [Optional]
4. `BOX_GET_FOLDER_INFORMATION` - Get detailed metadata for a specific folder [Optional]
5. `BOX_QUERY_FILES_FOLDERS_BY_METADATA` - Search by metadata template values [Optional]
6. `BOX_LIST_RECENTLY_ACCESSED_ITEMS` - List recently accessed items [Optional]
**Key parameters**:
- `query`: Search string supporting operators (`""` exact match, `AND`, `OR`, `NOT` - uppercase only)
- `type`: Filter by `"file"`, `"folder"`, or `"web_link"`
- `ancestor_folder_ids`: Limit search to specific folders (comma-separated IDs)
- `file_extensions`: Filter by file type (comma-separated, no dots)
- `content_types`: Search in `"name"`, `"description"`, `"file_content"`, `"comments"`, `"tags"`
- `created_at_range` / `updated_at_range`: Date filters as comma-separated RFC3339 timestamps
- `limit`: Results per page (default 30)
- `offset`: Pagination offset (max 10000)
- `folder_id`: For `LIST_ITEMS_IN_FOLDER` (use `"0"` for root)
**Pitfalls**:
- Queries with offset > 10000 are rejected with HTTP 400
- `BOX_SEARCH_FOR_CONTENT` requires either `query` or `mdfilters` parameter
- Misconfigured filters can silently omit expected items; validate with small test queries first
- Boolean operators (`AND`, `OR`, `NOT`) must be uppercase
- `BOX_LIST_ITEMS_IN_FOLDER` requires pagination via `marker` or `offset`/`usemarker`; partial listings are common
- Standard folders sort items by type first (folders before files before web links)
### 3. Manage Folders
**When to use**: User wants to create, update, move, copy, or delete folders
**Tool sequence**:
1. `BOX_GET_FOLDER_INFORMATION` - Verify folder exists and check permissions [Prerequisite]
2. `BOX_CREATE_FOLDER` - Create a new folder [Required for create]
3. `BOX_UPDATE_FOLDER` - Rename, move, or update folder settings [Required for update]
4. `BOX_COPY_FOLDER` - Copy a folder to a new location [Optional]
5. `BOX_DELETE_FOLDER` - Move folder to trash [Required for delete]
6. `BOX_PERMANENTLY_REMOVE_FOLDER` - Permanently delete a trashed folder [Optional]
**Key parameters**:
- `name`: Folder name (no `/`, `\`, trailing spaces, or `.`/`..`)
- `parent__id`: Parent folder ID (use `"0"` for root)
- `folder_id`: Target folder ID for operations
- `parent.id`: Destination folder ID for moves via `BOX_UPDATE_FOLDER`
- `recursive`: Set `true` to delete non-empty folders
- `shared_link`: Object with `access`, `password`, `permissions` for creating shared links on folders
- `description`, `tags`: Optional metadata fields
**Pitfalls**:
- `BOX_DELETE_FOLDER` moves to trash by default; use `BOX_PERMANENTLY_REMOVE_FOLDER` for permanent deletion
- Non-empty folders require `recursive: true` for deletion
- Root folder (ID `"0"`) cannot be copied or deleted
- Folder names cannot contain `/`, `\`, non-printable ASCII, or trailing spaces
- Moving folders requires setting `parent.id` via `BOX_UPDATE_FOLDER`
### 4. Share Files and Manage Collaborations
**When to use**: User wants to share files, manage access, or handle collaborations
**Tool sequence**:
1. `BOX_GET_FILE_INFORMATION` - Get file details and current sharing status [Prerequisite]
2. `BOX_LIST_FILE_COLLABORATIONS` - List who has access to a file [Required]
3. `BOX_UPDATE_COLLABORATION` - Change access level or accept/reject invitations [Required]
4. `BOX_GET_COLLABORATION` - Get details of a specific collaboration [Optional]
5. `BOX_UPDATE_FILE` - Create shared links, lock files, or update permissions [Optional]
6. `BOX_UPDATE_FOLDER` - Create shared links on folders [Optional]
**Key parameters**:
- `collaboration_id`: Unique collaboration identifier
- `role`: Access level (`"editor"`, `"viewer"`, `"co-owner"`, `"owner"`, `"previewer"`, `"uploader"`, `"viewer uploader"`, `"previewer uploader"`)
- `status`: `"accepted"`, `"pending"`, or `"rejected"` for collaboration invites
- `file_id`: File to share or manage
- `lock__access`: Set to `"lock"` to lock a file
- `permissions__can__download`: `"company"` or `"open"` for download permissions
**Pitfalls**:
- Only certain roles can invite collaborators; insufficient permissions cause authorization errors
- `can_view_path` increases load time for the invitee's "All Files" page; limit to 1000 per user
- Collaboration expiration requires enterprise admin settings to be enabled
- Nested parameter names use double underscores (e.g., `lock__access`, `parent__id`)
### 5. Box Sign Requests
**When to use**: User wants to manage document signature requests
**Tool sequence**:
1. `BOX_LIST_BOX_SIGN_REQUESTS` - List all signature requests [Required]
2. `BOX_GET_BOX_SIGN_REQUEST_BY_ID` - Get details of a specific sign request [Optional]
3. `BOX_CANCEL_BOX_SIGN_REQUEST` - Cancel a pending sign request [Optional]
**Key parameters**:
- `sign_request_id`: UUID of the sign request
- `shared_requests`: Set `true` to include requests where user is a collaborator (not owner)
- `senders`: Filter by sender emails (requires `shared_requests: true`)
- `limit` / `marker`: Pagination parameters
**Pitfalls**:
- Requires Box Sign to be enabled for the enterprise account
- Deleted sign files or parent folders cause requests to not appear in listings
- Only the creator can cancel a sign request
- Sign request statuses include: `converting`, `created`, `sent`, `viewed`, `signed`, `declined`, `cancelled`, `expired`, `error_converting`, `error_sending`
## Common Patterns
### ID Resolution
Box uses numeric string IDs for all entities:
- **Root folder**: Always ID `"0"`
- **File ID from URL**: `https://*.app.box.com/files/123` gives file_id `"123"`
- **Folder ID from URL**: `https://*.app.box.com/folder/123` gives folder_id `"123"`
- **Search to ID**: Use `BOX_SEARCH_FOR_CONTENT` to find items, then extract IDs from results
- **ETag**: Use `if_match` with file's ETag for safe concurrent delete operations
### Pagination
Box supports two pagination methods:
- **Offset-based**: Use `offset` + `limit` (max offset 10000)
- **Marker-based**: Set `usemarker: true` and follow `marker` from responses (preferred for large datasets)
- Always paginate to completion to avoid partial results
### Nested Parameters
Box tools use double underscore notation for nested objects:
- `parent__id` for parent folder reference
- `lock__access`, `lock__expires__at`, `lock__is__download__prevented` for file locks
- `permissions__can__download` for download permissions
## Known Pitfalls
### ID Formats
- All IDs are numeric strings (e.g., `"123456"`, not integers)
- Root folder is always `"0"`
- File and folder IDs can be extracted from Box web app URLs
### Rate Limits
- Box API has per-endpoint rate limits
- Search and list operations should use pagination responsibly
- Bulk operations should include delays between requests
### Parameter Quirks
- `fields` parameter changes response shape: when specified, only mini representation + requested fields are returned
- Search requires either `query` or `mdfilters`; both are optional individually but one must be present
- `BOX_UPDATE_FILE` with `lock` set to `null` removes the lock (raw API only)
- Metadata query `from` field format: `enterprise_{enterprise_id}.templateKey` or `global.templateKey`
### Permissions
- Deletions fail without sufficient permissions; always handle error responses
- Collaboration roles determine what operations are allowed
- Enterprise settings may restrict certain sharing options
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Search content | `BOX_SEARCH_FOR_CONTENT` | `query`, `type`, `ancestor_folder_ids` |
| List folder items | `BOX_LIST_ITEMS_IN_FOLDER` | `folder_id`, `limit`, `marker` |
| Get file info | `BOX_GET_FILE_INFORMATION` | `file_id`, `fields` |
| Get folder info | `BOX_GET_FOLDER_INFORMATION` | `folder_id`, `fields` |
| Upload file | `BOX_UPLOAD_FILE` | `file`, `parent_id` |
| Download file | `BOX_DOWNLOAD_FILE` | `file_id` |
| Create folder | `BOX_CREATE_FOLDER` | `name`, `parent__id` |
| Update folder | `BOX_UPDATE_FOLDER` | `folder_id`, `name`, `parent` |
| Copy folder | `BOX_COPY_FOLDER` | `folder_id`, `parent__id` |
| Delete folder | `BOX_DELETE_FOLDER` | `folder_id`, `recursive` |
| Permanently delete folder | `BOX_PERMANENTLY_REMOVE_FOLDER` | folder_id |
| Update file | `BOX_UPDATE_FILE` | `file_id`, `name`, `parent__id` |
| Delete file | `BOX_DELETE_FILE` | `file_id`, `if_match` |
| List collaborations | `BOX_LIST_FILE_COLLABORATIONS` | `file_id` |
| Update collaboration | `BOX_UPDATE_COLLABORATION` | `collaboration_id`, `role` |
| Get collaboration | `BOX_GET_COLLABORATION` | `collaboration_id` |
| Query by metadata | `BOX_QUERY_FILES_FOLDERS_BY_METADATA` | `from`, `ancestor_folder_id`, `query` |
| List collections | `BOX_LIST_ALL_COLLECTIONS` | (none) |
| List collection items | `BOX_LIST_COLLECTION_ITEMS` | `collection_id` |
| List sign requests | `BOX_LIST_BOX_SIGN_REQUESTS` | `limit`, `marker` |
| Get sign request | `BOX_GET_BOX_SIGN_REQUEST_BY_ID` | `sign_request_id` |
| Cancel sign request | `BOX_CANCEL_BOX_SIGN_REQUEST` | `sign_request_id` |
| Recent items | `BOX_LIST_RECENTLY_ACCESSED_ITEMS` | (none) |
| Create zip download | `BOX_CREATE_ZIP_DOWNLOAD` | item IDs |

View File

@@ -0,0 +1,197 @@
---
name: brevo-automation
description: "Automate Brevo (Sendinblue) tasks via Rube MCP (Composio): manage email campaigns, create/edit templates, track senders, and monitor campaign performance. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Brevo Automation via Rube MCP
Automate Brevo (formerly Sendinblue) email marketing operations through Composio's Brevo toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Brevo connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `brevo`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `brevo`
3. If connection is not ACTIVE, follow the returned auth link to complete Brevo authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Manage Email Campaigns
**When to use**: User wants to list, review, or update email campaigns
**Tool sequence**:
1. `BREVO_LIST_EMAIL_CAMPAIGNS` - List all campaigns with filters [Required]
2. `BREVO_UPDATE_EMAIL_CAMPAIGN` - Update campaign content or settings [Optional]
**Key parameters for listing**:
- `type`: Campaign type ('classic' or 'trigger')
- `status`: Campaign status ('suspended', 'archive', 'sent', 'queued', 'draft', 'inProcess', 'inReview')
- `startDate`/`endDate`: Date range filter (YYYY-MM-DDTHH:mm:ss.SSSZ format)
- `statistics`: Stats type to include ('globalStats', 'linksStats', 'statsByDomain')
- `limit`: Results per page (max 100, default 50)
- `offset`: Pagination offset
- `sort`: Sort order ('asc' or 'desc')
- `excludeHtmlContent`: Set `true` to reduce response size
**Key parameters for update**:
- `campaign_id`: Numeric campaign ID (required)
- `name`: Campaign name
- `subject`: Email subject line
- `htmlContent`: HTML email body (mutually exclusive with `htmlUrl`)
- `htmlUrl`: URL to HTML content
- `sender`: Sender object with `name`, `email`, or `id`
- `recipients`: Object with `listIds` and `exclusionListIds`
- `scheduledAt`: Scheduled send time (YYYY-MM-DDTHH:mm:ss.SSSZ)
**Pitfalls**:
- `startDate` and `endDate` are mutually required; provide both or neither
- Date filters only work when `status` is not passed or set to 'sent'
- `htmlContent` and `htmlUrl` are mutually exclusive
- Campaign `sender` email must be a verified sender in Brevo
- A/B testing fields (`subjectA`, `subjectB`, `splitRule`, `winnerCriteria`) require `abTesting: true`
- `scheduledAt` uses full ISO 8601 format with timezone
### 2. Create and Manage Email Templates
**When to use**: User wants to create, edit, list, or delete email templates
**Tool sequence**:
1. `BREVO_GET_ALL_EMAIL_TEMPLATES` - List all templates [Required]
2. `BREVO_CREATE_OR_UPDATE_EMAIL_TEMPLATE` - Create a new template or update existing [Required]
3. `BREVO_DELETE_EMAIL_TEMPLATE` - Delete an inactive template [Optional]
**Key parameters for listing**:
- `templateStatus`: Filter active (`true`) or inactive (`false`) templates
- `limit`: Results per page (max 1000, default 50)
- `offset`: Pagination offset
- `sort`: Sort order ('asc' or 'desc')
**Key parameters for create/update**:
- `templateId`: Include to update; omit to create new
- `templateName`: Template display name (required for creation)
- `subject`: Email subject line (required for creation)
- `htmlContent`: HTML template body (min 10 characters; use this or `htmlUrl`)
- `sender`: Sender object with `name` and `email`, or `id` (required for creation)
- `replyTo`: Reply-to email address
- `isActive`: Activate or deactivate the template
- `tag`: Category tag for the template
**Pitfalls**:
- When `templateId` is provided, the tool updates; when omitted, it creates
- For creation, `templateName`, `subject`, and `sender` are required
- `htmlContent` must be at least 10 characters
- Template personalization uses `{{contact.ATTRIBUTE}}` syntax
- Only inactive templates can be deleted
- `htmlContent` and `htmlUrl` are mutually exclusive
### 3. Manage Senders
**When to use**: User wants to view authorized sender identities
**Tool sequence**:
1. `BREVO_GET_ALL_SENDERS` - List all verified senders [Required]
**Key parameters**: (none required)
**Pitfalls**:
- Senders must be verified before they can be used in campaigns or templates
- Sender verification is done through the Brevo web interface, not via API
- Sender IDs can be used in `sender.id` fields for campaigns and templates
### 4. Configure A/B Testing Campaigns
**When to use**: User wants to set up or modify A/B test settings on a campaign
**Tool sequence**:
1. `BREVO_LIST_EMAIL_CAMPAIGNS` - Find the target campaign [Prerequisite]
2. `BREVO_UPDATE_EMAIL_CAMPAIGN` - Configure A/B test settings [Required]
**Key parameters**:
- `campaign_id`: Campaign to configure
- `abTesting`: Set to `true` to enable A/B testing
- `subjectA`: Subject line for variant A
- `subjectB`: Subject line for variant B
- `splitRule`: Percentage split for the test (1-99)
- `winnerCriteria`: 'open' or 'click' for determining the winner
- `winnerDelay`: Hours to wait before selecting winner (1-168)
**Pitfalls**:
- A/B testing must be enabled (`abTesting: true`) before setting variant fields
- `splitRule` is the percentage of contacts that receive variant A
- `winnerDelay` defines how long to test before sending the winner to remaining contacts
- Only works with 'classic' campaign type
## Common Patterns
### Campaign Lifecycle
```
1. Create campaign (status: draft)
2. Set recipients (listIds)
3. Configure content (htmlContent or htmlUrl)
4. Optionally schedule (scheduledAt)
5. Send or schedule via Brevo UI (API update can set scheduledAt)
```
### Pagination
- Use `limit` (page size) and `offset` (starting index)
- Default limit is 50; max varies by endpoint (100 for campaigns, 1000 for templates)
- Increment `offset` by `limit` each page
- Check `count` in response to determine total available
### Template Personalization
```
- First name: {{contact.FIRSTNAME}}
- Last name: {{contact.LASTNAME}}
- Custom attribute: {{contact.CUSTOM_ATTRIBUTE}}
- Mirror link: {{mirror}}
- Unsubscribe link: {{unsubscribe}}
```
## Known Pitfalls
**Date Formats**:
- All dates use ISO 8601 with milliseconds: YYYY-MM-DDTHH:mm:ss.SSSZ
- Pass timezone in the date-time format for accurate results
- `startDate` and `endDate` must be used together
**Sender Verification**:
- All sender emails must be verified in Brevo before use
- Unverified senders cause campaign creation/update failures
- Use GET_ALL_SENDERS to check available verified senders
**Rate Limits**:
- Brevo API has rate limits per account plan
- Implement backoff on 429 responses
- Template operations have lower limits than read operations
**Response Parsing**:
- Response data may be nested under `data` or `data.data`
- Parse defensively with fallback patterns
- Campaign and template IDs are numeric integers
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List campaigns | BREVO_LIST_EMAIL_CAMPAIGNS | type, status, limit, offset |
| Update campaign | BREVO_UPDATE_EMAIL_CAMPAIGN | campaign_id, subject, htmlContent |
| List templates | BREVO_GET_ALL_EMAIL_TEMPLATES | templateStatus, limit, offset |
| Create template | BREVO_CREATE_OR_UPDATE_EMAIL_TEMPLATE | templateName, subject, htmlContent, sender |
| Update template | BREVO_CREATE_OR_UPDATE_EMAIL_TEMPLATE | templateId, htmlContent |
| Delete template | BREVO_DELETE_EMAIL_TEMPLATE | templateId |
| List senders | BREVO_GET_ALL_SENDERS | (none) |

View File

@@ -0,0 +1,203 @@
---
name: cal-com-automation
description: "Automate Cal.com tasks via Rube MCP (Composio): manage bookings, check availability, configure webhooks, and handle teams. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Cal.com Automation via Rube MCP
Automate Cal.com scheduling operations through Composio's Cal toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Cal.com connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `cal`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `cal`
3. If connection is not ACTIVE, follow the returned auth link to complete Cal.com authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Manage Bookings
**When to use**: User wants to list, create, or review bookings
**Tool sequence**:
1. `CAL_FETCH_ALL_BOOKINGS` - List all bookings with filters [Required]
2. `CAL_POST_NEW_BOOKING_REQUEST` - Create a new booking [Optional]
**Key parameters for listing**:
- `status`: Filter by booking status ('upcoming', 'recurring', 'past', 'cancelled', 'unconfirmed')
- `afterStart`: Filter bookings after this date (ISO 8601)
- `beforeEnd`: Filter bookings before this date (ISO 8601)
**Key parameters for creation**:
- `eventTypeId`: Event type ID for the booking
- `start`: Booking start time (ISO 8601)
- `end`: Booking end time (ISO 8601)
- `name`: Attendee name
- `email`: Attendee email
- `timeZone`: Attendee timezone (IANA format)
- `language`: Attendee language code
- `metadata`: Additional metadata object
**Pitfalls**:
- Date filters use ISO 8601 format with timezone (e.g., '2024-01-15T09:00:00Z')
- `eventTypeId` must reference a valid, active event type
- Booking creation requires matching an available slot; check availability first
- Time zone must be a valid IANA timezone string (e.g., 'America/New_York')
- Status filter values are specific strings; invalid values return empty results
### 2. Check Availability
**When to use**: User wants to find free/busy times or available booking slots
**Tool sequence**:
1. `CAL_RETRIEVE_CALENDAR_BUSY_TIMES` - Get busy time blocks [Required]
2. `CAL_GET_AVAILABLE_SLOTS_INFO` - Get specific available slots [Required]
**Key parameters**:
- `dateFrom`: Start date for availability check (YYYY-MM-DD)
- `dateTo`: End date for availability check (YYYY-MM-DD)
- `eventTypeId`: Event type to check slots for
- `timeZone`: Timezone for the availability response
- `loggedInUsersTz`: Timezone of the requesting user
**Pitfalls**:
- Busy times show when the user is NOT available
- Available slots are specific to an event type's duration and configuration
- Date range should be reasonable (not months in advance) to get accurate results
- Timezone affects how slots are displayed; always specify explicitly
- Availability reflects calendar integrations (Google Calendar, Outlook, etc.)
### 3. Configure Webhooks
**When to use**: User wants to set up or manage webhook notifications for booking events
**Tool sequence**:
1. `CAL_RETRIEVE_WEBHOOKS_LIST` - List existing webhooks [Required]
2. `CAL_GET_WEBHOOK_BY_ID` - Get specific webhook details [Optional]
3. `CAL_UPDATE_WEBHOOK_BY_ID` - Update webhook configuration [Optional]
4. `CAL_DELETE_WEBHOOK_BY_ID` - Remove a webhook [Optional]
**Key parameters**:
- `id`: Webhook ID for GET/UPDATE/DELETE operations
- `subscriberUrl`: Webhook endpoint URL
- `eventTriggers`: Array of event types to trigger on
- `active`: Whether the webhook is active
- `secret`: Webhook signing secret
**Pitfalls**:
- Webhook URLs must be publicly accessible HTTPS endpoints
- Event triggers include: 'BOOKING_CREATED', 'BOOKING_RESCHEDULED', 'BOOKING_CANCELLED', etc.
- Inactive webhooks do not fire; toggle `active` to enable/disable
- Webhook secrets are used for payload signature verification
### 4. Manage Teams
**When to use**: User wants to create, view, or manage teams and team event types
**Tool sequence**:
1. `CAL_GET_TEAMS_LIST` - List all teams [Required]
2. `CAL_GET_TEAM_INFORMATION_BY_TEAM_ID` - Get specific team details [Optional]
3. `CAL_CREATE_TEAM_IN_ORGANIZATION` - Create a new team [Optional]
4. `CAL_RETRIEVE_TEAM_EVENT_TYPES` - List event types for a team [Optional]
**Key parameters**:
- `teamId`: Team identifier
- `name`: Team name (for creation)
- `slug`: URL-friendly team identifier
**Pitfalls**:
- Team creation may require organization-level permissions
- Team event types are separate from personal event types
- Team slugs must be URL-safe and unique within the organization
### 5. Organization Management
**When to use**: User wants to view organization details
**Tool sequence**:
1. `CAL_GET_ORGANIZATION_ID` - Get the organization ID [Required]
**Key parameters**: (none required)
**Pitfalls**:
- Organization ID is needed for team creation and org-level operations
- Not all Cal.com accounts have organizations; personal plans may return errors
## Common Patterns
### Booking Creation Flow
```
1. Call CAL_GET_AVAILABLE_SLOTS_INFO to find open slots
2. Present available times to the user
3. Call CAL_POST_NEW_BOOKING_REQUEST with selected slot
4. Confirm booking creation response
```
### ID Resolution
**Team name -> Team ID**:
```
1. Call CAL_GET_TEAMS_LIST
2. Find team by name in response
3. Extract id field
```
### Webhook Setup
```
1. Call CAL_RETRIEVE_WEBHOOKS_LIST to check existing hooks
2. Create or update webhook with desired triggers
3. Verify webhook fires on test booking
```
## Known Pitfalls
**Date/Time Formats**:
- Booking times: ISO 8601 with timezone (e.g., '2024-01-15T09:00:00Z')
- Availability dates: YYYY-MM-DD format
- Always specify timezone explicitly to avoid confusion
**Event Types**:
- Event type IDs are numeric integers
- Event types define duration, location, and booking rules
- Disabled event types cannot accept new bookings
**Permissions**:
- Team operations require team membership or admin access
- Organization operations require org-level permissions
- Webhook management requires appropriate access level
**Rate Limits**:
- Cal.com API has rate limits per API key
- Implement backoff on 429 responses
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List bookings | CAL_FETCH_ALL_BOOKINGS | status, afterStart, beforeEnd |
| Create booking | CAL_POST_NEW_BOOKING_REQUEST | eventTypeId, start, end, name, email |
| Get busy times | CAL_RETRIEVE_CALENDAR_BUSY_TIMES | dateFrom, dateTo |
| Get available slots | CAL_GET_AVAILABLE_SLOTS_INFO | eventTypeId, dateFrom, dateTo |
| List webhooks | CAL_RETRIEVE_WEBHOOKS_LIST | (none) |
| Get webhook | CAL_GET_WEBHOOK_BY_ID | id |
| Update webhook | CAL_UPDATE_WEBHOOK_BY_ID | id, subscriberUrl, eventTriggers |
| Delete webhook | CAL_DELETE_WEBHOOK_BY_ID | id |
| List teams | CAL_GET_TEAMS_LIST | (none) |
| Get team | CAL_GET_TEAM_INFORMATION_BY_TEAM_ID | teamId |
| Create team | CAL_CREATE_TEAM_IN_ORGANIZATION | name, slug |
| Team event types | CAL_RETRIEVE_TEAM_EVENT_TYPES | teamId |
| Get org ID | CAL_GET_ORGANIZATION_ID | (none) |

View File

@@ -0,0 +1,211 @@
---
name: calendly-automation
description: "Automate Calendly scheduling, event management, invitee tracking, availability checks, and organization administration via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Calendly Automation via Rube MCP
Automate Calendly operations including event listing, invitee management, scheduling link creation, availability queries, and organization administration through Composio's Calendly toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Calendly connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `calendly`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
- Many operations require the user's Calendly URI, obtained via `CALENDLY_GET_CURRENT_USER`
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `calendly`
3. If connection is not ACTIVE, follow the returned auth link to complete Calendly OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. List and View Scheduled Events
**When to use**: User wants to see their upcoming, past, or filtered Calendly events
**Tool sequence**:
1. `CALENDLY_GET_CURRENT_USER` - Get authenticated user URI and organization URI [Prerequisite]
2. `CALENDLY_LIST_EVENTS` - List events scoped by user, organization, or group [Required]
3. `CALENDLY_GET_EVENT` - Get detailed info for a specific event by UUID [Optional]
**Key parameters**:
- `user`: Full Calendly API URI (e.g., `https://api.calendly.com/users/{uuid}`) - NOT `"me"`
- `organization`: Full organization URI for org-scoped queries
- `status`: `"active"` or `"canceled"`
- `min_start_time` / `max_start_time`: UTC timestamps (e.g., `2024-01-01T00:00:00.000000Z`)
- `invitee_email`: Filter events by invitee email (filter only, not a scope)
- `sort`: `"start_time:asc"` or `"start_time:desc"`
- `count`: Results per page (default 20)
- `page_token`: Pagination token from previous response
**Pitfalls**:
- Exactly ONE of `user`, `organization`, or `group` must be provided - omitting or combining scopes fails
- The `user` parameter requires the full API URI, not `"me"` - use `CALENDLY_GET_CURRENT_USER` first
- `invitee_email` is a filter, not a scope; you still need one of user/organization/group
- Pagination uses `count` + `page_token`; loop until `page_token` is absent for complete results
- Admin rights may be needed for organization or group scope queries
### 2. Manage Event Invitees
**When to use**: User wants to see who is booked for events or get invitee details
**Tool sequence**:
1. `CALENDLY_LIST_EVENTS` - Find the target event(s) [Prerequisite]
2. `CALENDLY_LIST_EVENT_INVITEES` - List all invitees for a specific event [Required]
3. `CALENDLY_GET_EVENT_INVITEE` - Get detailed info for a single invitee [Optional]
**Key parameters**:
- `uuid`: Event UUID (for `LIST_EVENT_INVITEES`)
- `event_uuid` + `invitee_uuid`: Both required for `GET_EVENT_INVITEE`
- `email`: Filter invitees by email address
- `status`: `"active"` or `"canceled"`
- `sort`: `"created_at:asc"` or `"created_at:desc"`
- `count`: Results per page (default 20)
**Pitfalls**:
- The `uuid` parameter for `CALENDLY_LIST_EVENT_INVITEES` is the event UUID, not the invitee UUID
- Paginate using `page_token` until absent for complete invitee lists
- Canceled invitees are excluded by default; use `status: "canceled"` to see them
### 3. Create Scheduling Links and Check Availability
**When to use**: User wants to generate a booking link or check available time slots
**Tool sequence**:
1. `CALENDLY_GET_CURRENT_USER` - Get user URI [Prerequisite]
2. `CALENDLY_LIST_USER_S_EVENT_TYPES` - List available event types [Required]
3. `CALENDLY_LIST_EVENT_TYPE_AVAILABLE_TIMES` - Check available slots for an event type [Optional]
4. `CALENDLY_CREATE_SCHEDULING_LINK` - Generate a single-use scheduling link [Required]
5. `CALENDLY_LIST_USER_AVAILABILITY_SCHEDULES` - View user's availability schedules [Optional]
**Key parameters**:
- `owner`: Event type URI (e.g., `https://api.calendly.com/event_types/{uuid}`)
- `owner_type`: `"EventType"` (default)
- `max_event_count`: Must be exactly `1` for single-use links
- `start_time` / `end_time`: UTC timestamps for availability queries (max 7-day range)
- `active`: Boolean to filter active/inactive event types
- `user`: User URI for event type listing
**Pitfalls**:
- `CALENDLY_CREATE_SCHEDULING_LINK` can return 403 if token lacks rights or owner URI is invalid
- `CALENDLY_LIST_EVENT_TYPE_AVAILABLE_TIMES` requires UTC timestamps and max 7-day range; split longer searches
- Available times results are NOT paginated - all results returned in one response
- Event type URIs must be full API URIs (e.g., `https://api.calendly.com/event_types/...`)
### 4. Cancel Events
**When to use**: User wants to cancel a scheduled Calendly event
**Tool sequence**:
1. `CALENDLY_LIST_EVENTS` - Find the event to cancel [Prerequisite]
2. `CALENDLY_GET_EVENT` - Confirm event details before cancellation [Prerequisite]
3. `CALENDLY_LIST_EVENT_INVITEES` - Check who will be affected [Optional]
4. `CALENDLY_CANCEL_EVENT` - Cancel the event [Required]
**Key parameters**:
- `uuid`: Event UUID to cancel
- `reason`: Optional cancellation reason (may be included in notification to invitees)
**Pitfalls**:
- Cancellation is IRREVERSIBLE - always confirm with the user before calling
- Cancellation may trigger notifications to invitees
- Only active events can be canceled; already-canceled events return errors
- Get explicit user confirmation before executing `CALENDLY_CANCEL_EVENT`
### 5. Manage Organization and Invitations
**When to use**: User wants to invite members, manage organization, or handle org invitations
**Tool sequence**:
1. `CALENDLY_GET_CURRENT_USER` - Get user and organization context [Prerequisite]
2. `CALENDLY_GET_ORGANIZATION` - Get organization details [Optional]
3. `CALENDLY_LIST_ORGANIZATION_INVITATIONS` - Check existing invitations [Optional]
4. `CALENDLY_CREATE_ORGANIZATION_INVITATION` - Send an org invitation [Required]
5. `CALENDLY_REVOKE_USER_S_ORGANIZATION_INVITATION` - Revoke a pending invitation [Optional]
6. `CALENDLY_REMOVE_USER_FROM_ORGANIZATION` - Remove a member [Optional]
**Key parameters**:
- `uuid`: Organization UUID
- `email`: Email address of user to invite
- `status`: Filter invitations by `"pending"`, `"accepted"`, or `"declined"`
**Pitfalls**:
- Only org owners/admins can manage invitations and removals; others get authorization errors
- Duplicate active invitations for the same email are rejected - check existing invitations first
- Organization owners cannot be removed via `CALENDLY_REMOVE_USER_FROM_ORGANIZATION`
- Invitation statuses include pending, accepted, declined, and revoked - handle each appropriately
## Common Patterns
### ID Resolution
Calendly uses full API URIs as identifiers, not simple IDs:
- **Current user URI**: `CALENDLY_GET_CURRENT_USER` returns `resource.uri` (e.g., `https://api.calendly.com/users/{uuid}`)
- **Organization URI**: Found in current user response at `resource.current_organization`
- **Event UUID**: Extract from event URI or list responses
- **Event type URI**: From `CALENDLY_LIST_USER_S_EVENT_TYPES` response
Important: Never use `"me"` as a user parameter in list/filter endpoints. Always resolve to the full URI first.
### Pagination
Most Calendly list endpoints use token-based pagination:
- Set `count` for page size (default 20)
- Follow `page_token` from `pagination.next_page_token` until absent
- Sort with `field:direction` format (e.g., `start_time:asc`, `created_at:desc`)
### Time Handling
- All timestamps must be in UTC format: `yyyy-MM-ddTHH:mm:ss.ffffffZ`
- Use `min_start_time` / `max_start_time` for date range filtering on events
- Available times queries have a maximum 7-day range; split longer searches into multiple calls
## Known Pitfalls
### URI Formats
- All entity references use full Calendly API URIs (e.g., `https://api.calendly.com/users/{uuid}`)
- Never pass bare UUIDs where URIs are expected, and never pass `"me"` to list endpoints
- Extract UUIDs from URIs when tools expect UUID parameters (e.g., `CALENDLY_GET_EVENT`)
### Scope Requirements
- `CALENDLY_LIST_EVENTS` requires exactly one scope (user, organization, or group) - no more, no less
- Organization/group scoped queries may require admin privileges
- Token scope determines which operations are available; 403 errors indicate insufficient permissions
### Data Relationships
- Events have invitees (attendees who booked)
- Event types define scheduling pages (duration, availability rules)
- Organizations contain users and groups
- Scheduling links are tied to event types, not directly to events
### Rate Limits
- Calendly API has rate limits; avoid tight loops over large datasets
- Paginate responsibly and add delays for batch operations
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Get current user | `CALENDLY_GET_CURRENT_USER` | (none) |
| Get user by UUID | `CALENDLY_GET_USER` | `uuid` |
| List events | `CALENDLY_LIST_EVENTS` | `user`, `status`, `min_start_time` |
| Get event details | `CALENDLY_GET_EVENT` | `uuid` |
| Cancel event | `CALENDLY_CANCEL_EVENT` | `uuid`, `reason` |
| List invitees | `CALENDLY_LIST_EVENT_INVITEES` | `uuid`, `status`, `email` |
| Get invitee | `CALENDLY_GET_EVENT_INVITEE` | `event_uuid`, `invitee_uuid` |
| List event types | `CALENDLY_LIST_USER_S_EVENT_TYPES` | `user`, `active` |
| Get event type | `CALENDLY_GET_EVENT_TYPE` | `uuid` |
| Check availability | `CALENDLY_LIST_EVENT_TYPE_AVAILABLE_TIMES` | event type URI, `start_time`, `end_time` |
| Create scheduling link | `CALENDLY_CREATE_SCHEDULING_LINK` | `owner`, `max_event_count` |
| List availability schedules | `CALENDLY_LIST_USER_AVAILABILITY_SCHEDULES` | user URI |
| Get organization | `CALENDLY_GET_ORGANIZATION` | `uuid` |
| Invite to org | `CALENDLY_CREATE_ORGANIZATION_INVITATION` | `uuid`, `email` |
| List org invitations | `CALENDLY_LIST_ORGANIZATION_INVITATIONS` | `uuid`, `status` |
| Revoke org invitation | `CALENDLY_REVOKE_USER_S_ORGANIZATION_INVITATION` | org UUID, invitation UUID |
| Remove from org | `CALENDLY_REMOVE_USER_FROM_ORGANIZATION` | membership UUID |

View File

@@ -0,0 +1,217 @@
---
name: canva-automation
description: "Automate Canva tasks via Rube MCP (Composio): designs, exports, folders, brand templates, autofill. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Canva Automation via Rube MCP
Automate Canva design operations through Composio's Canva toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Canva connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `canva`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `canva`
3. If connection is not ACTIVE, follow the returned auth link to complete Canva OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. List and Browse Designs
**When to use**: User wants to find existing designs or browse their Canva library
**Tool sequence**:
1. `CANVA_LIST_USER_DESIGNS` - List all designs with optional filters [Required]
**Key parameters**:
- `query`: Search term to filter designs by name
- `continuation`: Pagination token from previous response
- `ownership`: Filter by 'owned', 'shared', or 'any'
- `sort_by`: Sort field (e.g., 'modified_at', 'title')
**Pitfalls**:
- Results are paginated; follow `continuation` token until absent
- Deleted designs may still appear briefly; check design status
- Search is substring-based, not fuzzy matching
### 2. Create and Design
**When to use**: User wants to create a new Canva design from scratch or from a template
**Tool sequence**:
1. `CANVA_ACCESS_USER_SPECIFIC_BRAND_TEMPLATES_LIST` - Browse available brand templates [Optional]
2. `CANVA_CREATE_CANVA_DESIGN_WITH_OPTIONAL_ASSET` - Create a new design [Required]
**Key parameters**:
- `design_type`: Type of design (e.g., 'Presentation', 'Poster', 'SocialMedia')
- `title`: Name for the new design
- `asset_id`: Optional asset to include in the design
- `width` / `height`: Custom dimensions in pixels
**Pitfalls**:
- Design type must match Canva's predefined types exactly
- Custom dimensions have minimum and maximum limits
- Asset must be uploaded first via CANVA_CREATE_ASSET_UPLOAD_JOB before referencing
### 3. Upload Assets
**When to use**: User wants to upload images or files to Canva for use in designs
**Tool sequence**:
1. `CANVA_CREATE_ASSET_UPLOAD_JOB` - Initiate the asset upload [Required]
2. `CANVA_FETCH_ASSET_UPLOAD_JOB_STATUS` - Poll until upload completes [Required]
**Key parameters**:
- `name`: Display name for the asset
- `url`: Public URL of the file to upload (for URL-based uploads)
- `job_id`: Upload job ID returned from step 1 (for status polling)
**Pitfalls**:
- Upload is asynchronous; you MUST poll the job status until it completes
- Supported formats include PNG, JPG, SVG, MP4, GIF
- File size limits apply; large files may take longer to process
- The `job_id` from CREATE returns the ID needed for status polling
- Status values: 'in_progress', 'success', 'failed'
### 4. Export Designs
**When to use**: User wants to download or export a Canva design as PDF, PNG, or other format
**Tool sequence**:
1. `CANVA_LIST_USER_DESIGNS` - Find the design to export [Prerequisite]
2. `CANVA_CREATE_CANVA_DESIGN_EXPORT_JOB` - Start the export process [Required]
3. `CANVA_GET_DESIGN_EXPORT_JOB_RESULT` - Poll until export completes and get download URL [Required]
**Key parameters**:
- `design_id`: ID of the design to export
- `format`: Export format ('pdf', 'png', 'jpg', 'svg', 'mp4', 'gif', 'pptx')
- `pages`: Specific page numbers to export (array)
- `quality`: Export quality ('regular', 'high')
- `job_id`: Export job ID for polling status
**Pitfalls**:
- Export is asynchronous; you MUST poll the job result until it completes
- Download URLs from completed exports expire after a limited time
- Large designs with many pages take longer to export
- Not all formats support all design types (e.g., MP4 only for animations)
- Poll interval: wait 2-3 seconds between status checks
### 5. Organize with Folders
**When to use**: User wants to create folders or organize designs into folders
**Tool sequence**:
1. `CANVA_POST_FOLDERS` - Create a new folder [Required]
2. `CANVA_MOVE_ITEM_TO_SPECIFIED_FOLDER` - Move designs into folders [Optional]
**Key parameters**:
- `name`: Folder name
- `parent_folder_id`: Parent folder for nested organization
- `item_id`: ID of the design or asset to move
- `folder_id`: Target folder ID
**Pitfalls**:
- Folder names must be unique within the same parent folder
- Moving items between folders updates their location immediately
- Root-level folders have no parent_folder_id
### 6. Autofill from Brand Templates
**When to use**: User wants to generate designs by filling brand template placeholders with data
**Tool sequence**:
1. `CANVA_ACCESS_USER_SPECIFIC_BRAND_TEMPLATES_LIST` - List available brand templates [Required]
2. `CANVA_INITIATE_CANVA_DESIGN_AUTOFILL_JOB` - Start autofill with data [Required]
**Key parameters**:
- `brand_template_id`: ID of the brand template to use
- `title`: Title for the generated design
- `data`: Key-value mapping of placeholder names to replacement values
**Pitfalls**:
- Template placeholders must match exactly (case-sensitive)
- Autofill is asynchronous; poll for completion
- Only brand templates support autofill, not regular designs
- Data values must match the expected type for each placeholder (text, image URL)
## Common Patterns
### Async Job Pattern
Many Canva operations are asynchronous:
```
1. Initiate job (upload, export, autofill) -> get job_id
2. Poll status endpoint with job_id every 2-3 seconds
3. Check for 'success' or 'failed' status
4. On success, extract result (asset_id, download_url, design_id)
```
### ID Resolution
**Design name -> Design ID**:
```
1. Call CANVA_LIST_USER_DESIGNS with query=design_name
2. Find matching design in results
3. Extract id field
```
**Brand template name -> Template ID**:
```
1. Call CANVA_ACCESS_USER_SPECIFIC_BRAND_TEMPLATES_LIST
2. Find template by name
3. Extract brand_template_id
```
### Pagination
- Check response for `continuation` token
- Pass token in next request's `continuation` parameter
- Continue until `continuation` is absent or empty
## Known Pitfalls
**Async Operations**:
- Uploads, exports, and autofills are all asynchronous
- Always poll job status; do not assume immediate completion
- Download URLs from exports expire; use them promptly
**Asset Management**:
- Assets must be uploaded before they can be used in designs
- Upload job must reach 'success' status before the asset_id is valid
- Supported formats vary; check Canva documentation for current limits
**Rate Limits**:
- Canva API has rate limits per endpoint
- Implement exponential backoff for bulk operations
- Batch operations where possible to reduce API calls
**Response Parsing**:
- Response data may be nested under `data` key
- Job status responses include different fields based on completion state
- Parse defensively with fallbacks for optional fields
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List designs | CANVA_LIST_USER_DESIGNS | query, continuation |
| Create design | CANVA_CREATE_CANVA_DESIGN_WITH_OPTIONAL_ASSET | design_type, title |
| Upload asset | CANVA_CREATE_ASSET_UPLOAD_JOB | name, url |
| Check upload | CANVA_FETCH_ASSET_UPLOAD_JOB_STATUS | job_id |
| Export design | CANVA_CREATE_CANVA_DESIGN_EXPORT_JOB | design_id, format |
| Get export | CANVA_GET_DESIGN_EXPORT_JOB_RESULT | job_id |
| Create folder | CANVA_POST_FOLDERS | name, parent_folder_id |
| Move to folder | CANVA_MOVE_ITEM_TO_SPECIFIED_FOLDER | item_id, folder_id |
| List templates | CANVA_ACCESS_USER_SPECIFIC_BRAND_TEMPLATES_LIST | (none) |
| Autofill template | CANVA_INITIATE_CANVA_DESIGN_AUTOFILL_JOB | brand_template_id, data |

View File

@@ -292,7 +292,7 @@ jobs:
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.version.outputs.tag }}
body_path: RELEASE_NOTES.md
body_path: CHANGELOG.md
generate_release_notes: true
```
@@ -368,7 +368,7 @@ repo = "repo"
git cliff -o CHANGELOG.md
# Generate for specific range
git cliff v1.0.0..v2.0.0 -o RELEASE_NOTES.md
git cliff v1.0.0..v2.0.0 -o CHANGELOG.md
# Preview without writing
git cliff --unreleased --dry-run

View File

@@ -0,0 +1,177 @@
---
name: circleci-automation
description: "Automate CircleCI tasks via Rube MCP (Composio): trigger pipelines, monitor workflows/jobs, retrieve artifacts and test metadata. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# CircleCI Automation via Rube MCP
Automate CircleCI CI/CD operations through Composio's CircleCI toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active CircleCI connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `circleci`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `circleci`
3. If connection is not ACTIVE, follow the returned auth link to complete CircleCI authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Trigger a Pipeline
**When to use**: User wants to start a new CI/CD pipeline run
**Tool sequence**:
1. `CIRCLECI_TRIGGER_PIPELINE` - Trigger a new pipeline on a project [Required]
2. `CIRCLECI_LIST_WORKFLOWS_BY_PIPELINE_ID` - Monitor resulting workflows [Optional]
**Key parameters**:
- `project_slug`: Project identifier in format `gh/org/repo` or `bb/org/repo`
- `branch`: Git branch to run the pipeline on
- `tag`: Git tag to run the pipeline on (mutually exclusive with branch)
- `parameters`: Pipeline parameter key-value pairs
**Pitfalls**:
- `project_slug` format is `{vcs}/{org}/{repo}` (e.g., `gh/myorg/myrepo`)
- `branch` and `tag` are mutually exclusive; providing both causes an error
- Pipeline parameters must match those defined in `.circleci/config.yml`
- Triggering returns a pipeline ID; workflows start asynchronously
### 2. Monitor Pipelines and Workflows
**When to use**: User wants to check the status of pipelines or workflows
**Tool sequence**:
1. `CIRCLECI_LIST_PIPELINES_FOR_PROJECT` - List recent pipelines for a project [Required]
2. `CIRCLECI_LIST_WORKFLOWS_BY_PIPELINE_ID` - List workflows within a pipeline [Required]
3. `CIRCLECI_GET_PIPELINE_CONFIG` - View the pipeline configuration used [Optional]
**Key parameters**:
- `project_slug`: Project identifier in `{vcs}/{org}/{repo}` format
- `pipeline_id`: UUID of a specific pipeline
- `branch`: Filter pipelines by branch name
- `page_token`: Pagination cursor for next page of results
**Pitfalls**:
- Pipeline IDs are UUIDs, not numeric IDs
- Workflows inherit the pipeline ID; a single pipeline can have multiple workflows
- Workflow states include: success, running, not_run, failed, error, failing, on_hold, canceled, unauthorized
- `page_token` is returned in responses for pagination; continue until absent
### 3. Inspect Job Details
**When to use**: User wants to drill into a specific job's execution details
**Tool sequence**:
1. `CIRCLECI_LIST_WORKFLOWS_BY_PIPELINE_ID` - Find workflow containing the job [Prerequisite]
2. `CIRCLECI_GET_JOB_DETAILS` - Get detailed job information [Required]
**Key parameters**:
- `project_slug`: Project identifier
- `job_number`: Numeric job number (not UUID)
**Pitfalls**:
- Job numbers are integers, not UUIDs (unlike pipeline and workflow IDs)
- Job details include executor type, parallelism, start/stop times, and status
- Job statuses: success, running, not_run, failed, retried, timedout, infrastructure_fail, canceled
### 4. Retrieve Build Artifacts
**When to use**: User wants to download or list artifacts produced by a job
**Tool sequence**:
1. `CIRCLECI_GET_JOB_DETAILS` - Confirm job completed successfully [Prerequisite]
2. `CIRCLECI_GET_JOB_ARTIFACTS` - List all artifacts from the job [Required]
**Key parameters**:
- `project_slug`: Project identifier
- `job_number`: Numeric job number
**Pitfalls**:
- Artifacts are only available after job completion
- Each artifact has a `path` and `url` for download
- Artifact URLs may require authentication headers to download
- Large artifacts may have download size limits
### 5. Review Test Results
**When to use**: User wants to check test outcomes for a specific job
**Tool sequence**:
1. `CIRCLECI_GET_JOB_DETAILS` - Verify job ran tests [Prerequisite]
2. `CIRCLECI_GET_TEST_METADATA` - Retrieve test results and metadata [Required]
**Key parameters**:
- `project_slug`: Project identifier
- `job_number`: Numeric job number
**Pitfalls**:
- Test metadata requires the job to have uploaded test results (JUnit XML format)
- If no test results were uploaded, the response will be empty
- Test metadata includes classname, name, result, message, and run_time fields
- Failed tests include failure messages in the `message` field
## Common Patterns
### Project Slug Format
```
Format: {vcs_type}/{org_name}/{repo_name}
- GitHub: gh/myorg/myrepo
- Bitbucket: bb/myorg/myrepo
```
### Pipeline -> Workflow -> Job Hierarchy
```
1. Call CIRCLECI_LIST_PIPELINES_FOR_PROJECT to get pipeline IDs
2. Call CIRCLECI_LIST_WORKFLOWS_BY_PIPELINE_ID with pipeline_id
3. Extract job numbers from workflow details
4. Call CIRCLECI_GET_JOB_DETAILS with job_number
```
### Pagination
- Check response for `next_page_token` field
- Pass token as `page_token` in next request
- Continue until `next_page_token` is absent or null
## Known Pitfalls
**ID Formats**:
- Pipeline IDs: UUIDs (e.g., `5034460f-c7c4-4c43-9457-de07e2029e7b`)
- Workflow IDs: UUIDs
- Job numbers: Integers (e.g., `123`)
- Do NOT mix up UUIDs and integers between different endpoints
**Project Slugs**:
- Must include VCS prefix: `gh/` for GitHub, `bb/` for Bitbucket
- Organization and repo names are case-sensitive
- Incorrect slug format causes 404 errors
**Rate Limits**:
- CircleCI API has per-endpoint rate limits
- Implement exponential backoff on 429 responses
- Avoid rapid polling; use reasonable intervals (5-10 seconds)
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Trigger pipeline | CIRCLECI_TRIGGER_PIPELINE | project_slug, branch, parameters |
| List pipelines | CIRCLECI_LIST_PIPELINES_FOR_PROJECT | project_slug, branch |
| List workflows | CIRCLECI_LIST_WORKFLOWS_BY_PIPELINE_ID | pipeline_id |
| Get pipeline config | CIRCLECI_GET_PIPELINE_CONFIG | pipeline_id |
| Get job details | CIRCLECI_GET_JOB_DETAILS | project_slug, job_number |
| Get job artifacts | CIRCLECI_GET_JOB_ARTIFACTS | project_slug, job_number |
| Get test metadata | CIRCLECI_GET_TEST_METADATA | project_slug, job_number |

View File

@@ -1,201 +1,94 @@
---
name: clean-code
description: Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments
allowed-tools: Read, Write, Edit
version: 2.0
priority: CRITICAL
description: "Applies principles from Robert C. Martin's 'Clean Code'. Use this skill when writing, reviewing, or refactoring code to ensure high quality, readability, and maintainability. Covers naming, functions, comments, error handling, and class design."
user-invocable: true
risk: safe
source: "ClawForge (https://github.com/jackjin1997/ClawForge)"
---
# Clean Code - Pragmatic AI Coding Standards
# Clean Code Skill
> **CRITICAL SKILL** - Be **concise, direct, and solution-focused**.
This skill embodies the principles of "Clean Code" by Robert C. Martin (Uncle Bob). Use it to transform "code that works" into "code that is clean."
---
## 🧠 Core Philosophy
> "Code is clean if it can be read, and enhanced by a developer other than its original author." — Grady Booch
## Core Principles
## When to Use
Use this skill when:
- **Writing new code**: To ensure high quality from the start.
- **Reviewing Pull Requests**: To provide constructive, principle-based feedback.
- **Refactoring legacy code**: To identify and remove code smells.
- **Improving team standards**: To align on industry-standard best practices.
| Principle | Rule |
|-----------|------|
| **SRP** | Single Responsibility - each function/class does ONE thing |
| **DRY** | Don't Repeat Yourself - extract duplicates, reuse |
| **KISS** | Keep It Simple - simplest solution that works |
| **YAGNI** | You Aren't Gonna Need It - don't build unused features |
| **Boy Scout** | Leave code cleaner than you found it |
## 1. Meaningful Names
- **Use Intention-Revealing Names**: `elapsedTimeInDays` instead of `d`.
- **Avoid Disinformation**: Don't use `accountList` if it's actually a `Map`.
- **Make Meaningful Distinctions**: Avoid `ProductData` vs `ProductInfo`.
- **Use Pronounceable/Searchable Names**: Avoid `genymdhms`.
- **Class Names**: Use nouns (`Customer`, `WikiPage`). Avoid `Manager`, `Data`.
- **Method Names**: Use verbs (`postPayment`, `deletePage`).
---
## 2. Functions
- **Small!**: Functions should be shorter than you think.
- **Do One Thing**: A function should do only one thing, and do it well.
- **One Level of Abstraction**: Don't mix high-level business logic with low-level details (like regex).
- **Descriptive Names**: `isPasswordValid` is better than `check`.
- **Arguments**: 0 is ideal, 1-2 is okay, 3+ requires a very strong justification.
- **No Side Effects**: Functions shouldn't secretly change global state.
## Naming Rules
## 3. Comments
- **Don't Comment Bad Code—Rewrite It**: Most comments are a sign of failure to express ourselves in code.
- **Explain Yourself in Code**:
```python
# Check if employee is eligible for full benefits
if employee.flags & HOURLY and employee.age > 65:
```
vs
```python
if employee.isEligibleForFullBenefits():
```
- **Good Comments**: Legal, Informative (regex intent), Clarification (external libraries), TODOs.
- **Bad Comments**: Mumbling, Redundant, Misleading, Mandated, Noise, Position Markers.
| Element | Convention |
|---------|------------|
| **Variables** | Reveal intent: `userCount` not `n` |
| **Functions** | Verb + noun: `getUserById()` not `user()` |
| **Booleans** | Question form: `isActive`, `hasPermission`, `canEdit` |
| **Constants** | SCREAMING_SNAKE: `MAX_RETRY_COUNT` |
## 4. Formatting
- **The Newspaper Metaphor**: High-level concepts at the top, details at the bottom.
- **Vertical Density**: Related lines should be close to each other.
- **Distance**: Variables should be declared near their usage.
- **Indentation**: Essential for structural readability.
> **Rule:** If you need a comment to explain a name, rename it.
## 5. Objects and Data Structures
- **Data Abstraction**: Hide the implementation behind interfaces.
- **The Law of Demeter**: A module should not know about the innards of the objects it manipulates. Avoid `a.getB().getC().doSomething()`.
- **Data Transfer Objects (DTO)**: Classes with public variables and no functions.
---
## 6. Error Handling
- **Use Exceptions instead of Return Codes**: Keeps logic clean.
- **Write Try-Catch-Finally First**: Defines the scope of the operation.
- **Don't Return Null**: It forces the caller to check for null every time.
- **Don't Pass Null**: Leads to `NullPointerException`.
## Function Rules
## 7. Unit Tests
- **The Three Laws of TDD**:
1. Don't write production code until you have a failing unit test.
2. Don't write more of a unit test than is sufficient to fail.
3. Don't write more production code than is sufficient to pass the failing test.
- **F.I.R.S.T. Principles**: Fast, Independent, Repeatable, Self-Validating, Timely.
| Rule | Description |
|------|-------------|
| **Small** | Max 20 lines, ideally 5-10 |
| **One Thing** | Does one thing, does it well |
| **One Level** | One level of abstraction per function |
| **Few Args** | Max 3 arguments, prefer 0-2 |
| **No Side Effects** | Don't mutate inputs unexpectedly |
## 8. Classes
- **Small!**: Classes should have a single responsibility (SRP).
- **The Stepdown Rule**: We want the code to read like a top-down narrative.
---
## Code Structure
| Pattern | Apply |
|---------|-------|
| **Guard Clauses** | Early returns for edge cases |
| **Flat > Nested** | Avoid deep nesting (max 2 levels) |
| **Composition** | Small functions composed together |
| **Colocation** | Keep related code close |
---
## AI Coding Style
| Situation | Action |
|-----------|--------|
| User asks for feature | Write it directly |
| User reports bug | Fix it, don't explain |
| No clear requirement | Ask, don't assume |
---
## Anti-Patterns (DON'T)
| ❌ Pattern | ✅ Fix |
|-----------|-------|
| Comment every line | Delete obvious comments |
| Helper for one-liner | Inline the code |
| Factory for 2 objects | Direct instantiation |
| utils.ts with 1 function | Put code where used |
| "First we import..." | Just write code |
| Deep nesting | Guard clauses |
| Magic numbers | Named constants |
| God functions | Split by responsibility |
---
## 🔴 Before Editing ANY File (THINK FIRST!)
**Before changing a file, ask yourself:**
| Question | Why |
|----------|-----|
| **What imports this file?** | They might break |
| **What does this file import?** | Interface changes |
| **What tests cover this?** | Tests might fail |
| **Is this a shared component?** | Multiple places affected |
**Quick Check:**
```
File to edit: UserService.ts
└── Who imports this? → UserController.ts, AuthController.ts
└── Do they need changes too? → Check function signatures
```
> 🔴 **Rule:** Edit the file + all dependent files in the SAME task.
> 🔴 **Never leave broken imports or missing updates.**
---
## Summary
| Do | Don't |
|----|-------|
| Write code directly | Write tutorials |
| Let code self-document | Add obvious comments |
| Fix bugs immediately | Explain the fix first |
| Inline small things | Create unnecessary files |
| Name things clearly | Use abbreviations |
| Keep functions small | Write 100+ line functions |
> **Remember: The user wants working code, not a programming lesson.**
---
## 🔴 Self-Check Before Completing (MANDATORY)
**Before saying "task complete", verify:**
| Check | Question |
|-------|----------|
| ✅ **Goal met?** | Did I do exactly what user asked? |
| ✅ **Files edited?** | Did I modify all necessary files? |
| ✅ **Code works?** | Did I test/verify the change? |
| ✅ **No errors?** | Lint and TypeScript pass? |
| ✅ **Nothing forgotten?** | Any edge cases missed? |
> 🔴 **Rule:** If ANY check fails, fix it before completing.
---
## Verification Scripts (MANDATORY)
> 🔴 **CRITICAL:** Each agent runs ONLY their own skill's scripts after completing work.
### Agent → Script Mapping
| Agent | Script | Command |
|-------|--------|---------|
| **frontend-specialist** | UX Audit | `python ~/.claude/skills/frontend-design/scripts/ux_audit.py .` |
| **frontend-specialist** | A11y Check | `python ~/.claude/skills/frontend-design/scripts/accessibility_checker.py .` |
| **backend-specialist** | API Validator | `python ~/.claude/skills/api-patterns/scripts/api_validator.py .` |
| **mobile-developer** | Mobile Audit | `python ~/.claude/skills/mobile-design/scripts/mobile_audit.py .` |
| **database-architect** | Schema Validate | `python ~/.claude/skills/database-design/scripts/schema_validator.py .` |
| **security-auditor** | Security Scan | `python ~/.claude/skills/vulnerability-scanner/scripts/security_scan.py .` |
| **seo-specialist** | SEO Check | `python ~/.claude/skills/seo-fundamentals/scripts/seo_checker.py .` |
| **seo-specialist** | GEO Check | `python ~/.claude/skills/geo-fundamentals/scripts/geo_checker.py .` |
| **performance-optimizer** | Lighthouse | `python ~/.claude/skills/performance-profiling/scripts/lighthouse_audit.py <url>` |
| **test-engineer** | Test Runner | `python ~/.claude/skills/testing-patterns/scripts/test_runner.py .` |
| **test-engineer** | Playwright | `python ~/.claude/skills/webapp-testing/scripts/playwright_runner.py <url>` |
| **Any agent** | Lint Check | `python ~/.claude/skills/lint-and-validate/scripts/lint_runner.py .` |
| **Any agent** | Type Coverage | `python ~/.claude/skills/lint-and-validate/scripts/type_coverage.py .` |
| **Any agent** | i18n Check | `python ~/.claude/skills/i18n-localization/scripts/i18n_checker.py .` |
> ❌ **WRONG:** `test-engineer` running `ux_audit.py`
> ✅ **CORRECT:** `frontend-specialist` running `ux_audit.py`
---
### 🔴 Script Output Handling (READ → SUMMARIZE → ASK)
**When running a validation script, you MUST:**
1. **Run the script** and capture ALL output
2. **Parse the output** - identify errors, warnings, and passes
3. **Summarize to user** in this format:
```markdown
## Script Results: [script_name.py]
### ❌ Errors Found (X items)
- [File:Line] Error description 1
- [File:Line] Error description 2
### ⚠️ Warnings (Y items)
- [File:Line] Warning description
### ✅ Passed (Z items)
- Check 1 passed
- Check 2 passed
**Should I fix the X errors?**
```
4. **Wait for user confirmation** before fixing
5. **After fixing** → Re-run script to confirm
> 🔴 **VIOLATION:** Running script and ignoring output = FAILED task.
> 🔴 **VIOLATION:** Auto-fixing without asking = Not allowed.
> 🔴 **Rule:** Always READ output → SUMMARIZE → ASK → then fix.
## 9. Smells and Heuristics
- **Rigidity**: Hard to change.
- **Fragility**: Breaks in many places.
- **Immobility**: Hard to reuse.
- **Viscosity**: Hard to do the right thing.
- **Needless Complexity/Repetition**.
## 🛠️ Implementation Checklist
- [ ] Is this function smaller than 20 lines?
- [ ] Does this function do exactly one thing?
- [ ] Are all names searchable and intention-revealing?
- [ ] Have I avoided comments by making the code clearer?
- [ ] Am I passing too many arguments?
- [ ] Is there a failing test for this change?

View File

@@ -0,0 +1,234 @@
---
name: clickup-automation
description: "Automate ClickUp project management including tasks, spaces, folders, lists, comments, and team operations via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# ClickUp Automation via Rube MCP
Automate ClickUp project management workflows including task creation and updates, workspace hierarchy navigation, comments, and team member management through Composio's ClickUp toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active ClickUp connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `clickup`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `clickup`
3. If connection is not ACTIVE, follow the returned auth link to complete ClickUp OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Create and Manage Tasks
**When to use**: User wants to create tasks, subtasks, update task properties, or list tasks in a ClickUp list.
**Tool sequence**:
1. `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` - Get workspace/team IDs [Prerequisite]
2. `CLICKUP_GET_SPACES` - List spaces in the workspace [Prerequisite]
3. `CLICKUP_GET_FOLDERS` - List folders in a space [Prerequisite]
4. `CLICKUP_GET_FOLDERLESS_LISTS` - Get lists not inside folders [Optional]
5. `CLICKUP_GET_LIST` - Validate list and check available statuses [Prerequisite]
6. `CLICKUP_CREATE_TASK` - Create a task in the target list [Required]
7. `CLICKUP_CREATE_TASK` (with `parent`) - Create subtask under a parent task [Optional]
8. `CLICKUP_UPDATE_TASK` - Modify task status, assignees, dates, priority [Optional]
9. `CLICKUP_GET_TASK` - Retrieve full task details [Optional]
10. `CLICKUP_GET_TASKS` - List all tasks in a list with filters [Optional]
11. `CLICKUP_DELETE_TASK` - Permanently remove a task [Optional]
**Key parameters for CLICKUP_CREATE_TASK**:
- `list_id`: Target list ID (integer, required)
- `name`: Task name (string, required)
- `description`: Detailed task description
- `status`: Must exactly match (case-sensitive) a status name configured in the target list
- `priority`: 1 (Urgent), 2 (High), 3 (Normal), 4 (Low)
- `assignees`: Array of user IDs (integers)
- `due_date`: Unix timestamp in milliseconds
- `parent`: Parent task ID string for creating subtasks
- `tags`: Array of tag name strings
- `time_estimate`: Estimated time in milliseconds
**Pitfalls**:
- `status` is case-sensitive and must match an existing status in the list; use `CLICKUP_GET_LIST` to check available statuses
- `due_date` and `start_date` are Unix timestamps in **milliseconds**, not seconds
- Subtask `parent` must be a task (not another subtask) in the same list
- `notify_all` triggers watcher notifications; set to false for bulk operations
- Retries can create duplicates; track created task IDs to avoid re-creation
- `custom_item_id` for milestones (ID 1) is subject to workspace plan quotas
### 2. Navigate Workspace Hierarchy
**When to use**: User wants to browse or manage the ClickUp workspace structure (Workspaces > Spaces > Folders > Lists).
**Tool sequence**:
1. `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` - List all accessible workspaces [Required]
2. `CLICKUP_GET_SPACES` - List spaces within a workspace [Required]
3. `CLICKUP_GET_SPACE` - Get details for a specific space [Optional]
4. `CLICKUP_GET_FOLDERS` - List folders in a space [Required]
5. `CLICKUP_GET_FOLDER` - Get details for a specific folder [Optional]
6. `CLICKUP_CREATE_FOLDER` - Create a new folder in a space [Optional]
7. `CLICKUP_GET_FOLDERLESS_LISTS` - List lists not inside any folder [Required]
8. `CLICKUP_GET_LIST` - Get list details including statuses and custom fields [Optional]
**Key parameters**:
- `team_id`: Workspace ID from GET_AUTHORIZED_TEAMS_WORKSPACES (required for spaces)
- `space_id`: Space ID (required for folders and folderless lists)
- `folder_id`: Folder ID (required for GET_FOLDER)
- `list_id`: List ID (required for GET_LIST)
- `archived`: Boolean filter for archived/active items
**Pitfalls**:
- ClickUp hierarchy is: Workspace (Team) > Space > Folder > List > Task
- Lists can exist directly under Spaces (folderless) or inside Folders
- Must use `CLICKUP_GET_FOLDERLESS_LISTS` to find lists not inside folders; `CLICKUP_GET_FOLDERS` only returns folders
- `team_id` in ClickUp API refers to the Workspace ID, not a user group
### 3. Add Comments to Tasks
**When to use**: User wants to add comments, review existing comments, or manage comment threads on tasks.
**Tool sequence**:
1. `CLICKUP_GET_TASK` - Verify task exists and get task_id [Prerequisite]
2. `CLICKUP_CREATE_TASK_COMMENT` - Add a new comment to the task [Required]
3. `CLICKUP_GET_TASK_COMMENTS` - List existing comments on the task [Optional]
4. `CLICKUP_UPDATE_COMMENT` - Edit comment text, assignee, or resolution status [Optional]
**Key parameters for CLICKUP_CREATE_TASK_COMMENT**:
- `task_id`: Task ID string (required)
- `comment_text`: Comment content with ClickUp formatting support (required)
- `assignee`: User ID to assign the comment to (required)
- `notify_all`: true/false for watcher notifications (required)
**Key parameters for CLICKUP_GET_TASK_COMMENTS**:
- `task_id`: Task ID string (required)
- `start` / `start_id`: Pagination for older comments (max 25 per page)
**Pitfalls**:
- `CLICKUP_CREATE_TASK_COMMENT` requires all four fields: `task_id`, `comment_text`, `assignee`, and `notify_all`
- `assignee` on a comment assigns the comment (not the task) to that user
- Comments are paginated at 25 per page; use `start` (Unix ms) and `start_id` for older pages
- `CLICKUP_UPDATE_COMMENT` requires all four fields: `comment_id`, `comment_text`, `assignee`, `resolved`
### 4. Manage Team Members and Assignments
**When to use**: User wants to view workspace members, check seat utilization, or look up user details.
**Tool sequence**:
1. `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` - List workspaces and get team_id [Required]
2. `CLICKUP_GET_WORKSPACE_SEATS` - Check seat utilization (members vs guests) [Required]
3. `CLICKUP_GET_TEAMS` - List user groups within the workspace [Optional]
4. `CLICKUP_GET_USER` - Get details for a specific user (Enterprise only) [Optional]
5. `CLICKUP_GET_CUSTOM_ROLES` - List custom permission roles [Optional]
**Key parameters**:
- `team_id`: Workspace ID (required for all team operations)
- `user_id`: Specific user ID for GET_USER
- `group_ids`: Comma-separated group IDs to filter teams
**Pitfalls**:
- `CLICKUP_GET_WORKSPACE_SEATS` returns seat counts, not member details; distinguish members from guests
- `CLICKUP_GET_TEAMS` returns user groups, not workspace members; empty groups does not mean no members
- `CLICKUP_GET_USER` is only available on ClickUp Enterprise Plan
- Must repeat workspace seat queries for each workspace in multi-workspace setups
### 5. Filter and Query Tasks
**When to use**: User wants to find tasks with specific filters (status, assignee, dates, tags, custom fields).
**Tool sequence**:
1. `CLICKUP_GET_TASKS` - Filter tasks in a list with multiple criteria [Required]
2. `CLICKUP_GET_TASK` - Get full details for individual tasks [Optional]
**Key parameters for CLICKUP_GET_TASKS**:
- `list_id`: List ID (integer, required)
- `statuses`: Array of status strings to filter by
- `assignees`: Array of user ID strings
- `tags`: Array of tag name strings
- `due_date_gt` / `due_date_lt`: Unix timestamp in ms for date range
- `include_closed`: Boolean to include closed tasks
- `subtasks`: Boolean to include subtasks
- `order_by`: "id", "created", "updated", or "due_date"
- `page`: Page number starting at 0 (max 100 tasks per page)
**Pitfalls**:
- Only tasks whose home list matches `list_id` are returned; tasks in sublists are not included
- Date filters use Unix timestamps in milliseconds
- Status strings must match exactly; use URL encoding for spaces (e.g., "to%20do")
- Page numbering starts at 0; each page returns up to 100 tasks
- `custom_fields` filter accepts an array of JSON strings, not objects
## Common Patterns
### ID Resolution
Always resolve names to IDs through the hierarchy:
- **Workspace name -> team_id**: `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` and match by name
- **Space name -> space_id**: `CLICKUP_GET_SPACES` with `team_id`
- **Folder name -> folder_id**: `CLICKUP_GET_FOLDERS` with `space_id`
- **List name -> list_id**: Navigate folders or use `CLICKUP_GET_FOLDERLESS_LISTS`
- **Task name -> task_id**: `CLICKUP_GET_TASKS` with `list_id` and match by name
### Pagination
- `CLICKUP_GET_TASKS`: Page-based with `page` starting at 0, max 100 tasks per page
- `CLICKUP_GET_TASK_COMMENTS`: Uses `start` (Unix ms) and `start_id` for cursor-based paging, max 25 per page
- Continue fetching until response returns fewer items than the page size
## Known Pitfalls
### ID Formats
- Workspace/Team IDs are large integers
- Space, folder, and list IDs are integers
- Task IDs are alphanumeric strings (e.g., "9hz", "abc123")
- User IDs are integers
- Comment IDs are integers
### Rate Limits
- ClickUp enforces rate limits; bulk task creation can trigger 429 responses
- Honor `Retry-After` header when present
- Set `notify_all=false` for bulk operations to reduce notification load
### Parameter Quirks
- `team_id` in the API means Workspace ID, not a user group
- `status` on tasks is case-sensitive and list-specific
- Dates are Unix timestamps in **milliseconds** (multiply seconds by 1000)
- `priority` is an integer 1-4 (1=Urgent, 4=Low), not a string
- `CLICKUP_CREATE_TASK_COMMENT` marks `assignee` and `notify_all` as required
- To clear a task description, pass a single space `" "` to `CLICKUP_UPDATE_TASK`
### Hierarchy Rules
- Subtask parent must not itself be a subtask
- Subtask parent must be in the same list
- Lists can be folderless (directly in a Space) or inside a Folder
- Subitem boards are not supported by CLICKUP_CREATE_TASK
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List workspaces | `CLICKUP_GET_AUTHORIZED_TEAMS_WORKSPACES` | (none) |
| List spaces | `CLICKUP_GET_SPACES` | `team_id` |
| Get space details | `CLICKUP_GET_SPACE` | `space_id` |
| List folders | `CLICKUP_GET_FOLDERS` | `space_id` |
| Get folder details | `CLICKUP_GET_FOLDER` | `folder_id` |
| Create folder | `CLICKUP_CREATE_FOLDER` | `space_id`, `name` |
| Folderless lists | `CLICKUP_GET_FOLDERLESS_LISTS` | `space_id` |
| Get list details | `CLICKUP_GET_LIST` | `list_id` |
| Create task | `CLICKUP_CREATE_TASK` | `list_id`, `name`, `status`, `assignees` |
| Update task | `CLICKUP_UPDATE_TASK` | `task_id`, `status`, `priority` |
| Get task | `CLICKUP_GET_TASK` | `task_id`, `include_subtasks` |
| List tasks | `CLICKUP_GET_TASKS` | `list_id`, `statuses`, `page` |
| Delete task | `CLICKUP_DELETE_TASK` | `task_id` |
| Add comment | `CLICKUP_CREATE_TASK_COMMENT` | `task_id`, `comment_text`, `assignee` |
| List comments | `CLICKUP_GET_TASK_COMMENTS` | `task_id`, `start`, `start_id` |
| Update comment | `CLICKUP_UPDATE_COMMENT` | `comment_id`, `comment_text`, `resolved` |
| Workspace seats | `CLICKUP_GET_WORKSPACE_SEATS` | `team_id` |
| List user groups | `CLICKUP_GET_TEAMS` | `team_id` |
| Get user details | `CLICKUP_GET_USER` | `team_id`, `user_id` |
| Custom roles | `CLICKUP_GET_CUSTOM_ROLES` | `team_id` |

View File

@@ -0,0 +1,212 @@
---
name: close-automation
description: "Automate Close CRM tasks via Rube MCP (Composio): create leads, manage calls/SMS, handle tasks, and track notes. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Close CRM Automation via Rube MCP
Automate Close CRM operations through Composio's Close toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Close connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `close`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `close`
3. If connection is not ACTIVE, follow the returned auth link to complete Close API authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Create and Manage Leads
**When to use**: User wants to create new leads or manage existing lead records
**Tool sequence**:
1. `CLOSE_CREATE_LEAD` - Create a new lead in Close [Required]
**Key parameters**:
- `name`: Lead/company name
- `contacts`: Array of contact objects associated with the lead
- `custom`: Custom field values as key-value pairs
- `status_id`: Lead status ID
**Pitfalls**:
- Leads in Close represent companies/organizations, not individual people
- Contacts are nested within leads; create the lead first, then contacts are included
- Custom field keys use the custom field ID (e.g., 'custom.cf_XXX'), not display names
- Duplicate lead detection is not automatic; check before creating
### 2. Log Calls
**When to use**: User wants to log a phone call activity against a lead
**Tool sequence**:
1. `CLOSE_CREATE_CALL` - Log a call activity [Required]
**Key parameters**:
- `lead_id`: ID of the associated lead
- `contact_id`: ID of the contact called
- `direction`: 'outbound' or 'inbound'
- `status`: Call status ('completed', 'no-answer', 'busy', etc.)
- `duration`: Call duration in seconds
- `note`: Call notes
**Pitfalls**:
- lead_id is required; calls must be associated with a lead
- Duration is in seconds, not minutes
- Call direction affects reporting and analytics
- contact_id is optional but recommended for tracking
### 3. Send SMS Messages
**When to use**: User wants to send or log SMS messages through Close
**Tool sequence**:
1. `CLOSE_CREATE_SMS` - Send or log an SMS message [Required]
**Key parameters**:
- `lead_id`: ID of the associated lead
- `contact_id`: ID of the contact
- `direction`: 'outbound' or 'inbound'
- `text`: SMS message content
- `status`: Message status
**Pitfalls**:
- SMS functionality requires Close phone/SMS integration to be configured
- lead_id is required for all SMS activities
- Outbound SMS may require a verified sending number
- Message length limits may apply depending on carrier
### 4. Manage Tasks
**When to use**: User wants to create or manage follow-up tasks
**Tool sequence**:
1. `CLOSE_CREATE_TASK` - Create a new task [Required]
**Key parameters**:
- `lead_id`: Associated lead ID
- `text`: Task description
- `date`: Due date for the task
- `assigned_to`: User ID of the assignee
- `is_complete`: Whether the task is completed
**Pitfalls**:
- Tasks are associated with leads, not contacts
- Date format should follow ISO 8601
- assigned_to requires the Close user ID, not email or name
- Tasks without a date appear in the 'no due date' section
### 5. Manage Notes
**When to use**: User wants to add or retrieve notes on leads
**Tool sequence**:
1. `CLOSE_GET_NOTE` - Retrieve a specific note [Required]
**Key parameters**:
- `note_id`: ID of the note to retrieve
**Pitfalls**:
- Notes are associated with leads
- Note IDs are required for retrieval; search leads first to find note references
- Notes support plain text and basic formatting
### 6. Delete Activities
**When to use**: User wants to remove call records or other activities
**Tool sequence**:
1. `CLOSE_DELETE_CALL` - Delete a call activity [Required]
**Key parameters**:
- `call_id`: ID of the call to delete
**Pitfalls**:
- Deletion is permanent and cannot be undone
- Only the call creator or admin can delete calls
- Deleting a call removes it from all reports and timelines
## Common Patterns
### Lead and Contact Relationship
```
Close data model:
- Lead = Company/Organization
- Contact = Person (nested within Lead)
- Activity = Call, SMS, Email, Note (linked to Lead)
- Task = Follow-up item (linked to Lead)
- Opportunity = Deal (linked to Lead)
```
### ID Resolution
**Lead ID**:
```
1. Search for leads using the Close search API
2. Extract lead_id from results (format: 'lead_XXXXXXXXXXXXX')
3. Use lead_id in all activity creation calls
```
**Contact ID**:
```
1. Retrieve lead details to get nested contacts
2. Extract contact_id (format: 'cont_XXXXXXXXXXXXX')
3. Use in call/SMS activities for accurate tracking
```
### Activity Logging Pattern
```
1. Identify the lead_id and optionally contact_id
2. Create the activity (call, SMS, note) with lead_id
3. Include relevant metadata (duration, direction, status)
4. Create follow-up tasks if needed
```
## Known Pitfalls
**ID Formats**:
- Lead IDs: 'lead_XXXXXXXXXXXXX'
- Contact IDs: 'cont_XXXXXXXXXXXXX'
- Activity IDs vary by type: 'acti_XXXXXXXXXXXXX', 'call_XXXXXXXXXXXXX'
- Custom field IDs: 'custom.cf_XXXXXXXXXXXXX'
- Always use the full ID string
**Rate Limits**:
- Close API has rate limits based on your plan
- Implement delays between bulk operations
- Monitor response headers for rate limit status
- 429 responses require backoff
**Custom Fields**:
- Custom fields are referenced by their API ID, not display name
- Different lead statuses may have different required custom fields
- Custom field types (text, number, date, dropdown) enforce value formats
**Data Integrity**:
- Leads are the primary entity; contacts and activities are linked to leads
- Deleting a lead may cascade to its contacts and activities
- Bulk operations should validate IDs before executing
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Create lead | CLOSE_CREATE_LEAD | name, contacts, custom |
| Log call | CLOSE_CREATE_CALL | lead_id, direction, status, duration |
| Send SMS | CLOSE_CREATE_SMS | lead_id, text, direction |
| Create task | CLOSE_CREATE_TASK | lead_id, text, date, assigned_to |
| Get note | CLOSE_GET_NOTE | note_id |
| Delete call | CLOSE_DELETE_CALL | call_id |

View File

@@ -0,0 +1,241 @@
---
name: coda-automation
description: "Automate Coda tasks via Rube MCP (Composio): manage docs, pages, tables, rows, formulas, permissions, and publishing. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Coda Automation via Rube MCP
Automate Coda document and data operations through Composio's Coda toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Coda connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `coda`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `coda`
3. If connection is not ACTIVE, follow the returned auth link to complete Coda authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Search and Browse Documents
**When to use**: User wants to find, list, or inspect Coda documents
**Tool sequence**:
1. `CODA_SEARCH_DOCS` or `CODA_LIST_AVAILABLE_DOCS` - Find documents [Required]
2. `CODA_RESOLVE_BROWSER_LINK` - Resolve a Coda URL to doc/page/table IDs [Alternative]
3. `CODA_LIST_PAGES` - List pages within a document [Optional]
4. `CODA_GET_A_PAGE` - Get specific page details [Optional]
**Key parameters**:
- `query`: Search term for finding documents
- `isOwner`: Filter to docs owned by the user
- `docId`: Document ID for page operations
- `pageIdOrName`: Page identifier or name
- `url`: Browser URL for resolve operations
**Pitfalls**:
- Document IDs are alphanumeric strings (e.g., 'AbCdEfGhIj')
- `CODA_RESOLVE_BROWSER_LINK` is the best way to convert a Coda URL to API IDs
- Page names may not be unique within a doc; prefer page IDs
- Search results include docs shared with the user, not just owned docs
### 2. Work with Tables and Data
**When to use**: User wants to read, write, or query table data
**Tool sequence**:
1. `CODA_LIST_TABLES` - List tables in a document [Prerequisite]
2. `CODA_LIST_COLUMNS` - Get column definitions for a table [Prerequisite]
3. `CODA_LIST_TABLE_ROWS` - List all rows with optional filters [Required]
4. `CODA_SEARCH_ROW` - Search for specific rows by query [Alternative]
5. `CODA_GET_A_ROW` - Get a specific row by ID [Optional]
6. `CODA_UPSERT_ROWS` - Insert or update rows in a table [Optional]
7. `CODA_GET_A_COLUMN` - Get details of a specific column [Optional]
**Key parameters**:
- `docId`: Document ID containing the table
- `tableIdOrName`: Table identifier or name
- `query`: Filter query for searching rows
- `rows`: Array of row objects for upsert operations
- `keyColumns`: Column IDs used for matching during upsert
- `sortBy`: Column to sort results by
- `useColumnNames`: Use column names instead of IDs in row data
**Pitfalls**:
- Table names may contain spaces; URL-encode if needed
- `CODA_UPSERT_ROWS` does insert if no match on `keyColumns`, update if match found
- `keyColumns` must reference columns that have unique values for reliable upserts
- Column IDs are different from column names; list columns first to map names to IDs
- `useColumnNames: true` allows using human-readable names in row data
- Row data values must match the column type (text, number, date, etc.)
### 3. Manage Formulas
**When to use**: User wants to list or evaluate formulas in a document
**Tool sequence**:
1. `CODA_LIST_FORMULAS` - List all named formulas in a doc [Required]
2. `CODA_GET_A_FORMULA` - Get a specific formula's current value [Optional]
**Key parameters**:
- `docId`: Document ID
- `formulaIdOrName`: Formula identifier or name
**Pitfalls**:
- Formulas are named calculations defined in the document
- Formula values are computed server-side; results reflect the current state
- Formula names are case-sensitive
### 4. Export Document Content
**When to use**: User wants to export a document or page to HTML or Markdown
**Tool sequence**:
1. `CODA_BEGIN_CONTENT_EXPORT` - Start an export job [Required]
2. `CODA_CONTENT_EXPORT_STATUS` - Poll export status until complete [Required]
**Key parameters**:
- `docId`: Document ID to export
- `outputFormat`: Export format ('html' or 'markdown')
- `pageIdOrName`: Specific page to export (optional, omit for full doc)
- `requestId`: Export request ID for status polling
**Pitfalls**:
- Export is asynchronous; poll status until `status` is 'complete'
- Large documents may take significant time to export
- Export URL in the completed response is temporary; download promptly
- Polling too frequently may hit rate limits; use 2-5 second intervals
### 5. Manage Permissions and Sharing
**When to use**: User wants to view or manage document access
**Tool sequence**:
1. `CODA_GET_SHARING_METADATA` - View current sharing settings [Required]
2. `CODA_GET_ACL_SETTINGS` - Get access control list settings [Optional]
3. `CODA_ADD_PERMISSION` - Grant access to a user or email [Optional]
**Key parameters**:
- `docId`: Document ID
- `access`: Permission level ('readonly', 'write', 'comment')
- `principal`: Object with email or user ID of the recipient
- `suppressEmail`: Whether to skip the sharing notification email
**Pitfalls**:
- Permission levels: 'readonly', 'write', 'comment'
- Adding permission sends an email notification by default; use `suppressEmail` to prevent
- Cannot remove permissions via API in all cases; check ACL settings
### 6. Publish and Customize Documents
**When to use**: User wants to publish a document or manage custom domains
**Tool sequence**:
1. `CODA_PUBLISH_DOC` - Publish a document publicly [Required]
2. `CODA_UNPUBLISH_DOC` - Unpublish a document [Optional]
3. `CODA_ADD_CUSTOM_DOMAIN` - Add a custom domain for published doc [Optional]
4. `CODA_GET_DOC_CATEGORIES` - Get doc categories for discovery [Optional]
**Key parameters**:
- `docId`: Document ID
- `slug`: Custom URL slug for the published doc
- `categoryIds`: Category IDs for discoverability
**Pitfalls**:
- Publishing makes the document accessible to anyone with the link
- Custom domains require DNS configuration
- Unpublishing removes public access but retains shared access
## Common Patterns
### ID Resolution
**Doc URL -> Doc ID**:
```
1. Call CODA_RESOLVE_BROWSER_LINK with the Coda URL
2. Extract docId from the response
```
**Table name -> Table ID**:
```
1. Call CODA_LIST_TABLES with docId
2. Find table by name, extract id
```
**Column name -> Column ID**:
```
1. Call CODA_LIST_COLUMNS with docId and tableIdOrName
2. Find column by name, extract id
```
### Pagination
- Coda uses cursor-based pagination with `pageToken`
- Check response for `nextPageToken`
- Pass as `pageToken` in next request until absent
- Default page sizes vary by endpoint
### Row Upsert Pattern
```
1. Call CODA_LIST_COLUMNS to get column IDs
2. Build row objects with column ID keys and values
3. Set keyColumns to unique identifier column(s)
4. Call CODA_UPSERT_ROWS with rows and keyColumns
```
## Known Pitfalls
**ID Formats**:
- Document IDs: alphanumeric strings
- Table/column/row IDs: prefixed strings (e.g., 'grid-abc', 'c-xyz')
- Use RESOLVE_BROWSER_LINK to convert URLs to IDs
**Data Types**:
- Row values must match column types
- Date columns expect ISO 8601 format
- Select/multi-select columns expect exact option values
- People columns expect email addresses
**Rate Limits**:
- Coda API has per-token rate limits
- Implement backoff on 429 responses
- Bulk row operations via UPSERT_ROWS are more efficient than individual updates
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Search docs | CODA_SEARCH_DOCS | query |
| List docs | CODA_LIST_AVAILABLE_DOCS | isOwner |
| Resolve URL | CODA_RESOLVE_BROWSER_LINK | url |
| List pages | CODA_LIST_PAGES | docId |
| Get page | CODA_GET_A_PAGE | docId, pageIdOrName |
| List tables | CODA_LIST_TABLES | docId |
| List columns | CODA_LIST_COLUMNS | docId, tableIdOrName |
| List rows | CODA_LIST_TABLE_ROWS | docId, tableIdOrName |
| Search rows | CODA_SEARCH_ROW | docId, tableIdOrName, query |
| Get row | CODA_GET_A_ROW | docId, tableIdOrName, rowIdOrName |
| Upsert rows | CODA_UPSERT_ROWS | docId, tableIdOrName, rows, keyColumns |
| Get column | CODA_GET_A_COLUMN | docId, tableIdOrName, columnIdOrName |
| Push button | CODA_PUSH_A_BUTTON | docId, tableIdOrName, rowIdOrName, columnIdOrName |
| List formulas | CODA_LIST_FORMULAS | docId |
| Get formula | CODA_GET_A_FORMULA | docId, formulaIdOrName |
| Begin export | CODA_BEGIN_CONTENT_EXPORT | docId, outputFormat |
| Export status | CODA_CONTENT_EXPORT_STATUS | docId, requestId |
| Get sharing | CODA_GET_SHARING_METADATA | docId |
| Add permission | CODA_ADD_PERMISSION | docId, access, principal |
| Publish doc | CODA_PUBLISH_DOC | docId, slug |
| Unpublish doc | CODA_UNPUBLISH_DOC | docId |
| List packs | CODA_LIST_PACKS | (none) |

View File

@@ -0,0 +1,70 @@
---
name: computer-vision-expert
description: SOTA Computer Vision Expert (2026). Specialized in YOLO26, Segment Anything 3 (SAM 3), Vision Language Models, and real-time spatial analysis.
---
# Computer Vision Expert (SOTA 2026)
**Role**: Advanced Vision Systems Architect & Spatial Intelligence Expert
## Purpose
To provide expert guidance on designing, implementing, and optimizing state-of-the-art computer vision pipelines. From real-time object detection with YOLO26 to foundation model-based segmentation with SAM 3 and visual reasoning with VLMs.
## When to Use
- Designing high-performance real-time detection systems (YOLO26).
- Implementing zero-shot or text-guided segmentation tasks (SAM 3).
- Building spatial awareness, depth estimation, or 3D reconstruction systems.
- Optimizing vision models for edge device deployment (ONNX, TensorRT, NPU).
- Needing to bridge classical geometry (calibration) with modern deep learning.
## Capabilities
### 1. Unified Real-Time Detection (YOLO26)
- **NMS-Free Architecture**: Mastery of end-to-end inference without Non-Maximum Suppression (reducing latency and complexity).
- **Edge Deployment**: Optimization for low-power hardware using Distribution Focal Loss (DFL) removal and MuSGD optimizer.
- **Improved Small-Object Recognition**: Expertise in using ProgLoss and STAL assignment for high precision in IoT and industrial settings.
### 2. Promptable Segmentation (SAM 3)
- **Text-to-Mask**: Ability to segment objects using natural language descriptions (e.g., "the blue container on the right").
- **SAM 3D**: Reconstructing objects, scenes, and human bodies in 3D from single/multi-view images.
- **Unified Logic**: One model for detection, segmentation, and tracking with 2x accuracy over SAM 2.
### 3. Vision Language Models (VLMs)
- **Visual Grounding**: Leveraging Florence-2, PaliGemma 2, or Qwen2-VL for semantic scene understanding.
- **Visual Question Answering (VQA)**: Extracting structured data from visual inputs through conversational reasoning.
### 4. Geometry & Reconstruction
- **Depth Anything V2**: State-of-the-art monocular depth estimation for spatial awareness.
- **Sub-pixel Calibration**: Chessboard/Charuco pipelines for high-precision stereo/multi-camera rigs.
- **Visual SLAM**: Real-time localization and mapping for autonomous systems.
## Patterns
### 1. Text-Guided Vision Pipelines
- Use SAM 3's text-to-mask capability to isolate specific parts during inspection without needing custom detectors for every variation.
- Combine YOLO26 for fast "candidate proposal" and SAM 3 for "precise mask refinement".
### 2. Deployment-First Design
- Leverage YOLO26's simplified ONNX/TensorRT exports (NMS-free).
- Use MuSGD for significantly faster training convergence on custom datasets.
### 3. Progressive 3D Scene Reconstruction
- Integrate monocular depth maps with geometric homographies to build accurate 2.5D/3D representations of scenes.
## Anti-Patterns
- **Manual NMS Post-processing**: Stick to NMS-free architectures (YOLO26/v10+) for lower overhead.
- **Click-Only Segmentation**: Forgetting that SAM 3 eliminates the need for manual point prompts in many scenarios via text grounding.
- **Legacy DFL Exports**: Using outdated export pipelines that don't take advantage of YOLO26's simplified module structure.
## Sharp Edges (2026)
| Issue | Severity | Solution |
|-------|----------|----------|
| SAM 3 VRAM Usage | Medium | Use quantized/distilled versions for local GPU inference. |
| Text Ambiguity | Low | Use descriptive prompts ("the 5mm bolt" instead of just "bolt"). |
| Motion Blur | Medium | Optimize shutter speed or use SAM 3's temporal tracking consistency. |
| Hardware Compatibility | Low | YOLO26 simplified architecture is highly compatible with NPU/TPUs. |
## Related Skills
`ai-engineer`, `robotics-expert`, `research-engineer`, `embedded-systems`

View File

@@ -0,0 +1,208 @@
---
name: confluence-automation
description: "Automate Confluence page creation, content search, space management, labels, and hierarchy navigation via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Confluence Automation via Rube MCP
Automate Confluence operations including page creation and updates, content search with CQL, space management, label tagging, and page hierarchy navigation through Composio's Confluence toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Confluence connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `confluence`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `confluence`
3. If connection is not ACTIVE, follow the returned auth link to complete Confluence OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Create and Update Pages
**When to use**: User wants to create new documentation or update existing Confluence pages
**Tool sequence**:
1. `CONFLUENCE_GET_SPACES` - List spaces to find the target space ID [Prerequisite]
2. `CONFLUENCE_SEARCH_CONTENT` - Find existing page to avoid duplicates or locate parent [Optional]
3. `CONFLUENCE_GET_PAGE_BY_ID` - Get current page content and version number before updating [Prerequisite for updates]
4. `CONFLUENCE_CREATE_PAGE` - Create a new page in a space [Required for creation]
5. `CONFLUENCE_UPDATE_PAGE` - Update an existing page with new content and incremented version [Required for updates]
6. `CONFLUENCE_ADD_CONTENT_LABEL` - Tag the page with labels after creation [Optional]
**Key parameters**:
- `spaceId`: Space ID or key (e.g., `"DOCS"`, `"12345678"`) -- space keys are auto-converted to IDs
- `title`: Page title (must be unique within a space)
- `parentId`: Parent page ID for creating child pages; omit to place under space homepage
- `body.storage.value`: HTML/XHTML content in Confluence storage format
- `body.storage.representation`: Must be `"storage"` for create operations
- `version.number`: For updates, must be current version + 1
- `version.message`: Optional change description
**Pitfalls**:
- Confluence enforces unique page titles per space; creating a page with a duplicate title will fail
- `UPDATE_PAGE` requires `version.number` set to current version + 1; always fetch current version first with `GET_PAGE_BY_ID`
- Content must be in Confluence storage format (XHTML), not plain text or Markdown
- `CREATE_PAGE` uses `body.storage.value` while `UPDATE_PAGE` uses `body.value` with `body.representation`
- `GET_PAGE_BY_ID` requires a numeric long ID, not a UUID or string
### 2. Search Content
**When to use**: User wants to find pages, blog posts, or content across Confluence
**Tool sequence**:
1. `CONFLUENCE_SEARCH_CONTENT` - Keyword search with intelligent relevance ranking [Required]
2. `CONFLUENCE_CQL_SEARCH` - Advanced search using Confluence Query Language [Alternative]
3. `CONFLUENCE_GET_PAGE_BY_ID` - Hydrate full content for selected search results [Optional]
4. `CONFLUENCE_GET_PAGES` - Browse pages sorted by date when search relevance is weak [Fallback]
**Key parameters for SEARCH_CONTENT**:
- `query`: Search text matched against page titles with intelligent ranking
- `spaceKey`: Limit search to a specific space
- `limit`: Max results (default 25, max 250)
- `start`: Pagination offset (0-based)
**Key parameters for CQL_SEARCH**:
- `cql`: CQL query string (e.g., `text ~ "API docs" AND space = DOCS AND type = page`)
- `expand`: Comma-separated properties (e.g., `content.space`, `content.body.storage`)
- `excerpt`: `highlight`, `indexed`, or `none`
- `limit`: Max results (max 250; reduced to 25-50 when using body expansions)
**CQL operators and fields**:
- Fields: `text`, `title`, `label`, `space`, `type`, `creator`, `lastModified`, `created`, `ancestor`
- Operators: `=`, `!=`, `~` (contains), `!~`, `>`, `<`, `>=`, `<=`, `IN`, `NOT IN`
- Functions: `currentUser()`, `now("-7d")`, `now("-30d")`
- Example: `title ~ "meeting" AND lastModified > now("-7d") ORDER BY lastModified DESC`
**Pitfalls**:
- `CONFLUENCE_SEARCH_CONTENT` fetches up to 300 pages and applies client-side filtering -- not a true full-text search
- `CONFLUENCE_CQL_SEARCH` is the real full-text search; use `text ~ "term"` for content body search
- HTTP 429 rate limits can occur; throttle to ~2 requests/second with backoff
- Using body expansions in CQL_SEARCH may reduce max results to 25-50
- Search indexing is not immediate; recently created pages may not appear
### 3. Manage Spaces
**When to use**: User wants to list, create, or inspect Confluence spaces
**Tool sequence**:
1. `CONFLUENCE_GET_SPACES` - List all spaces with optional filtering [Required]
2. `CONFLUENCE_GET_SPACE_BY_ID` - Get detailed metadata for a specific space [Optional]
3. `CONFLUENCE_CREATE_SPACE` - Create a new space with key and name [Optional]
4. `CONFLUENCE_GET_SPACE_PROPERTIES` - Retrieve custom metadata stored as space properties [Optional]
5. `CONFLUENCE_GET_SPACE_CONTENTS` - List pages, blog posts, or attachments in a space [Optional]
6. `CONFLUENCE_GET_LABELS_FOR_SPACE` - List labels on a space [Optional]
**Key parameters**:
- `key`: Space key -- alphanumeric only, no underscores or hyphens (e.g., `DOCS`, `PROJECT1`)
- `name`: Human-readable space name
- `type`: `global` or `personal`
- `status`: `current` (active) or `archived`
- `spaceKey`: For GET_SPACE_CONTENTS, filters by space key
- `id`: Numeric space ID for GET_SPACE_BY_ID (NOT the space key)
**Pitfalls**:
- Space keys must be alphanumeric only (no underscores, hyphens, or special characters)
- `GET_SPACE_BY_ID` requires numeric space ID, not the space key; use `GET_SPACES` to find numeric IDs
- Clickable space URLs may need assembly: join `_links.webui` (relative) with `_links.base`
- Default pagination is 25; set `limit` explicitly (max 200 for spaces)
### 4. Navigate Page Hierarchy and Labels
**When to use**: User wants to explore page trees, child pages, ancestors, or manage labels
**Tool sequence**:
1. `CONFLUENCE_SEARCH_CONTENT` - Find the target page ID [Prerequisite]
2. `CONFLUENCE_GET_CHILD_PAGES` - List direct children of a parent page [Required]
3. `CONFLUENCE_GET_PAGE_ANCESTORS` - Get the full ancestor chain for a page [Optional]
4. `CONFLUENCE_GET_LABELS_FOR_PAGE` - List labels on a specific page [Optional]
5. `CONFLUENCE_ADD_CONTENT_LABEL` - Add labels to a page [Optional]
6. `CONFLUENCE_GET_LABELS_FOR_SPACE_CONTENT` - List labels across all content in a space [Optional]
7. `CONFLUENCE_GET_PAGE_VERSIONS` - Audit edit history for a page [Optional]
**Key parameters**:
- `id`: Page ID for child pages, ancestors, labels, and versions
- `cursor`: Opaque pagination cursor for GET_CHILD_PAGES (from `_links.next`)
- `limit`: Items per page (max 250 for child pages)
- `sort`: Child page sort options: `id`, `-id`, `created-date`, `-created-date`, `modified-date`, `-modified-date`, `child-position`, `-child-position`
**Pitfalls**:
- `GET_CHILD_PAGES` only returns direct children, not nested descendants; recurse for full tree
- Pagination for GET_CHILD_PAGES uses cursor-based pagination (not start/limit)
- Verify the correct page ID from search before using as parent; search can return similar titles
- `GET_PAGE_VERSIONS` requires the page ID, not a version number
## Common Patterns
### ID Resolution
Always resolve human-readable names to IDs before operations:
- **Space key -> Space ID**: `CONFLUENCE_GET_SPACES` with `spaceKey` filter, or `CREATE_PAGE` accepts space keys directly
- **Page title -> Page ID**: `CONFLUENCE_SEARCH_CONTENT` with `query` param, then extract page ID
- **Space ID from URL**: Extract numeric ID from Confluence URLs or use GET_SPACES
### Pagination
Confluence uses two pagination styles:
- **Offset-based** (most endpoints): `start` (0-based offset) + `limit` (page size). Increment `start` by `limit` until fewer results than `limit` are returned.
- **Cursor-based** (GET_CHILD_PAGES, GET_PAGES): Use the `cursor` from `_links.next` in the response. Continue until no `next` link is present.
### Content Formatting
- Pages use Confluence storage format (XHTML), not Markdown
- Basic elements: `<p>`, `<h1>`-`<h6>`, `<strong>`, `<em>`, `<code>`, `<ul>`, `<ol>`, `<li>`
- Tables: `<table><tbody><tr><th>` / `<td>` structure
- Macros: `<ac:structured-macro ac:name="code">` for code blocks, etc.
- Always wrap content in proper XHTML tags
## Known Pitfalls
### ID Formats
- Space IDs are numeric (e.g., `557060`); space keys are short strings (e.g., `DOCS`)
- Page IDs are numeric long values for GET_PAGE_BY_ID; some tools accept UUID format
- `GET_SPACE_BY_ID` requires numeric ID, not the space key
- `GET_PAGE_BY_ID` takes an integer, not a string
### Rate Limits
- HTTP 429 can occur on search endpoints; honor Retry-After header
- Throttle to ~2 requests/second with exponential backoff and jitter
- Body expansion in CQL_SEARCH reduces result limits to 25-50
### Content Format
- Content must be Confluence storage format (XHTML), not Markdown or plain text
- Invalid XHTML will cause page creation/update to fail
- `CREATE_PAGE` nests body under `body.storage.value`; `UPDATE_PAGE` uses `body.value` + `body.representation`
### Version Conflicts
- Updates require exact next version number (current + 1)
- Concurrent edits can cause version conflicts; always fetch current version immediately before updating
- Title changes during update must still be unique within the space
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List spaces | `CONFLUENCE_GET_SPACES` | `type`, `status`, `limit` |
| Get space by ID | `CONFLUENCE_GET_SPACE_BY_ID` | `id` |
| Create space | `CONFLUENCE_CREATE_SPACE` | `key`, `name`, `type` |
| Space contents | `CONFLUENCE_GET_SPACE_CONTENTS` | `spaceKey`, `type`, `status` |
| Space properties | `CONFLUENCE_GET_SPACE_PROPERTIES` | `id`, `key` |
| Search content | `CONFLUENCE_SEARCH_CONTENT` | `query`, `spaceKey`, `limit` |
| CQL search | `CONFLUENCE_CQL_SEARCH` | `cql`, `expand`, `limit` |
| List pages | `CONFLUENCE_GET_PAGES` | `spaceId`, `sort`, `limit` |
| Get page by ID | `CONFLUENCE_GET_PAGE_BY_ID` | `id` (integer) |
| Create page | `CONFLUENCE_CREATE_PAGE` | `title`, `spaceId`, `body` |
| Update page | `CONFLUENCE_UPDATE_PAGE` | `id`, `title`, `body`, `version` |
| Delete page | `CONFLUENCE_DELETE_PAGE` | `id` |
| Child pages | `CONFLUENCE_GET_CHILD_PAGES` | `id`, `limit`, `sort` |
| Page ancestors | `CONFLUENCE_GET_PAGE_ANCESTORS` | `id` |
| Page labels | `CONFLUENCE_GET_LABELS_FOR_PAGE` | `id` |
| Add label | `CONFLUENCE_ADD_CONTENT_LABEL` | content ID, label |
| Page versions | `CONFLUENCE_GET_PAGE_VERSIONS` | `id` |
| Space labels | `CONFLUENCE_GET_LABELS_FOR_SPACE` | space ID |

View File

@@ -0,0 +1,195 @@
---
name: convertkit-automation
description: "Automate ConvertKit (Kit) tasks via Rube MCP (Composio): manage subscribers, tags, broadcasts, and broadcast stats. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# ConvertKit (Kit) Automation via Rube MCP
Automate ConvertKit (now known as Kit) email marketing operations through Composio's Kit toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Kit connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `kit`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `kit`
3. If connection is not ACTIVE, follow the returned auth link to complete Kit authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. List and Search Subscribers
**When to use**: User wants to browse, search, or filter email subscribers
**Tool sequence**:
1. `KIT_LIST_SUBSCRIBERS` - List subscribers with filters and pagination [Required]
**Key parameters**:
- `status`: Filter by status ('active' or 'inactive')
- `email_address`: Exact email to search for
- `created_after`/`created_before`: Date range filter (YYYY-MM-DD)
- `updated_after`/`updated_before`: Date range filter (YYYY-MM-DD)
- `sort_field`: Sort by 'id', 'cancelled_at', or 'updated_at'
- `sort_order`: 'asc' or 'desc'
- `per_page`: Results per page (min 1)
- `after`/`before`: Cursor strings for pagination
- `include_total_count`: Set to 'true' to get total subscriber count
**Pitfalls**:
- If `sort_field` is 'cancelled_at', the `status` must be set to 'cancelled'
- Date filters use YYYY-MM-DD format (no time component)
- `email_address` is an exact match; partial email search is not supported
- Pagination uses cursor-based approach with `after`/`before` cursor strings
- `include_total_count` is a string 'true', not a boolean
### 2. Manage Subscriber Tags
**When to use**: User wants to tag subscribers for segmentation
**Tool sequence**:
1. `KIT_LIST_SUBSCRIBERS` - Find subscriber ID by email [Prerequisite]
2. `KIT_TAG_SUBSCRIBER` - Associate a subscriber with a tag [Required]
3. `KIT_LIST_TAG_SUBSCRIBERS` - List subscribers for a specific tag [Optional]
**Key parameters for tagging**:
- `tag_id`: Numeric tag ID (required)
- `subscriber_id`: Numeric subscriber ID (required)
**Pitfalls**:
- Both `tag_id` and `subscriber_id` must be positive integers
- Tag IDs must reference existing tags; tags are created via the Kit web UI
- Tagging an already-tagged subscriber is idempotent (no error)
- Subscriber IDs are returned from LIST_SUBSCRIBERS; use `email_address` filter to find specific subscribers
### 3. Unsubscribe a Subscriber
**When to use**: User wants to unsubscribe a subscriber from all communications
**Tool sequence**:
1. `KIT_LIST_SUBSCRIBERS` - Find subscriber ID [Prerequisite]
2. `KIT_DELETE_SUBSCRIBER` - Unsubscribe the subscriber [Required]
**Key parameters**:
- `id`: Subscriber ID (required, positive integer)
**Pitfalls**:
- This permanently unsubscribes the subscriber from ALL email communications
- The subscriber's historical data is retained but they will no longer receive emails
- Operation is idempotent; unsubscribing an already-unsubscribed subscriber succeeds without error
- Returns empty response (HTTP 204 No Content) on success
- Subscriber ID must exist; non-existent IDs return 404
### 4. List and View Broadcasts
**When to use**: User wants to browse email broadcasts or get details of a specific one
**Tool sequence**:
1. `KIT_LIST_BROADCASTS` - List all broadcasts with pagination [Required]
2. `KIT_GET_BROADCAST` - Get detailed information for a specific broadcast [Optional]
3. `KIT_GET_BROADCAST_STATS` - Get performance statistics for a broadcast [Optional]
**Key parameters for listing**:
- `per_page`: Results per page (1-500)
- `after`/`before`: Cursor strings for pagination
- `include_total_count`: Set to 'true' for total count
**Key parameters for details**:
- `id`: Broadcast ID (required, positive integer)
**Pitfalls**:
- `per_page` max is 500 for broadcasts
- Broadcast stats are only available for sent broadcasts
- Draft broadcasts will not have stats
- Broadcast IDs are numeric integers
### 5. Delete a Broadcast
**When to use**: User wants to permanently remove a broadcast
**Tool sequence**:
1. `KIT_LIST_BROADCASTS` - Find the broadcast to delete [Prerequisite]
2. `KIT_GET_BROADCAST` - Verify it is the correct broadcast [Optional]
3. `KIT_DELETE_BROADCAST` - Permanently delete the broadcast [Required]
**Key parameters**:
- `id`: Broadcast ID (required)
**Pitfalls**:
- Deletion is permanent and cannot be undone
- Deleting a sent broadcast removes it but does not unsend the emails
- Confirm the broadcast ID before deleting
## Common Patterns
### Subscriber Lookup by Email
```
1. Call KIT_LIST_SUBSCRIBERS with email_address='user@example.com'
2. Extract subscriber ID from the response
3. Use ID for tagging, unsubscribing, or other operations
```
### Pagination
Kit uses cursor-based pagination:
- Check response for `after` cursor value
- Pass cursor as `after` parameter in next request
- Continue until no more cursor is returned
- Use `include_total_count: 'true'` to track progress
### Tag-Based Segmentation
```
1. Create tags in Kit web UI
2. Use KIT_TAG_SUBSCRIBER to assign tags to subscribers
3. Use KIT_LIST_TAG_SUBSCRIBERS to view subscribers per tag
```
## Known Pitfalls
**ID Formats**:
- Subscriber IDs: positive integers (e.g., 3887204736)
- Tag IDs: positive integers
- Broadcast IDs: positive integers
- All IDs are numeric, not strings
**Status Values**:
- Subscriber statuses: 'active', 'inactive', 'cancelled'
- Some operations are restricted by status (e.g., sorting by cancelled_at requires status='cancelled')
**String vs Boolean Parameters**:
- `include_total_count` is a string 'true', not a boolean true
- `sort_order` is a string enum: 'asc' or 'desc'
**Rate Limits**:
- Kit API has per-account rate limits
- Implement backoff on 429 responses
- Bulk operations should be paced appropriately
**Response Parsing**:
- Response data may be nested under `data` or `data.data`
- Parse defensively with fallback patterns
- Cursor values are opaque strings; use exactly as returned
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List subscribers | KIT_LIST_SUBSCRIBERS | status, email_address, per_page |
| Tag subscriber | KIT_TAG_SUBSCRIBER | tag_id, subscriber_id |
| List tag subscribers | KIT_LIST_TAG_SUBSCRIBERS | tag_id |
| Unsubscribe | KIT_DELETE_SUBSCRIBER | id |
| List broadcasts | KIT_LIST_BROADCASTS | per_page, after |
| Get broadcast | KIT_GET_BROADCAST | id |
| Get broadcast stats | KIT_GET_BROADCAST_STATS | id |
| Delete broadcast | KIT_DELETE_BROADCAST | id |

View File

@@ -0,0 +1,235 @@
---
name: datadog-automation
description: "Automate Datadog tasks via Rube MCP (Composio): query metrics, search logs, manage monitors/dashboards, create events and downtimes. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Datadog Automation via Rube MCP
Automate Datadog monitoring and observability operations through Composio's Datadog toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Datadog connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `datadog`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `datadog`
3. If connection is not ACTIVE, follow the returned auth link to complete Datadog authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Query and Explore Metrics
**When to use**: User wants to query metric data or list available metrics
**Tool sequence**:
1. `DATADOG_LIST_METRICS` - List available metric names [Optional]
2. `DATADOG_QUERY_METRICS` - Query metric time series data [Required]
**Key parameters**:
- `query`: Datadog metric query string (e.g., `avg:system.cpu.user{host:web01}`)
- `from`: Start timestamp (Unix epoch seconds)
- `to`: End timestamp (Unix epoch seconds)
- `q`: Search string for listing metrics
**Pitfalls**:
- Query syntax follows Datadog's metric query format: `aggregation:metric_name{tag_filters}`
- `from` and `to` are Unix epoch timestamps in seconds, not milliseconds
- Valid aggregations: `avg`, `sum`, `min`, `max`, `count`
- Tag filters use curly braces: `{host:web01,env:prod}`
- Time range should not exceed Datadog's retention limits for the metric type
### 2. Search and Analyze Logs
**When to use**: User wants to search log entries or list log indexes
**Tool sequence**:
1. `DATADOG_LIST_LOG_INDEXES` - List available log indexes [Optional]
2. `DATADOG_SEARCH_LOGS` - Search logs with query and filters [Required]
**Key parameters**:
- `query`: Log search query using Datadog log query syntax
- `from`: Start time (ISO 8601 or Unix timestamp)
- `to`: End time (ISO 8601 or Unix timestamp)
- `sort`: Sort order ('asc' or 'desc')
- `limit`: Number of log entries to return
**Pitfalls**:
- Log queries use Datadog's log search syntax: `service:web status:error`
- Search is limited to retained logs within the configured retention period
- Large result sets require pagination; check for cursor/page tokens
- Log indexes control routing and retention; filter by index if known
### 3. Manage Monitors
**When to use**: User wants to create, update, mute, or inspect monitors
**Tool sequence**:
1. `DATADOG_LIST_MONITORS` - List all monitors with filters [Required]
2. `DATADOG_GET_MONITOR` - Get specific monitor details [Optional]
3. `DATADOG_CREATE_MONITOR` - Create a new monitor [Optional]
4. `DATADOG_UPDATE_MONITOR` - Update monitor configuration [Optional]
5. `DATADOG_MUTE_MONITOR` - Silence a monitor temporarily [Optional]
6. `DATADOG_UNMUTE_MONITOR` - Re-enable a muted monitor [Optional]
**Key parameters**:
- `monitor_id`: Numeric monitor ID
- `name`: Monitor display name
- `type`: Monitor type ('metric alert', 'service check', 'log alert', 'query alert', etc.)
- `query`: Monitor query defining the alert condition
- `message`: Notification message with @mentions
- `tags`: Array of tag strings
- `thresholds`: Alert threshold values (`critical`, `warning`, `ok`)
**Pitfalls**:
- Monitor `type` must match the query type; mismatches cause creation failures
- `message` supports @mentions for notifications (e.g., `@slack-channel`, `@pagerduty`)
- Thresholds vary by monitor type; metric monitors need `critical` at minimum
- Muting a monitor suppresses notifications but the monitor still evaluates
- Monitor IDs are numeric integers
### 4. Manage Dashboards
**When to use**: User wants to list, view, update, or delete dashboards
**Tool sequence**:
1. `DATADOG_LIST_DASHBOARDS` - List all dashboards [Required]
2. `DATADOG_GET_DASHBOARD` - Get full dashboard definition [Optional]
3. `DATADOG_UPDATE_DASHBOARD` - Update dashboard layout or widgets [Optional]
4. `DATADOG_DELETE_DASHBOARD` - Remove a dashboard (irreversible) [Optional]
**Key parameters**:
- `dashboard_id`: Dashboard identifier string
- `title`: Dashboard title
- `layout_type`: 'ordered' (grid) or 'free' (freeform positioning)
- `widgets`: Array of widget definition objects
- `description`: Dashboard description
**Pitfalls**:
- Dashboard IDs are alphanumeric strings (e.g., 'abc-def-ghi'), not numeric
- `layout_type` cannot be changed after creation; must recreate the dashboard
- Widget definitions are complex nested objects; get existing dashboard first to understand structure
- DELETE is permanent; there is no undo
### 5. Create Events and Manage Downtimes
**When to use**: User wants to post events or schedule maintenance downtimes
**Tool sequence**:
1. `DATADOG_LIST_EVENTS` - List existing events [Optional]
2. `DATADOG_CREATE_EVENT` - Post a new event [Required]
3. `DATADOG_CREATE_DOWNTIME` - Schedule a maintenance downtime [Optional]
**Key parameters for events**:
- `title`: Event title
- `text`: Event body text (supports markdown)
- `alert_type`: Event severity ('error', 'warning', 'info', 'success')
- `tags`: Array of tag strings
**Key parameters for downtimes**:
- `scope`: Tag scope for the downtime (e.g., `host:web01`)
- `start`: Start time (Unix epoch)
- `end`: End time (Unix epoch; omit for indefinite)
- `message`: Downtime description
- `monitor_id`: Specific monitor to downtime (optional, omit for scope-based)
**Pitfalls**:
- Event `text` supports Datadog's markdown format including @mentions
- Downtimes scope uses tag syntax: `host:web01`, `env:staging`
- Omitting `end` creates an indefinite downtime; always set an end time for maintenance
- Downtime `monitor_id` narrows to a single monitor; scope applies to all matching monitors
### 6. Manage Hosts and Traces
**When to use**: User wants to list infrastructure hosts or inspect distributed traces
**Tool sequence**:
1. `DATADOG_LIST_HOSTS` - List all reporting hosts [Required]
2. `DATADOG_GET_TRACE_BY_ID` - Get a specific distributed trace [Optional]
**Key parameters**:
- `filter`: Host search filter string
- `sort_field`: Sort hosts by field (e.g., 'name', 'apps', 'cpu')
- `sort_dir`: Sort direction ('asc' or 'desc')
- `trace_id`: Distributed trace ID for trace lookup
**Pitfalls**:
- Host list includes all hosts reporting to Datadog within the retention window
- Trace IDs are long numeric strings; ensure exact match
- Hosts that stop reporting are retained for a configured period before removal
## Common Patterns
### Monitor Query Syntax
**Metric alerts**:
```
avg(last_5m):avg:system.cpu.user{env:prod} > 90
```
**Log alerts**:
```
logs("service:web status:error").index("main").rollup("count").last("5m") > 10
```
### Tag Filtering
- Tags use `key:value` format: `host:web01`, `env:prod`, `service:api`
- Multiple tags: `{host:web01,env:prod}` (AND logic)
- Wildcard: `host:web*`
### Pagination
- Use `page` and `page_size` or offset-based pagination depending on endpoint
- Check response for total count to determine if more pages exist
- Continue until all results are retrieved
## Known Pitfalls
**Timestamps**:
- Most endpoints use Unix epoch seconds (not milliseconds)
- Some endpoints accept ISO 8601; check tool schema
- Time ranges should be reasonable (not years of data)
**Query Syntax**:
- Metric queries: `aggregation:metric{tags}`
- Log queries: `field:value` pairs
- Monitor queries vary by type; check Datadog documentation
**Rate Limits**:
- Datadog API has per-endpoint rate limits
- Implement backoff on 429 responses
- Batch operations where possible
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Query metrics | DATADOG_QUERY_METRICS | query, from, to |
| List metrics | DATADOG_LIST_METRICS | q |
| Search logs | DATADOG_SEARCH_LOGS | query, from, to, limit |
| List log indexes | DATADOG_LIST_LOG_INDEXES | (none) |
| List monitors | DATADOG_LIST_MONITORS | tags |
| Get monitor | DATADOG_GET_MONITOR | monitor_id |
| Create monitor | DATADOG_CREATE_MONITOR | name, type, query, message |
| Update monitor | DATADOG_UPDATE_MONITOR | monitor_id |
| Mute monitor | DATADOG_MUTE_MONITOR | monitor_id |
| Unmute monitor | DATADOG_UNMUTE_MONITOR | monitor_id |
| List dashboards | DATADOG_LIST_DASHBOARDS | (none) |
| Get dashboard | DATADOG_GET_DASHBOARD | dashboard_id |
| Update dashboard | DATADOG_UPDATE_DASHBOARD | dashboard_id, title, widgets |
| Delete dashboard | DATADOG_DELETE_DASHBOARD | dashboard_id |
| List events | DATADOG_LIST_EVENTS | start, end |
| Create event | DATADOG_CREATE_EVENT | title, text, alert_type |
| Create downtime | DATADOG_CREATE_DOWNTIME | scope, start, end |
| List hosts | DATADOG_LIST_HOSTS | filter, sort_field |
| Get trace | DATADOG_GET_TRACE_BY_ID | trace_id |

View File

@@ -0,0 +1,187 @@
---
name: discord-automation
description: "Automate Discord tasks via Rube MCP (Composio): messages, channels, roles, webhooks, reactions. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Discord Automation via Rube MCP
Automate Discord operations through Composio's Discord/Discordbot toolkits via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Discord connection via `RUBE_MANAGE_CONNECTIONS` with toolkits `discord` and `discordbot`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `discordbot` (bot operations) or `discord` (user operations)
3. If connection is not ACTIVE, follow the returned auth link to complete Discord auth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Send Messages
**When to use**: User wants to send messages to channels or DMs
**Tool sequence**:
1. `DISCORD_LIST_MY_GUILDS` - List guilds the bot belongs to [Prerequisite]
2. `DISCORDBOT_LIST_GUILD_CHANNELS` - List channels in a guild [Prerequisite]
3. `DISCORDBOT_CREATE_MESSAGE` - Send a message [Required]
4. `DISCORDBOT_UPDATE_MESSAGE` - Edit a sent message [Optional]
**Key parameters**:
- `channel_id`: Channel snowflake ID
- `content`: Message text (max 2000 characters)
- `embeds`: Array of embed objects for rich content
- `guild_id`: Guild ID for channel listing
**Pitfalls**:
- Bot must have SEND_MESSAGES permission in the channel
- High-frequency sends can hit per-route rate limits; respect Retry-After headers
- Only messages sent by the same bot can be edited
### 2. Send Direct Messages
**When to use**: User wants to DM a Discord user
**Tool sequence**:
1. `DISCORDBOT_CREATE_DM` - Create or get DM channel [Required]
2. `DISCORDBOT_CREATE_MESSAGE` - Send message to DM channel [Required]
**Key parameters**:
- `recipient_id`: User snowflake ID for DM
- `channel_id`: DM channel ID from CREATE_DM
**Pitfalls**:
- Cannot DM users who have DMs disabled or have blocked the bot
- CREATE_DM returns existing channel if one already exists
### 3. Manage Roles
**When to use**: User wants to create, assign, or remove roles
**Tool sequence**:
1. `DISCORDBOT_CREATE_GUILD_ROLE` - Create a new role [Optional]
2. `DISCORDBOT_ADD_GUILD_MEMBER_ROLE` - Assign role to member [Optional]
3. `DISCORDBOT_DELETE_GUILD_ROLE` - Delete a role [Optional]
4. `DISCORDBOT_GET_GUILD_MEMBER` - Get member details [Optional]
5. `DISCORDBOT_UPDATE_GUILD_MEMBER` - Update member (roles, nick, etc.) [Optional]
**Key parameters**:
- `guild_id`: Guild snowflake ID
- `user_id`: User snowflake ID
- `role_id`: Role snowflake ID
- `name`: Role name
- `permissions`: Bitwise permission value
- `color`: RGB color integer
**Pitfalls**:
- Role assignment requires MANAGE_ROLES permission
- Target role must be lower in hierarchy than bot's highest role
- DELETE permanently removes the role from all members
### 4. Manage Webhooks
**When to use**: User wants to create or use webhooks for external integrations
**Tool sequence**:
1. `DISCORDBOT_GET_GUILD_WEBHOOKS` / `DISCORDBOT_LIST_CHANNEL_WEBHOOKS` - List webhooks [Optional]
2. `DISCORDBOT_CREATE_WEBHOOK` - Create a new webhook [Optional]
3. `DISCORDBOT_EXECUTE_WEBHOOK` - Send message via webhook [Optional]
4. `DISCORDBOT_UPDATE_WEBHOOK` - Update webhook settings [Optional]
**Key parameters**:
- `webhook_id`: Webhook ID
- `webhook_token`: Webhook secret token
- `channel_id`: Channel for webhook creation
- `name`: Webhook name
- `content`/`embeds`: Message content for execution
**Pitfalls**:
- Webhook tokens are secrets; handle securely
- Webhooks can post with custom username and avatar per message
- MANAGE_WEBHOOKS permission required for creation
### 5. Manage Reactions
**When to use**: User wants to view or manage message reactions
**Tool sequence**:
1. `DISCORDBOT_LIST_MESSAGE_REACTIONS_BY_EMOJI` - List users who reacted [Optional]
2. `DISCORDBOT_DELETE_ALL_MESSAGE_REACTIONS` - Remove all reactions [Optional]
3. `DISCORDBOT_DELETE_ALL_MESSAGE_REACTIONS_BY_EMOJI` - Remove specific emoji reactions [Optional]
4. `DISCORDBOT_DELETE_USER_MESSAGE_REACTION` - Remove specific user's reaction [Optional]
**Key parameters**:
- `channel_id`: Channel ID
- `message_id`: Message snowflake ID
- `emoji_name`: URL-encoded emoji or `name:id` for custom emojis
- `user_id`: User ID for specific reaction removal
**Pitfalls**:
- Unicode emojis must be URL-encoded (e.g., '%F0%9F%91%8D' for thumbs up)
- Custom emojis use `name:id` format
- DELETE_ALL requires MANAGE_MESSAGES permission
## Common Patterns
### Snowflake IDs
Discord uses snowflake IDs (64-bit integers as strings) for all entities:
- Guilds, channels, users, roles, messages, webhooks
### Permission Bitfields
Permissions are combined using bitwise OR:
- SEND_MESSAGES = 0x800
- MANAGE_ROLES = 0x10000000
- MANAGE_MESSAGES = 0x2000
- ADMINISTRATOR = 0x8
### Pagination
- Most list endpoints support `limit`, `before`, `after` parameters
- Messages: max 100 per request
- Reactions: max 100 per request, use `after` for pagination
## Known Pitfalls
**Bot vs User Tokens**:
- `discordbot` toolkit uses bot tokens; `discord` uses user OAuth
- Bot operations are preferred for automation
**Rate Limits**:
- Discord enforces per-route rate limits
- Respect `Retry-After` headers on 429 responses
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List guilds | DISCORD_LIST_MY_GUILDS | (none) |
| List channels | DISCORDBOT_LIST_GUILD_CHANNELS | guild_id |
| Send message | DISCORDBOT_CREATE_MESSAGE | channel_id, content |
| Edit message | DISCORDBOT_UPDATE_MESSAGE | channel_id, message_id |
| Get messages | DISCORDBOT_LIST_MESSAGES | channel_id, limit |
| Create DM | DISCORDBOT_CREATE_DM | recipient_id |
| Create role | DISCORDBOT_CREATE_GUILD_ROLE | guild_id, name |
| Assign role | DISCORDBOT_ADD_GUILD_MEMBER_ROLE | guild_id, user_id, role_id |
| Delete role | DISCORDBOT_DELETE_GUILD_ROLE | guild_id, role_id |
| Get member | DISCORDBOT_GET_GUILD_MEMBER | guild_id, user_id |
| Update member | DISCORDBOT_UPDATE_GUILD_MEMBER | guild_id, user_id |
| Get guild | DISCORDBOT_GET_GUILD | guild_id |
| Create webhook | DISCORDBOT_CREATE_WEBHOOK | channel_id, name |
| Execute webhook | DISCORDBOT_EXECUTE_WEBHOOK | webhook_id, webhook_token |
| List webhooks | DISCORDBOT_GET_GUILD_WEBHOOKS | guild_id |
| Get reactions | DISCORDBOT_LIST_MESSAGE_REACTIONS_BY_EMOJI | channel_id, message_id, emoji_name |
| Clear reactions | DISCORDBOT_DELETE_ALL_MESSAGE_REACTIONS | channel_id, message_id |
| Test auth | DISCORDBOT_TEST_AUTH | (none) |
| Get channel | DISCORDBOT_GET_CHANNEL | channel_id |

View File

@@ -0,0 +1,208 @@
---
name: docusign-automation
description: "Automate DocuSign tasks via Rube MCP (Composio): templates, envelopes, signatures, document management. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# DocuSign Automation via Rube MCP
Automate DocuSign e-signature workflows through Composio's DocuSign toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active DocuSign connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `docusign`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `docusign`
3. If connection is not ACTIVE, follow the returned auth link to complete DocuSign OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Browse and Select Templates
**When to use**: User wants to find available document templates for sending
**Tool sequence**:
1. `DOCUSIGN_LIST_ALL_TEMPLATES` - List all available templates [Required]
2. `DOCUSIGN_GET_TEMPLATE` - Get detailed template information [Optional]
**Key parameters**:
- For listing: Optional search/filter parameters
- For details: `templateId` (from list results)
- Response includes template `templateId`, `name`, `description`, roles, and fields
**Pitfalls**:
- Template IDs are GUIDs (e.g., '12345678-abcd-1234-efgh-123456789012')
- Templates define recipient roles with signing tabs; understand roles before creating envelopes
- Large template libraries require pagination; check for continuation tokens
- Template access depends on account permissions
### 2. Create and Send Envelopes from Templates
**When to use**: User wants to send documents for signature using a pre-built template
**Tool sequence**:
1. `DOCUSIGN_LIST_ALL_TEMPLATES` - Find the template to use [Prerequisite]
2. `DOCUSIGN_GET_TEMPLATE` - Review template roles and fields [Optional]
3. `DOCUSIGN_CREATE_ENVELOPE_FROM_TEMPLATE` - Create the envelope [Required]
4. `DOCUSIGN_SEND_ENVELOPE` - Send the envelope for signing [Required]
**Key parameters**:
- For CREATE_ENVELOPE_FROM_TEMPLATE:
- `templateId`: Template to use
- `templateRoles`: Array of role assignments with `roleName`, `name`, `email`
- `status`: 'created' (draft) or 'sent' (send immediately)
- `emailSubject`: Custom subject line for the signing email
- `emailBlurb`: Custom message in the signing email
- For SEND_ENVELOPE:
- `envelopeId`: Envelope ID from creation response
**Pitfalls**:
- `templateRoles` must match the role names defined in the template exactly (case-sensitive)
- Setting `status` to 'sent' during creation sends immediately; use 'created' for drafts
- If status is 'sent' at creation, no need to call SEND_ENVELOPE separately
- Each role requires at minimum `roleName`, `name`, and `email`
- `emailSubject` overrides the template's default email subject
### 3. Monitor Envelope Status
**When to use**: User wants to check the status of sent envelopes or track signing progress
**Tool sequence**:
1. `DOCUSIGN_GET_ENVELOPE` - Get envelope details and status [Required]
**Key parameters**:
- `envelopeId`: Envelope identifier (GUID)
- Response includes `status`, `recipients`, `sentDateTime`, `completedDateTime`
**Pitfalls**:
- Envelope statuses: 'created', 'sent', 'delivered', 'signed', 'completed', 'declined', 'voided'
- 'delivered' means the email was opened, not that the document was signed
- 'completed' means all recipients have signed
- Recipients array shows individual signing status per recipient
- Envelope IDs are GUIDs; always resolve from creation or search results
### 4. Add Templates to Existing Envelopes
**When to use**: User wants to add additional documents or templates to an existing envelope
**Tool sequence**:
1. `DOCUSIGN_GET_ENVELOPE` - Verify envelope exists and is in draft state [Prerequisite]
2. `DOCUSIGN_ADD_TEMPLATES_TO_DOCUMENT_IN_ENVELOPE` - Add template to envelope [Required]
**Key parameters**:
- `envelopeId`: Target envelope ID
- `documentId`: Document ID within the envelope
- `templateId`: Template to add
**Pitfalls**:
- Envelope must be in 'created' (draft) status to add templates
- Cannot add templates to already-sent envelopes
- Document IDs are sequential within an envelope (starting from '1')
- Adding a template merges its fields and roles into the existing envelope
### 5. Manage Envelope Lifecycle
**When to use**: User wants to send, void, or manage draft envelopes
**Tool sequence**:
1. `DOCUSIGN_GET_ENVELOPE` - Check current envelope status [Prerequisite]
2. `DOCUSIGN_SEND_ENVELOPE` - Send a draft envelope [Optional]
**Key parameters**:
- `envelopeId`: Envelope to manage
- For sending: envelope must be in 'created' status with all required recipients
**Pitfalls**:
- Only 'created' (draft) envelopes can be sent
- Sent envelopes cannot be unsent; they can only be voided
- Voiding an envelope notifies all recipients
- All required recipients must have valid email addresses before sending
## Common Patterns
### ID Resolution
**Template name -> Template ID**:
```
1. Call DOCUSIGN_LIST_ALL_TEMPLATES
2. Find template by name in results
3. Extract templateId (GUID format)
```
**Envelope tracking**:
```
1. Store envelopeId from CREATE_ENVELOPE_FROM_TEMPLATE response
2. Call DOCUSIGN_GET_ENVELOPE periodically to check status
3. Check recipient-level status for individual signing progress
```
### Template Role Mapping
When creating an envelope from a template:
```
1. Call DOCUSIGN_GET_TEMPLATE to see defined roles
2. Map each role to actual recipients:
{
"roleName": "Signer 1", // Must match template role name exactly
"name": "John Smith",
"email": "john@example.com"
}
3. Include ALL required roles in templateRoles array
```
### Envelope Status Flow
```
created (draft) -> sent -> delivered -> signed -> completed
\-> declined
\-> voided (by sender)
```
## Known Pitfalls
**Template Roles**:
- Role names are case-sensitive; must match template definition exactly
- All required roles must be assigned when creating an envelope
- Missing role assignments cause envelope creation to fail
**Envelope Status**:
- 'delivered' means email opened, NOT document signed
- 'completed' is the final successful state (all parties signed)
- Status transitions are one-way; cannot revert to previous states
**GUIDs**:
- All DocuSign IDs (templates, envelopes) are GUID format
- Always resolve names to GUIDs via list/search endpoints
- Do not hardcode GUIDs; they are unique per account
**Rate Limits**:
- DocuSign API has per-account rate limits
- Bulk envelope creation should be throttled
- Polling envelope status should use reasonable intervals (30-60 seconds)
**Response Parsing**:
- Response data may be nested under `data` key
- Recipient information is nested within envelope response
- Date fields use ISO 8601 format
- Parse defensively with fallbacks for optional fields
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List templates | DOCUSIGN_LIST_ALL_TEMPLATES | (optional filters) |
| Get template | DOCUSIGN_GET_TEMPLATE | templateId |
| Create envelope | DOCUSIGN_CREATE_ENVELOPE_FROM_TEMPLATE | templateId, templateRoles, status |
| Send envelope | DOCUSIGN_SEND_ENVELOPE | envelopeId |
| Get envelope status | DOCUSIGN_GET_ENVELOPE | envelopeId |
| Add template to envelope | DOCUSIGN_ADD_TEMPLATES_TO_DOCUMENT_IN_ENVELOPE | envelopeId, documentId, templateId |

View File

@@ -0,0 +1,266 @@
---
name: dotnet-backend
description: Build ASP.NET Core 8+ backend services with EF Core, auth, background jobs, and production API patterns.
risk: safe
source: self
allowed-tools: Read, Write, Edit, Bash
model: opus
---
# .NET Backend Agent - ASP.NET Core & Enterprise API Expert
You are an expert .NET/C# backend developer with 8+ years of experience building enterprise-grade APIs and services.
## When to Use
Use this skill when the user asks to:
- Build or refactor ASP.NET Core APIs (controller-based or Minimal APIs)
- Implement authentication/authorization in a .NET backend
- Design or optimize EF Core data access patterns
- Add background workers, scheduled jobs, or integration services in C#
- Improve reliability/performance of a .NET backend service
## Your Expertise
- **Frameworks**: ASP.NET Core 8+, Minimal APIs, Web API
- **ORM**: Entity Framework Core 8+, Dapper
- **Databases**: SQL Server, PostgreSQL, MySQL
- **Authentication**: ASP.NET Core Identity, JWT, OAuth 2.0, Azure AD
- **Authorization**: Policy-based, role-based, claims-based
- **API Patterns**: RESTful, gRPC, GraphQL (HotChocolate)
- **Background**: IHostedService, BackgroundService, Hangfire
- **Real-time**: SignalR
- **Testing**: xUnit, NUnit, Moq, FluentAssertions
- **Dependency Injection**: Built-in DI container
- **Validation**: FluentValidation, Data Annotations
## Your Responsibilities
1. **Build ASP.NET Core APIs**
- RESTful controllers or Minimal APIs
- Model validation
- Exception handling middleware
- CORS configuration
- Response compression
2. **Entity Framework Core**
- DbContext configuration
- Code-first migrations
- Query optimization
- Include/ThenInclude for eager loading
- AsNoTracking for read-only queries
3. **Authentication & Authorization**
- JWT token generation/validation
- ASP.NET Core Identity integration
- Policy-based authorization
- Custom authorization handlers
4. **Background Services**
- IHostedService for long-running tasks
- Scoped services in background workers
- Scheduled jobs with Hangfire/Quartz.NET
5. **Performance**
- Async/await throughout
- Connection pooling
- Response caching
- Output caching (.NET 8+)
## Code Patterns You Follow
### Minimal API with EF Core
```csharp
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Services
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
var app = builder.Build();
// Create user endpoint
app.MapPost("/api/users", async (CreateUserRequest request, AppDbContext db) =>
{
// Validate
if (string.IsNullOrEmpty(request.Email))
return Results.BadRequest("Email is required");
// Hash password
var hashedPassword = BCrypt.Net.BCrypt.HashPassword(request.Password);
// Create user
var user = new User
{
Email = request.Email,
PasswordHash = hashedPassword,
Name = request.Name
};
db.Users.Add(user);
await db.SaveChangesAsync();
return Results.Created($"/api/users/{user.Id}", new UserResponse(user));
})
.WithName("CreateUser")
.WithOpenApi();
app.Run();
record CreateUserRequest(string Email, string Password, string Name);
record UserResponse(int Id, string Email, string Name);
```
### Controller-based API
```csharp
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly AppDbContext _db;
private readonly ILogger<UsersController> _logger;
public UsersController(AppDbContext db, ILogger<UsersController> logger)
{
_db = db;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<List<UserDto>>> GetUsers()
{
var users = await _db.Users
.AsNoTracking()
.Select(u => new UserDto(u.Id, u.Email, u.Name))
.ToListAsync();
return Ok(users);
}
[HttpPost]
public async Task<ActionResult<UserDto>> CreateUser(CreateUserDto dto)
{
var user = new User
{
Email = dto.Email,
PasswordHash = BCrypt.Net.BCrypt.HashPassword(dto.Password),
Name = dto.Name
};
_db.Users.Add(user);
await _db.SaveChangesAsync();
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, new UserDto(user));
}
}
```
### JWT Authentication
```csharp
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
public class TokenService
{
private readonly IConfiguration _config;
public TokenService(IConfiguration config) => _config = config;
public string GenerateToken(User user)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Name, user.Name)
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
```
### Background Service
```csharp
public class EmailSenderService : BackgroundService
{
private readonly ILogger<EmailSenderService> _logger;
private readonly IServiceProvider _services;
public EmailSenderService(ILogger<EmailSenderService> logger, IServiceProvider services)
{
_logger = logger;
_services = services;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using var scope = _services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var pendingEmails = await db.PendingEmails
.Where(e => !e.Sent)
.Take(10)
.ToListAsync(stoppingToken);
foreach (var email in pendingEmails)
{
await SendEmailAsync(email);
email.Sent = true;
}
await db.SaveChangesAsync(stoppingToken);
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
private async Task SendEmailAsync(PendingEmail email)
{
// Send email logic
_logger.LogInformation("Sending email to {Email}", email.To);
}
}
```
## Best Practices You Follow
- ✅ Async/await for all I/O operations
- ✅ Dependency Injection for all services
- ✅ appsettings.json for configuration
- ✅ User Secrets for local development
- ✅ Entity Framework migrations (Add-Migration, Update-Database)
- ✅ Global exception handling middleware
- ✅ FluentValidation for complex validation
- ✅ Serilog for structured logging
- ✅ Health checks (AddHealthChecks)
- ✅ API versioning
- ✅ Swagger/OpenAPI documentation
- ✅ AutoMapper for DTO mapping
- ✅ CQRS with MediatR (for complex domains)
## Limitations
- Assumes modern .NET (ASP.NET Core 8+); older .NET Framework projects may require different patterns.
- Does not cover client-side/frontend implementations.
- Cloud-provider-specific deployment details (Azure/AWS/GCP) are out of scope unless explicitly requested.

View File

@@ -0,0 +1,230 @@
---
name: dropbox-automation
description: "Automate Dropbox file management, sharing, search, uploads, downloads, and folder operations via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Dropbox Automation via Rube MCP
Automate Dropbox operations including file upload/download, search, folder management, sharing links, batch operations, and metadata retrieval through Composio's Dropbox toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Dropbox connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `dropbox`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `dropbox`
3. If connection is not ACTIVE, follow the returned auth link to complete Dropbox OAuth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Search for Files and Folders
**When to use**: User wants to find files or folders by name, content, or type
**Tool sequence**:
1. `DROPBOX_SEARCH_FILE_OR_FOLDER` - Search by query string with optional path scope and filters [Required]
2. `DROPBOX_SEARCH_CONTINUE` - Paginate through additional results using cursor [Required if has_more]
3. `DROPBOX_GET_METADATA` - Validate and get canonical path for a search result [Optional]
4. `DROPBOX_READ_FILE` - Read file content to verify it is the intended document [Optional]
**Key parameters**:
- `query`: Search string (case-insensitive, 1+ non-whitespace characters)
- `options.path`: Scope search to a folder (e.g., `"/Documents"`); empty string for root
- `options.file_categories`: Filter by type (`"image"`, `"document"`, `"pdf"`, `"folder"`, etc.)
- `options.file_extensions`: Filter by extension (e.g., `["jpg", "png"]`)
- `options.filename_only`: Set `true` to match filenames only (not content)
- `options.max_results`: Results per page (default 100, max 1000)
**Pitfalls**:
- Search returns `has_more: true` with a `cursor` when more results exist; MUST continue to avoid silently missing matches
- Maximum 10,000 matches total across all pages of search + search_continue
- `DROPBOX_GET_METADATA` returned `path_display` may differ in casing from user input; always use the returned canonical path
- File content from `DROPBOX_READ_FILE` may be returned as base64-encoded `file_content_bytes`; decode before parsing
### 2. Upload and Download Files
**When to use**: User wants to upload files to Dropbox or download files from it
**Tool sequence**:
1. `DROPBOX_UPLOAD_FILE` - Upload a file to a specified path [Required for upload]
2. `DROPBOX_READ_FILE` - Download/read a file from Dropbox [Required for download]
3. `DROPBOX_DOWNLOAD_ZIP` - Download an entire folder as a zip file [Optional]
4. `DROPBOX_SAVE_URL` - Save a file from a public URL directly to Dropbox [Optional]
5. `DROPBOX_GET_SHARED_LINK_FILE` - Download a file from a shared link URL [Optional]
6. `DROPBOX_EXPORT_FILE` - Export non-downloadable files like Dropbox Paper to markdown/HTML [Optional]
**Key parameters**:
- `path`: Dropbox path (must start with `/`, e.g., `"/Documents/report.pdf"`)
- `mode`: `"add"` (default, fail on conflict) or `"overwrite"` for uploads
- `autorename`: `true` to auto-rename on conflict instead of failing
- `content`: FileUploadable object with `s3key`, `mimetype`, and `name` for uploads
- `url`: Public URL for `DROPBOX_SAVE_URL`
- `export_format`: `"markdown"`, `"html"`, or `"plain_text"` for Paper docs
**Pitfalls**:
- `DROPBOX_SAVE_URL` is asynchronous and may take up to 15 minutes for large files
- `DROPBOX_DOWNLOAD_ZIP` folder must be under 20 GB with no single file over 4 GB and fewer than 10,000 entries
- `DROPBOX_READ_FILE` content may be base64-encoded; check response format
- Shared link downloads via `DROPBOX_GET_SHARED_LINK_FILE` may require `link_password` for protected links
### 3. Share Files and Manage Links
**When to use**: User wants to create sharing links or manage existing shared links
**Tool sequence**:
1. `DROPBOX_GET_METADATA` - Confirm file/folder exists and get canonical path [Prerequisite]
2. `DROPBOX_LIST_SHARED_LINKS` - Check for existing shared links to avoid duplicates [Prerequisite]
3. `DROPBOX_CREATE_SHARED_LINK` - Create a new shared link [Required]
4. `DROPBOX_GET_SHARED_LINK_METADATA` - Resolve a shared link URL to metadata [Optional]
5. `DROPBOX_LIST_SHARED_FOLDERS` - List all shared folders the user has access to [Optional]
**Key parameters**:
- `path`: File or folder path for link creation
- `settings.audience`: `"public"`, `"team"`, or `"no_one"`
- `settings.access`: `"viewer"` or `"editor"`
- `settings.expires`: ISO 8601 expiration date (e.g., `"2026-12-31T23:59:59Z"`)
- `settings.require_password` / `settings.link_password`: Password protection
- `settings.allow_download`: Boolean for download permission
- `direct_only`: For `LIST_SHARED_LINKS`, set `true` to only return direct links (not parent folder links)
**Pitfalls**:
- `DROPBOX_CREATE_SHARED_LINK` fails with 409 Conflict if a shared link already exists for the path; check with `DROPBOX_LIST_SHARED_LINKS` first
- Always validate path with `DROPBOX_GET_METADATA` before creating links to avoid `path/not_found` errors
- Reuse existing links from `DROPBOX_LIST_SHARED_LINKS` instead of creating duplicates
- `requested_visibility` is deprecated; use `audience` for newer implementations
### 4. Manage Folders (Create, Move, Delete)
**When to use**: User wants to create, move, rename, or delete files and folders
**Tool sequence**:
1. `DROPBOX_CREATE_FOLDER` - Create a single folder [Required for create]
2. `DROPBOX_CREATE_FOLDER_BATCH` - Create multiple folders at once [Optional]
3. `DROPBOX_MOVE_FILE_OR_FOLDER` - Move or rename a single file/folder [Required for move]
4. `DROPBOX_MOVE_BATCH` - Move multiple items at once [Optional]
5. `DROPBOX_DELETE_FILE_OR_FOLDER` - Delete a single file or folder [Required for delete]
6. `DROPBOX_DELETE_BATCH` - Delete multiple items at once [Optional]
7. `DROPBOX_COPY_FILE_OR_FOLDER` - Copy a file or folder to a new location [Optional]
8. `DROPBOX_CHECK_MOVE_BATCH` / `DROPBOX_CHECK_FOLDER_BATCH` - Poll async batch job status [Required for batch ops]
**Key parameters**:
- `path`: Target path (must start with `/`, case-sensitive)
- `from_path` / `to_path`: Source and destination for move/copy operations
- `autorename`: `true` to auto-rename on conflict
- `entries`: Array of `{from_path, to_path}` for batch moves; array of paths for batch creates
- `allow_shared_folder`: Set `true` to allow moving shared folders
- `allow_ownership_transfer`: Set `true` if move changes ownership
**Pitfalls**:
- All paths are case-sensitive and must start with `/`
- Paths must NOT end with `/` or whitespace
- Batch operations may be asynchronous; poll with `DROPBOX_CHECK_MOVE_BATCH` or `DROPBOX_CHECK_FOLDER_BATCH`
- `DROPBOX_FILES_MOVE_BATCH` (v1) has "all or nothing" behavior - if any entry fails, entire batch fails
- `DROPBOX_MOVE_BATCH` (v2) is preferred over `DROPBOX_FILES_MOVE_BATCH` (v1)
- Maximum 1000 entries per batch delete/move; 10,000 paths per batch folder create
- Case-only renaming is not supported in batch move operations
### 5. List Folder Contents
**When to use**: User wants to browse or enumerate files in a Dropbox folder
**Tool sequence**:
1. `DROPBOX_LIST_FILES_IN_FOLDER` - List contents of a folder [Required]
2. `DROPBOX_LIST_FOLDERS` - Alternative folder listing with deleted entries support [Optional]
3. `DROPBOX_GET_METADATA` - Get details for a specific item [Optional]
**Key parameters**:
- `path`: Folder path (empty string `""` for root)
- `recursive`: `true` to list all nested contents
- `limit`: Max results per request (default/max 2000)
- `include_deleted`: `true` to include deleted but recoverable items
- `include_media_info`: `true` to get photo/video metadata
**Pitfalls**:
- Use empty string `""` for root folder, not `"/"`
- Recursive listings can be very large; use `limit` to control page size
- Results may paginate via cursor even with small limits
- `DROPBOX_LIST_FILES_IN_FOLDER` returns 409 Conflict with `path/not_found` for incorrect paths
## Common Patterns
### ID Resolution
- **Path-based**: Most Dropbox tools use path strings (e.g., `"/Documents/file.pdf"`)
- **ID-based**: Some tools accept `id:...` format (e.g., `"id:4g0reWVRsAAAAAAAAAAAQ"`)
- **Canonical path**: Always use `path_display` or `path_lower` from `DROPBOX_GET_METADATA` responses for subsequent calls
- **Shared link URL**: Use `DROPBOX_GET_SHARED_LINK_METADATA` to resolve URLs to paths/IDs
### Pagination
Dropbox uses cursor-based pagination across most endpoints:
- Search: Follow `has_more` + `cursor` with `DROPBOX_SEARCH_CONTINUE` (max 10,000 total matches)
- Folder listing: Follow cursor from response until no more pages
- Shared links: Follow `has_more` + `cursor` in `DROPBOX_LIST_SHARED_LINKS`
- Batch job status: Poll with `DROPBOX_CHECK_MOVE_BATCH` / `DROPBOX_CHECK_FOLDER_BATCH`
### Async Operations
Several Dropbox operations run asynchronously:
- `DROPBOX_SAVE_URL` - returns job ID; poll or set `wait: true` (up to 120s default)
- `DROPBOX_MOVE_BATCH` / `DROPBOX_FILES_MOVE_BATCH` - may return job ID
- `DROPBOX_CREATE_FOLDER_BATCH` - may return job ID
- `DROPBOX_DELETE_BATCH` - returns job ID
## Known Pitfalls
### Path Formats
- All paths must start with `/` (except empty string for root in some endpoints)
- Paths must NOT end with `/` or contain trailing whitespace
- Paths are case-sensitive for write operations
- `path_display` from API may differ in casing from user input; always prefer API-returned paths
### Rate Limits
- Dropbox API has per-endpoint rate limits; batch operations help reduce call count
- Search is limited to 10,000 total matches across all pagination
- `DROPBOX_SAVE_URL` has a 15-minute timeout for large files
### File Content
- `DROPBOX_READ_FILE` may return content as base64-encoded `file_content_bytes`
- Non-downloadable files (Dropbox Paper, Google Docs) require `DROPBOX_EXPORT_FILE` instead
- Download URLs from shared links require proper authentication headers
### Sharing
- Creating a shared link when one already exists returns a 409 Conflict error
- Always check `DROPBOX_LIST_SHARED_LINKS` before creating new links
- Shared folder access may not appear in standard path listings; use `DROPBOX_LIST_SHARED_FOLDERS`
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Search files | `DROPBOX_SEARCH_FILE_OR_FOLDER` | `query`, `options.path` |
| Continue search | `DROPBOX_SEARCH_CONTINUE` | `cursor` |
| List folder | `DROPBOX_LIST_FILES_IN_FOLDER` | `path`, `recursive`, `limit` |
| List folders | `DROPBOX_LIST_FOLDERS` | `path`, `recursive` |
| Get metadata | `DROPBOX_GET_METADATA` | `path` |
| Read/download file | `DROPBOX_READ_FILE` | `path` |
| Upload file | `DROPBOX_UPLOAD_FILE` | `path`, `content`, `mode` |
| Save URL to Dropbox | `DROPBOX_SAVE_URL` | `path`, `url` |
| Download folder zip | `DROPBOX_DOWNLOAD_ZIP` | `path` |
| Export Paper doc | `DROPBOX_EXPORT_FILE` | `path`, `export_format` |
| Download shared link | `DROPBOX_GET_SHARED_LINK_FILE` | `url` |
| Create shared link | `DROPBOX_CREATE_SHARED_LINK` | `path`, `settings` |
| List shared links | `DROPBOX_LIST_SHARED_LINKS` | `path`, `direct_only` |
| Shared link metadata | `DROPBOX_GET_SHARED_LINK_METADATA` | `url` |
| List shared folders | `DROPBOX_LIST_SHARED_FOLDERS` | `limit` |
| Create folder | `DROPBOX_CREATE_FOLDER` | `path` |
| Create folders batch | `DROPBOX_CREATE_FOLDER_BATCH` | `paths` |
| Move file/folder | `DROPBOX_MOVE_FILE_OR_FOLDER` | `from_path`, `to_path` |
| Move batch | `DROPBOX_MOVE_BATCH` | `entries` |
| Delete file/folder | `DROPBOX_DELETE_FILE_OR_FOLDER` | `path` |
| Delete batch | `DROPBOX_DELETE_BATCH` | `entries` |
| Copy file/folder | `DROPBOX_COPY_FILE_OR_FOLDER` | `from_path`, `to_path` |
| Check batch status | `DROPBOX_CHECK_MOVE_BATCH` | `async_job_id` |

View File

@@ -0,0 +1,181 @@
---
name: figma-automation
description: "Automate Figma tasks via Rube MCP (Composio): files, components, design tokens, comments, exports. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Figma Automation via Rube MCP
Automate Figma operations through Composio's Figma toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Figma connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `figma`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `figma`
3. If connection is not ACTIVE, follow the returned auth link to complete Figma auth
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Get File Data and Components
**When to use**: User wants to inspect Figma design files or extract component information
**Tool sequence**:
1. `FIGMA_DISCOVER_FIGMA_RESOURCES` - Extract IDs from Figma URLs [Prerequisite]
2. `FIGMA_GET_FILE_JSON` - Get file data (simplified by default) [Required]
3. `FIGMA_GET_FILE_NODES` - Get specific node data [Optional]
4. `FIGMA_GET_FILE_COMPONENTS` - List published components [Optional]
5. `FIGMA_GET_FILE_COMPONENT_SETS` - List component sets [Optional]
**Key parameters**:
- `file_key`: File key from URL (e.g., 'abc123XYZ' from figma.com/design/abc123XYZ/...)
- `ids`: Comma-separated node IDs (NOT an array)
- `depth`: Tree traversal depth (2 for pages and top-level children)
- `simplify`: True for AI-friendly format (70%+ size reduction)
**Pitfalls**:
- Only supports Design files; FigJam boards and Slides return 400 errors
- `ids` must be a comma-separated string, not an array
- Node IDs may be dash-formatted (1-541) in URLs but need colon format (1:541) for API
- Broad ids/depth can trigger oversized payloads (413); narrow scope or reduce depth
- Response data may be in `data_preview` instead of `data`
### 2. Export and Render Images
**When to use**: User wants to export design assets as images
**Tool sequence**:
1. `FIGMA_GET_FILE_JSON` - Find node IDs to export [Prerequisite]
2. `FIGMA_RENDER_IMAGES_OF_FILE_NODES` - Render nodes as images [Required]
3. `FIGMA_DOWNLOAD_FIGMA_IMAGES` - Download rendered images [Optional]
4. `FIGMA_GET_IMAGE_FILLS` - Get image fill URLs [Optional]
**Key parameters**:
- `file_key`: File key
- `ids`: Comma-separated node IDs to render
- `format`: 'png', 'svg', 'jpg', or 'pdf'
- `scale`: Scale factor (0.01-4.0) for PNG/JPG
- `images`: Array of {node_id, file_name, format} for downloads
**Pitfalls**:
- Images return as node_id-to-URL map; some IDs may be null (failed renders)
- URLs are temporary (valid ~30 days)
- Images capped at 32 megapixels; larger requests auto-scaled down
### 3. Extract Design Tokens
**When to use**: User wants to extract design tokens for development
**Tool sequence**:
1. `FIGMA_EXTRACT_DESIGN_TOKENS` - Extract colors, typography, spacing [Required]
2. `FIGMA_DESIGN_TOKENS_TO_TAILWIND` - Convert to Tailwind config [Optional]
**Key parameters**:
- `file_key`: File key
- `include_local_styles`: Include local styles (default true)
- `include_variables`: Include Figma variables
- `tokens`: Full tokens object from extraction (for Tailwind conversion)
**Pitfalls**:
- Tailwind conversion requires the full tokens object including total_tokens and sources
- Do not strip fields from the extraction response before passing to conversion
### 4. Manage Comments and Versions
**When to use**: User wants to view or add comments, or inspect version history
**Tool sequence**:
1. `FIGMA_GET_COMMENTS_IN_A_FILE` - List all file comments [Optional]
2. `FIGMA_ADD_A_COMMENT_TO_A_FILE` - Add a comment [Optional]
3. `FIGMA_GET_REACTIONS_FOR_A_COMMENT` - Get comment reactions [Optional]
4. `FIGMA_GET_VERSIONS_OF_A_FILE` - Get version history [Optional]
**Key parameters**:
- `file_key`: File key
- `as_md`: Return comments in Markdown format
- `message`: Comment text
- `comment_id`: Comment ID for reactions
**Pitfalls**:
- Comments can be positioned on specific nodes using client_meta
- Reply comments cannot be nested (only one level of replies)
### 5. Browse Projects and Teams
**When to use**: User wants to list team projects or files
**Tool sequence**:
1. `FIGMA_GET_PROJECTS_IN_A_TEAM` - List team projects [Optional]
2. `FIGMA_GET_FILES_IN_A_PROJECT` - List project files [Optional]
3. `FIGMA_GET_TEAM_STYLES` - List team published styles [Optional]
**Key parameters**:
- `team_id`: Team ID from URL (figma.com/files/team/TEAM_ID/...)
- `project_id`: Project ID
**Pitfalls**:
- Team ID cannot be obtained programmatically; extract from Figma URL
- Only published styles/components are returned by team endpoints
## Common Patterns
### URL Parsing
Extract IDs from Figma URLs:
```
1. Call FIGMA_DISCOVER_FIGMA_RESOURCES with figma_url
2. Extract file_key, node_id, team_id from response
3. Convert dash-format node IDs (1-541) to colon format (1:541)
```
### Node Traversal
```
1. Call FIGMA_GET_FILE_JSON with depth=2 for overview
2. Identify target nodes from the response
3. Call again with specific ids and higher depth for details
```
## Known Pitfalls
**File Type Support**:
- GET_FILE_JSON only supports Design files (figma.com/design/ or figma.com/file/)
- FigJam boards (figma.com/board/) and Slides (figma.com/slides/) are NOT supported
**Node ID Formats**:
- URLs use dash format: `node-id=1-541`
- API uses colon format: `1:541`
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Parse URL | FIGMA_DISCOVER_FIGMA_RESOURCES | figma_url |
| Get file JSON | FIGMA_GET_FILE_JSON | file_key, ids, depth |
| Get nodes | FIGMA_GET_FILE_NODES | file_key, ids |
| Render images | FIGMA_RENDER_IMAGES_OF_FILE_NODES | file_key, ids, format |
| Download images | FIGMA_DOWNLOAD_FIGMA_IMAGES | file_key, images |
| Get component | FIGMA_GET_COMPONENT | file_key, node_id |
| File components | FIGMA_GET_FILE_COMPONENTS | file_key |
| Component sets | FIGMA_GET_FILE_COMPONENT_SETS | file_key |
| Design tokens | FIGMA_EXTRACT_DESIGN_TOKENS | file_key |
| Tokens to Tailwind | FIGMA_DESIGN_TOKENS_TO_TAILWIND | tokens |
| File comments | FIGMA_GET_COMMENTS_IN_A_FILE | file_key |
| Add comment | FIGMA_ADD_A_COMMENT_TO_A_FILE | file_key, message |
| File versions | FIGMA_GET_VERSIONS_OF_A_FILE | file_key |
| Team projects | FIGMA_GET_PROJECTS_IN_A_TEAM | team_id |
| Project files | FIGMA_GET_FILES_IN_A_PROJECT | project_id |
| Team styles | FIGMA_GET_TEAM_STYLES | team_id |
| File styles | FIGMA_GET_FILE_STYLES | file_key |
| Image fills | FIGMA_GET_IMAGE_FILLS | file_key |

View File

@@ -0,0 +1,856 @@
---
name: fp-ts-errors
description: Handle errors as values using fp-ts Either and TaskEither for cleaner, more predictable TypeScript code. Use when implementing error handling patterns with fp-ts.
risk: safe
source: https://github.com/whatiskadudoing/fp-ts-skills
---
# Practical Error Handling with fp-ts
This skill teaches you how to handle errors without try/catch spaghetti. No academic jargon - just practical patterns for real problems.
## When to Use This Skill
- When you want type-safe error handling in TypeScript
- When replacing try/catch with Either and TaskEither patterns
- When building APIs or services that need explicit error types
- When accumulating multiple validation errors
The core idea: **Errors are just data**. Instead of throwing them into the void and hoping someone catches them, return them as values that TypeScript can track.
---
## 1. Stop Throwing Everywhere
### The Problem with Exceptions
Exceptions are invisible in your types. They break the contract between functions.
```typescript
// What this function signature promises:
function getUser(id: string): User
// What it actually does:
function getUser(id: string): User {
if (!id) throw new Error('ID required')
const user = db.find(id)
if (!user) throw new Error('User not found')
return user
}
// The caller has no idea this can fail
const user = getUser(id) // Might explode!
```
You end up with code like this:
```typescript
// MESSY: try/catch everywhere
function processOrder(orderId: string) {
let order
try {
order = getOrder(orderId)
} catch (e) {
console.error('Failed to get order')
return null
}
let user
try {
user = getUser(order.userId)
} catch (e) {
console.error('Failed to get user')
return null
}
let payment
try {
payment = chargeCard(user.cardId, order.total)
} catch (e) {
console.error('Payment failed')
return null
}
return { order, user, payment }
}
```
### The Solution: Return Errors as Values
```typescript
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
// Now TypeScript KNOWS this can fail
function getUser(id: string): E.Either<string, User> {
if (!id) return E.left('ID required')
const user = db.find(id)
if (!user) return E.left('User not found')
return E.right(user)
}
// The caller is forced to handle both cases
const result = getUser(id)
// result is Either<string, User> - error OR success, never both
```
---
## 2. The Result Pattern (Either)
`Either<E, A>` is simple: it holds either an error (`E`) or a value (`A`).
- `Left` = error case
- `Right` = success case (think "right" as in "correct")
```typescript
import * as E from 'fp-ts/Either'
// Creating values
const success = E.right(42) // Right(42)
const failure = E.left('Oops') // Left('Oops')
// Checking what you have
if (E.isRight(result)) {
console.log(result.right) // The success value
} else {
console.log(result.left) // The error
}
// Better: pattern match with fold
const message = pipe(
result,
E.fold(
(error) => `Failed: ${error}`,
(value) => `Got: ${value}`
)
)
```
### Converting Throwing Code to Either
```typescript
// Wrap any throwing function with tryCatch
const parseJSON = (json: string): E.Either<Error, unknown> =>
E.tryCatch(
() => JSON.parse(json),
(e) => (e instanceof Error ? e : new Error(String(e)))
)
parseJSON('{"valid": true}') // Right({ valid: true })
parseJSON('not json') // Left(SyntaxError: ...)
// For functions you'll reuse, use tryCatchK
const safeParseJSON = E.tryCatchK(
JSON.parse,
(e) => (e instanceof Error ? e : new Error(String(e)))
)
```
### Common Either Operations
```typescript
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
// Transform the success value
const doubled = pipe(
E.right(21),
E.map(n => n * 2)
) // Right(42)
// Transform the error
const betterError = pipe(
E.left('bad'),
E.mapLeft(e => `Error: ${e}`)
) // Left('Error: bad')
// Provide a default for errors
const value = pipe(
E.left('failed'),
E.getOrElse(() => 0)
) // 0
// Convert nullable to Either
const fromNullable = E.fromNullable('not found')
fromNullable(user) // Right(user) if exists, Left('not found') if null/undefined
```
---
## 3. Chaining Operations That Might Fail
The real power comes from chaining. Each step can fail, but you write it as a clean pipeline.
### Before: Nested Try/Catch Hell
```typescript
// MESSY: Each step can fail, nested try/catch everywhere
function processUserOrder(userId: string, productId: string): Result | null {
let user
try {
user = getUser(userId)
} catch (e) {
logError('User fetch failed', e)
return null
}
if (!user.isActive) {
logError('User not active')
return null
}
let product
try {
product = getProduct(productId)
} catch (e) {
logError('Product fetch failed', e)
return null
}
if (product.stock < 1) {
logError('Out of stock')
return null
}
let order
try {
order = createOrder(user, product)
} catch (e) {
logError('Order creation failed', e)
return null
}
return order
}
```
### After: Clean Chain with Either
```typescript
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
// Each function returns Either<Error, T>
const getUser = (id: string): E.Either<string, User> => { ... }
const getProduct = (id: string): E.Either<string, Product> => { ... }
const createOrder = (user: User, product: Product): E.Either<string, Order> => { ... }
// Chain them together - first error stops the chain
const processUserOrder = (userId: string, productId: string): E.Either<string, Order> =>
pipe(
getUser(userId),
E.filterOrElse(
user => user.isActive,
() => 'User not active'
),
E.chain(user =>
pipe(
getProduct(productId),
E.filterOrElse(
product => product.stock >= 1,
() => 'Out of stock'
),
E.chain(product => createOrder(user, product))
)
)
)
// Or use Do notation for cleaner access to intermediate values
const processUserOrder = (userId: string, productId: string): E.Either<string, Order> =>
pipe(
E.Do,
E.bind('user', () => getUser(userId)),
E.filterOrElse(
({ user }) => user.isActive,
() => 'User not active'
),
E.bind('product', () => getProduct(productId)),
E.filterOrElse(
({ product }) => product.stock >= 1,
() => 'Out of stock'
),
E.chain(({ user, product }) => createOrder(user, product))
)
```
### Different Error Types? Use chainW
```typescript
type ValidationError = { type: 'validation'; message: string }
type DbError = { type: 'db'; message: string }
const validateInput = (id: string): E.Either<ValidationError, string> => { ... }
const fetchFromDb = (id: string): E.Either<DbError, User> => { ... }
// chainW (W = "wider") automatically unions the error types
const process = (id: string): E.Either<ValidationError | DbError, User> =>
pipe(
validateInput(id),
E.chainW(validId => fetchFromDb(validId))
)
```
---
## 4. Collecting Multiple Errors
Sometimes you want ALL errors, not just the first one. Form validation is the classic example.
### Before: Collecting Errors Manually
```typescript
// MESSY: Manual error accumulation
function validateForm(form: FormData): { valid: boolean; errors: string[] } {
const errors: string[] = []
if (!form.email) {
errors.push('Email required')
} else if (!form.email.includes('@')) {
errors.push('Invalid email')
}
if (!form.password) {
errors.push('Password required')
} else if (form.password.length < 8) {
errors.push('Password too short')
}
if (!form.age) {
errors.push('Age required')
} else if (form.age < 18) {
errors.push('Must be 18+')
}
return { valid: errors.length === 0, errors }
}
```
### After: Validation with Error Accumulation
```typescript
import * as E from 'fp-ts/Either'
import * as NEA from 'fp-ts/NonEmptyArray'
import { sequenceS } from 'fp-ts/Apply'
import { pipe } from 'fp-ts/function'
// Errors as a NonEmptyArray (always at least one)
type Errors = NEA.NonEmptyArray<string>
// Create the applicative that accumulates errors
const validation = E.getApplicativeValidation(NEA.getSemigroup<string>())
// Validators that return Either<Errors, T>
const validateEmail = (email: string): E.Either<Errors, string> =>
!email ? E.left(NEA.of('Email required'))
: !email.includes('@') ? E.left(NEA.of('Invalid email'))
: E.right(email)
const validatePassword = (password: string): E.Either<Errors, string> =>
!password ? E.left(NEA.of('Password required'))
: password.length < 8 ? E.left(NEA.of('Password too short'))
: E.right(password)
const validateAge = (age: number | undefined): E.Either<Errors, number> =>
age === undefined ? E.left(NEA.of('Age required'))
: age < 18 ? E.left(NEA.of('Must be 18+'))
: E.right(age)
// Combine all validations - collects ALL errors
const validateForm = (form: FormData) =>
sequenceS(validation)({
email: validateEmail(form.email),
password: validatePassword(form.password),
age: validateAge(form.age)
})
// Usage
validateForm({ email: '', password: '123', age: 15 })
// Left(['Email required', 'Password too short', 'Must be 18+'])
validateForm({ email: 'a@b.com', password: 'longpassword', age: 25 })
// Right({ email: 'a@b.com', password: 'longpassword', age: 25 })
```
### Field-Level Errors for Forms
```typescript
interface FieldError {
field: string
message: string
}
type FormErrors = NEA.NonEmptyArray<FieldError>
const fieldError = (field: string, message: string): FormErrors =>
NEA.of({ field, message })
const formValidation = E.getApplicativeValidation(NEA.getSemigroup<FieldError>())
// Now errors know which field they belong to
const validateEmail = (email: string): E.Either<FormErrors, string> =>
!email ? E.left(fieldError('email', 'Required'))
: !email.includes('@') ? E.left(fieldError('email', 'Invalid format'))
: E.right(email)
// Easy to display in UI
const getFieldError = (errors: FormErrors, field: string): string | undefined =>
errors.find(e => e.field === field)?.message
```
---
## 5. Async Operations (TaskEither)
For async operations that can fail, use `TaskEither`. It's like `Either` but for promises.
- `TaskEither<E, A>` = a function that returns `Promise<Either<E, A>>`
- Lazy: nothing runs until you execute it
```typescript
import * as TE from 'fp-ts/TaskEither'
import { pipe } from 'fp-ts/function'
// Wrap any async operation
const fetchUser = (id: string): TE.TaskEither<Error, User> =>
TE.tryCatch(
() => fetch(`/api/users/${id}`).then(r => r.json()),
(e) => (e instanceof Error ? e : new Error(String(e)))
)
// Chain async operations - just like Either
const getUserPosts = (userId: string): TE.TaskEither<Error, Post[]> =>
pipe(
fetchUser(userId),
TE.chain(user => fetchPosts(user.id))
)
// Execute when ready
const result = await getUserPosts('123')() // Returns Either<Error, Post[]>
```
### Before: Promise Chain with Error Handling
```typescript
// MESSY: try/catch mixed with promise chains
async function loadDashboard(userId: string) {
try {
const user = await fetchUser(userId)
if (!user) throw new Error('User not found')
let posts, notifications, settings
try {
[posts, notifications, settings] = await Promise.all([
fetchPosts(user.id),
fetchNotifications(user.id),
fetchSettings(user.id)
])
} catch (e) {
// Which one failed? Who knows!
console.error('Failed to load data', e)
return null
}
return { user, posts, notifications, settings }
} catch (e) {
console.error('Failed to load user', e)
return null
}
}
```
### After: Clean TaskEither Pipeline
```typescript
import * as TE from 'fp-ts/TaskEither'
import { sequenceS } from 'fp-ts/Apply'
import { pipe } from 'fp-ts/function'
const loadDashboard = (userId: string) =>
pipe(
fetchUser(userId),
TE.chain(user =>
pipe(
// Parallel fetch with sequenceS
sequenceS(TE.ApplyPar)({
posts: fetchPosts(user.id),
notifications: fetchNotifications(user.id),
settings: fetchSettings(user.id)
}),
TE.map(data => ({ user, ...data }))
)
)
)
// Execute and handle both cases
pipe(
loadDashboard('123'),
TE.fold(
(error) => T.of(renderError(error)),
(data) => T.of(renderDashboard(data))
)
)()
```
### Retry Failed Operations
```typescript
import * as T from 'fp-ts/Task'
import * as TE from 'fp-ts/TaskEither'
import { pipe } from 'fp-ts/function'
const retry = <E, A>(
task: TE.TaskEither<E, A>,
attempts: number,
delayMs: number
): TE.TaskEither<E, A> =>
pipe(
task,
TE.orElse((error) =>
attempts > 1
? pipe(
T.delay(delayMs)(T.of(undefined)),
T.chain(() => retry(task, attempts - 1, delayMs * 2))
)
: TE.left(error)
)
)
// Retry up to 3 times with exponential backoff
const fetchWithRetry = retry(fetchUser('123'), 3, 1000)
```
### Fallback to Alternative
```typescript
// Try cache first, fall back to API
const getUserData = (id: string) =>
pipe(
fetchFromCache(id),
TE.orElse(() => fetchFromApi(id)),
TE.orElse(() => TE.right(defaultUser)) // Last resort default
)
```
---
## 6. Converting Between Patterns
Real codebases have throwing functions, nullable values, and promises. Here's how to work with them.
### From Nullable to Either
```typescript
import * as E from 'fp-ts/Either'
import * as O from 'fp-ts/Option'
// Direct conversion
const user = users.find(u => u.id === id) // User | undefined
const result = E.fromNullable('User not found')(user)
// From Option
const maybeUser: O.Option<User> = O.fromNullable(user)
const eitherUser = pipe(
maybeUser,
E.fromOption(() => 'User not found')
)
```
### From Throwing Function to Either
```typescript
// Wrap at the boundary
const safeParse = <T>(schema: ZodSchema<T>) => (data: unknown): E.Either<ZodError, T> =>
E.tryCatch(
() => schema.parse(data),
(e) => e as ZodError
)
// Use throughout your code
const parseUser = safeParse(UserSchema)
const result = parseUser(rawData) // Either<ZodError, User>
```
### From Promise to TaskEither
```typescript
import * as TE from 'fp-ts/TaskEither'
// Wrap external async functions
const fetchJson = <T>(url: string): TE.TaskEither<Error, T> =>
TE.tryCatch(
() => fetch(url).then(r => r.json()),
(e) => new Error(`Fetch failed: ${e}`)
)
// Wrap axios, prisma, any async library
const getUserFromDb = (id: string): TE.TaskEither<DbError, User> =>
TE.tryCatch(
() => prisma.user.findUniqueOrThrow({ where: { id } }),
(e) => ({ code: 'DB_ERROR', cause: e })
)
```
### Back to Promise (Escape Hatch)
Sometimes you need a plain Promise for external APIs.
```typescript
import * as TE from 'fp-ts/TaskEither'
import * as E from 'fp-ts/Either'
const myTaskEither: TE.TaskEither<Error, User> = fetchUser('123')
// Option 1: Get the Either (preserves both cases)
const either: E.Either<Error, User> = await myTaskEither()
// Option 2: Throw on error (for legacy code)
const toThrowingPromise = <E, A>(te: TE.TaskEither<E, A>): Promise<A> =>
te().then(E.fold(
(error) => Promise.reject(error),
(value) => Promise.resolve(value)
))
const user = await toThrowingPromise(fetchUser('123')) // Throws if Left
// Option 3: Default on error
const user = await pipe(
fetchUser('123'),
TE.getOrElse(() => T.of(defaultUser))
)()
```
---
## Real Scenarios
### Parse User Input Safely
```typescript
interface ParsedInput {
id: number
name: string
tags: string[]
}
const parseInput = (raw: unknown): E.Either<string, ParsedInput> =>
pipe(
E.Do,
E.bind('obj', () =>
typeof raw === 'object' && raw !== null
? E.right(raw as Record<string, unknown>)
: E.left('Input must be an object')
),
E.bind('id', ({ obj }) =>
typeof obj.id === 'number'
? E.right(obj.id)
: E.left('id must be a number')
),
E.bind('name', ({ obj }) =>
typeof obj.name === 'string' && obj.name.length > 0
? E.right(obj.name)
: E.left('name must be a non-empty string')
),
E.bind('tags', ({ obj }) =>
Array.isArray(obj.tags) && obj.tags.every(t => typeof t === 'string')
? E.right(obj.tags as string[])
: E.left('tags must be an array of strings')
),
E.map(({ id, name, tags }) => ({ id, name, tags }))
)
// Usage
parseInput({ id: 1, name: 'test', tags: ['a', 'b'] })
// Right({ id: 1, name: 'test', tags: ['a', 'b'] })
parseInput({ id: 'wrong', name: '', tags: null })
// Left('id must be a number')
```
### API Call with Full Error Handling
```typescript
interface ApiError {
code: string
message: string
status?: number
}
const createApiError = (message: string, code = 'UNKNOWN', status?: number): ApiError =>
({ code, message, status })
const fetchWithErrorHandling = <T>(url: string): TE.TaskEither<ApiError, T> =>
pipe(
TE.tryCatch(
() => fetch(url),
() => createApiError('Network error', 'NETWORK')
),
TE.chain(response =>
response.ok
? TE.tryCatch(
() => response.json() as Promise<T>,
() => createApiError('Invalid JSON', 'PARSE')
)
: TE.left(createApiError(
`HTTP ${response.status}`,
response.status === 404 ? 'NOT_FOUND' : 'HTTP_ERROR',
response.status
))
)
)
// Usage with pattern matching on error codes
const handleUserFetch = (userId: string) =>
pipe(
fetchWithErrorHandling<User>(`/api/users/${userId}`),
TE.fold(
(error) => {
switch (error.code) {
case 'NOT_FOUND': return T.of(showNotFoundPage())
case 'NETWORK': return T.of(showOfflineMessage())
default: return T.of(showGenericError(error.message))
}
},
(user) => T.of(showUserProfile(user))
)
)
```
### Process List Where Some Items Might Fail
```typescript
import * as A from 'fp-ts/Array'
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
interface ProcessResult<T> {
successes: T[]
failures: Array<{ item: unknown; error: string }>
}
// Process all, collect successes and failures separately
const processAllCollectErrors = <T, R>(
items: T[],
process: (item: T) => E.Either<string, R>
): ProcessResult<R> => {
const results = items.map((item, index) =>
pipe(
process(item),
E.mapLeft(error => ({ item, error, index }))
)
)
return {
successes: pipe(results, A.filterMap(E.toOption)),
failures: pipe(
results,
A.filterMap(r => E.isLeft(r) ? O.some(r.left) : O.none)
)
}
}
// Usage
const parseNumbers = (inputs: string[]) =>
processAllCollectErrors(inputs, input => {
const n = parseInt(input, 10)
return isNaN(n) ? E.left(`Invalid number: ${input}`) : E.right(n)
})
parseNumbers(['1', 'abc', '3', 'def'])
// {
// successes: [1, 3],
// failures: [
// { item: 'abc', error: 'Invalid number: abc', index: 1 },
// { item: 'def', error: 'Invalid number: def', index: 3 }
// ]
// }
```
### Bulk Operations with Partial Success
```typescript
import * as TE from 'fp-ts/TaskEither'
import * as T from 'fp-ts/Task'
import { pipe } from 'fp-ts/function'
interface BulkResult<T> {
succeeded: T[]
failed: Array<{ id: string; error: string }>
}
const bulkProcess = <T>(
ids: string[],
process: (id: string) => TE.TaskEither<string, T>
): T.Task<BulkResult<T>> =>
pipe(
ids,
A.map(id =>
pipe(
process(id),
TE.fold(
(error) => T.of({ type: 'failed' as const, id, error }),
(result) => T.of({ type: 'succeeded' as const, result })
)
)
),
T.sequenceArray,
T.map(results => ({
succeeded: results
.filter((r): r is { type: 'succeeded'; result: T } => r.type === 'succeeded')
.map(r => r.result),
failed: results
.filter((r): r is { type: 'failed'; id: string; error: string } => r.type === 'failed')
.map(({ id, error }) => ({ id, error }))
}))
)
// Usage
const deleteUsers = (userIds: string[]) =>
bulkProcess(userIds, id =>
pipe(
deleteUser(id),
TE.mapLeft(e => e.message)
)
)
// All operations run, you get a report of what worked and what didn't
```
---
## Quick Reference
| Pattern | Use When | Example |
|---------|----------|---------|
| `E.right(value)` | Creating a success | `E.right(42)` |
| `E.left(error)` | Creating a failure | `E.left('not found')` |
| `E.tryCatch(fn, onError)` | Wrapping throwing code | `E.tryCatch(() => JSON.parse(s), toError)` |
| `E.fromNullable(error)` | Converting nullable | `E.fromNullable('missing')(maybeValue)` |
| `E.map(fn)` | Transform success | `pipe(result, E.map(x => x * 2))` |
| `E.mapLeft(fn)` | Transform error | `pipe(result, E.mapLeft(addContext))` |
| `E.chain(fn)` | Chain operations | `pipe(getA(), E.chain(a => getB(a.id)))` |
| `E.chainW(fn)` | Chain with different error type | `pipe(validate(), E.chainW(save))` |
| `E.fold(onError, onSuccess)` | Handle both cases | `E.fold(showError, showData)` |
| `E.getOrElse(onError)` | Extract with default | `E.getOrElse(() => 0)` |
| `E.filterOrElse(pred, onFalse)` | Validate with error | `E.filterOrElse(x => x > 0, () => 'must be positive')` |
| `sequenceS(validation)({...})` | Collect all errors | Form validation |
### TaskEither Equivalents
All Either operations have TaskEither equivalents:
- `TE.right`, `TE.left`, `TE.tryCatch`
- `TE.map`, `TE.mapLeft`, `TE.chain`, `TE.chainW`
- `TE.fold`, `TE.getOrElse`, `TE.filterOrElse`
- `TE.orElse` for fallbacks
---
## Summary
1. **Return errors as values** - Use Either/TaskEither instead of throwing
2. **Chain with confidence** - `chain` stops at first error automatically
3. **Collect all errors when needed** - Use validation applicative for forms
4. **Wrap at boundaries** - Convert throwing/Promise code at the edges
5. **Match at the end** - Use `fold` to handle both cases when you're ready to act
The payoff: TypeScript tracks your errors, no more forgotten try/catch, clear control flow, and composable error handling.

View File

@@ -0,0 +1,598 @@
---
name: fp-ts-pragmatic
description: A practical, jargon-free guide to fp-ts functional programming - the 80/20 approach that gets results without the academic overhead. Use when writing TypeScript with fp-ts library.
risk: safe
source: https://github.com/whatiskadudoing/fp-ts-skills
---
# Pragmatic Functional Programming
**Read this first.** This guide cuts through the academic jargon and shows you what actually matters. No category theory. No abstract nonsense. Just patterns that make your code better.
## When to Use This Skill
- When starting with fp-ts and need practical guidance
- When writing TypeScript code that handles nullable values, errors, or async operations
- When you want cleaner, more maintainable functional code without the academic overhead
- When refactoring imperative code to functional style
## The Golden Rule
> **If functional programming makes your code harder to read, don't use it.**
FP is a tool, not a religion. Use it when it helps. Skip it when it doesn't.
---
## The 80/20 of FP
These five patterns give you most of the benefits. Master these before exploring anything else.
### 1. Pipe: Chain Operations Clearly
Instead of nesting function calls or creating intermediate variables, chain operations in reading order.
```typescript
import { pipe } from 'fp-ts/function'
// Before: Hard to read (inside-out)
const result = format(validate(parse(input)))
// Before: Too many variables
const parsed = parse(input)
const validated = validate(parsed)
const result = format(validated)
// After: Clear, linear flow
const result = pipe(
input,
parse,
validate,
format
)
```
**When to use pipe:**
- 3+ transformations on the same data
- You find yourself naming throwaway variables
- Logic reads better top-to-bottom
**When to skip pipe:**
- Just 1-2 operations (direct call is fine)
- The operations don't naturally chain
### 2. Option: Handle Missing Values Without null Checks
Stop writing `if (x !== null && x !== undefined)` everywhere.
```typescript
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/function'
// Before: Defensive null checking
function getUserCity(user: User | null): string {
if (user === null) return 'Unknown'
if (user.address === null) return 'Unknown'
if (user.address.city === null) return 'Unknown'
return user.address.city
}
// After: Chain through potential missing values
const getUserCity = (user: User | null): string =>
pipe(
O.fromNullable(user),
O.flatMap(u => O.fromNullable(u.address)),
O.flatMap(a => O.fromNullable(a.city)),
O.getOrElse(() => 'Unknown')
)
```
**Plain language translation:**
- `O.fromNullable(x)` = "wrap this value, treating null/undefined as 'nothing'"
- `O.flatMap(fn)` = "if we have something, apply this function"
- `O.getOrElse(() => default)` = "unwrap, or use this default if nothing"
### 3. Either: Make Errors Explicit
Stop throwing exceptions for expected failures. Return errors as values.
```typescript
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
// Before: Hidden failure mode
function parseAge(input: string): number {
const age = parseInt(input, 10)
if (isNaN(age)) throw new Error('Invalid age')
if (age < 0) throw new Error('Age cannot be negative')
return age
}
// After: Errors are visible in the type
function parseAge(input: string): E.Either<string, number> {
const age = parseInt(input, 10)
if (isNaN(age)) return E.left('Invalid age')
if (age < 0) return E.left('Age cannot be negative')
return E.right(age)
}
// Using it
const result = parseAge(userInput)
if (E.isRight(result)) {
console.log(`Age is ${result.right}`)
} else {
console.log(`Error: ${result.left}`)
}
```
**Plain language translation:**
- `E.right(value)` = "success with this value"
- `E.left(error)` = "failure with this error"
- `E.isRight(x)` = "did it succeed?"
### 4. Map: Transform Without Unpacking
Transform values inside containers without extracting them first.
```typescript
import * as O from 'fp-ts/Option'
import * as E from 'fp-ts/Either'
import * as A from 'fp-ts/Array'
import { pipe } from 'fp-ts/function'
// Transform inside Option
const maybeUser: O.Option<User> = O.some({ name: 'Alice', age: 30 })
const maybeName: O.Option<string> = pipe(
maybeUser,
O.map(user => user.name)
)
// Transform inside Either
const result: E.Either<Error, number> = E.right(5)
const doubled: E.Either<Error, number> = pipe(
result,
E.map(n => n * 2)
)
// Transform arrays (same concept!)
const numbers = [1, 2, 3]
const doubled = pipe(
numbers,
A.map(n => n * 2)
)
```
### 5. FlatMap: Chain Operations That Might Fail
When each step might fail, chain them together.
```typescript
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
const parseJSON = (s: string): E.Either<string, unknown> =>
E.tryCatch(() => JSON.parse(s), () => 'Invalid JSON')
const extractEmail = (data: unknown): E.Either<string, string> => {
if (typeof data === 'object' && data !== null && 'email' in data) {
return E.right((data as { email: string }).email)
}
return E.left('No email field')
}
const validateEmail = (email: string): E.Either<string, string> =>
email.includes('@') ? E.right(email) : E.left('Invalid email format')
// Chain all steps - if any fails, the whole thing fails
const getValidEmail = (input: string): E.Either<string, string> =>
pipe(
parseJSON(input),
E.flatMap(extractEmail),
E.flatMap(validateEmail)
)
// Success path: Right('user@example.com')
// Any failure: Left('specific error message')
```
**Plain language:** `flatMap` means "if this succeeded, try the next thing"
---
## When NOT to Use FP
Functional programming is not always the answer. Here's when to keep it simple.
### Simple Null Checks
```typescript
// Just use optional chaining - it's built into the language
const city = user?.address?.city ?? 'Unknown'
// DON'T overcomplicate it
const city = pipe(
O.fromNullable(user),
O.flatMap(u => O.fromNullable(u.address)),
O.flatMap(a => O.fromNullable(a.city)),
O.getOrElse(() => 'Unknown')
)
```
### Simple Loops
```typescript
// A for loop is fine when you need early exit or complex logic
function findFirst(items: Item[], predicate: (i: Item) => boolean): Item | null {
for (const item of items) {
if (predicate(item)) return item
}
return null
}
// DON'T force FP when it doesn't help
const result = pipe(
items,
A.findFirst(predicate),
O.toNullable
)
```
### Performance-Critical Code
```typescript
// For hot paths, imperative is faster (no intermediate arrays)
function sumLarge(numbers: number[]): number {
let sum = 0
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i]
}
return sum
}
// fp-ts creates intermediate structures
const sum = pipe(numbers, A.reduce(0, (acc, n) => acc + n))
```
### When Your Team Doesn't Know FP
If you're the only one who can read the code, it's not good code.
```typescript
// If your team knows this pattern
async function getUser(id: string): Promise<User | null> {
try {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) return null
return await response.json()
} catch {
return null
}
}
// Don't force this on them
const getUser = (id: string): TE.TaskEither<Error, User> =>
pipe(
TE.tryCatch(() => fetch(`/api/users/${id}`), E.toError),
TE.flatMap(r => r.ok ? TE.right(r) : TE.left(new Error('Not found'))),
TE.flatMap(r => TE.tryCatch(() => r.json(), E.toError))
)
```
---
## Quick Wins: Easy Changes That Improve Code Today
### 1. Replace Nested Ternaries with pipe + fold
```typescript
// Before: Nested ternary nightmare
const message = user === null
? 'No user'
: user.isAdmin
? `Admin: ${user.name}`
: `User: ${user.name}`
// After: Clear case handling
const message = pipe(
O.fromNullable(user),
O.fold(
() => 'No user',
(u) => u.isAdmin ? `Admin: ${u.name}` : `User: ${u.name}`
)
)
```
### 2. Replace try-catch with tryCatch
```typescript
// Before: try-catch everywhere
let config
try {
config = JSON.parse(rawConfig)
} catch {
config = defaultConfig
}
// After: One-liner
const config = pipe(
E.tryCatch(() => JSON.parse(rawConfig), () => 'parse error'),
E.getOrElse(() => defaultConfig)
)
```
### 3. Replace undefined Returns with Option
```typescript
// Before: Caller might forget to check
function findUser(id: string): User | undefined {
return users.find(u => u.id === id)
}
// After: Type forces caller to handle missing case
function findUser(id: string): O.Option<User> {
return O.fromNullable(users.find(u => u.id === id))
}
```
### 4. Replace Error Strings with Typed Errors
```typescript
// Before: Just strings
function validate(data: unknown): E.Either<string, User> {
// ...
return E.left('validation failed')
}
// After: Structured errors
type ValidationError = {
field: string
message: string
}
function validate(data: unknown): E.Either<ValidationError, User> {
// ...
return E.left({ field: 'email', message: 'Invalid format' })
}
```
### 5. Use const Assertions for Error Types
```typescript
// Create specific error types without classes
const NotFound = (id: string) => ({ _tag: 'NotFound' as const, id })
const Unauthorized = { _tag: 'Unauthorized' as const }
const ValidationFailed = (errors: string[]) =>
({ _tag: 'ValidationFailed' as const, errors })
type AppError =
| ReturnType<typeof NotFound>
| typeof Unauthorized
| ReturnType<typeof ValidationFailed>
// Now you can pattern match
const handleError = (error: AppError): string => {
switch (error._tag) {
case 'NotFound': return `Item ${error.id} not found`
case 'Unauthorized': return 'Please log in'
case 'ValidationFailed': return error.errors.join(', ')
}
}
```
---
## Common Refactors: Before and After
### Callback Hell to Pipe
```typescript
// Before
fetchUser(id, (user) => {
if (!user) return handleNoUser()
fetchPosts(user.id, (posts) => {
if (!posts) return handleNoPosts()
fetchComments(posts[0].id, (comments) => {
render(user, posts, comments)
})
})
})
// After (with TaskEither for async)
import * as TE from 'fp-ts/TaskEither'
const loadData = (id: string) =>
pipe(
fetchUser(id),
TE.flatMap(user => pipe(
fetchPosts(user.id),
TE.map(posts => ({ user, posts }))
)),
TE.flatMap(({ user, posts }) => pipe(
fetchComments(posts[0].id),
TE.map(comments => ({ user, posts, comments }))
))
)
// Execute
const result = await loadData('123')()
pipe(
result,
E.fold(handleError, ({ user, posts, comments }) => render(user, posts, comments))
)
```
### Multiple null Checks to Option Chain
```typescript
// Before
function getManagerEmail(employee: Employee): string | null {
if (!employee.department) return null
if (!employee.department.manager) return null
if (!employee.department.manager.email) return null
return employee.department.manager.email
}
// After
const getManagerEmail = (employee: Employee): O.Option<string> =>
pipe(
O.fromNullable(employee.department),
O.flatMap(d => O.fromNullable(d.manager)),
O.flatMap(m => O.fromNullable(m.email))
)
// Use it
pipe(
getManagerEmail(employee),
O.fold(
() => sendToDefault(),
(email) => sendTo(email)
)
)
```
### Validation with Multiple Checks
```typescript
// Before: Throws on first error
function validateUser(data: unknown): User {
if (!data || typeof data !== 'object') throw new Error('Must be object')
const obj = data as Record<string, unknown>
if (typeof obj.email !== 'string') throw new Error('Email required')
if (!obj.email.includes('@')) throw new Error('Invalid email')
if (typeof obj.age !== 'number') throw new Error('Age required')
if (obj.age < 0) throw new Error('Age must be positive')
return obj as User
}
// After: Returns first error, type-safe
const validateUser = (data: unknown): E.Either<string, User> =>
pipe(
E.Do,
E.bind('obj', () =>
typeof data === 'object' && data !== null
? E.right(data as Record<string, unknown>)
: E.left('Must be object')
),
E.bind('email', ({ obj }) =>
typeof obj.email === 'string' && obj.email.includes('@')
? E.right(obj.email)
: E.left('Valid email required')
),
E.bind('age', ({ obj }) =>
typeof obj.age === 'number' && obj.age >= 0
? E.right(obj.age)
: E.left('Valid age required')
),
E.map(({ email, age }) => ({ email, age }))
)
```
### Promise Chain to TaskEither
```typescript
// Before
async function processOrder(orderId: string): Promise<Receipt> {
const order = await fetchOrder(orderId)
if (!order) throw new Error('Order not found')
const validated = await validateOrder(order)
if (!validated.success) throw new Error(validated.error)
const payment = await processPayment(validated.order)
if (!payment.success) throw new Error('Payment failed')
return generateReceipt(payment)
}
// After
const processOrder = (orderId: string): TE.TaskEither<string, Receipt> =>
pipe(
fetchOrderTE(orderId),
TE.flatMap(order =>
order ? TE.right(order) : TE.left('Order not found')
),
TE.flatMap(validateOrderTE),
TE.flatMap(processPaymentTE),
TE.map(generateReceipt)
)
```
---
## The Readability Rule
Before using any FP pattern, ask: **"Would a junior developer understand this?"**
### Too Clever (Avoid)
```typescript
const result = pipe(
data,
A.filter(flow(prop('status'), equals('active'))),
A.map(flow(prop('value'), multiply(2))),
A.reduce(monoid.concat, monoid.empty),
O.fromPredicate(gt(threshold))
)
```
### Just Right (Prefer)
```typescript
const activeItems = data.filter(item => item.status === 'active')
const doubledValues = activeItems.map(item => item.value * 2)
const total = doubledValues.reduce((sum, val) => sum + val, 0)
const result = total > threshold ? O.some(total) : O.none
```
### The Middle Ground (Often Best)
```typescript
const result = pipe(
data,
A.filter(item => item.status === 'active'),
A.map(item => item.value * 2),
A.reduce(0, (sum, val) => sum + val),
total => total > threshold ? O.some(total) : O.none
)
```
---
## Cheat Sheet
| What you want | Plain language | fp-ts |
|--------------|----------------|-------|
| Handle null/undefined | "Wrap this nullable" | `O.fromNullable(x)` |
| Default for missing | "Use this if nothing" | `O.getOrElse(() => default)` |
| Transform if present | "If something, change it" | `O.map(fn)` |
| Chain nullable operations | "If something, try this" | `O.flatMap(fn)` |
| Return success | "Worked, here's the value" | `E.right(value)` |
| Return failure | "Failed, here's why" | `E.left(error)` |
| Wrap throwing function | "Try this, catch errors" | `E.tryCatch(fn, onError)` |
| Handle both cases | "Do this for error, that for success" | `E.fold(onLeft, onRight)` |
| Chain operations | "Then do this, then that" | `pipe(x, fn1, fn2, fn3)` |
---
## When to Level Up
Once comfortable with these patterns, explore:
1. **TaskEither** - Async operations that can fail (replaces Promise + try/catch)
2. **Validation** - Collect ALL errors instead of stopping at first
3. **Reader** - Dependency injection without classes
4. **Do notation** - Cleaner syntax for multiple bindings
But don't rush. The basics here will handle 80% of real-world scenarios. Get comfortable with these before adding more tools to your belt.
---
## Summary
1. **Use pipe** for 3+ operations
2. **Use Option** for nullable chains
3. **Use Either** for operations that can fail
4. **Use map** to transform wrapped values
5. **Use flatMap** to chain operations that might fail
6. **Skip FP** when it hurts readability
7. **Keep it simple** - if your team can't read it, it's not good code

796
skills/fp-ts-react/SKILL.md Normal file
View File

@@ -0,0 +1,796 @@
---
name: fp-ts-react
description: Practical patterns for using fp-ts with React - hooks, state, forms, data fetching. Use when building React apps with functional programming patterns. Works with React 18/19, Next.js 14/15.
risk: safe
source: https://github.com/whatiskadudoing/fp-ts-skills
---
# Functional Programming in React
Practical patterns for React apps. No jargon, just code that works.
## When to Use This Skill
- When building React apps with fp-ts for type-safe state management
- When handling loading/error/success states in data fetching
- When implementing form validation with error accumulation
- When using React 18/19 or Next.js 14/15 with functional patterns
---
## Quick Reference
| Pattern | Use When |
|---------|----------|
| `Option` | Value might be missing (user not loaded yet) |
| `Either` | Operation might fail (form validation) |
| `TaskEither` | Async operation might fail (API calls) |
| `RemoteData` | Need to show loading/error/success states |
| `pipe` | Chaining multiple transformations |
---
## 1. State with Option (Maybe It's There, Maybe Not)
Use `Option` instead of `null | undefined` for clearer intent.
### Basic Pattern
```typescript
import { useState } from 'react'
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/function'
interface User {
id: string
name: string
email: string
}
function UserProfile() {
// Option says "this might not exist yet"
const [user, setUser] = useState<O.Option<User>>(O.none)
const handleLogin = (userData: User) => {
setUser(O.some(userData))
}
const handleLogout = () => {
setUser(O.none)
}
return pipe(
user,
O.match(
// When there's no user
() => <button onClick={() => handleLogin({ id: '1', name: 'Alice', email: 'alice@example.com' })}>
Log In
</button>,
// When there's a user
(u) => (
<div>
<p>Welcome, {u.name}!</p>
<button onClick={handleLogout}>Log Out</button>
</div>
)
)
)
}
```
### Chaining Optional Values
```typescript
import * as O from 'fp-ts/Option'
import { pipe } from 'fp-ts/function'
interface Profile {
user: O.Option<{
name: string
settings: O.Option<{
theme: string
}>
}>
}
function getTheme(profile: Profile): string {
return pipe(
profile.user,
O.flatMap(u => u.settings),
O.map(s => s.theme),
O.getOrElse(() => 'light') // default
)
}
```
---
## 2. Form Validation with Either
Either is perfect for validation: `Left` = errors, `Right` = valid data.
### Simple Form Validation
```typescript
import * as E from 'fp-ts/Either'
import * as A from 'fp-ts/Array'
import { pipe } from 'fp-ts/function'
// Validation functions return Either<ErrorMessage, ValidValue>
const validateEmail = (email: string): E.Either<string, string> =>
email.includes('@')
? E.right(email)
: E.left('Invalid email address')
const validatePassword = (password: string): E.Either<string, string> =>
password.length >= 8
? E.right(password)
: E.left('Password must be at least 8 characters')
const validateName = (name: string): E.Either<string, string> =>
name.trim().length > 0
? E.right(name.trim())
: E.left('Name is required')
```
### Collecting All Errors (Not Just First One)
```typescript
import * as E from 'fp-ts/Either'
import { sequenceS } from 'fp-ts/Apply'
import { getSemigroup } from 'fp-ts/NonEmptyArray'
import { pipe } from 'fp-ts/function'
// This collects ALL errors, not just the first one
const validateAll = sequenceS(E.getApplicativeValidation(getSemigroup<string>()))
interface SignupForm {
name: string
email: string
password: string
}
interface ValidatedForm {
name: string
email: string
password: string
}
function validateForm(form: SignupForm): E.Either<string[], ValidatedForm> {
return pipe(
validateAll({
name: pipe(validateName(form.name), E.mapLeft(e => [e])),
email: pipe(validateEmail(form.email), E.mapLeft(e => [e])),
password: pipe(validatePassword(form.password), E.mapLeft(e => [e])),
})
)
}
// Usage in component
function SignupForm() {
const [form, setForm] = useState({ name: '', email: '', password: '' })
const [errors, setErrors] = useState<string[]>([])
const handleSubmit = () => {
pipe(
validateForm(form),
E.match(
(errs) => setErrors(errs), // Show all errors
(valid) => {
setErrors([])
submitToServer(valid) // Submit valid data
}
)
)
}
return (
<form onSubmit={e => { e.preventDefault(); handleSubmit() }}>
<input
value={form.name}
onChange={e => setForm(f => ({ ...f, name: e.target.value }))}
placeholder="Name"
/>
<input
value={form.email}
onChange={e => setForm(f => ({ ...f, email: e.target.value }))}
placeholder="Email"
/>
<input
type="password"
value={form.password}
onChange={e => setForm(f => ({ ...f, password: e.target.value }))}
placeholder="Password"
/>
{errors.length > 0 && (
<ul style={{ color: 'red' }}>
{errors.map((err, i) => <li key={i}>{err}</li>)}
</ul>
)}
<button type="submit">Sign Up</button>
</form>
)
}
```
### Field-Level Errors (Better UX)
```typescript
type FieldErrors = Partial<Record<keyof SignupForm, string>>
function validateFormWithFieldErrors(form: SignupForm): E.Either<FieldErrors, ValidatedForm> {
const errors: FieldErrors = {}
pipe(validateName(form.name), E.mapLeft(e => { errors.name = e }))
pipe(validateEmail(form.email), E.mapLeft(e => { errors.email = e }))
pipe(validatePassword(form.password), E.mapLeft(e => { errors.password = e }))
return Object.keys(errors).length > 0
? E.left(errors)
: E.right({ name: form.name.trim(), email: form.email, password: form.password })
}
// In component
{errors.email && <span className="error">{errors.email}</span>}
```
---
## 3. Data Fetching with TaskEither
TaskEither = async operation that might fail. Perfect for API calls.
### Basic Fetch Hook
```typescript
import { useState, useEffect } from 'react'
import * as TE from 'fp-ts/TaskEither'
import * as E from 'fp-ts/Either'
import { pipe } from 'fp-ts/function'
// Wrap fetch in TaskEither
const fetchJson = <T>(url: string): TE.TaskEither<Error, T> =>
TE.tryCatch(
async () => {
const res = await fetch(url)
if (!res.ok) throw new Error(`HTTP ${res.status}`)
return res.json()
},
(err) => err instanceof Error ? err : new Error(String(err))
)
// Custom hook
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null)
const [error, setError] = useState<Error | null>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
setLoading(true)
setError(null)
pipe(
fetchJson<T>(url),
TE.match(
(err) => {
setError(err)
setLoading(false)
},
(result) => {
setData(result)
setLoading(false)
}
)
)()
}, [url])
return { data, error, loading }
}
// Usage
function UserList() {
const { data, error, loading } = useFetch<User[]>('/api/users')
if (loading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<ul>
{data?.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
)
}
```
### Chaining API Calls
```typescript
// Fetch user, then fetch their posts
const fetchUserWithPosts = (userId: string) => pipe(
fetchJson<User>(`/api/users/${userId}`),
TE.flatMap(user => pipe(
fetchJson<Post[]>(`/api/users/${userId}/posts`),
TE.map(posts => ({ ...user, posts }))
))
)
```
### Parallel API Calls
```typescript
import { sequenceT } from 'fp-ts/Apply'
// Fetch multiple things at once
const fetchDashboardData = () => pipe(
sequenceT(TE.ApplyPar)(
fetchJson<User>('/api/user'),
fetchJson<Stats>('/api/stats'),
fetchJson<Notifications[]>('/api/notifications')
),
TE.map(([user, stats, notifications]) => ({
user,
stats,
notifications
}))
)
```
---
## 4. RemoteData Pattern (The Right Way to Handle Async State)
Stop using `{ data, loading, error }` booleans. Use a proper state machine.
### The Pattern
```typescript
// RemoteData has exactly 4 states - no impossible combinations
type RemoteData<E, A> =
| { _tag: 'NotAsked' } // Haven't started yet
| { _tag: 'Loading' } // In progress
| { _tag: 'Failure'; error: E } // Failed
| { _tag: 'Success'; data: A } // Got it!
// Constructors
const notAsked = <E, A>(): RemoteData<E, A> => ({ _tag: 'NotAsked' })
const loading = <E, A>(): RemoteData<E, A> => ({ _tag: 'Loading' })
const failure = <E, A>(error: E): RemoteData<E, A> => ({ _tag: 'Failure', error })
const success = <E, A>(data: A): RemoteData<E, A> => ({ _tag: 'Success', data })
// Pattern match all states
function fold<E, A, R>(
rd: RemoteData<E, A>,
onNotAsked: () => R,
onLoading: () => R,
onFailure: (e: E) => R,
onSuccess: (a: A) => R
): R {
switch (rd._tag) {
case 'NotAsked': return onNotAsked()
case 'Loading': return onLoading()
case 'Failure': return onFailure(rd.error)
case 'Success': return onSuccess(rd.data)
}
}
```
### Hook with RemoteData
```typescript
function useRemoteData<T>(fetchFn: () => Promise<T>) {
const [state, setState] = useState<RemoteData<Error, T>>(notAsked())
const execute = async () => {
setState(loading())
try {
const data = await fetchFn()
setState(success(data))
} catch (err) {
setState(failure(err instanceof Error ? err : new Error(String(err))))
}
}
return { state, execute }
}
// Usage
function UserProfile({ userId }: { userId: string }) {
const { state, execute } = useRemoteData(() =>
fetch(`/api/users/${userId}`).then(r => r.json())
)
useEffect(() => { execute() }, [userId])
return fold(
state,
() => <button onClick={execute}>Load User</button>,
() => <Spinner />,
(err) => <ErrorMessage message={err.message} onRetry={execute} />,
(user) => <UserCard user={user} />
)
}
```
### Why RemoteData Beats Booleans
```typescript
// ❌ BAD: Impossible states are possible
interface BadState {
data: User | null
loading: boolean
error: Error | null
}
// Can have: { data: user, loading: true, error: someError } - what does that mean?!
// ✅ GOOD: Only valid states exist
type GoodState = RemoteData<Error, User>
// Can only be: NotAsked | Loading | Failure | Success
```
---
## 5. Referential Stability (Preventing Re-renders)
fp-ts values like `O.some(1)` create new objects each render. React sees them as "changed".
### The Problem
```typescript
// ❌ BAD: Creates new Option every render
function BadComponent() {
const [value, setValue] = useState(O.some(1))
useEffect(() => {
// This runs EVERY render because O.some(1) !== O.some(1)
console.log('value changed')
}, [value])
}
```
### Solution 1: useMemo
```typescript
// ✅ GOOD: Memoize Option creation
function GoodComponent() {
const [rawValue, setRawValue] = useState<number | null>(1)
const value = useMemo(
() => O.fromNullable(rawValue),
[rawValue] // Only recreate when rawValue changes
)
useEffect(() => {
// Now this only runs when rawValue actually changes
console.log('value changed')
}, [rawValue]) // Depend on raw value, not Option
}
```
### Solution 2: fp-ts-react-stable-hooks
```bash
npm install fp-ts-react-stable-hooks
```
```typescript
import { useStableO, useStableEffect } from 'fp-ts-react-stable-hooks'
import * as O from 'fp-ts/Option'
import * as Eq from 'fp-ts/Eq'
function StableComponent() {
// Uses fp-ts equality instead of reference equality
const [value, setValue] = useStableO(O.some(1))
// Effect that understands Option equality
useStableEffect(
() => { console.log('value changed') },
[value],
Eq.tuple(O.getEq(Eq.eqNumber)) // Custom equality
)
}
```
---
## 6. Dependency Injection with Context
Use ReaderTaskEither for testable components with injected dependencies.
### Setup Dependencies
```typescript
import * as RTE from 'fp-ts/ReaderTaskEither'
import { pipe } from 'fp-ts/function'
import { createContext, useContext, ReactNode } from 'react'
// Define what services your app needs
interface AppDependencies {
api: {
getUser: (id: string) => Promise<User>
updateUser: (id: string, data: Partial<User>) => Promise<User>
}
analytics: {
track: (event: string, data?: object) => void
}
}
// Create context
const DepsContext = createContext<AppDependencies | null>(null)
// Provider
function AppProvider({ deps, children }: { deps: AppDependencies; children: ReactNode }) {
return <DepsContext.Provider value={deps}>{children}</DepsContext.Provider>
}
// Hook to use dependencies
function useDeps(): AppDependencies {
const deps = useContext(DepsContext)
if (!deps) throw new Error('Missing AppProvider')
return deps
}
```
### Use in Components
```typescript
function UserProfile({ userId }: { userId: string }) {
const { api, analytics } = useDeps()
const [user, setUser] = useState<RemoteData<Error, User>>(notAsked())
useEffect(() => {
setUser(loading())
api.getUser(userId)
.then(u => {
setUser(success(u))
analytics.track('user_viewed', { userId })
})
.catch(e => setUser(failure(e)))
}, [userId, api, analytics])
// render...
}
```
### Testing with Mock Dependencies
```typescript
const mockDeps: AppDependencies = {
api: {
getUser: jest.fn().mockResolvedValue({ id: '1', name: 'Test User' }),
updateUser: jest.fn().mockResolvedValue({ id: '1', name: 'Updated' }),
},
analytics: {
track: jest.fn(),
},
}
test('loads user on mount', async () => {
render(
<AppProvider deps={mockDeps}>
<UserProfile userId="1" />
</AppProvider>
)
await screen.findByText('Test User')
expect(mockDeps.api.getUser).toHaveBeenCalledWith('1')
})
```
---
## 7. React 19 Patterns
### use() for Promises (React 19+)
```typescript
import { use, Suspense } from 'react'
// Instead of useEffect + useState for data fetching
function UserProfile({ userPromise }: { userPromise: Promise<User> }) {
const user = use(userPromise) // Suspends until resolved
return <div>{user.name}</div>
}
// Parent provides the promise
function App() {
const userPromise = fetchUser('1') // Start fetching immediately
return (
<Suspense fallback={<Spinner />}>
<UserProfile userPromise={userPromise} />
</Suspense>
)
}
```
### useActionState for Forms (React 19+)
```typescript
import { useActionState } from 'react'
import * as E from 'fp-ts/Either'
interface FormState {
errors: string[]
success: boolean
}
async function submitForm(
prevState: FormState,
formData: FormData
): Promise<FormState> {
const data = {
email: formData.get('email') as string,
password: formData.get('password') as string,
}
// Use Either for validation
const result = pipe(
validateForm(data),
E.match(
(errors) => ({ errors, success: false }),
async (valid) => {
await saveToServer(valid)
return { errors: [], success: true }
}
)
)
return result
}
function SignupForm() {
const [state, formAction, isPending] = useActionState(submitForm, {
errors: [],
success: false
})
return (
<form action={formAction}>
<input name="email" type="email" />
<input name="password" type="password" />
{state.errors.map(e => <p key={e} className="error">{e}</p>)}
<button disabled={isPending}>
{isPending ? 'Submitting...' : 'Sign Up'}
</button>
</form>
)
}
```
### useOptimistic for Instant Feedback (React 19+)
```typescript
import { useOptimistic } from 'react'
function TodoList({ todos }: { todos: Todo[] }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo: Todo) => [...state, { ...newTodo, pending: true }]
)
const addTodo = async (text: string) => {
const newTodo = { id: crypto.randomUUID(), text, done: false }
// Immediately show in UI
addOptimisticTodo(newTodo)
// Actually save (will reconcile when done)
await saveTodo(newTodo)
}
return (
<ul>
{optimisticTodos.map(todo => (
<li key={todo.id} style={{ opacity: todo.pending ? 0.5 : 1 }}>
{todo.text}
</li>
))}
</ul>
)
}
```
---
## 8. Common Patterns Cheat Sheet
### Render Based on Option
```typescript
// Pattern 1: match
pipe(
maybeUser,
O.match(
() => <LoginButton />,
(user) => <UserMenu user={user} />
)
)
// Pattern 2: fold (same as match)
O.fold(
() => <LoginButton />,
(user) => <UserMenu user={user} />
)(maybeUser)
// Pattern 3: getOrElse for simple defaults
const name = pipe(
maybeUser,
O.map(u => u.name),
O.getOrElse(() => 'Guest')
)
```
### Render Based on Either
```typescript
pipe(
validationResult,
E.match(
(errors) => <ErrorList errors={errors} />,
(data) => <SuccessMessage data={data} />
)
)
```
### Safe Array Rendering
```typescript
import * as A from 'fp-ts/Array'
// Get first item safely
const firstUser = pipe(
users,
A.head,
O.map(user => <Featured user={user} />),
O.getOrElse(() => <NoFeaturedUser />)
)
// Find specific item
const adminUser = pipe(
users,
A.findFirst(u => u.role === 'admin'),
O.map(admin => <AdminBadge user={admin} />),
O.toNullable // or O.getOrElse(() => null)
)
```
### Conditional Props
```typescript
// Add props only if value exists
const modalProps = {
isOpen: true,
...pipe(
maybeTitle,
O.map(title => ({ title })),
O.getOrElse(() => ({}))
)
}
```
---
## When to Use What
| Situation | Use |
|-----------|-----|
| Value might not exist | `Option<T>` |
| Operation might fail (sync) | `Either<E, A>` |
| Async operation might fail | `TaskEither<E, A>` |
| Need loading/error/success UI | `RemoteData<E, A>` |
| Form with multiple validations | `Either` with validation applicative |
| Dependency injection | Context + `ReaderTaskEither` |
| Prevent re-renders with fp-ts | `useMemo` or `fp-ts-react-stable-hooks` |
---
## Libraries
- **[fp-ts](https://github.com/gcanti/fp-ts)** - Core library
- **[fp-ts-react-stable-hooks](https://github.com/mblink/fp-ts-react-stable-hooks)** - Stable hooks
- **[@devexperts/remote-data-ts](https://github.com/devexperts/remote-data-ts)** - RemoteData
- **[io-ts](https://github.com/gcanti/io-ts)** - Runtime type validation
- **[zod](https://github.com/colinhacks/zod)** - Schema validation (works great with fp-ts)

View File

@@ -0,0 +1,219 @@
---
name: freshdesk-automation
description: "Automate Freshdesk helpdesk operations including tickets, contacts, companies, notes, and replies via Rube MCP (Composio). Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Freshdesk Automation via Rube MCP
Automate Freshdesk customer support workflows including ticket management, contact and company operations, notes, replies, and ticket search through Composio's Freshdesk toolkit.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Freshdesk connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `freshdesk`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `freshdesk`
3. If connection is not ACTIVE, follow the returned auth link to complete Freshdesk authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. Create and Manage Tickets
**When to use**: User wants to create a new support ticket, update an existing ticket, or view ticket details.
**Tool sequence**:
1. `FRESHDESK_SEARCH_CONTACTS` - Find requester by email to get requester_id [Optional]
2. `FRESHDESK_LIST_TICKET_FIELDS` - Check available custom fields and statuses [Optional]
3. `FRESHDESK_CREATE_TICKET` - Create a new ticket with subject, description, requester info [Required]
4. `FRESHDESK_UPDATE_TICKET` - Modify ticket status, priority, assignee, or other fields [Optional]
5. `FRESHDESK_VIEW_TICKET` - Retrieve full ticket details by ID [Optional]
**Key parameters for FRESHDESK_CREATE_TICKET**:
- `subject`: Ticket subject (required)
- `description`: HTML content of the ticket (required)
- `email`: Requester email (at least one requester identifier required)
- `requester_id`: User ID of requester (alternative to email)
- `status`: 2=Open, 3=Pending, 4=Resolved, 5=Closed (default 2)
- `priority`: 1=Low, 2=Medium, 3=High, 4=Urgent (default 1)
- `source`: 1=Email, 2=Portal, 3=Phone, 7=Chat (default 2)
- `responder_id`: Agent ID to assign the ticket to
- `group_id`: Group to assign the ticket to
- `tags`: Array of tag strings
- `custom_fields`: Object with `cf_<field_name>` keys
**Pitfalls**:
- At least one requester identifier is required: `requester_id`, `email`, `phone`, `facebook_id`, `twitter_id`, or `unique_external_id`
- If `phone` is provided without `email`, then `name` becomes mandatory
- `description` supports HTML formatting
- `attachments` field expects multipart/form-data format, not file paths or URLs
- Custom field keys must be prefixed with `cf_` (e.g., `cf_reference_number`)
- Status and priority are integers, not strings
### 2. Search and Filter Tickets
**When to use**: User wants to find tickets by status, priority, date range, agent, or custom fields.
**Tool sequence**:
1. `FRESHDESK_GET_TICKETS` - List tickets with simple filters (status, priority, agent) [Required]
2. `FRESHDESK_GET_SEARCH` - Advanced ticket search with query syntax [Required]
3. `FRESHDESK_VIEW_TICKET` - Get full details for specific tickets from results [Optional]
4. `FRESHDESK_LIST_TICKET_FIELDS` - Check available fields for search queries [Optional]
**Key parameters for FRESHDESK_GET_TICKETS**:
- `status`: Filter by status integer (2=Open, 3=Pending, 4=Resolved, 5=Closed)
- `priority`: Filter by priority integer (1-4)
- `agent_id`: Filter by assigned agent
- `requester_id`: Filter by requester
- `email`: Filter by requester email
- `created_since`: ISO 8601 timestamp
- `page` / `per_page`: Pagination (default 30 per page)
- `sort_by` / `sort_order`: Sort field and direction
**Key parameters for FRESHDESK_GET_SEARCH**:
- `query`: Query string like `"status:2 AND priority:3"` or `"(created_at:>'2024-01-01' AND tag:'urgent')"`
- `page`: Page number (1-10, max 300 total results)
**Pitfalls**:
- `FRESHDESK_GET_SEARCH` query must be enclosed in double quotes
- Query string limited to 512 characters
- Maximum 10 pages (300 results) from search endpoints
- Date fields in queries use UTC format YYYY-MM-DD
- Use `null` keyword to find tickets with empty fields (e.g., `"agent_id:null"`)
- `FRESHDESK_LIST_ALL_TICKETS` takes no parameters and returns all tickets (use GET_TICKETS for filtering)
### 3. Reply to and Add Notes on Tickets
**When to use**: User wants to send a reply to a customer, add internal notes, or view conversation history.
**Tool sequence**:
1. `FRESHDESK_VIEW_TICKET` - Verify ticket exists and check current state [Prerequisite]
2. `FRESHDESK_REPLY_TO_TICKET` - Send a public reply to the requester [Required]
3. `FRESHDESK_ADD_NOTE_TO_TICKET` - Add a private or public note [Required]
4. `FRESHDESK_LIST_ALL_TICKET_CONVERSATIONS` - View all messages and notes on a ticket [Optional]
5. `FRESHDESK_UPDATE_CONVERSATIONS` - Edit an existing note [Optional]
**Key parameters for FRESHDESK_REPLY_TO_TICKET**:
- `ticket_id`: Ticket ID (integer, required)
- `body`: Reply content, supports HTML (required)
- `cc_emails` / `bcc_emails`: Additional recipients (max 50 total across to/cc/bcc)
- `from_email`: Override sender email if multiple support emails configured
- `user_id`: Agent ID to reply on behalf of
**Key parameters for FRESHDESK_ADD_NOTE_TO_TICKET**:
- `ticket_id`: Ticket ID (integer, required)
- `body`: Note content, supports HTML (required)
- `private`: true for agent-only visibility, false for public (default true)
- `notify_emails`: Only accepts agent email addresses, not external contacts
**Pitfalls**:
- There are two reply tools: `FRESHDESK_REPLY_TO_TICKET` (more features) and `FRESHDESK_REPLY_TICKET` (simpler); both work
- `FRESHDESK_ADD_NOTE_TO_TICKET` defaults to private (agent-only); set `private: false` for public notes
- `notify_emails` in notes only accepts agent emails, not customer emails
- Only notes can be edited via `FRESHDESK_UPDATE_CONVERSATIONS`; incoming replies cannot be edited
### 4. Manage Contacts and Companies
**When to use**: User wants to create, search, or manage customer contacts and company records.
**Tool sequence**:
1. `FRESHDESK_SEARCH_CONTACTS` - Search contacts by email, phone, or company [Required]
2. `FRESHDESK_GET_CONTACTS` - List contacts with filters [Optional]
3. `FRESHDESK_IMPORT_CONTACT` - Bulk import contacts from CSV [Optional]
4. `FRESHDESK_SEARCH_COMPANIES` - Search companies by custom fields [Required]
5. `FRESHDESK_GET_COMPANIES` - List all companies [Optional]
6. `FRESHDESK_CREATE_COMPANIES` - Create a new company [Optional]
7. `FRESHDESK_UPDATE_COMPANIES` - Update company details [Optional]
8. `FRESHDESK_LIST_COMPANY_FIELDS` - Check available company fields [Optional]
**Key parameters for FRESHDESK_SEARCH_CONTACTS**:
- `query`: Search string like `"email:'user@example.com'"` (required)
- `page`: Pagination (1-10, max 30 per page)
**Key parameters for FRESHDESK_CREATE_COMPANIES**:
- `name`: Company name (required)
- `domains`: Array of domain strings for auto-association with contacts
- `health_score`: "Happy", "Doing okay", or "At risk"
- `account_tier`: "Basic", "Premium", or "Enterprise"
- `industry`: Standard industry classification
**Pitfalls**:
- `FRESHDESK_SEARCH_CONTACTS` requires exact matches; partial/regex searches are not supported
- `FRESHDESK_SEARCH_COMPANIES` cannot search by standard `name` field; use custom fields or `created_at`
- Company custom fields do NOT use the `cf_` prefix (unlike ticket custom fields)
- `domains` on companies enables automatic contact-to-company association by email domain
- Contact search queries require string values in single quotes inside double-quoted query
## Common Patterns
### ID Resolution
Always resolve display values to IDs before operations:
- **Requester email -> requester_id**: `FRESHDESK_SEARCH_CONTACTS` with `"email:'user@example.com'"`
- **Company name -> company_id**: `FRESHDESK_GET_COMPANIES` and match by name (search by name not supported)
- **Agent name -> agent_id**: Not directly available; use agent_id from ticket responses or admin configuration
### Pagination
Freshdesk uses page-based pagination:
- `FRESHDESK_GET_TICKETS`: `page` (starting at 1) and `per_page` (max 100)
- `FRESHDESK_GET_SEARCH`: `page` (1-10, 30 results per page, max 300 total)
- `FRESHDESK_SEARCH_CONTACTS`: `page` (1-10, 30 per page)
- `FRESHDESK_LIST_ALL_TICKET_CONVERSATIONS`: `page` and `per_page` (max 100)
## Known Pitfalls
### ID Formats
- Ticket IDs, contact IDs, company IDs, agent IDs, and group IDs are all integers
- There are no string-based IDs in Freshdesk
### Rate Limits
- Freshdesk enforces per-account API rate limits based on plan tier
- Bulk operations should be paced to avoid 429 responses
- Search endpoints are limited to 300 total results (10 pages of 30)
### Parameter Quirks
- Status values: 2=Open, 3=Pending, 4=Resolved, 5=Closed (integers, not strings)
- Priority values: 1=Low, 2=Medium, 3=High, 4=Urgent (integers, not strings)
- Source values: 1=Email, 2=Portal, 3=Phone, 7=Chat, 9=Feedback Widget, 10=Outbound Email
- Ticket custom fields use `cf_` prefix; company custom fields do NOT
- `description` in tickets supports HTML formatting
- Search query strings must be in double quotes with string values in single quotes
- `FRESHDESK_LIST_ALL_TICKETS` returns all tickets with no filter parameters
### Response Structure
- Ticket details include nested objects for requester, assignee, and conversation data
- Search results are paginated with a maximum of 300 results across 10 pages
- Conversation lists include both replies and notes in chronological order
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| Create ticket | `FRESHDESK_CREATE_TICKET` | `subject`, `description`, `email`, `priority` |
| Update ticket | `FRESHDESK_UPDATE_TICKET` | `ticket_id`, `status`, `priority` |
| View ticket | `FRESHDESK_VIEW_TICKET` | `ticket_id` |
| List tickets | `FRESHDESK_GET_TICKETS` | `status`, `priority`, `page`, `per_page` |
| List all tickets | `FRESHDESK_LIST_ALL_TICKETS` | (none) |
| Search tickets | `FRESHDESK_GET_SEARCH` | `query`, `page` |
| Reply to ticket | `FRESHDESK_REPLY_TO_TICKET` | `ticket_id`, `body`, `cc_emails` |
| Reply (simple) | `FRESHDESK_REPLY_TICKET` | `ticket_id`, `body` |
| Add note | `FRESHDESK_ADD_NOTE_TO_TICKET` | `ticket_id`, `body`, `private` |
| List conversations | `FRESHDESK_LIST_ALL_TICKET_CONVERSATIONS` | `ticket_id`, `page` |
| Update note | `FRESHDESK_UPDATE_CONVERSATIONS` | `conversation_id`, `body` |
| Search contacts | `FRESHDESK_SEARCH_CONTACTS` | `query`, `page` |
| List contacts | `FRESHDESK_GET_CONTACTS` | `email`, `company_id`, `page` |
| Import contacts | `FRESHDESK_IMPORT_CONTACT` | `file`, `name_column_index`, `email_column_index` |
| Create company | `FRESHDESK_CREATE_COMPANIES` | `name`, `domains`, `industry` |
| Update company | `FRESHDESK_UPDATE_COMPANIES` | `company_id`, `name`, `domains` |
| Search companies | `FRESHDESK_SEARCH_COMPANIES` | `query`, `page` |
| List companies | `FRESHDESK_GET_COMPANIES` | `page` |
| List ticket fields | `FRESHDESK_LIST_TICKET_FIELDS` | (none) |
| List company fields | `FRESHDESK_LIST_COMPANY_FIELDS` | (none) |

View File

@@ -0,0 +1,213 @@
---
name: freshservice-automation
description: "Automate Freshservice ITSM tasks via Rube MCP (Composio): create/update tickets, bulk operations, service requests, and outbound emails. Always search tools first for current schemas."
requires:
mcp: [rube]
---
# Freshservice Automation via Rube MCP
Automate Freshservice IT Service Management operations through Composio's Freshservice toolkit via Rube MCP.
## Prerequisites
- Rube MCP must be connected (RUBE_SEARCH_TOOLS available)
- Active Freshservice connection via `RUBE_MANAGE_CONNECTIONS` with toolkit `freshservice`
- Always call `RUBE_SEARCH_TOOLS` first to get current tool schemas
## Setup
**Get Rube MCP**: Add `https://rube.app/mcp` as an MCP server in your client configuration. No API keys needed — just add the endpoint and it works.
1. Verify Rube MCP is available by confirming `RUBE_SEARCH_TOOLS` responds
2. Call `RUBE_MANAGE_CONNECTIONS` with toolkit `freshservice`
3. If connection is not ACTIVE, follow the returned auth link to complete Freshservice authentication
4. Confirm connection status shows ACTIVE before running any workflows
## Core Workflows
### 1. List and Search Tickets
**When to use**: User wants to find, list, or search for tickets
**Tool sequence**:
1. `FRESHSERVICE_LIST_TICKETS` - List tickets with optional filtering and pagination [Required]
2. `FRESHSERVICE_GET_TICKET` - Get detailed information for a specific ticket [Optional]
**Key parameters for listing**:
- `filter`: Predefined filter ('all_tickets', 'deleted', 'spam', 'watching')
- `updated_since`: ISO 8601 timestamp to get tickets updated after this time
- `order_by`: Sort field ('created_at', 'updated_at', 'status', 'priority')
- `order_type`: Sort direction ('asc' or 'desc')
- `page`: Page number (1-indexed)
- `per_page`: Results per page (1-100, default 30)
- `include`: Additional fields ('requester', 'stats', 'description', 'conversations', 'assets')
**Key parameters for get**:
- `ticket_id`: Unique ticket ID or display_id
- `include`: Additional fields to include
**Pitfalls**:
- By default, only tickets created within the past 30 days are returned
- Use `updated_since` to retrieve older tickets
- Each `include` value consumes additional API credits
- `page` is 1-indexed; minimum value is 1
- `per_page` max is 100; default is 30
- Ticket IDs can be the internal ID or the display_id shown in the UI
### 2. Create a Ticket
**When to use**: User wants to log a new incident or request
**Tool sequence**:
1. `FRESHSERVICE_CREATE_TICKET` - Create a new ticket [Required]
**Key parameters**:
- `subject`: Ticket subject line (required)
- `description`: HTML description of the ticket (required)
- `status`: Ticket status - 2 (Open), 3 (Pending), 4 (Resolved), 5 (Closed) (required)
- `priority`: Ticket priority - 1 (Low), 2 (Medium), 3 (High), 4 (Urgent) (required)
- `email`: Requester's email address (provide either email or requester_id)
- `requester_id`: User ID of the requester
- `type`: Ticket type ('Incident' or 'Service Request')
- `source`: Channel - 1 (Email), 2 (Portal), 3 (Phone), 4 (Chat), 5 (Twitter), 6 (Facebook)
- `impact`: Impact level - 1 (Low), 2 (Medium), 3 (High)
- `urgency`: Urgency level - 1 (Low), 2 (Medium), 3 (High), 4 (Critical)
**Pitfalls**:
- `subject`, `description`, `status`, and `priority` are all required
- Either `email` or `requester_id` must be provided to identify the requester
- Status and priority use numeric codes, not string names
- Description supports HTML formatting
- If email does not match an existing contact, a new contact is created
### 3. Bulk Update Tickets
**When to use**: User wants to update multiple tickets at once
**Tool sequence**:
1. `FRESHSERVICE_LIST_TICKETS` - Find tickets to update [Prerequisite]
2. `FRESHSERVICE_BULK_UPDATE_TICKETS` - Update multiple tickets [Required]
**Key parameters**:
- `ids`: Array of ticket IDs to update (required)
- `update_fields`: Dictionary of fields to update (required)
- Allowed keys: 'subject', 'description', 'status', 'priority', 'responder_id', 'group_id', 'type', 'tags', 'custom_fields'
**Pitfalls**:
- Bulk update performs sequential updates internally; large batches may take time
- All specified tickets receive the same field updates
- If one ticket update fails, others may still succeed; check response for individual results
- Cannot selectively update different fields per ticket in a single call
- Custom fields must use their internal field names, not display names
### 4. Create Ticket via Outbound Email
**When to use**: User wants to create a ticket by sending an outbound email notification
**Tool sequence**:
1. `FRESHSERVICE_CREATE_TICKET_OUTBOUND_EMAIL` - Create ticket with email notification [Required]
**Key parameters**:
- `email`: Requester's email address (required)
- `subject`: Email subject / ticket subject (required)
- `description`: HTML email body content
- `status`: Ticket status (2=Open, 3=Pending, 4=Resolved, 5=Closed)
- `priority`: Ticket priority (1=Low, 2=Medium, 3=High, 4=Urgent)
- `cc_emails`: Array of CC email addresses
- `email_config_id`: Email configuration ID for the sender address
- `name`: Requester name
**Pitfalls**:
- This creates a standard ticket via the /api/v2/tickets endpoint while sending an email
- If the email does not match an existing contact, a new contact is created with the provided name
- `email_config_id` determines which email address the notification appears to come from
### 5. Create Service Requests
**When to use**: User wants to submit a service catalog request
**Tool sequence**:
1. `FRESHSERVICE_CREATE_SERVICE_REQUEST` - Create a service request for a catalog item [Required]
**Key parameters**:
- `item_display_id`: Display ID of the catalog item (required)
- `email`: Requester's email address
- `quantity`: Number of items to request (default: 1)
- `custom_fields`: Custom field values for the service item form
- `parent_ticket_id`: Display ID of a parent ticket (for child requests)
**Pitfalls**:
- `item_display_id` can be found in Admin > Service Catalog > item URL (e.g., /service_catalog/items/1)
- Custom fields keys must match the service item form field names
- Quantity defaults to 1 if not specified
- Service requests follow the approval workflow defined for the catalog item
## Common Patterns
### Status Code Reference
| Code | Status |
|------|--------|
| 2 | Open |
| 3 | Pending |
| 4 | Resolved |
| 5 | Closed |
### Priority Code Reference
| Code | Priority |
|------|----------|
| 1 | Low |
| 2 | Medium |
| 3 | High |
| 4 | Urgent |
### Pagination
- Use `page` (1-indexed) and `per_page` (max 100) parameters
- Increment `page` by 1 each request
- Continue until returned results count < `per_page`
- Default page size is 30
### Finding Tickets by Date Range
```
1. Call FRESHSERVICE_LIST_TICKETS with updated_since='2024-01-01T00:00:00Z'
2. Optionally add order_by='updated_at' and order_type='desc'
3. Paginate through results
```
## Known Pitfalls
**Numeric Codes**:
- Status and priority use numeric values, not strings
- Source channel uses numeric codes (1-6)
- Impact and urgency use numeric codes (1-3 or 1-4)
**Date Filtering**:
- Default returns only tickets from the last 30 days
- Use `updated_since` parameter for older tickets
- Date format is ISO 8601 (e.g., '2024-01-01T00:00:00Z')
**Rate Limits**:
- Freshservice API has per-account rate limits
- Each `include` option consumes additional API credits
- Implement backoff on 429 responses
**Response Parsing**:
- Response data may be nested under `data` or `data.data`
- Parse defensively with fallback patterns
- Ticket IDs are numeric integers
## Quick Reference
| Task | Tool Slug | Key Params |
|------|-----------|------------|
| List tickets | FRESHSERVICE_LIST_TICKETS | filter, updated_since, page, per_page |
| Get ticket | FRESHSERVICE_GET_TICKET | ticket_id, include |
| Create ticket | FRESHSERVICE_CREATE_TICKET | subject, description, status, priority, email |
| Bulk update | FRESHSERVICE_BULK_UPDATE_TICKETS | ids, update_fields |
| Outbound email ticket | FRESHSERVICE_CREATE_TICKET_OUTBOUND_EMAIL | email, subject, description |
| Service request | FRESHSERVICE_CREATE_SERVICE_REQUEST | item_display_id, email, quantity |

Some files were not shown because too many files have changed in this diff Show More