erpnext-frappe
Skill1 starsChanged 54 days agoMITView on GitHub
Token-efficient ERPNext and Frappe work: analyzing an existing site or app, building or changing DocTypes, custom apps, client and server scripts, reports, print formats, workflows, fixtures, pages, permissions, and bench operations. Use for any ERPNext, Frappe, bench, DocType, or ERP-site task, including "analyze the whole system" and "make a page like this one in my app", even when the user never names Frappe. Answers from metadata, the API, and bench instead of browsing pages one by one.
In this repository5 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- data-analysisSkill
- design-mdSkill
- report-writingSkill
- video-productionSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 1 is distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 58
Only then decide which screens need a look.
- Very specific: line 65
Never edit erpnext or frappe core.
- Very specific: line 86
After JSON or fixture changes: bench --site <site> migrate 2>&1 | tail -n 20.
- Very specific: line 89
Keep only failures and the summary: 2>&1 | grep -E "FAIL|ERROR|Error|Ran |OK|FAILED" | head -n 40.
- Very specific: line 96
Never cat a DocType JSON, workspace JSON, or get_meta output.
- Very specific: line 98
Every get_all and REST call carries explicit fields and a limit.
- Distinctive: line 99
Keep field tables in a file and cite only the fieldnames you use in chat.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
ERPNext and Frappe, efficiently
Why this playbook exists
An ERPNext site is thousands of DocTypes, reports, and pages. Browsing it costs a screenshot per page, and every image is re-sent on every later turn. Reading a DocType JSON in full costs hundreds of lines for a handful of useful fields. The metadata, the database, and bench answer almost every question in a few lines, so start there and open the browser only to confirm a specific screen.
Where things live
| What | Where |
| DocType of a custom app | apps/<app>/<app>/<module>/doctype/<name>/<name>.json, .py (controller), .js (form script), test_<name>.py |
| Hooks | apps/<app>/<app>/hooks.py: doc_events, doctype_js, override_doctype_class, scheduler_events, fixtures, app_include_js |
| Reports | <module>/report/<name>/<name>.json, plus .py for Script Reports and .js for filters |
| Pages, workspaces, print formats | <module>/page/<name>/, <module>/workspace/<name>/<name>.json, <module>/print_format/<name>/<name>.json |
| Site-only customizations | In the database, not in files: Custom Field, Property Setter, Client Script, Server Script, Workflow, custom Report and Print Format, Role, Custom DocPerm. Version them with fixtures in hooks.py and bench --site <site> export-fixtures. |
| Access details | The project's CLAUDE.md or docs/ARCHITECTURE.md: site URL, SSH host, bench path, existing pipelines. Read the relevant section before writing a new script; the plumbing usually exists already. |
Read metadata cheaply
Pick the cheapest source that answers the question.
- Fields of a DocType from its JSON, without printing the file:
python <skill>/scripts/doctype_fields.py path/to/<name>.jsonprints one line per field (fieldname, type, label, options, flags) plus counts of Links and child Tables. Add--csvto save the table next to the JSON,--type Link,Tableto filter. - Live site, inside the bench, one compact query with explicit fields and a limit:
bench --site <site> execute frappe.get_all --kwargs "{'doctype':'Custom Field','filters':{'dt':'Project'},'fields':['fieldname','fieldtype','options','insert_after'],'limit_page_length':500}"Same shape for Property Setter (doc_type), Client Script (dt), Server Script (reference_doctype), Workflow (document_type), Report (ref_doctype,is_standard). - REST, when bench is out of reach:
GET /api/resource/<DocType>?fields=["name","modified"]&limit_page_length=20. Meta comes fromGET /api/method/frappe.desk.form.load.getdoctype?doctype=<X>; pipe it into the field script with-as the path instead of printing it. - SQL only when the query API cannot express it:
bench --site <site> mariadb -e "select count(*) from \tabProject`"`.
Inventory a whole system without browsing
Build an inventory from metadata, then read the inventory.
- App level:
python <skill>/scripts/app_inventory.py apps/<app> --out inventory/writesdoctypes.csv,reports.csv,pages.csv,workspaces.csv,print_formats.csvand prints the counts. One line per object is enough to plan work or a report. - Site level: the
get_allqueries above, one per customization category, saved to CSV. - Only then decide which screens need a look. Use
get_page_textfor what a screen shows; screenshot only when the question is visual (layout, colors, alignment). - Existing pipelines beat new ones: if the project already has an inventory script or export, run it instead of writing another.
Implement
- Never edit
erpnextorfrappecore. Work in the custom app. For standard DocTypes use Custom Fields and Property Setters exported as fixtures,doc_eventsin hooks.py, oroverride_doctype_class. - Respect stated boundaries. "Use my fields without adding custom fields" means read the DocType JSON first and build with what exists.
- Client side:
<name>.jsin the app (frappe.ui.form.on) or a Client Script fixture. Server side: controller methods (validate,before_save,on_submit) or@frappe.whitelist()methods;frappe.get_doc,frappe.db.get_value,frappe.get_all; rawfrappe.db.sqlonly when the query API cannot express it. - Reports: a Script Report is
<name>.pywithexecute(filters)returning(columns, data); a Query Report is SQL stored in the Report doc. Prefer Script Report for anything with logic and Report Builder for plain lists. - Pages: a Page doctype with
<name>.jsfor desk pages, Workspace for navigation,www/or a Web Form for the website. - Permissions:
permissionsin the DocType JSON for app DocTypes, Custom DocPerm for standard ones. Test with a non-Administrator user. - New fields in an app DocType go into its JSON with a sensible
insert_after, followed bybench --site <site> migrate.
Apply and verify, with filtered output
- After JSON or fixture changes:
bench --site <site> migrate 2>&1 | tail -n 20. After JS or CSS:bench build --app <app> 2>&1 | tail -n 5. Thenbench --site <site> clear-cache. - Tests:
bench --site <site> run-tests --app <app> --doctype "<DocType>"(or--module). Keep only failures and the summary:2>&1 | grep -E "FAIL|ERROR|Error|Ran |OK|FAILED" | head -n 40. - Errors:
tail -n 40 logs/*.error.log, orfrappe.get_all('Error Log', fields=['method','error'], limit_page_length=5, order_by='creation desc'). - Remote site: run bench over SSH inside the VM or server, with the same filters on every command.
Token rules specific to Frappe
- Never
cata DocType JSON, workspace JSON, orget_metaoutput. Use the field script or a targeted grep. - Every
get_alland REST call carries explicitfieldsand a limit. - Keep field tables in a file and cite only the fieldnames you use in chat.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

