Add generic Claw skill-template (manifest, CLI, docs, optional snippets)
Made-with: Cursor
This commit is contained in:
17
optional/README.md
Normal file
17
optional/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# optional/ 目录说明
|
||||
|
||||
本目录下的文件**不会**被 `scripts/skill_main.py` 自动引用。
|
||||
|
||||
## 为什么要单独放
|
||||
|
||||
- 避免模板入口脚本依赖过多,同事从「最小 health」起步时零干扰。
|
||||
- 需要时**整文件复制**到 `scripts/` 或你们自己的包路径下,再按文件头注释改名、改常量。
|
||||
|
||||
## 文件列表
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| `paths_snippet.py` | `CLAW_*` 数据目录解析与 fallback 说明 |
|
||||
| `sqlite_minimal.py` | 无业务含义的 SQLite 建表示例 |
|
||||
|
||||
复制后务必全局替换 `your-skill-slug` 与表名,避免与别的技能冲突。
|
||||
92
optional/paths_snippet.py
Normal file
92
optional/paths_snippet.py
Normal file
@@ -0,0 +1,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
可选片段:路径与环境变量(请复制到 scripts/ 或作为独立模块使用)
|
||||
================================================================
|
||||
|
||||
【用途】
|
||||
统一解析「用户数据根」「用户 ID」「本技能私有目录」,避免在业务代码里重复 os.getenv。
|
||||
|
||||
【使用步骤】
|
||||
1. 将本文件复制到 skills/your-slug/scripts/paths.py(或任意模块名)。
|
||||
2. 把 SKILL_SLUG 改为与 SKILL.md 中 metadata.skill.slug 一致。
|
||||
3. 在业务代码中: from paths import get_skill_data_dir (按实际包路径调整)
|
||||
|
||||
【可移植性】
|
||||
- 优先读取标准名 CLAW_*(见 docs/RUNTIME.md)。
|
||||
- 若你的组织在宿主侧仍使用历史变量名,可在此文件 _aliases 列表中追加 (标准名, 备选名),
|
||||
由宿主注入其一即可;不要在业务里再写第三套名字。
|
||||
|
||||
【注意】
|
||||
- 未设置 CLAW_DATA_ROOT 时的 fallback 仅适合开发机;生产环境应由宿主注入。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# TODO: 复制本文件后改为你的 slug(与 SKILL.md metadata.skill.slug 一致)
|
||||
SKILL_SLUG = "your-skill-slug"
|
||||
|
||||
|
||||
def _getenv_first(names: tuple[str, ...]) -> str:
|
||||
"""按顺序读取多个环境变量名,返回第一个非空值。"""
|
||||
for n in names:
|
||||
v = (os.getenv(n) or "").strip()
|
||||
if v:
|
||||
return v
|
||||
return ""
|
||||
|
||||
|
||||
def get_data_root() -> str:
|
||||
"""
|
||||
用户数据根目录。
|
||||
顺序:CLAW_DATA_ROOT → (可选)宿主别名,见下方元组。
|
||||
若皆空:Windows 默认 D:\\claw-data;其它系统默认 ~/.claw-data —— 仅开发便利,生产请注入 CLAW_DATA_ROOT。
|
||||
"""
|
||||
root = _getenv_first(
|
||||
(
|
||||
"CLAW_DATA_ROOT",
|
||||
# 在此追加组织内别名,例如 "MYORG_USER_DATA_ROOT",
|
||||
)
|
||||
)
|
||||
if root:
|
||||
return root
|
||||
if sys.platform == "win32":
|
||||
return r"D:\claw-data"
|
||||
return os.path.join(os.path.expanduser("~"), ".claw-data")
|
||||
|
||||
|
||||
def get_user_id() -> str:
|
||||
"""当前用户或工作空间 ID;未设置时用 _anon(仅开发)。"""
|
||||
uid = _getenv_first(
|
||||
(
|
||||
"CLAW_USER_ID",
|
||||
# 在此追加别名,例如 "MYORG_WORKSPACE_ID",
|
||||
)
|
||||
)
|
||||
return uid or "_anon"
|
||||
|
||||
|
||||
def get_skill_data_dir() -> str:
|
||||
"""
|
||||
本技能可写目录:{数据根}/{用户ID}/{skill_slug}/
|
||||
会自动 os.makedirs(..., exist_ok=True)。
|
||||
"""
|
||||
path = os.path.join(get_data_root(), get_user_id(), SKILL_SLUG)
|
||||
os.makedirs(path, exist_ok=True)
|
||||
return path
|
||||
|
||||
|
||||
def get_skills_root() -> str:
|
||||
"""
|
||||
可选:并列安装的多技能根目录。
|
||||
未设置 CLAW_SKILLS_ROOT 时,默认使用本文件所在仓库的上一级目录的上一级
|
||||
(即:.../skill-template/scripts/ → 误推断;复制后请改为 BASE_DIR 逻辑)。
|
||||
"""
|
||||
root = _getenv_first(("CLAW_SKILLS_ROOT",))
|
||||
if root:
|
||||
return root
|
||||
# 模板占位:脚本位于 scripts/,仓库根为 dirname(dirname(__file__))
|
||||
here = os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.dirname(here)
|
||||
48
optional/sqlite_minimal.py
Normal file
48
optional/sqlite_minimal.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
可选片段:最小 SQLite 示例(请复制后按需修改)
|
||||
==============================================
|
||||
|
||||
【用途】
|
||||
演示「单表 + 自增主键 + INTEGER 时间戳」的一种严谨写法;与具体业务无关。
|
||||
|
||||
【使用步骤】
|
||||
1. 复制到 scripts/db_example.py(或并入你的模块)。
|
||||
2. 修改 TABLE_SQL 中的表名与字段;保持时间字段为 INTEGER Unix 秒(UTC)若需跨时区一致。
|
||||
3. 在入口脚本中仅在需要持久化时 import。
|
||||
|
||||
【注意】
|
||||
- 不在模板中做迁移兼容;schema 变更请用你们组织的迁移策略。
|
||||
- 数据库文件路径建议:get_skill_data_dir() / "skill.db"(paths_snippet 中函数)。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
import time
|
||||
|
||||
# 示例表:与任何业务无关
|
||||
TABLE_SQL = """
|
||||
CREATE TABLE IF NOT EXISTS template_audit (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT, -- 自增主键
|
||||
action TEXT NOT NULL, -- 动作标识,如 health_ok
|
||||
created_at INTEGER NOT NULL -- Unix 秒 UTC
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
def connect(db_path: str) -> sqlite3.Connection:
|
||||
return sqlite3.connect(db_path)
|
||||
|
||||
|
||||
def init_db(conn: sqlite3.Connection) -> None:
|
||||
conn.execute(TABLE_SQL)
|
||||
conn.commit()
|
||||
|
||||
|
||||
def record_action(conn: sqlite3.Connection, action: str) -> None:
|
||||
conn.execute(
|
||||
"INSERT INTO template_audit (action, created_at) VALUES (?, ?)",
|
||||
(action, int(time.time())),
|
||||
)
|
||||
conn.commit()
|
||||
Reference in New Issue
Block a user