Agent skill

Frappe Impl Controllers

by Impertio-Studio in Impertio-Studio/Frappe_Claude_Skill_Package

A skill your agent uses when building Document Controllers in a custom Frappe app: file creation, lifecycle hooks, validation, autoname, submittable workflows, controller override, child table…

MITAuto-check passed

Install Frappe Impl Controllers

skills CLI
$ npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-impl-controllers -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Impertio-Studio/Frappe_Claude_Skill_Package frappe-impl-controllers --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Impertio-Studio/Frappe_Claude_Skill_Package.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/source/impl/frappe-impl-controllers .claude/skills/frappe-impl-controllers && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
frappe-impl-controllers
GitHub stars
187
Token cost
~2.8k tokens
SKILL.md length
358 words
Files
5 (incl. references)
Skills in repo
61
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when building Document Controllers in a custom Frappe app: file creation, lifecycle hooks, validation, autoname, submittable workflows, controller override, child table…

  • Building Document Controllers in a custom Frappe app: file creation
  • SKILL.md covers Quick Decision: Controller vs…, Workflow 1: Create a New…, Workflow 2: Choose the Right… and CRITICAL: validate vs on_update, plus 11 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • Lifecycle hooks

What it does

Frappe Impl Controllers is an agent skill from Impertio-Studio/Frappe_Claude_Skill_Package. Use when building Document Controllers in a custom Frappe app: file creation, lifecycle hooks, validation, autoname, submittable workflows, controller override, child table controllers, flags system, migration from hooks.py and Server Scripts. Keywords: how to implement controller, which hook to use, validate vs onupdate, override controller, submittable document, autoname, flags, extenddoctypeclass, controller testing, child table controller, which hook to use, when does validate run, how to override save…

Its SKILL.md is about 2.8k tokens, which your agent loads only when the skill is triggered. The skill folder holds 5 other files, including reference files (for example `references/anti-patterns.md`, `references/decision-tree.md` and `references/examples.md`). Compatibility notes: Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16.

The repository describes itself as: 60 deterministic Claude AI skills for Frappe Framework & ERPNext v14-v16 development and operations. The licence is MIT.

When your agent uses it

  • Building Document Controllers in a custom Frappe app: file creation
  • Lifecycle hooks
  • Submittable workflows
  • Controller override

Example prompts

  • “/frappe-impl-controllers”

Requirements

  • Python 3
  • Compatibility (from SKILL.md): Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16.

What it can do on your machine

Read from SKILL.md and the folder at commit 36cfa80. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are python and javascript).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

  • Compatibility

    Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16.

    From compatibility in the SKILL.md frontmatter.

Context cost

Frappe Impl Controllers loads about 2.8k tokens when it runs, and up to ~11k if it reads all its reference files. Until then it costs about 140 tokens; SKILL.md has 358 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~140
When it runs · the whole SKILL.md, loaded when a task matches
~2.8k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~11k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Impertio-Studio/Frappe_Claude_Skill_Package at commit 36cfa80, republished under its MIT licence (© Impertio-Studio). 358 words, ~2,799 tokens.

Download SKILL.mdSave it as .claude/skills/frappe-impl-controllers/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.
name
frappe-impl-controllers
description
Use when building Document Controllers in a custom Frappe app: file creation, lifecycle hooks, validation, autoname, submittable workflows, controller override, child table controllers, flags system, migration from hooks.py and Server Scripts. Keywords: how to implement controller, which hook to use, validate vs on_update, override controller, submittable document, autoname, flags, extend_doctype_class, controller testing, child table controller, which hook to use, when does validate run, how to override save, document lifecycle.
compatibility
Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16.
license
MIT
metadata.author
OpenAEC-Foundation
metadata.version
2.0

Document Controllers — Implementation Workflows

Step-by-step workflows for building server-side DocType logic with full Python power. For exact syntax, see frappe-syntax-controllers.

Version: v14/v15/v16 | v15+: Supports auto-generated type annotations

Quick Decision: Controller vs Server Script?

NEED full Python (imports, classes, generators)?     → Controller
NEED external libraries (requests, pandas)?          → Controller
NEED try/except with rollback?                       → Controller
NEED frappe.enqueue() for background jobs?           → Controller
NEED to extend standard ERPNext DocType?             → Controller
Quick validation without custom app?                 → Server Script
Simple auto-fill or notification?                    → Server Script

