소스 정보
- 저장소
- SimHacker/moollm
- 최근 소스 활동
- 2026년 2월 9일 21:17
- 감지된 SKILL.md 언어
- 영어
- 스타
- 60
- 포크
- 5
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
파일 탐색기
6 개 파일SKILL.md 표시 중
SKILL.md
소스 지침 · 읽기 전용 미리보기- name
- sniffable-python
- description
- Structure Python so LLMs can understand it in 50 lines.
- license
- MIT
- tier
- 0
- allowed-tools
- ["read_file","write_file"]
- related
- ["moollm","sister-script","play-learn-lift","yaml-jazz","plain-text","postel","adventure","debugging"]
- tags
- ["moollm","python","structure","llm-readable","code"]
- credits
- ["MOOLLM — Dual-audience code structure","Python argparse — Built-in CLI with clean structure/implementation separation","Steve Jobs — Lickable pixels as quality signal (Aqua, 2000)"]
# Sniffable Python
> **"Structure code for the first 50 lines. That's all the LLM needs."**
Don't invent new syntax — **structure existing syntax** for optimal LLM comprehension.
*If your code smells good, the LLM can sniff it from the first whiff.*
*Steve Jobs wanted pixels you could lick. We want code you can sniff.*
---
## The Problem
LLMs can read Python. But:
- Large files overwhelm context
- Implementation details bury the API
- Comments scattered or missing
- No clear entry point for understanding
**Solution:** Structure Python so the first ~50 lines contain everything needed to understand and use the tool. Make your code's bouquet apparent from the opening notes.
---
## The Pattern
### Canonical Structure
```python
#!/usr/bin/env python3
"""skill-name: Brief description of what the script does.
This docstring becomes --help output AND is immediately visible to the LLM.
It should contain:
- Purpose (one sentence)
- Usage examples
- Key behaviors
Usage:
python script.py command [options]
Examples:
python script.py move north --quiet
python script.py examine sword --verbose
"""
import argparse
from pathlib import Path
import yaml
# Configuration
DEFAULT_ROOM = "start"
VALID_DIRECTIONS = ["north", "south", "east", "west"]
MAX_INVENTORY = 10
def main():
"""Main entry point — CLI structure only, no implementation."""
parser = argparse.ArgumentParser(
description=__doc__.split('\n')[0], # First line of module docstring
formatter_class=argparse.RawDescriptionHelpFormatter
)
subparsers = parser.add_subparsers(dest="command", required=True)
# move command
move_parser = subparsers.add_parser("move", help="Move in a direction")
move_parser.add_argument("direction", choices=VALID_DIRECTIONS,
help="Direction to move")
move_parser.add_argument("--quiet", "-q", action="store_true",
help="Suppress output")
# examine command
examine_parser = subparsers.add_parser("examine", help="Look at something")
examine_parser.add_argument("target", help="What to examine")
examine_parser.add_argument("--verbose", "-v", action="store_true",
help="Show details")
# status command
status_parser = subparsers.add_parser("status", help="Show game state")
status_parser.add_argument("--verbose", "-v", action="store_true",
help="Show details")
args = parser.parse_args()
_dispatch(args)
# Implementation (LLM only reads past here if modifying behavior)
def _dispatch(args):
"""Route to appropriate handler."""
if args.command == "move":
_do_move(args.direction, args.quiet)
elif args.command == "examine":
_do_examine(args.target, args.verbose)
elif args.command == "status":
_show_status(args.verbose)
def _do_move(direction: str, quiet: bool) -> None:
"""Internal: Execute movement."""
...
def _do_examine(target: str, verbose: bool) -> None:
"""Internal: Examine an object."""
...
def _show_status(verbose: bool) -> None:
"""Internal: Display status."""
...
if __name__ == "__main__":
main()
```
### The Zones
| Zone | Lines | Purpose |
|------|-------|---------|
| **Shebang + Docstring** | 1-15 | Purpose, usage, becomes `--help` |
| **Imports** | 16-22 | Dependencies visible at a glance |
| **Constants** | 23-30 | Configuration, valid values, limits |
| **CLI Structure** | 31-50 | Command tree with types and docs |
| **Implementation** | 51+ | Only read if modifying |
---
## Why This Works
### Dual-Audience Design
```yaml
# One file, two audiences, same source of truth
dual_audience:
source: "Python file (sniffable)"
audiences:
human:
entry_point: "--help"
sees: "CLI usage, arguments, examples"
llm:
entry_point: "first 50 lines"
sees: "docstring, imports, constants, CLI tree"
convergence: "Same source of truth — no duplication, no drift"
```
### DRY Principle
The CLI decorators ARE the documentation:
```python
@click.option('--verbose', '-v', is_flag=True, help='Show details')
```
This single line defines:
- The flag name (`--verbose`)
- The short form (`-v`)
- The type (boolean flag)
- The help text
- The Python parameter name and type
No duplication. No drift. One source.
---
## Why Syntax Compression Fails
Some argue for compressing syntax to save tokens — dense symbols, sigils, minimal keywords. This is the wrong optimization.
**Perl is the cautionary tale.** Its obsessive fetish for compact syntax, sigils, punctuation, and performative TMTOWTDI one-liners — to the point of looking like line noise — is exactly why it's no longer relevant for LLM comprehension and generation.
| Approach | Tokens | Comprehension | Training Data |
|----------|--------|---------------|---------------|
| Dense novel syntax | Fewer | Low (unfamiliar) | Minimal |
| Sniffable Python | More | High (known syntax) | Billions |
**The LLM already knows Python cold.** Teaching it a novel syntax costs millions of tokens per context window (docs, examples, corrections) — and that cost is paid every single prompt, because prompting is not training. LLMs have no memory. Sniffable Python costs zero tokens to teach — the LLM just reads code it understands deeply from massive pre-training.
### The Symbol Collision Problem
Short symbols cause semantic collisions. When `@` appears, it activates Python decorators, shell patterns, email addresses, and more — simultaneously. The model has to do disambiguation work that wouldn't exist with unambiguous keywords. That disambiguation costs compute and introduces error modes.
### Comprehension Fidelity > Token Count
You're not optimizing for token count. You're optimizing for **how well the LLM understands your code**.
Dense punctuation is anti-optimized for how transformers tokenize and reason. Verbose, well-structured code with semantic comments actually compresses better in the LLM's internal representations.
---
## Comments as YAML Jazz
Apply YAML-JAZZ principles to Python comments:
```python
# CONSTANTS
TIMEOUT = 30 # generous — API is flaky on Mondays
MAX_RETRIES = 3 # based on observed failure patterns in prod
BATCH_SIZE = 100 # memory-safe for 8GB instances
# TODO: Add circuit breaker after next major outage
# FIXME: Rate limiting not yet implemented
# NOTE: This duplicates logic in api_client.py — consider extracting
```
These comments ARE data. The LLM reads them. Acts on them. Uses them to understand *why*, not just *what*.
---
## Comments: Substance Over Decoration
**Don't waste tokens on decorative separators:**
```python
# BAD: Decorative separators (long = or - lines add no meaning)
# GOOD: Plain and functional
# Imports
import argparse
```
**Don't trim Christmas trees:**
Avoid ASCII art or box-drawing in comments. Use plain section comments instead:
```python
# Configuration
TIMEOUT = 30 # generous — API flaky on Mondays
```
**Do include useful semantic comments:**
```python
# ✓ GOOD: Explains WHY
TIMEOUT = 30 # generous — API flaky on Mondays
MAX_RETRIES = 3 # based on observed failure patterns
BATCH_SIZE = 100 # memory-safe for 8GB instances
# ✓ GOOD: Documents intent
# TODO: Add circuit breaker after next outage
# NOTE: Duplicates logic in api_client.py — consider extracting
```
**The rule:** Every comment token should carry meaning. If it's just decoration, delete it.
---
## Argparse vs Click vs Typer
**Argparse is preferred** for sniffable Python because it separates structure from implementation:
| Feature | Argparse | Click | Typer |
|---------|----------|-------|-------|
| Structure/impl separation | ✓ Clean | ✗ Mixed | ✗ Mixed |
| Top-down tree order | ✓ | ✗ | ✗ |
| Built-in (no deps) | ✓ | ✗ | ✗ |
| Training data | Abundant | Abundant | Growing |
| LLM familiarity | Highest | High | Medium |
### The Argparse Advantage
With Click/Typer, decorators attach to functions — so CLI structure is **interleaved** with implementation:
```python
# Click: structure mixed with implementation
@cli.command()
def examine(target: str): # ← implementation starts here
"""Look at something."""
do_stuff() # ← can't sniff without reading this
```
With argparse, `main()` contains the **entire CLI tree** with no implementation:
```python
# Argparse: clean separation
def main():
"""CLI structure only — no implementation."""
parser = argparse.ArgumentParser(description="Tool description")
subparsers = parser.add_subparsers(dest="command")
# examine command
examine_parser = subparsers.add_parser("examine", help="Look at something")
examine_parser.add_argument("target", help="What to examine")
examine_parser.add_argument("--verbose", "-v", action="store_true")
# move command
move_parser = subparsers.add_parser("move", help="Move in a direction")
move_parser.add_argument("direction", choices=VALID_DIRECTIONS)
args = parser.parse_args()
_dispatch(args) # ← implementation is ELSEWHERE
# IMPLEMENTATION (completely separate, below the fold)
def _dispatch(args):
...
```
**The LLM reads `main()` and sees the entire command tree** — arguments, types, choices, help text — without any implementation noise. Pure sniffability. No need to hold your nose.
---
## Integration with Sister Scripts
Sniffable Python is how sister scripts should be structured:
```
skill/
├── SKILL.md # Tells LLM how to generate scripts
├── CARD.yml # Interface definition
└── scripts/
└── helper.py # Sniffable Python
```
When the skill/SKILL.md instructs the LLM to generate a sister script, it should follow sniffable-python conventions:
1. Docstring with usage at top, no decorations
2. Imports grouped and labeled
3. Constants with explanatory comments
4. CLI structure before implementation
5. Implementation below the fold
---
## Directory-Agnostic Invocation
**Critical pattern:** All scripts — including sniffable Python — must work when invoked from ANY directory. Scripts find their skill context using `__file__`, not `os.getcwd()`.
For bash scripts, see [sister-script/](../sister-script/) for the equivalent pattern.
### The Pattern
```python
from pathlib import Path
# Find THIS script's location (not the caller's cwd)
SCRIPT_DIR = Path(__file__).resolve().parent
SKILL_DIR = SCRIPT_DIR.parent # If script is in skill/scripts/
# Now find sibling files relative to script location
CONFIG_FILE = SKILL_DIR / "config.yml"
PATTERNS_DIR = SKILL_DIR / "patterns"
TEMPLATES_DIR = SKILL_DIR / "templates"
```
**Why `__file__`?**
- `Path(__file__)` — path to THIS script file
- `.resolve()` — resolve symlinks to get real location
- `.parent` — containing directory
**Why NOT `os.getcwd()`?**
- `os.getcwd()` returns the CALLER's directory
- Script invoked from `/home/user/` won't find `skills/foo/patterns/`
### The Complete Template
```python
#!/usr/bin/env python3
"""sister-tool: Brief description.
Usage:
python3 skills/my-skill/scripts/sister-tool.py command [options]
Can be invoked from any directory — finds its own context.
"""
from pathlib import Path
import argparse
import yaml
# DIRECTORY CONTEXT
# Find script location regardless of caller's cwd
SCRIPT_DIR = Path(__file__).resolve().parent
SKILL_DIR = SCRIPT_DIR.parent # scripts/ is one level down from skill/
# Skill-relative paths
CARD_FILE = SKILL_DIR / "CARD.yml"
PATTERNS_DIR = SKILL_DIR / "patterns"
TEMPLATES_DIR = SKILL_DIR / "templates"
CONFIG_DIR = SKILL_DIR / ".moollm" / "skills" / SKILL_DIR.name
# CONFIGURATION
def load_card():
"""Load skill's CARD.yml for metadata."""
if CARD_FILE.exists():
return yaml.safe_load(CARD_FILE.read_text())
return {}
def main():
"""CLI structure — sniffable, directory-agnostic."""
card = load_card()
parser = argparse.ArgumentParser(
description=card.get("description", __doc__.split('\n')[0])
)
# ... CLI structure ...
args = parser.parse_args()
_dispatch(args)
# IMPLEMENTATION
def _dispatch(args):
...
if __name__ == "__main__":
main()
```
### Why This Matters
| Invocation | `os.getcwd()` | `Path(__file__).parent` |
|------------|---------------|-------------------------|
GitHub에서 보기이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기