Token导航 LogoToken导航

Agent Skill · 研究检索

erpnext-impl-whitelisted(erpnext impl 已列入白名单)

erpnext-impl-whitelisted 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

erpnext-impl-whitelisted 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描有提醒项,按安装量在研究检索类的 73,675 个 Skill 里排第 42,473。

总安装 1,071周安装 46GitHub Stars 87下载 375核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:erpnext-impl-whitelisted(erpnext impl 已列入白名单)
来源仓库:https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package
仓库路径:skills/erpnext-impl-whitelisted
安装命令:
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-impl-whitelisted
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill erpnext-impl-whitelisted

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

指导 REST API 端点的白名单方法实现,支持访客访问与权限分级控制。适用于 Codex、Claude、Cursor、Gemini CLI 中暴露安全可控的服务接口。强调输入验证与输出过滤,避免 SQL 注入或敏感信息泄露风险。使用前需明确认证机制,并根据业务敏感度设置 allow_guest 参数。

erpnext-impl-whitelisted 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/erpnext-impl-whitelisted

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_de…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

erpnext-impl-whitelisted 怎么安装?

在终端执行 npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

erpnext-impl-whitelisted 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

erpnext-impl-whitelisted 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

erpnext-impl-whitelisted 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

erpnext-impl-whitelisted 用的人多吗?

公开数据是累计安装 1,071 次,近一周安装 46 次,下载 375 次,GitHub 87 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

erpnext-impl-whitelisted 安全吗?

第三方扫描有提醒项,说明存在需要人工确认的行为。安装前请打开源码看清它读了什么、联网到哪里。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
erpnext-impl-whitelisted

erpnext impl 已列入白名单 · 本页

1,07187需要联网未明确有提醒

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

ERPNext Whitelisted Methods - Implementation

This skill helps you determine HOW to implement REST API endpoints. For exact syntax, see erpnext-syntax-whitelisted.

Version: v14/v15/v16 compatible

Main Decision: What Type of API?

┌───────────────────────────────────────────────────────────────────┐
│ WHAT ARE YOU BUILDING?                                            │
├───────────────────────────────────────────────────────────────────┤
│                                                                   │
│ ► Public API (contact forms, status checks)?                      │
│   └── allow_guest=True + strict input validation                  │
│                                                                   │
│ ► Internal API for logged-in users?                               │
│   └── Default (no allow_guest) + permission checks                │
│                                                                   │
│ ► Admin-only API?                                                 │
│   └── frappe.only_for("System Manager")                           │
│                                                                   │
│ ► Document-specific method (on a form)?                           │
│   └── Controller method + frm.call()                              │
│                                                                   │
│ ► Standalone utility API?                                         │
│   └── Separate api.py + frappe.call()                             │
│                                                                   │
└───────────────────────────────────────────────────────────────────┘

→ See references/decision-tree.md for complete guide.


Decision: Where to Put API Code?

WHERE SHOULD YOUR API LIVE?
│
├─► Related to a specific DocType?
│   │
│   ├─► Called from that DocType's form?
│   │   └─► Controller method (doctype/xxx/xxx.py)
│   │       Client: frm.call('method_name', args)
│   │
│   └─► Standalone but DocType-related?
│       └─► Same file or doctype/xxx/xxx_api.py
│           Client: frappe.call('path.to.method', args)
│
├─► General utility API?
│   └─► myapp/api.py or myapp/api/module.py
│       Client: frappe.call('myapp.api.method', args)
│
└─► External integration?
    └─► myapp/integrations/service_name.py
        Often combined with webhooks

Decision: Permission Model

WHO CAN ACCESS THIS API?
│
├─► Anyone (public)?
│   └─► allow_guest=True
│       ⚠️ MUST validate all input
│       ⚠️ MUST rate limit if possible
│       ⚠️ NEVER expose sensitive data
│
├─► Any logged-in user?
│   └─► Default (no allow_guest)
│       Still check document permissions!
│
├─► Specific role(s)?
│   └─► frappe.only_for("Role") or frappe.only_for(["Role1", "Role2"])
│       Throws PermissionError if user lacks role
│
├─► Document-level permission?
│   └─► frappe.has_permission(doctype, ptype, doc)
│       Check before accessing each document
│
└─► Custom permission logic?
    └─► Implement your own checks
        Always deny by default

Quick Implementation Patterns