Rule: ALWAYS use Controllers when you need a custom app. ALWAYS use Server Scripts for no-code prototyping.

Workflow 1: Create a New Controller

Step 1: Create DocType via Frappe UI or bench new-doctype

Step 2: File is auto-generated at:

apps/myapp/myapp/{module}/doctype/{doctype_name}/{doctype_name}.py

Step 3: Implement the controller class:

python
import frappe
from frappe import _
from frappe.model.document import Document

class MyDocType(Document):
    def validate(self):
        self.validate_dates()
        self.calculate_totals()

    def validate_dates(self):
        if self.from_date and self.to_date and self.from_date > self.to_date:
            frappe.throw(_("From Date cannot be after To Date"))

    def calculate_totals(self):
        self.total = sum(item.amount for item in self.items)

Step 4: Run bench restart (or bench watch for hot-reload in dev)

Naming convention: DocType "Sales Order" → class SalesOrder, file sales_order.py

Workflow 2: Choose the Right Hook

WHAT DO YOU WANT?
├── Validate data / calculate fields before save?
│   └── validate — changes to self ARE saved
│
├── Action AFTER save (emails, linked docs, logs)?
│   └── on_update — changes to self NOT saved (use db_set)
│
├── Only for NEW documents?
│   └── after_insert
│
├── Before/after SUBMIT?
│   ├── Check before submit → before_submit
│   └── Ledger entries after → on_submit
│
├── Before/after CANCEL?
│   ├── Prevent cancel → before_cancel
│   └── Reverse entries → on_cancel
│
├── Before DELETE?
│   └── on_trash (throw to prevent)
│
├── Custom document naming?
│   └── autoname
│
└── Detect ANY change (including db_set)?
    └── on_change

See references/decision-tree.md for all hooks with execution order.

CRITICAL: validate vs on_update

Aspectvalidateon_update
WhenBefore DB writeAfter DB write
self.x = y saved?YESNO — use db_set
Can abort with throw?YESAlready saved
get_doc_before_save()AvailableAvailable
Use forValidation, calculationsNotifications, linked docs
python
# WRONG — changes in on_update are NOT saved
def on_update(self):
    self.status = "Completed"  # LOST!

# CORRECT — use db_set
def on_update(self):
    frappe.db.set_value(self.doctype, self.name, "status", "Completed")

Workflow 3: Validation with Error Collection

python
def validate(self):
    errors = []
    if not self.items:
        errors.append(_("At least one item is required"))
    for item in self.items:
        if item.qty <= 0:
            errors.append(_("Row {0}: Qty must be positive").format(item.idx))
    if self.from_date > self.to_date:
        errors.append(_("From Date cannot be after To Date"))
    if errors:
        frappe.throw("<br>".join(errors))

Workflow 4: Detect Field Changes

python
def validate(self):
    old = self.get_doc_before_save()
    if old and old.status != self.status:
        self.flags.status_changed = True
        self.status_changed_on = frappe.utils.now()

def on_update(self):
    if self.flags.get('status_changed'):
        self.notify_status_change()

Rule: ALWAYS use self.flags to pass data between hooks. NEVER rely on external state.

Workflow 5: Custom Naming (autoname)

python
from frappe.model.naming import getseries

def autoname(self):
    # Format: PRJ-CUST-2025-001
    code = (self.customer or "GEN")[:4].upper()
    year = frappe.utils.getdate(self.start_date or frappe.utils.today()).year
    prefix = f"PRJ-{code}-{year}-"
    self.name = getseries(prefix, 3)

Alternative — before_naming:

python
def before_naming(self):
    if self.is_priority:
        self.naming_series = "PRIORITY-.#####"
    else:
        self.naming_series = "STD-.#####"

Workflow 6: Submittable Document

DRAFT (docstatus=0) → submit() → SUBMITTED (docstatus=1) → cancel() → CANCELLED (docstatus=2)

