{"skill":{"slug":"tandoor-cli","displayName":"Tandoor Recipe CLI","summary":"Manage recipes, meal plans, and shopping lists on a Tandoor Recipe Manager instance via CLI.","description":"---\nname: tandoor-recipe-cli\ndescription: Manage recipes, meal plans, and shopping lists on a Tandoor Recipe Manager instance via CLI.\nversion: 1.5.0\ncompatibility: \">=18\"\nlicense: MIT\nmetadata:\n  author: dcenatiempo\n  repository: https://github.com/dcenatiempo/tandoor-cli\n---\n\n## Tandoor CLI Skill\n\nThis skill provides AI agents with the ability to interact with a Tandoor Recipe Manager instance using the `tandoor-cli` command-line tool.\n\n### Prerequisites\n\nThe `tandoor-cli` tool must be installed and configured.\n\n**Version Compatibility:** This skill documentation corresponds to the version specified in the metadata above. Before using this skill:\n1. Verify your installed CLI version: `tandoor -V`\n2. Ensure the installed version matches the skill version to avoid unexpected behavior or missing commands\n3. If versions don't match, reinstall the CLI tool following the setup instructions in `references/SETUP.md`\n\nIf `tandoor -V` produces no valid version, see the setup instructions in `references/SETUP.md`.\n\n### Security & Permission Model\n\n**⚠️ IMPORTANT: This skill provides mutation authority over your Tandoor instance.**\n\n- **Read operations** (list, search, get, random) are safe and require no confirmation\n- **Write operations** (add, update, import) modify data but are typically reversible\n- **Destructive operations** (delete, clear, household management) require explicit user approval before execution\n- **Bulk operations** (shopping check --all, clear) affect multiple items and require confirmation\n- **Administrative operations** (household management, user assignment, invite creation) require privileged credentials and explicit approval\n\n**Token Security:**\n- Use the **least-privileged token** possible for your use case\n- Prefer read-only tokens if you only need to query recipes\n- Avoid using space-owner or admin tokens unless household management is required\n- Consider short-lived tokens (days/weeks) instead of long-lived tokens (years)\n- Store tokens securely and rotate them regularly\n- Revoke tokens immediately if compromised or no longer needed\n\n**Supply Chain:**\n- This skill uses the `tandoor-cli` npm package\n- Verify the package source before first use: https://www.npmjs.com/package/tandoor-cli\n- Review the package repository: https://github.com/dcenatiempo/tandoor-cli\n- **Recommended:** Pin to the specific version matching this skill (see version in metadata above) to avoid unexpected updates\n- Install pinned version: `npm install -g tandoor-cli@<version>` (replace `<version>` with the skill version)\n\n### Invocation\n\n```bash\ntandoor <command> [options]\n```\n\n### Output formats and deprecated flags\n\nCommands that print data accept **`--format text|json|api`** (default: `text`):\n\n| `--format` | Use for |\n|------------|---------|\n| `text` | Human-readable output (default) |\n| `json` | Slim JSON where supported (recipe add/update shape + `id` on `get`, `list`, `search`, `random`) |\n| `api` | Raw Tandoor API JSON |\n\n**Deprecated (output):** `--json` with no file path — alias for **`--format api`**; stderr warning. Do not use in new agent workflows.\n\n**Recommended (input):** `tandoor add --file recipe.json`, `tandoor update <id> --file patch.json`\n\n**Deprecated (input):** `tandoor add --json <file>`, `tandoor update <id> --json <file>` — still work with stderr warning.\n\n| Deprecated | Use instead |\n|------------|-------------|\n| `tandoor get 1 --json` | `--format api` (full) or `--format json` (slim, for edit round-trips) |\n| `tandoor list --json` | `--format api` |\n| `tandoor add --json recipe.json` | `--file recipe.json` |\n| `tandoor update 42 --json patch.json` | `--file patch.json` |\n\n### Commands\n\n#### Read Operations (Safe)\n\n**Recipes:**\n| Command | Description |\n|---|---|\n| `list [--limit N] [--page N] [--all]` | List recipes (default 20 per page, max 100) |\n| `search <query>` | Search recipes by keyword |\n| `get <id>` | Get full recipe details |\n| `random` | Get a random recipe |\n\n**Meal Plans:**\n| Command | Description |\n|---|---|\n| `mealplan list [--startdate DATE] [--enddate DATE]` | List meal plan entries (optionally filtered by date range) |\n\n**Shopping List:**\n| Command | Description |\n|---|---|\n| `shopping list` | List shopping list entries |\n\n**Food Ingredients:**\n| Command | Description |\n|---|---|\n| `food list [--limit N] [--page N] [--all] [--search TERM] [--ignored] [--onhand]` | List food ingredients |\n\n**Grocery Categories:**\n| Command | Description |\n|---|---|\n| `category list` | List all supermarket categories (sorted A-Z) |\n| `category uncategorised [--search TERM]` | List food items with no category assigned |\n\n**Cook Logs:**\n| Command | Description |\n|---|---|\n| `cooklog list [--recipe ID] [--limit N] [--page N] [--all] [--startdate YYYY-MM-DD] [--enddate YYYY-MM-DD] [--min-rating 1-5] [--max-rating 1-5]` | List cook log entries (sorted by most recent first) |\n| `cooklog ingredient <name> [--limit N] [--startdate YYYY-MM-DD] [--enddate YYYY-MM-DD] [--min-rating 1-5] [--max-rating 1-5]` | Find cook logs by ingredient name (e.g., \"when did we last have eggs?\") |\n\n**Households & Users:**\n| Command | Description |\n|---|---|\n| `household list` | List all households |\n| `household get <id>` | Get household details by ID |\n| `household users list` | List all users in the space |\n| `household users memberships` | List user-space memberships |\n| `household invite list` | List all invite links |\n\n#### Write Operations (Require Confirmation)\n\n| Command | Description | Approval Required |\n|---|---|---|\n| `add [--file file] [--interactive]` | Create a recipe (`--json <file>` deprecated) | ✓ Before execution |\n| `update <id> --file file` | Patch an existing recipe (`--json <file>` deprecated) | ✓ Before execution |\n| `import <url> [--dry-run]` | Import a recipe from a URL | ✓ Before execution |\n| `image <recipeId> <imagePath>` | Upload an image to a recipe | ✓ Before execution |\n| `mealplan add --recipe ID --date YYYY-MM-DD --meal-type N` | Add a meal plan entry | ✓ Before execution |\n| `shopping add --food NAME --amount N --unit UNIT` | Add a shopping list item | ✓ Before execution |\n| `shopping check <id>` | Mark a shopping item as checked | ✓ Before execution |\n| `food edit <id\\|name> --ignore-shopping <true\\|false>` | Edit a food's ignore_shopping flag | ✓ Before execution |\n| `food ignore <id\\|name> [--unset]` | Set or clear ignore_shopping by ID or name | ✓ Before execution |\n| `food onhand <id\\|name> [--unset]` | Set or clear the on-hand flag by ID or name | ✓ Before execution |\n| `category set <food-id\\|name> --category <name\\|id>` | Assign a grocery category to a food item | ✓ Before execution |\n| `category set <food-id\\|name> --unset` | Remove the category from a food item | ✓ Before execution |\n| `cooklog add --recipe ID --servings N [--rating 1-5] [--comment TEXT] [--date ISO8601]` | Add a cook log entry | ✓ Before execution |\n| `cooklog update <id> [--recipe ID] [--servings N] [--rating 1-5] [--comment TEXT] [--date ISO8601]` | Update a cook log entry | ✓ Before execution |\n\n#### Destructive Operations (Require Explicit Confirmation)\n\n| Command | Description | Approval Required |\n|---|---|---|\n| `delete <id> [--force]` | Delete a recipe | ✓✓ Explicit confirmation required |\n| `mealplan delete <id>` | Delete a meal plan entry | ✓✓ Explicit confirmation required |\n| `shopping clear [--force]` | Clear all checked items | ✓✓ Explicit confirmation (bulk operation) |\n| `shopping check --all` | Mark all items as checked | ✓✓ Explicit confirmation (bulk operation) |\n| `cooklog delete <id>` | Delete a cook log entry | ✓✓ Explicit confirmation required |\n\n#### Administrative Operations (Require Privileged Token + Explicit Confirmation)\n\n**Important:** Tandoor uses **households** to organize users and recipes. Users are added to households via **invite links** — you cannot create users directly via the API.\n\n> **Permission Requirements:** Household management commands require special permissions in Tandoor. Most operations need admin/staff privileges. The `household invite create` command specifically requires **space owner** authentication — even superusers or staff members will receive a 403 Permission Denied error if they're not the space owner. If you encounter permission errors, you must use the space owner's API token or contact your Tandoor administrator.\n\n| Command | Description | Approval Required |\n|---|---|---|\n| `household add <name>` | Create a new household | ✓✓ Admin token + explicit confirmation |\n| `household edit <id> --name <name>` | Rename a household | ✓✓ Admin token + explicit confirmation |\n| `household delete <id> [--force]` | Delete a household | ✓✓ Admin token + explicit confirmation |\n| `household users assign <user-space-id> <household-id>` | Assign user to household | ✓✓ Admin token + explicit confirmation |\n| `household invite create <household-id> [--email EMAIL] [--expires DATE] [--group-id ID]` | Create invite link | ✓✓ Space-owner token + explicit confirmation |\n| `household invite delete <id> [--force]` | Delete invite link | ✓✓ Admin token + explicit confirmation |\n\nRead commands accept **`--format json`** (slim, where supported) or **`--format api`** (raw). Deprecated: `--json` (same as `--format api`).\n\n### Agent Behavior Rules\n\n**Before executing any command, the agent MUST:**\n\n1. **For read operations:** Proceed without confirmation\n2. **For write operations:** Describe the action and wait for user approval\n3. **For destructive operations:** \n   - Clearly explain what will be deleted/modified\n   - Warn that the action cannot be easily reversed\n   - Wait for explicit user confirmation (e.g., \"yes, delete recipe 42\")\n4. **For bulk operations:**\n   - State how many items will be affected\n   - Wait for explicit confirmation\n5. **For administrative operations:**\n   - Verify the user has provided an admin/space-owner token\n   - Explain the scope of the change (e.g., \"this will move user X to household Y\")\n   - Wait for explicit confirmation\n\n**The agent MUST NOT:**\n- Execute delete, force, bulk, household, invite, or user-assignment commands without explicit user approval\n- Assume the user wants destructive actions even if implied by context\n- Use `--force` flags without explicit user instruction\n- Log or display the `TANDOOR_API_TOKEN` value in any output\n\n### Configuration\n\nThe CLI supports three configuration methods (in precedence order):\n\n1. **Environment variables** — `TANDOOR_URL` and `TANDOOR_API_TOKEN` in the current shell\n2. **Config file** — `~/.config/tandoor-cli/config.json` (created by `tandoor configure`)\n3. **`.env` file** — a `.env` file in the current working directory\n\nRun `tandoor configure` once to save credentials interactively.\n\n### Examples\n\n**Configure credentials:**\n```bash\ntandoor configure\n```\n\n**Read example — list recipes as JSON:**\n```bash\ntandoor list --limit 5 --format api\n```\n\n**Read example — get recipe for editing:**\n```bash\ntandoor get 42 --format json\n```\n\n**Write example — create a recipe from a JSON file:**\n```bash\n# Agent should first ask: \"I will create a new recipe from recipe.json. Proceed?\"\n# Only after user confirms:\ntandoor add --file recipe.json\n```\n\n### Recipe JSON Schema\n\nWhen creating recipes with `tandoor add --file <file>` (or deprecated `--json <file>`), the JSON file must conform to the following structure:\n\n**TypeScript Definition:**\n```typescript\ninterface RecipeCreatePayload {\n  name: string;                    // Required: Recipe name\n  description?: string;            // Optional: Recipe description\n  servings?: number;               // Optional: Number of servings\n  working_time?: number;           // Optional: Active cooking time in minutes\n  waiting_time?: number;           // Optional: Passive time (baking, marinating) in minutes\n  steps: StepCreatePayload[];      // Required: At least one step\n}\n\ninterface StepCreatePayload {\n  instruction: string;             // Required: Step instructions\n  order: number;                   // Required: Step order (1, 2, 3, ...)\n  ingredients: IngredientCreatePayload[];  // Required: Can be empty array\n}\n\ninterface IngredientCreatePayload {\n  food: { name: string };          // Required: Ingredient name\n  unit: { name: string } | null;   // Optional: Unit of measurement (null if not applicable)\n  amount: number;                  // Required: Quantity\n  note?: string;                   // Optional: Additional notes (e.g., \"finely chopped\")\n  order?: number | null;           // Optional: Order within the step\n}\n```\n\n**Example Recipe JSON:**\n```json\n{\n  \"name\": \"Scrambled Eggs\",\n  \"description\": \"Quick and easy scrambled eggs\",\n  \"servings\": 2,\n  \"working_time\": 5,\n  \"steps\": [\n    {\n      \"instruction\": \"Crack eggs into a bowl, add milk and salt. Whisk until well combined.\",\n      \"order\": 1,\n      \"ingredients\": [\n        {\n          \"food\": { \"name\": \"eggs\" },\n          \"unit\": { \"name\": \"whole\" },\n          \"amount\": 4\n        },\n        {\n          \"food\": { \"name\": \"milk\" },\n          \"unit\": { \"name\": \"tbsp\" },\n          \"amount\": 2\n        },\n        {\n          \"food\": { \"name\": \"salt\" },\n          \"unit\": null,\n          \"amount\": 1,\n          \"note\": \"to taste\"\n        }\n      ]\n    },\n    {\n      \"instruction\": \"Heat butter in a pan over medium heat. Pour in egg mixture and stir gently until cooked to desired consistency.\",\n      \"order\": 2,\n      \"ingredients\": [\n        {\n          \"food\": { \"name\": \"butter\" },\n          \"unit\": { \"name\": \"tbsp\" },\n          \"amount\": 1\n        }\n      ]\n    }\n  ]\n}\n```\n\n**Key Points for Agents:**\n- `name` and `steps` are required fields\n- Each step must have `instruction`, `order`, and `ingredients` (can be empty array)\n- Each ingredient must have `food.name` and `amount`\n- Use `null` for `unit` when no unit applies (e.g., \"to taste\", \"pinch\")\n- Common units: `g`, `kg`, `ml`, `l`, `cup`, `tbsp`, `tsp`, `whole`, `pinch`\n- Times are in minutes\n- Steps should be ordered sequentially (1, 2, 3, ...)\n\n**Destructive example — delete a recipe:**\n```bash\n# Agent should first ask: \"This will permanently delete recipe 42. This cannot be undone. Confirm deletion?\"\n# Only after explicit user confirmation:\ntandoor delete 42 --force\n```\n\n**Image example — upload an image to a recipe:**\n```bash\n# Agent should first ask: \"I will upload my-recipe-photo.jpg to recipe 42. Proceed?\"\n# Only after user confirms:\ntandoor image 42 ./my-recipe-photo.jpg\n```\n\n**Household example — create a household and generate an invite link:**\n```bash\n# Agent should first ask: \"I will create a new household named 'My Family'. This requires admin privileges. Proceed?\"\n# Only after user confirms:\ntandoor household add \"My Family\"\n\n# Agent should first ask: \"I will create an invite link for household 1. This requires space-owner token. Proceed?\"\n# Only after user confirms:\ntandoor household invite create 1 --email user@example.com --expires 2026-12-31\n```\n\n**Shopping list example — add items and check them off:**\n```bash\n# Agent should first ask: \"I will add flour (500g) to the shopping list. Proceed?\"\n# Only after user confirms:\ntandoor shopping add --food flour --amount 500 --unit g\n\n# Agent should first ask: \"This will mark ALL shopping items as checked. Confirm?\"\n# Only after explicit confirmation:\ntandoor shopping check --all\n```\n\n**Grocery category example — organise foods for a better shopping list:**\n```bash\n# Read example — see what categories exist:\ntandoor category list\n\n# Read example — find foods with no category yet:\ntandoor category uncategorised\ntandoor category uncategorised --search pasta\n\n# Agent should first ask: \"I will assign 'milk' to the Dairy category. Proceed?\"\n# Only after user confirms:\ntandoor category set milk --category Dairy\ntandoor category set \"olive oil\" --category Oils\ntandoor category set 42 --category \"Canned Goods\"   # by food ID\n\n# Agent should first ask: \"I will remove the category from 'milk'. Proceed?\"\n# Only after user confirms:\ntandoor category set milk --unset\n```\n\n**Cook log example — track when you cook a recipe:**\n```bash\n# Agent should first ask: \"I will add a cook log entry for recipe 42 (4 servings, rating 5). Proceed?\"\n# Only after user confirms:\ntandoor cooklog add --recipe 42 --servings 4 --rating 5\ntandoor cooklog add --recipe 42 --servings 4 --rating 5 --comment \"Kids loved it\"\n\n# Read example — list cook logs for a specific recipe:\ntandoor cooklog list --recipe 42 --format api\n\n# Read example — find when you last had eggs:\ntandoor cooklog ingredient eggs\n\n# Read example — count how many times you had chicken last month:\ntandoor cooklog ingredient chicken --startdate 2026-04-01 --enddate 2026-04-30\n\n# Read example — find highly-rated egg recipes (4-5 stars):\ntandoor cooklog ingredient eggs --min-rating 4\n\n# Read example — find poorly-rated recipes from last month (1-2 stars):\ntandoor cooklog list --startdate 2026-04-01 --enddate 2026-04-30 --max-rating 2\n\n# Agent should first ask: \"I will update cook log 2 with a new comment. Proceed?\"\n# Only after user confirms:\ntandoor cooklog update 2 --comment \"Next time add more garlic\"\n\n# Agent should first ask: \"This will delete cook log entry 2. Confirm?\"\n# Only after explicit confirmation:\ntandoor cooklog delete 2\n```\n\n### Installation & Setup\n\n**Before first use:**\n1. Verify the npm package: https://www.npmjs.com/package/tandoor-cli\n2. Review the source code: https://github.com/dcenatiempo/tandoor-cli\n3. **Recommended:** Install the pinned version matching this skill: `npm install -g tandoor-cli@<version>` (see version in metadata above)\n4. Generate a token with minimal required permissions (see SECURITY.md)\n5. Consider using a test Tandoor instance first\n\n### Reference\n\n- See `references/SETUP.md` for detailed setup documentation including authentication configuration\n- See `SECURITY.md` for comprehensive security guidelines and token management best practices\n","tags":{"latest":"1.5.0"},"stats":{"comments":0,"downloads":885,"installsAllTime":0,"installsCurrent":0,"stars":0,"versions":10},"createdAt":1777939600589,"updatedAt":1779130788715},"latestVersion":{"version":"1.5.0","createdAt":1779130756604,"changelog":"v1.5.0\n\n- Adds `--comment TEXT` to `cooklog add` and `cooklog update` commands for entering comments on cook logs.\n- `cooklog update` now allows updating individual fields without requiring all parameters, supporting partial updates.\n- No other significant changes; compatibility and security guidelines remain unchanged.","license":"MIT-0"},"metadata":null,"owner":{"handle":"dcenatiempo","userId":"s174qsh3740skgwa1m8x5xsgpd8641p7","displayName":"Devin Cenatiempo","image":"https://avatars.githubusercontent.com/u/29043782?v=4"},"moderation":null}