Pattern 1: Simple Authenticated API

# myapp/api.py
import frappe
from frappe import _

@frappe.whitelist()
def get_customer_balance(customer):
    """Get customer's outstanding balance."""
    # Permission check
    if not frappe.has_permission("Customer", "read", customer):
        frappe.throw(_("Not permitted"), frappe.PermissionError)

    # Fetch data
    balance = frappe.db.get_value("Customer", customer, "outstanding_amount")

    return {"customer": customer, "balance": balance or 0}
// Client call
frappe.call({
    method: 'myapp.api.get_customer_balance',
    args: { customer: 'CUST-00001' }
}).then(r => {
    console.log(r.message.balance);
});

Pattern 2: Public API with Validation

@frappe.whitelist(allow_guest=True, methods=["POST"])
def submit_inquiry(name, email, message):
    """Public contact form - strict validation required."""
    # Validate required fields
    if not all([name, email, message]):
        frappe.throw(_("All fields are required"))

    # Validate email format
    if not frappe.utils.validate_email_address(email):
        frappe.throw(_("Invalid email address"))

    # Sanitize input
    name = frappe.utils.strip_html(name)[:100]
    message = frappe.utils.strip_html(message)[:2000]

    # Create record
    doc = frappe.get_doc({
        "doctype": "Lead",
        "lead_name": name,
        "email_id": email,
        "notes": message,
        "source": "Website"
    })
    doc.insert(ignore_permissions=True)

    return {"success": True, "id": doc.name}

Pattern 3: Role-Restricted API

@frappe.whitelist()
def get_salary_data(employee):
    """HR-only endpoint."""
    # Role check - throws if not HR
    frappe.only_for(["HR Manager", "HR User"])

    return frappe.get_doc("Employee", employee).as_dict()

Pattern 4: Document Controller Method

# In doctype/sales_order/sales_order.py
class SalesOrder(Document):
    @frappe.whitelist()
    def calculate_shipping(self, carrier):
        """Called via frm.call() from form."""
        # Permission already checked by Frappe for doc access
        rate = get_shipping_rate(self.shipping_address, carrier)
        return {"carrier": carrier, "rate": rate}
// Client (in sales_order.js)
frm.call('calculate_shipping', {
    carrier: 'FedEx'
}).then(r => {
    frm.set_value('shipping_amount', r.message.rate);
});

→ See references/workflows.md for 10+ complete workflows.


Critical Security Rules

1. ALWAYS Check Permissions

# ❌ WRONG - exposes all data
@frappe.whitelist()
def get_document(doctype, name):
    return frappe.get_doc(doctype, name).as_dict()

# ✅ CORRECT
@frappe.whitelist()
def get_document(doctype, name):
    if not frappe.has_permission(doctype, "read", name):
        frappe.throw(_("Not permitted"), frappe.PermissionError)
    return frappe.get_doc(doctype, name).as_dict()

2. NEVER Trust User Input in SQL

# ❌ WRONG - SQL injection!
@frappe.whitelist()
def search(term):
    return frappe.db.sql(f"SELECT * FROM tabItem WHERE name LIKE '%{term}%'")

# ✅ CORRECT - parameterized
@frappe.whitelist()
def search(term):
    return frappe.db.sql("""
        SELECT name, item_name FROM tabItem
        WHERE name LIKE %(term)s
        LIMIT 20
    """, {"term": f"%{term}%"}, as_dict=True)

3. VALIDATE All Input for Guest APIs

@frappe.whitelist(allow_guest=True)
def public_api(data):
    # ❌ WRONG - trusts input
    doc = frappe.get_doc(data)
    doc.insert(ignore_permissions=True)

    # ✅ CORRECT - validate everything
    if not isinstance(data, dict):
        frappe.throw(_("Invalid data format"))

    allowed_fields = {"name", "email", "message"}
    clean_data = {k: v for k, v in data.items() if k in allowed_fields}

    # Validate each field...

4. NEVER Expose Sensitive Data in Errors

# ❌ WRONG - leaks internal info
except Exception as e:
    frappe.throw(str(e))

# ✅ CORRECT - generic message, log details
except Exception:
    frappe.log_error(frappe.get_traceback(), "API Error")
    frappe.throw(_("An error occurred. Please try again."))

5. Use ignore_permissions Sparingly