submit():  validate → before_submit → [DB: docstatus=1] → on_update → on_submit
cancel():  before_cancel → [DB: docstatus=2] → on_cancel
python
class PurchaseOrder(Document):
    def validate(self):
        self.validate_items()
        self.calculate_totals()

    def before_submit(self):
        # ONLY submit-specific checks here
        if self.total > 100000 and not self.manager_approval:
            frappe.throw(_("Manager approval required for POs over 100,000"))

    def on_submit(self):
        self.update_ordered_qty()
        self.create_purchase_receipt_draft()

    def before_cancel(self):
        if frappe.db.exists("Purchase Invoice",
                {"purchase_order": self.name, "docstatus": 1}):
            frappe.throw(_("Cancel linked invoices first"))

    def on_cancel(self):
        self.reverse_ordered_qty()

Rule: NEVER duplicate validation between validate and before_submit. validate ALWAYS runs before before_submit.

Workflow 7: Override Standard ERPNext Controller

Method A: Full Override (hooks.py)
python
# hooks.py
override_doctype_class = {
    "Sales Invoice": "myapp.overrides.CustomSalesInvoice"
}

# myapp/overrides.py
from erpnext.accounts.doctype.sales_invoice.sales_invoice import SalesInvoice

class CustomSalesInvoice(SalesInvoice):
    def validate(self):
        super().validate()  # ALWAYS call parent first
        self.custom_validation()
Show full SKILL.md (147 more words)Show less
Method B: Event Handler (Safer, no class override)
python
# hooks.py
doc_events = {
    "Sales Invoice": {
        "validate": "myapp.events.validate_sales_invoice",
    }
}

# myapp/events.py
def validate_sales_invoice(doc, method=None):
    if doc.grand_total < 0:
        frappe.throw(_("Invalid total"))
Method C: extend_doctype_class (v16+)
python
# hooks.py
extend_doctype_class = {
    "Sales Invoice": "myapp.extends.SalesInvoiceExtend"
}

# myapp/extends.py — Only methods to add/override
class SalesInvoiceExtend:
    def custom_method(self):
        pass

Rule: ALWAYS call super().validate() in override. NEVER skip parent methods — standard ERPNext logic depends on it.

Workflow 8: Whitelisted Methods (Client-Callable)

python
class Quotation(Document):
    @frappe.whitelist()
    def apply_discount(self, discount_percent):
        if discount_percent < 0 or discount_percent > 100:
            frappe.throw(_("Discount must be 0-100"))
        self.discount_amount = self.total * (discount_percent / 100)
        self.grand_total = self.total - self.discount_amount
        self.save()
        return {"grand_total": self.grand_total}

Client-side call:

javascript
frm.call('apply_discount', { discount_percent: 10 }).then(r => {
    frm.reload_doc();
});

Workflow 9: Flags System

python
# Document-level flags (built-in)
doc.flags.ignore_permissions = True    # Bypass permission checks
doc.flags.ignore_validate = True       # Skip validate() hook
doc.flags.ignore_mandatory = True      # Skip required field check

# Custom flags for inter-hook communication
def validate(self):
    if self.is_urgent:
        self.flags.needs_notification = True

def on_update(self):
    if self.flags.get('needs_notification'):
        self.notify_team()

Workflow 10: Testing Controllers

python
# tests/test_my_doctype.py
import frappe
from frappe.tests.utils import FrappeTestCase

class TestMyDocType(FrappeTestCase):
    def test_validate_dates(self):
        doc = frappe.get_doc({
            "doctype": "My DocType",
            "from_date": "2025-01-10",
            "to_date": "2025-01-01"  # Before from_date
        })
        self.assertRaises(frappe.ValidationError, doc.insert)

    def test_calculate_totals(self):
        doc = frappe.get_doc({
            "doctype": "My DocType",
            "items": [
                {"item": "A", "qty": 2, "rate": 100},
                {"item": "B", "qty": 3, "rate": 50}
            ]
        })
        doc.insert()
        self.assertEqual(doc.total, 350)

Run: bench run-tests --module myapp.module.doctype.my_doctype.test_my_doctype

Execution Order Reference

INSERT
before_insert → before_naming → autoname → before_validate →
validate → before_save → [DB INSERT] → after_insert →
on_update → on_change
SAVE (existing)
before_validate → validate → before_save → [DB UPDATE] →
on_update → on_change
SUBMIT
validate → before_submit → [DB: docstatus=1] →
on_update → on_submit → on_change

