frappe-agent-architect
Use when designing multi-app Frappe architectures, deciding whether to split functionality into separate apps, or implementing…
Use when configuring Frappe hooks.py for app events, scheduler tasks, document events, fixtures, boot session, jenv customization, or website routing. Covers v14/v15/v16 including extend_doctype_class. Keywords: hooks.py, doc_events, scheduler_events, fixtures, app_include_js,
Claude Code
$ npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-syntax-hooks --agent claude-code
Codex
$ npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-syntax-hooks -a codex -y
Cursor
$ npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-syntax-hooks -a cursor -y
Gemini CLI
$ npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-syntax-hooks -a gemini-cli -y
GitHub Copilot
$ npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-syntax-hooks -a github-copilot -y
OpenCode
$ npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-syntax-hooks -a opencode -y
Windsurf
$ npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-syntax-hooks -a windsurf -y
name: frappe-syntax-hooks description: > Use when configuring Frappe hooks.py for app events, scheduler tasks, document events, fixtures, boot session, jenv customization, or website routing. Covers v14/v15/v16 including extend_doctype_class. Keywords: hooks.py, doc_events, scheduler_events, fixtures, app_include_js, override_whitelisted_methods, extend_doctype_class, hooks.py example, how to register hook, available hooks list, extend_doctype_class example. license: MIT compatibility: "Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16." metadata: author: OpenAEC-Foundation version: "2.0"
Configuration hooks in hooks.py enable custom apps to extend Frappe/ERPNext behavior. This skill covers ALL non-document-event hooks. For `doc_events` (validate, on_submit, on_update, etc.), see **frappe-syntax-hooks-events**.
| Category | Key Hooks | Reference | |----------|-----------|-----------| | App metadata | `app_name`, `app_title`, `required_apps` | Below | | Frontend assets | `app_include_js/css`, `web_include_js/css` | Below | | Install/migrate | `before_install`, `after_install`, `after_migrate` | Below | | Scheduler | `hourly`, `daily`, `cron`, `*_long` | [scheduler-events.md](references/scheduler-events.md) | | Session/auth | `on_login`, `on_logout`, `auth_hooks` | [bootinfo.md](references/bootinfo.md) | | Request middleware | `before_request`, `after_request` | [request-lifecycle.md](references/request-lifecycle.md) | | Permissions | `permission_query_conditions`, `has_permission` | [permissions.md](references/permissions.md) | | DocType overrides | `override_doctype_class`, `doctype_js` | [overrides.md](references/overrides.md) | | Website/portal | `website_route_rules`, `portal_menu_items` | [request-lifecycle.md](references/request-lifecycle.md) | | File handling | `before_write_file`, `write_file` | Below | | Email | `override_email_send`, `default_mail_footer` | Below | | PDF | `pdf_header_html`, `pdf_footer_html` | Below | | Jinja | `jinja.methods`, `jinja.filters` | Below | | Boot/client data | `extend_bootinfo`, `notification_config` | [bootinfo.md](references/bootinfo.md) | | Data/fixtures | `fixtures`, `global_search_doctypes` | Below | | Method overrides | `override_whitelisted_methods`, `standard_queries` | [overrides.md](references/overrides.md) |
---
What do you want to achieve? | +-- ADD JS/CSS to desk or portal? | +-- Desk --> app_include_js / app_include_css | +-- Portal --> web_include_js / web_include_css | +-- Specific form --> doctype_js | +-- List view --> doctype_list_js | +-- RUN periodic background tasks? | +-- < 5 min execution --> hourly / daily / weekly / monthly | +-- 5-25 min execution --> hourly_long / daily_long / etc. | +-- Exact time needed --> cron | See: frappe-syntax-hooks > scheduler-events.md | +-- SEND data to client at page load? | +-- extend_bootinfo | +-- MODIFY controller of existing DocType? | +-- v16+ --> extend_doctype_class (RECOMMENDED) | +-- v14/v15 --> override_doctype_class (last app wins) | +-- MODIFY API endpoint? | +-- override_whitelisted_methods | +-- CUSTOMIZE permissions? | +-- List filtering --> permission_query_conditions | +-- Document-level --> has_permission | +-- REACT to document save/submit/delete? | +-- See frappe-syntax-hooks-events skill | +-- EXPORT/IMPORT configuration? | +-- fixtures | +-- SETUP on install or migrate? | +-- after_install / after_migrate | +-- ADD custom Jinja functions? | +-- jinja.methods / jinja.filters | +-- CUSTOMIZE website routing? | +-- website_route_rules | See: request-lifecycle.md for full routing pipeline | +-- INTERCEPT every request/response? | +-- before_request / after_request | See: request-lifecycle.md for lifecycle flow | +-- CUSTOM page rendering? | +-- page_renderer hook | See: request-lifecycle.md for renderer architecture
---
ALWAYS include these in every hooks.py:
app_name = "myapp" app_title = "My App" app_publisher = "My Company" app_description = "Custom ERPNext extensions" app_email = "info@mycompany.com" app_license = "MIT" required_apps = ["erpnext"] # Declare dependencies
---
# Desk (backend UI) assets — loaded on EVERY desk page
app_include_js = "/assets/myapp/js/myapp.min.js" # string or list
app_include_css = "/assets/myapp/css/myapp.min.css"
# Website/portal assets — loaded on EVERY web page
web_include_js = "/assets/myapp/js/web.min.js"
web_include_css = "/assets/myapp/css/web.min.css"
# Web form specific assets
webform_include_js = {"My Web Form": "public/js/my_webform.js"}
webform_include_css = {"My Web Form": "public/css/my_webform.css"}
# Form script extensions (extend OTHER apps' forms)
doctype_js = {"Sales Invoice": "public/js/sales_invoice.js"}
# List view script extensions
doctype_list_js = {"Sales Invoice": "public/js/sales_invoice_list.js"}
# Custom sounds
sounds = [{"name": "alert", "src": "/assets/myapp/sounds/alert.mp3", "volume": 0.5}]NEVER put heavy libraries in `app_include_js` — they load on every page.
---
before_install = "myapp.setup.before_install" after_install = "myapp.setup.after_install" after_sync = "myapp.setup.after_sync" # After fixture sync before_migrate = "myapp.setup.before_migrate" after_migrate = "myapp.setup.after_migrate" before_uninstall = "myapp.setup.before_uninstall" after_uninstall = "myapp.setup.after_uninstall" before_tests = "myapp.setup.seed_test_data"
All accept a single dotted-path string. The function receives no arguments.
---
See [scheduler-events.md](references/scheduler-events.md) for full reference.
scheduler_events = {
"all": ["myapp.tasks.every_minute"], # ~60s interval
"hour60 deterministic Claude AI skills for Frappe Framework & ERPNext v14-v16 development and operations
Use when designing multi-app Frappe architectures, deciding whether to split functionality into separate apps, or implementing…
Use when debugging Frappe errors, using bench console for live inspection, analyzing tracebacks, or reading Frappe log files.…
Use when receiving vague or unclear ERPNext/Frappe development requests that need interpretation. Transforms requirements like…
Use when migrating a Frappe app between major versions, detecting breaking API changes, or resolving post-migration errors.…
Use when reviewing or validating Frappe/ERPNext code against best practices and common pitfalls. Checks generated code before…
Use when building ERPNext/Frappe API integrations (v14/v15/v16) including REST API, RPC API, authentication, webhooks, and rate…
Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid…
Design and build AI agents for any domain. Use when users: (1) ask to "create an agent", "build an assistant", or "design an AI…