360 Secure SkillHub
360 安全技能中心

Thoth

核心功能:扫描指定项目代码与元文件,自动生成README、API参考、使用指南三类规范文档。典型场景:开发者快速为项目补全专业文档,提升项目规范性。输入需配置项目路径、授权密钥,可自定义项目名及输出目录;输出为保存至指定目录的三个MD格式文件,覆盖项目全维度文档需求。

occupythemilkyway
occupythemilkyway
热度 23.00
最近更新 2026-05-28 09:17:05
分类:开发依赖:代码执行 / 读写文件应用场景:摘要总结 / 报告撰写 / DevOps

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add thoth
Metadata
name
thoth
description
Thoth Standard -- Auto-Documentation Engine. Reads your entire project and generates README, API reference, and usage guide. Saved to .md files.
version
1.0.0
metadata
{"openclaw":{"requires":{"env":["PROJECT_PATH","LICENSE_KEY"],"bins":["python3","pip3"]},"primaryEnv":"PROJECT_PATH","emoji":"📜📖","homepage":"https://clawhub.ai/occupythemilkyway/thoth","tags":["documentation","readme","api-reference","code","autodoc","developer","standard","thoth"],"envVars":[{"name":"LICENSE_KEY","required":true,"description":"Your Thoth Standard license key. Get one at: ko-fi.com/occupythemilkyway"},{"name":"PROJECT_PATH","required":true,"description":"Path to the project folder to document"},{"name":"PROJECT_NAME","required":false,"description":"Project name override (default: folder name)","default":""},{"name":"OUTPUT_DIR","required":false,"description":"Directory to save docs (default: ./docs)","default":"./docs"}]}}

Thoth Standard -- Auto-Documentation Engine

Full project documentation in minutes. README, API reference, usage guide -- all saved to files.


Step 1 -- Install

pip3 install rich --break-system-packages --quiet

Step 2 -- Validate and scan

import os, sys, ast
from datetime import datetime
from rich.console import Console
from rich.panel import Panel
from rich.tree import Tree
from rich.table import Table
from rich import box

console = Console()

LICENSE_KEY = os.environ.get("LICENSE_KEY", "").strip()
if not LICENSE_KEY or not LICENSE_KEY.startswith("THOTH-STD-"):
    console.print(Panel(
        "[red bold]Thoth Standard requires a license key.[/red bold]\n\n"
        "Get your key at: [bold cyan]ko-fi.com/occupythemilkyway[/bold cyan]\n\n"
        "Or use the free version: [dim]openclaw skills install thoth-lite[/dim]",
        title="License Required",
        border_style="red"
    ))
    sys.exit(1)

PROJECT_PATH = os.environ.get("PROJECT_PATH", "").strip()
PROJECT_NAME = os.environ.get("PROJECT_NAME", "").strip()
OUTPUT_DIR   = os.environ.get("OUTPUT_DIR", "./docs").strip()

if not PROJECT_PATH or not os.path.exists(PROJECT_PATH):
    console.print(Panel(f"[red]PROJECT_PATH not found: {PROJECT_PATH}[/red]", title="Error", border_style="red"))
    sys.exit(1)

if not PROJECT_NAME:
    PROJECT_NAME = os.path.basename(os.path.abspath(PROJECT_PATH))

os.makedirs(OUTPUT_DIR, exist_ok=True)

console.print()
console.print(Panel.fit(
    f"[bold cyan]📜 Thoth Standard -- Auto-Documentation[/bold cyan]\n"
    f"Project: [yellow]{PROJECT_NAME}[/yellow]\n"
    f"Path:    [dim]{PROJECT_PATH}[/dim]\n"
    f"Output:  [green]{OUTPUT_DIR}/[/green]",
    border_style="cyan"
))

SKIP_DIRS = {".git", "__pycache__", "node_modules", ".venv", "venv", "dist", "build", ".next", ".pytest_cache"}
CODE_EXTS  = {".py", ".js", ".ts", ".jsx", ".tsx", ".go", ".rs", ".java", ".rb", ".cs", ".cpp", ".c", ".sh"}
META_FILES = {"requirements.txt", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "setup.py", "setup.cfg"}

all_files, meta_files, functions = [], {}, []