Anti-Pattern Quick Check

Do NOTDo Instead
self.x = y in on_updatefrappe.db.set_value(...)
self.save() in on_updateCauses infinite loop
frappe.db.commit() in hooksLet framework handle
Heavy ops in validateUse frappe.enqueue() in on_update
Skip super().validate()ALWAYS call parent first
frappe.get_doc() in loopsUse frappe.get_cached_doc()
Hardcoded thresholdsUse Settings DocType

See references/anti-patterns.md for complete list.

  • frappe-syntax-controllers — Exact hook signatures and API
  • frappe-errors-controllers — Error handling patterns
  • frappe-impl-serverscripts — When Server Script suffices
  • frappe-syntax-hooks — hooks.py configuration
  • frappe-core-database — frappe.db.* operations

See references/decision-tree.md for all hooks. See references/workflows.md for extended patterns. See references/examples.md for complete working examples.

© Impertio-Studio, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 4 other files (references) in skills/source/impl/frappe-impl-controllers of Impertio-Studio/Frappe_Claude_Skill_Package.

  • SKILL.md
  • references/anti-patterns.md
  • references/decision-tree.md
  • references/examples.md
  • references/workflows.md

Open the folder on GitHubat commit 36cfa80

Compare with similar skills

Frappe Impl Controllers next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Frappe Impl Controllers compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Frappe Impl Controllers this skillImpertio-Studio/Frappe_Claude_Skill_Package187—~2.8kAutomated safety check: PassMIT
Control UIopenclaw/openclaw392k—~1.8kAutomated safety check: PassMIT
Control UI E2Eopenclaw/openclaw392k—~2.9kAutomated safety check: PassMIT
Control D AutomationComposioHQ/awesome-claude-skills77k3 repos~738Automated safety check: PassNone
Controlhashgraph-online/awesome-codex-plugins1.2k—~3.4kAutomated safety check: PassApache-2.0
Data Privacy Controlssickn33/agentic-awesome-skills47k1 repos~3.4kAutomated safety check: PassMIT

Similar skills

  • Control UI

    openclaw/openclaw

    Operate and troubleshoot the OpenClaw Control UI: navigate connected clients, organize sessions, build session dashboards, and handle direct or Tailscale-hosted Gateways.

    392k GitHub stars~1.8k tokensUpdated today
    Auto-check passed
  • Control UI E2E

    openclaw/openclaw

    A skill your agent uses when designing, testing, fixing, or extending the OpenClaw Control UI GUI, including UI stress-test galleries with feedback inputs, Vitest + Playwright end-to-end checks…

    392k GitHub stars~2.9k tokensUpdated today
    Testing & QAAuto-check passed
  • Control D Automation

    ComposioHQ/awesome-claude-skills

    Automate Control D tasks via Rube MCP (Composio). An agent skill from ComposioHQ/awesome-claude-skills.

    77k GitHub starsUsed in 3 repos~738 tokens
    Productivity & AutomationAuto-check passed
  • Control

    hashgraph-online/awesome-codex-plugins

    Apply the principle of Control — the level of autonomy a system gives the user, and how that level should be matched to the user's expertise and the task's stakes.

    1.2k GitHub stars~3.4k tokensUpdated yesterday
    Auto-check passed
  • Data Privacy Controls

    sickn33/agentic-awesome-skills

    Data privacy control register: data category, lawful basis, retention period, access roles, encryption and consent requirement per module.

    47k GitHub starsUsed in 1 repo~3.4k tokens
    Legal & ComplianceAuto-check passed
  • Manage the experimental Nasiko CLI lifecycle through ECC — read-only status checks, consent-gated install of the pinned qualified version with dry-run preview, and ownership-checked uninstall, under…

    275k GitHub starsUsed in 1 repo~660 tokens
    Auto-check passed

More from Impertio-Studio/Frappe_Claude_Skill_Package

