@timbenniks/rootnotes
v0.1.2
Published
CLI for Rootnotes plant care app — manage plants, log events, and access AI tools from the terminal
Maintainers
Readme
rootnotes
Command-line interface for Rootnotes, a calm plant care tracker. Manage plants, log care events, access AI tools, and export data — all from the terminal.
Install
npm install -g @timbenniks/rootnotesRequires Node.js 18 or later.
Authentication
Generate a token in the Rootnotes web app under Settings > AI Clients, then:
rootnotes auth loginYou'll be prompted to paste your token (must start with tnd_mcp_). The CLI validates it against the API, then stores it in ~/.rootnotes/config.json.
Alternative auth methods:
- Set
ROOTNOTES_TOKENas an environment variable - Pass
--token <token>on any command
Token resolution priority: --token flag > ROOTNOTES_TOKEN env var > stored config.
Auth commands
rootnotes auth login # Authenticate with a token
rootnotes auth logout # Remove stored credentials
rootnotes auth status # Show current auth status and validate tokenCommands
Plants
rootnotes plants list # List all plants
rootnotes plants get <id> # Get detailed plant info
rootnotes plants search <query> # Search by name, species, or location
rootnotes plants create --name "Monstera" \ # Create a new plant
--species "Monstera deliciosa" \
--location "Living room" \
--watering-days 7 \
--light bright_indirect
rootnotes plants update <id> --watering-days 7 # Update plant fields
rootnotes plants delete <id> # Delete a plant (hard delete, cascades)
rootnotes plants delete <id> --yes # Skip confirmation promptCreate/update options:
| Option | Description |
|--------|-------------|
| -n, --name <name> | Plant name (required for create) |
| --species <species> | Species name |
| --location <location> | Physical location |
| --notes <notes> | Notes about the plant |
| --watering-days <days> | Watering frequency in days |
| --light <level> | Light requirement: low, medium, bright_indirect, full_sun |
Events
rootnotes events list <plant-id> # List events (default: 20)
rootnotes events list <plant-id> --limit 50 # List more events
rootnotes events add <plant-id> --type watered # Log a care event
rootnotes events add <plant-id> --type fertilized \ # Event with note and date
--text "Half-strength liquid feed" \
--date 2026-03-20T10:00:00Z
rootnotes events delete <id> # Soft-delete an eventEvent types: watered, fertilized, repotted, soil_change, note, journal, growth
Add options:
| Option | Description |
|--------|-------------|
| -t, --type <type> | Event type (required) |
| --text <text> | Optional note text |
| --date <date> | Event date in ISO 8601 format (defaults to now) |
Insights
rootnotes insights overview # Account-wide stats and attention list
rootnotes insights summary <plant-id> # Per-plant summary and recent activity
rootnotes insights summary # Aggregate stats (no plant ID)The overview command uses the MCP plants_overview tool when available, falling back to the REST /api/insights endpoint.
AI tools (requires Pro)
All AI commands communicate via the MCP protocol and require a Pro subscription.
# Identify a plant from an image URL
rootnotes ai identify <image-url>
rootnotes ai identify <image-url> --hint "tropical, large leaves"
# Look up a care profile for a species
rootnotes ai care-profile "Monstera deliciosa"
# Apply a care profile to an existing plant
rootnotes ai set-care <plant-id> --species "Monstera deliciosa"
rootnotes ai set-care <plant-id> --species "Monstera deliciosa" --overwrite
# Analyze light conditions from an image
rootnotes ai light <image-url>
rootnotes ai light <image-url> --hint "south-facing window"
# Check if observed light matches a plant's requirements
rootnotes ai light-match --observed bright_indirect --required medium
rootnotes ai light-match --observed low --required bright_indirect --species "Ficus"
# Identify + create a plant in one command
rootnotes ai add-from-image <image-url> --name "Kitchen Fern" --location "Kitchen"Light levels: low, medium, bright_indirect, full_sun
Export
rootnotes export # Print all account data as JSON
rootnotes export -o my-data.json # Write to fileGlobal options
| Flag | Description |
|------|-------------|
| --json | Output as JSON (for piping to jq, scripts, etc.) |
| --no-color | Disable colored output |
| --api-url <url> | Override the API base URL (default: https://rootnotes.app) |
| --token <token> | Use a specific token instead of the stored one |
Token scopes
When generating a token, you can select which permissions to grant:
| Scope | Description |
|-------|-------------|
| plants:read | View plants and their details |
| plants:write | Create, update, and delete plants |
| events:write | Add and delete care events |
| insights:read | View analytics and summaries |
| account:export | Download all account data |
Configuration
Config file: ~/.rootnotes/config.json
{
"apiUrl": "https://rootnotes.app",
"token": "tnd_mcp_...",
"scopes": ["plants:read", "plants:write", "events:write"]
}Environment variables:
| Variable | Description |
|----------|-------------|
| ROOTNOTES_TOKEN | Override stored token |
| ROOTNOTES_API_URL | Override API base URL |
Error handling
The CLI provides friendly error messages for common issues:
| Error | Message |
|-------|---------|
| 401 | Authentication failed — run rootnotes auth login |
| 403 (scope) | Permission denied — regenerate token with required scopes |
| 403 (FEATURE_DISABLED) | Feature not available on your plan — requires Pro |
| 403 (PLANT_LIMIT_REACHED) | Plant limit reached — upgrade your plan |
| 404 | Resource not found |
| 429 | Rate limited — wait and retry |
AI-specific errors (ai_unavailable, ai_upstream_error, ai_invalid_response) are also surfaced with descriptive messages.
Output modes
By default, the CLI renders human-readable colored tables. Add --json to any command for structured JSON output suitable for scripting.
Table output uses color coding:
- Green: success, names, recent activity (today/yesterday)
- Yellow: moderate staleness (2–7 days)
- Red: stale (30+ days), delete confirmations
- Blue/magenta: event type indicators
Examples
# Quick morning watering workflow
rootnotes plants list --json | jq '.[] | select(.lastWatered == null) | .name'
rootnotes events add <plant-id> --type watered
# Export data as backup
rootnotes export -o "backup-$(date +%Y-%m-%d).json"
# Identify a plant from a photo URL
rootnotes ai identify "https://example.com/photo.jpg"
# Create a plant from a photo in one step
rootnotes ai add-from-image "https://example.com/photo.jpg" --name "New Fern" --location "Bathroom"
# Check auth status
rootnotes auth status
# Search and pipe to jq
rootnotes plants search "fern" --json | jq '.[].name'Development
cd cli
npm install
npm run dev # Watch mode (tsup)
npm run build # Production build
npm run test # Run tests (vitest)
npm run typecheck # Type checkArchitecture:
cli/
src/
bin/rootnotes.ts # Entry point
index.ts # Program setup, command registration
commands/
auth.ts # auth login/logout/status
plants.ts # plants list/get/search/create/update/delete
events.ts # events list/add/delete
insights.ts # insights overview/summary
ai.ts # ai identify/care-profile/set-care/light/light-match/add-from-image
export.ts # export
lib/
client.ts # REST API client (RootnotesClient)
mcp-client.ts # JSON-RPC 2.0 MCP client (McpClient)
config.ts # Config file management (~/.rootnotes/config.json)
errors.ts # Error types (CliError, ApiError, McpToolError) and formatting
output.ts # Table/JSON output formatting, date helpersThe CLI uses two API clients:
RootnotesClient— REST client for CRUD operations (plants, events, export, account)McpClient— JSON-RPC 2.0 client for AI tools and insights, communicating with/api/mcp
Both clients are lazy-initialized and share the same auth token.
License
MIT
