6.8 KiB
Scripts and Code
Best practices for including scripts, handling errors, managing dependencies, and documenting configuration in skills.
Table of Contents
- When to Include Scripts
- Error Handling
- Dependencies and Packages
- File Paths and Cross-Platform Compatibility
- Configuration Documentation
- Script Execution vs. Reference
- Validation Scripts
- MCP Tools Integration
When to Include Scripts
Pre-made scripts are more reliable than code generation for critical operations.
Scripts vs. Generated Code
Use pre-made scripts for:
- Critical operations requiring exact sequences
- Complex error handling
- Repeated utility functions
- Fragile operations (database migrations, API calls)
- Operations where order matters
Use code generation for:
- Creative solutions
- Context-specific implementations
- One-off operations
- Exploratory tasks
Error Handling
Scripts should solve problems, not punt to Claude. Provide specific, actionable error messages.
Good Error Handling
✓ What to do:
def process_file(filename):
"""
Process input file with comprehensive error handling.
Args:
filename: Path to the file to process
Returns:
Processed data string
Raises:
FileNotFoundError: With specific path and suggestions
PermissionError: With permission requirements
ValueError: With format expectations
"""
import os
# Check file exists
if not os.path.exists(filename):
raise FileNotFoundError(
f"File not found: {filename}\n"
f"Current directory: {os.getcwd()}\n"
f"Please verify:\n"
f" 1. File path is correct\n"
f" 2. File exists in the expected location\n"
f" 3. You have permission to access the directory"
)
# Check file is readable
if not os.access(filename, os.R_OK):
raise PermissionError(
f"Cannot read file: {filename}\n"
f"Current user: {os.getenv('USER')}\n"
f"File permissions: {oct(os.stat(filename).st_mode)[-3:]}\n"
f"Solution: Run 'chmod +r {filename}' or contact system administrator"
)
# Check file is not empty
if os.path.getsize(filename) == 0:
raise ValueError(
f"File is empty: {filename}\n"
f"Expected: Non-empty CSV file with headers\n"
f"Please provide a file with data"
)
# Check file format
try:
with open(filename, 'r') as f:
first_line = f.readline()
if not first_line.strip():
raise ValueError(
f"File appears to be empty or invalid: {filename}\n"
f"Expected: CSV file with comma-separated headers"
)
if ',' not in first_line:
raise ValueError(
f"File does not appear to be CSV format: {filename}\n"
f"First line: {first_line[:100]}\n"
f"Expected: Comma-separated values\n"
f"Detected: {first_line.count('\t')} tabs, {first_line.count('|')} pipes\n"
f"Suggestion: Check delimiter or convert to CSV"
)
# Process file
f.seek(0)
data = f.read()
return data
except UnicodeDecodeError as e:
raise ValueError(
f"File encoding error: {filename}\n"
f"Error: {str(e)}\n"
f"File might be binary or use unsupported encoding\n"
f"Solution: Convert to UTF-8 encoding or verify file type"
)
Dependencies and Packages
Document required packages with versions and explain why they're needed.
File Paths and Cross-Platform Compatibility
Always use forward slashes for file paths to ensure cross-platform compatibility.
Path Best Practices
Always use forward slashes:
# ✓ Correct - works on all platforms
data_file = "data/input/customers.csv"
output_dir = "reports/2024/march"
config_path = "config/settings.json"
# ✗ Wrong - fails on Unix-like systems
data_file = "data\\input\\customers.csv"
output_dir = "reports\\2024\\march"
Use pathlib for path operations:
from pathlib import Path
# Automatically handles platform differences
data_dir = Path("data") / "input"
output_file = data_dir / "processed_data.csv"
# Always converts to forward slashes for display
print(output_file.as_posix()) # "data/input/processed_data.csv"
Convert user-provided paths:
def normalize_path(path_str):
"""Convert any path format to forward-slash format."""
from pathlib import Path
return Path(path_str).as_posix()
# Example usage
user_path = "data\\input\\file.csv" # User on Windows
normalized = normalize_path(user_path) # "data/input/file.csv"
Configuration Documentation
Document why configuration values exist. No "magic numbers."
Good Configuration
✓ What to do:
# Maximum retry attempts for API calls
# Set to 3 because:
# - API typically recovers within 3 attempts
# - Higher values cause unacceptable user wait times
# - Exponential backoff means 3 attempts = ~7 seconds total
MAX_RETRIES = 3
# Request timeout in seconds
# Set to 30 because:
# - API SLA guarantees response within 20 seconds
# - 10 second buffer prevents false timeouts
# - Longer timeouts risk resource exhaustion
TIMEOUT = 30
Script Execution vs. Reference
Clarify whether Claude should execute scripts or use them as reference patterns.
Validation Scripts
Create validation scripts with explicit, actionable error messages for critical operations.
MCP Tools Integration
When referencing MCP (Model Context Protocol) tools, always use fully qualified names.
Fully Qualified Names
MCP tools must be referenced with the server name prefix:
✓ Correct:
Use the `DatabaseServer:search_database` tool to find records.
Use the `FileServer:list_files` tool to see available files.
Validation Checklist
Scripts and code checklist:
- Scripts included only for critical/complex/repeated operations
- Error messages are specific and actionable
- Error messages include context and solutions
- All error conditions explicitly handled
- Dependencies documented with versions and purposes
- File paths use forward slashes (cross-platform)
- Configuration values explained (no magic numbers)
- Clear indication whether to execute or reference scripts
- Validation scripts provide comprehensive error reports
- MCP tools referenced with fully qualified names (ServerName:tool_name)