All 61 skills in this repo
  • Frappe Agent Interpreter

    Impertio-Studio/Frappe_Claude_Skill_Package

    A skill your agent uses when receiving vague or unclear ERPNext/Frappe development requests that need interpretation.

    187 GitHub starsUsed in 1 repo~3.2k tokens
    Auto-check passed
  • Frappe Ops Website Deploy

    Impertio-Studio/Frappe_Claude_Skill_Package

    Deploy HTML/CSS websites to ERPNext/Frappe (v15/v16) as Web Pages via the REST API.

    187 GitHub stars~2.5k tokensUpdated 21 days ago
    Auto-check passed
  • Frappe Core API

    Impertio-Studio/Frappe_Claude_Skill_Package

    A skill your agent uses when building ERPNext/Frappe API integrations (v14/v15/v16) including REST API, RPC API, authentication, webhooks, and rate limiting.

    187 GitHub starsUsed in 1 repo~3.2k tokens
    Auto-check passed
  • Frappe Errors API

    Impertio-Studio/Frappe_Claude_Skill_Package

    A skill your agent uses when debugging or handling API errors in Frappe/ERPNext v14/v15/v16.

    187 GitHub starsUsed in 1 repo~4k tokens
    Auto-check passed
  • Frappe Impl Hooks

    Impertio-Studio/Frappe_Claude_Skill_Package

    A skill your agent uses when implementing hooks.py configurations in a Frappe custom app.

    187 GitHub starsUsed in 1 repo~3k tokens
    Auto-check passed
  • Frappe Impl Whitelisted

    Impertio-Studio/Frappe_Claude_Skill_Package

    A skill your agent uses when building API endpoints with @frappe.whitelist() in Frappe.

    187 GitHub starsUsed in 1 repo~3.1k tokens
    Auto-check passed

Questions about Frappe Impl Controllers

What does Frappe Impl Controllers do?

A skill your agent uses when building Document Controllers in a custom Frappe app: file creation, lifecycle hooks, validation, autoname, submittable workflows, controller override, child table…. Frappe Impl Controllers is an agent skill from Impertio-Studio/Frappe_Claude_Skill_Package.py and Server Scripts.

When should I use Frappe Impl Controllers?

Frappe Impl Controllers fits situations like: building Document Controllers in a custom Frappe app: file creation; lifecycle hooks; submittable workflows; controller override.

How do I install Frappe Impl Controllers in Claude Code?

Run `npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-impl-controllers -a claude-code`. Or copy the skill folder (skills/source/impl/frappe-impl-controllers in Impertio-Studio/Frappe_Claude_Skill_Package) into .claude/skills/frappe-impl-controllers in your project. Claude Code loads it when a task matches its description.

How do I install Frappe Impl Controllers in Codex?

Run `npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-impl-controllers -a codex`. Or copy the skill folder (skills/source/impl/frappe-impl-controllers in Impertio-Studio/Frappe_Claude_Skill_Package) into .agents/skills/frappe-impl-controllers in your project. Codex loads it when a task matches its description.

Can I use Frappe Impl Controllers in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-impl-controllers -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/frappe-impl-controllers, .gemini/skills/frappe-impl-controllers, .github/skills/frappe-impl-controllers and .opencode/skills/frappe-impl-controllers in your project.

What does Frappe Impl Controllers need to run?

SKILL.md names no scripts, command-line tools or credentials: Frappe Impl Controllers is instructions for the agent only. Our summary lists: Python 3. Compatibility (from SKILL.md): Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16..

Does Frappe Impl Controllers access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Frappe Impl Controllers safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Frappe Impl Controllers use?

Frappe Impl Controllers is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Frappe Impl Controllers use?

About 2.8k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 8k tokens, read only when the agent opens those files.

What are the alternatives to Frappe Impl Controllers?

Skills that share tags, products or a category with Frappe Impl Controllers: Control UI (openclaw/openclaw, 392k stars), Control UI E2E (openclaw/openclaw, 392k stars), Control D Automation (ComposioHQ/awesome-claude-skills, 77k stars) and Control (hashgraph-online/awesome-codex-plugins, 1.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Frappe Impl Controllers?

Impertio-Studio (a GitHub organization) maintains it in Impertio-Studio/Frappe_Claude_Skill_Package, which has 187 GitHub stars. The repository holds 61 skills in this directory. The repository was last updated on September 17, 2026.

Source: Impertio-Studio/Frappe_Claude_Skill_Package on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.