for root, dirs, fnames in os.walk(PROJECT_PATH):
    dirs[:] = [d for d in dirs if d not in SKIP_DIRS]
    for fname in fnames:
        full = os.path.join(root, fname)
        rel  = os.path.relpath(full, PROJECT_PATH)
        ext  = os.path.splitext(fname)[1].lower()
        if fname in META_FILES:
            try:
                with open(full, encoding="utf-8", errors="replace") as fh:
                    meta_files[fname] = fh.read(2000)
            except Exception:
                pass
        if ext in CODE_EXTS:
            all_files.append((rel, full, ext))

# Extract Python functions/classes for API reference
for rel, full, ext in all_files:
    if ext == ".py":
        try:
            with open(full, encoding="utf-8", errors="replace") as fh:
                source = fh.read()
            tree = ast.parse(source)
            for node in ast.walk(tree):
                if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
                    doc = ast.get_docstring(node) or ""
                    args = []
                    if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
                        args = [a.arg for a in node.args.args]
                    functions.append({
                        "file": rel, "name": node.name,
                        "type": "class" if isinstance(node, ast.ClassDef) else "function",
                        "args": args, "doc": doc[:200]
                    })
        except Exception:
            pass

tbl = Table(title=f"Project Scan: {PROJECT_NAME}", box=box.ROUNDED, border_style="cyan")
tbl.add_column("Metric", style="dim")
tbl.add_column("Value", style="yellow")
tbl.add_row("Code files", str(len(all_files)))
tbl.add_row("Python symbols", str(len(functions)))
tbl.add_row("Meta files", ", ".join(meta_files.keys()) or "none")
tbl.add_row("Output dir", OUTPUT_DIR)
console.print(tbl)

# Print file tree and contents for Claude
console.print("\n[bold]Project structure:[/bold]")
for rel, full, ext in sorted(all_files)[:30]:
    print(f"  {rel}")

console.print("\n[bold]File contents (for documentation):[/bold]")
for rel, full, ext in sorted(all_files)[:25]:
    try:
        with open(full, encoding="utf-8", errors="replace") as fh:
            content = fh.read(4000)
        print(f"\n=== {rel} ===\n{content}\n=== END {rel} ===")
    except Exception:
        pass

if functions:
    console.print("\n[bold]Extracted symbols:[/bold]")
    for fn in functions[:50]:
        args_str = ", ".join(fn["args"]) if fn["type"] == "function" else ""
        print(f"  [{fn['type']}] {fn['file']}::{fn['name']}({args_str}) -- {fn['doc'][:80]}")

for name, content in meta_files.items():
    print(f"\n=== META: {name} ===\n{content}\n=== END META ===")

Step 3 -- Generate documentation

Based on the project scan above, generate three complete documents:

Document 1: README.md

# [PROJECT_NAME]
> Tagline

## Overview
What it does, why it exists, who it's for. (3-4 paragraphs, thorough)

## Features
Bullet list of all features found in the code.

## Installation
Exact install steps based on the actual meta files found.

## Quick Start
Working code example.

## Usage
Detailed usage with multiple examples.

## Configuration
All config options, env vars, or settings found.

## Project Structure
File/folder explanations.

## License

Document 2: API_REFERENCE.md

For every function, class, and method found in the scan:

# API Reference: [PROJECT_NAME]

## [module_name]

### `function_name(args)`
Description of what it does, parameters, return value, example.

Document 3: USAGE_GUIDE.md

Practical, real-world usage guide with worked examples from the actual code.


Step 4 -- Save and confirm

import os
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich import box
console = Console()

# (Claude saves the 3 files above to OUTPUT_DIR using its file tool)
readme_path  = os.path.join(OUTPUT_DIR, "README.md")
api_path     = os.path.join(OUTPUT_DIR, "API_REFERENCE.md")
usage_path   = os.path.join(OUTPUT_DIR, "USAGE_GUIDE.md")

tbl = Table(title="Documentation Generated", box=box.SIMPLE, border_style="green")
tbl.add_column("File", style="cyan")
tbl.add_column("Description", style="dim")
tbl.add_row(readme_path,  "Project overview and install")
tbl.add_row(api_path,     "Full API reference")
tbl.add_row(usage_path,   "Practical usage guide")
console.print()
console.print(tbl)
console.print(Panel(
    "[bold green]Documentation complete![/bold green]\n\n"
    "Upgrade to [magenta]Thoth Pro ($9)[/magenta] for auto-injected docstrings, git CHANGELOG, and architecture docs.\n"
    "-> [cyan]ko-fi.com/occupythemilkyway[/cyan]",
    border_style="green"
))

Save all three documents to OUTPUT_DIR using your file writing tool, then display the confirmation panel.