This project demonstrates a custom Claude skill approach for CLI tool integration, where structured tool definitions wrap CLI commands instead of using the generic bash tool.
User Request
↓
Claude Agent (agent.py)
↓
Custom Sentinel Skill (sentinel_skill.py)
├─ sentinel_find_closest tool
└─ sentinel_get_visual tool
↓
Sentinel CLI (sentinel/)
↓
NASA APIs
| Approach | Benefits | Drawbacks |
|---|---|---|
| Custom Skill (this project) | ✅ Type-safe tool inputs ✅ Semantic tool names ✅ Input validation before execution ✅ Better Claude understanding |
|
| Bash Tool (generic) | ✅ Simple, no wrapper ✅ Works with any command |
-
sentinel_skill.py: Custom tool definitions and executorSENTINEL_TOOLS: Tool schemas for ClaudeSentinelSkillExecutor: Wraps CLI command executioncreate_tool_handler(): Factory for tool handler function
-
agent.py: Example agent using the custom skill- Uses
SENTINEL_TOOLSinstead of bash tool - Handles tool execution loop
- Interactive CLI interface
- Uses
-
sentinel/: CLI implementation- Typer-based CLI commands
- Returns JSON output via
--jsonflag - Automatically loads .env file for NASA_API_KEY
# Install with UV (recommended)
uv pip install -e ".[agent]"
# Or with pip
pip install -e ".[agent]"
# Configure API keys
cp .env.example .env
# Edit .env and add your API keys:
# NASA_API_KEY=your_nasa_key_here
# ANTHROPIC_API_KEY=your_anthropic_key_here
# Both the CLI and agent will automatically load from .env fileNote: The project uses python-dotenv to automatically load .env file. You don't need to manually export environment variables if you use the .env file approach.
python agent.pyExample interaction:
You: What's the closest asteroid today?
Agent: The closest asteroid today is 2024 BX1, approaching at 2,340,000.5 miles...
You: Show me NASA's image from last week
Agent: Here's the Astronomy Picture of the Day...
from sentinel_skill import SENTINEL_TOOLS, create_tool_handler
import anthropic
client = anthropic.Anthropic()
tool_handler = create_tool_handler()
response = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=4096,
tools=SENTINEL_TOOLS, # Custom sentinel tools
messages=[{"role": "user", "content": "Find closest asteroid"}]
)
# Handle tool execution
if response.stop_reason == "tool_use":
for block in response.content:
if block.type == "tool_use":
result = tool_handler(block.name, block.input)
print(result)Find today's closest asteroid to Earth.
Input Schema:
{
"verbose": false // Optional: enable diagnostic output
}Output:
{
"status": "success",
"data": {
"asteroid": {
"name": "2024 BX1",
"distance_miles": 2340000.5,
"velocity_mph": 25000.3,
"approach_date": "2024-02-16T14:23:00Z"
}
},
"message": "Found closest asteroid: 2024 BX1"
}Get NASA Astronomy Picture of the Day for a date.
Input Schema:
{
"date": "2024-01-15", // Optional: YYYY-MM-DD format, defaults to today
"verbose": false // Optional: enable diagnostic output
}Output:
{
"status": "success",
"data": {
"visual": {
"date": "2024-01-15",
"url": "https://apod.nasa.gov/apod/image/...",
"title": "Orion Nebula in Infrared",
"description": "This stunning image...",
"media_type": "image"
}
},
"message": "Retrieved image for 2024-01-15"
}This approach aligns with the project's constitutional principles:
- Boundary: Business logic stays in CLI, skill only wraps execution
- Output Format: CLI returns structured JSON, skill passes through
- Rule of Discovery: Tool schemas serve as explicit contract (better than
--helpparsing)
The skill catches all exceptions and returns error responses in the standard CLIOutput format:
{
"status": "error",
"data": null,
"message": "Detailed error message here"
}This ensures Claude always receives structured output, even on failures.
Test the skill independently:
from sentinel_skill import create_tool_handler
handler = create_tool_handler()
# Test find-closest
result = handler("sentinel_find_closest", {})
print(result)
# Test get-visual
result = handler("sentinel_get_visual", {"date": "2024-01-15"})
print(result)- Implement CLI: Build
sentinel/package with Typer commands - Add Tests: Test skill executor and agent integration
- Enhance Tools: Add more parameters (date ranges, filters, etc.)
- Deploy: Package for distribution
See specs/001-sentinel-nasa-cli/ for complete planning documentation:
- plan.md - Implementation plan
- research.md - Technology decisions
- quickstart.md - Usage guide
- contracts/ - API contracts