# ❌ WRONG - bypasses all security
@frappe.whitelist()
def get_all_data():
    return frappe.get_all("Salary Slip", ignore_permissions=True)

# ✅ CORRECT - check role first
@frappe.whitelist()
def get_all_data():
    frappe.only_for("HR Manager")  # Verify role first!
    return frappe.get_all("Salary Slip", ignore_permissions=True)

Error Handling Pattern

Standard Error Response

@frappe.whitelist()
def robust_api(param):
    """API with proper error handling."""
    try:
        # Validate input
        if not param:
            frappe.throw(_("Parameter required"), frappe.ValidationError)

        # Check permissions
        if not frappe.has_permission("MyDocType", "read"):
            frappe.throw(_("Not permitted"), frappe.PermissionError)

        # Process
        result = do_something(param)
        return {"success": True, "data": result}

    except frappe.ValidationError:
        raise  # Let Frappe handle (417)
    except frappe.PermissionError:
        raise  # Let Frappe handle (403)
    except frappe.DoesNotExistError:
        frappe.local.response["http_status_code"] = 404
        return {"success": False, "error": "Not found"}
    except Exception:
        frappe.log_error(frappe.get_traceback(), "API Error")
        frappe.local.response["http_status_code"] = 500
        return {"success": False, "error": "Internal error"}

HTTP Status Codes

CodeExceptionWhen to Use
200-Success
201-Created (set manually)
400-Bad request (set manually)
401AuthenticationErrorNot logged in
403PermissionErrorAccess denied
404DoesNotExistErrorNot found
417ValidationErrorValidation failed
409DuplicateEntryErrorDuplicate
500ExceptionServer error

Response Patterns

Simple Return (Most Common)

@frappe.whitelist()
def get_data():
    return {"key": "value"}
# Response: {"message": {"key": "value"}}

List Response

@frappe.whitelist()
def get_items():
    return frappe.get_all("Item", fields=["name", "item_name"], limit=10)
# Response: {"message": [{"name": "...", "item_name": "..."}, ...]}

With Metadata

@frappe.whitelist()
def get_paged_data(page=1, page_size=20):
    offset = (int(page) - 1) * int(page_size)
    total = frappe.db.count("Item")
    items = frappe.get_all("Item", limit=page_size, start=offset)

    return {
        "data": items,
        "total": total,
        "page": page,
        "page_size": page_size,
        "pages": (total + page_size - 1) // page_size
    }

Client Integration

frappe.call() Options

frappe.call({
    method: 'myapp.api.my_method',
    args: { param1: 'value' },

    // UI Options
    freeze: true,                    // Show loading overlay
    freeze_message: __('Loading...'), // Custom message

    // Callbacks
    callback: function(r) {
        if (r.message) { /* success */ }
    },
    error: function(r) {
        // Handle error
    },
    always: function() {
        // Always runs (finally)
    },

    // Other
    async: true,                     // Default true
    type: 'POST'                     // Default POST
});

Async/Await Pattern

async function fetchData() {
    try {
        const r = await frappe.call({
            method: 'myapp.api.get_data',
            args: { id: 123 }
        });
        return r.message;
    } catch (e) {
        frappe.msgprint(__('Error loading data'));
        console.error(e);
    }
}

Reference Files

FileContents
decision-tree.mdComplete API type selection guide
workflows.mdStep-by-step implementation patterns
examples.mdComplete working examples
anti-patterns.mdCommon mistakes to avoid

Version Differences

Featurev14v15v16
@frappe.whitelist()✅✅✅
allow_guest✅✅✅
methods parameter✅✅✅
Type annotation validation❌✅✅
Rate limiting decorator❌✅✅
API v2 endpoints❌✅✅

v15+ Type Validation

# v15+ validates types automatically
@frappe.whitelist()
def typed_api(customer: str, limit: int = 10) -> dict:
    return {"customer": customer, "limit": limit}

v15+ Rate Limiting

from frappe.rate_limiter import rate_limit

@frappe.whitelist(allow_guest=True)
@rate_limit(limit=5, seconds=60)  # 5 calls per minute
def rate_limited_api():
    return {"status": "ok"}

平台分布

Codex

35.34%
按下载量换算133

Claude

28.03%
按下载量换算105

Cursor

21.36%
按下载量换算80

Gemini CLI

9.1%
按下载量换算34

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

可疑

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills