Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .claude/skills/n8n-export/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: n8n-export
description: Export all workflows from the local n8n instance into version-controlled JSON under apps/automation/workflows/. Use when the user asks to export, pull, snapshot, or sync workflows from the local n8n.
---

# n8n-export

Fetches every workflow from the local n8n instance via the REST API and writes each one to `apps/automation/workflows/<slug>/workflow.json` with instance-specific fields stripped for clean diffs.

## Preconditions

- n8n is running locally (`pnpm --filter automation n8n:ps` shows it).
- `apps/automation/.env` has `N8N_API_KEY` set. If missing, stop and direct the user to create one at <http://localhost:5678/settings/api> and paste into `.env`.

## Steps

1. **Pre-flight checks:**
```bash
grep -E '^N8N_API_KEY=.+' apps/automation/.env >/dev/null || echo 'MISSING N8N_API_KEY'
curl -sf http://localhost:5678/healthz >/dev/null || echo 'n8n not reachable'
```

2. **Run the export:**
```bash
pnpm --filter automation workflows:export
```

3. **Report the summary** to the user (added / updated / removed / skipped-with-notes counts printed by the script).

## What's stripped

Instance-specific fields (`id`, `versionId`, `createdAt`, `updatedAt`, `triggerCount`, `active`, `shared`, `meta`, `pinData`) are removed before writing. Tag IDs/timestamps are stripped too; tag names are kept.

## Preserved across exports

If `apps/automation/workflows/<slug>/README.md` exists and is non-empty, the script will NOT delete that directory even if the workflow has been removed from n8n. It warns instead, so you notice the dangling directory and can resolve it intentionally.

## Credentials

Credentials are never exported. Only the reference (name + id) appears in the JSON; secrets stay in n8n's encrypted store.
38 changes: 38 additions & 0 deletions .claude/skills/n8n-import/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: n8n-import
description: Import workflows from apps/automation/workflows/ into the local n8n instance. Use when the user asks to import, push, load, or sync workflow JSON files to the local n8n.
---

# n8n-import

Reads every `apps/automation/workflows/<slug>/workflow.json` and creates or updates the matching workflow on the local n8n instance. Matching is by workflow `name`.

## Preconditions

- n8n is running locally.
- `apps/automation/.env` has `N8N_API_KEY` set.

## Steps

1. **Pre-flight checks:**
```bash
grep -E '^N8N_API_KEY=.+' apps/automation/.env >/dev/null || echo 'MISSING N8N_API_KEY'
curl -sf http://localhost:5678/healthz >/dev/null || echo 'n8n not reachable'
```

2. **Run the import:**
```bash
pnpm --filter automation workflows:import
```

3. **Report the summary** to the user (created / updated / failed counts).

## Behavior

- **Match by name:** if a workflow with the same `name` already exists on the instance, it's updated in place via `PUT /api/v1/workflows/{id}`. The instance-side id and any activations are preserved.
- **Imported inactive:** the `active` field is stripped on export, so nothing is auto-activated on import. The user activates workflows manually in the UI.
- **Credentials:** dangling credential references are warned per-node. Recreate the credentials in the n8n UI to clear the warning — secrets are never in the JSON.

## Sanitization

Only whitelisted fields (`name`, `nodes`, `connections`, `settings`, `staticData`) are sent to the API. Tags aren't associated on import (n8n manages tag links via a separate endpoint; that's intentionally out of scope for now).
38 changes: 38 additions & 0 deletions .claude/skills/n8n-restart/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
name: n8n-restart
description: Restart the local n8n automation stack, preserving whatever profile (plain or mcp) is currently running. Use when the user asks to restart, reload, or reboot n8n.
---

# n8n-restart

Restarts the running services in place. This is faster than `down`/`up` because volumes stay mounted. It also preserves the currently active compose profile — if `n8n-mcp` was up, it stays up.

## Steps

1. **Detect whether the mcp profile is active:**
```bash
cd apps/automation
if ./scripts/compose.sh ps --services --status running | grep -q '^n8n-mcp$'; then
MCP_RUNNING=1
else
MCP_RUNNING=0
fi
```

2. **Restart the appropriate set of services:**
```bash
if [ "$MCP_RUNNING" = "1" ]; then
pnpm --filter automation n8n:restart:mcp
else
pnpm --filter automation n8n:restart
fi
```

3. **Verify:**
```bash
pnpm --filter automation n8n:ps
```

## Notes

- If nothing is currently running, `n8n-restart` will do nothing useful. Use `n8n-start` to bring the stack up instead.
55 changes: 55 additions & 0 deletions .claude/skills/n8n-start/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
name: n8n-start
description: Start the local n8n instance for the Strapi community hub. Use when the user asks to start, launch, bring up, or run n8n or the automation stack. Pass --mcp to also bring up n8n-mcp (requires N8N_API_KEY and MCP_AUTH_TOKEN in .env).
---

# n8n-start

Starts the n8n container(s) defined in `apps/automation/docker-compose.yml` via the engine-agnostic `scripts/compose.sh` wrapper (autodetects Docker or Podman).

## Steps

1. **Change to the automation directory.** All commands below run from `apps/automation/`.

2. **Ensure `.env` exists:**
```bash
test -f apps/automation/.env || cp apps/automation/.env.example apps/automation/.env
```
If it was just created, tell the user and point them at `apps/automation/.env.example`.

3. **Decide on MCP.** If the user's request didn't specify, ask whether to include `n8n-mcp`. Default is no.

4. **If starting with MCP, pre-check required env vars:**
```bash
grep -E '^(N8N_API_KEY|MCP_AUTH_TOKEN)=.+' apps/automation/.env
```
Both must be non-empty. If either is missing, stop and explain:
- `MCP_AUTH_TOKEN` — generate with `openssl rand -hex 32`.
- `N8N_API_KEY` — chicken-and-egg: start n8n first (without `--mcp`), create the key in the UI at <http://localhost:5678/settings/api>, paste it into `.env`, then run `n8n-start --mcp`.

5. **Start the stack:**
```bash
# without MCP
pnpm --filter automation n8n:up

# with MCP
pnpm --filter automation n8n:up:mcp
```

6. **Tail startup logs briefly** to confirm health:
```bash
pnpm --filter automation n8n:logs --tail=20 &
# (stop after a few seconds)
```
Or run `pnpm --filter automation n8n:ps` to confirm the containers are `running` / `healthy`.

7. **Report URLs to the user:**
- n8n UI: <http://localhost:5678>
- n8n-mcp endpoint (if started): <http://localhost:3100/mcp>

8. **If the `mcp` profile was started**, also remind the user that Claude Code must be registered against the MCP server to actually use it. Point them at the "Connecting Claude Code to the local n8n-mcp" section of `apps/automation/README.md`. The one-line summary:

- Project-scoped: `claude mcp add --scope project --transport http n8n-mcp http://localhost:3100/mcp --header "Authorization: Bearer \${MCP_AUTH_TOKEN}"` (writes `.mcp.json`; export `MCP_AUTH_TOKEN` before launching `claude`).
- User-scoped: same command without `--scope project` and with the literal token inlined.

Skip this reminder if the user has clearly registered it already (e.g. they're invoking an `n8n-*` tool and it's responding).
35 changes: 35 additions & 0 deletions .claude/skills/n8n-status/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
name: n8n-status
description: Show the health and status of the local n8n automation stack. Use when the user asks about n8n status, health, whether it is running, or which containers are up.
---

# n8n-status

Prints container status plus health probes for n8n and (if running) n8n-mcp.

## Steps

1. **List containers:**
```bash
pnpm --filter automation n8n:ps
```

2. **Probe n8n health:**
```bash
curl -sf -o /dev/null -w '%{http_code}\n' http://localhost:5678/healthz || echo 'unreachable'
```
A `200` means healthy. Anything else means n8n isn't ready (or isn't running).

3. **Probe n8n-mcp health (only if its container is running):**
```bash
curl -sf -o /dev/null -w '%{http_code}\n' http://localhost:3100/health || echo 'unreachable'
```

4. **Summarize** per service in one line each:
- engine (docker compose vs podman-compose, from `apps/automation/scripts/compose.sh`)
- container state (running / exited / healthy)
- local URL and probe result

## Notes

- If both probes fail but containers show as running, it usually means the service is still booting. Wait ~20s and retry, or inspect logs: `pnpm --filter automation n8n:logs`.
25 changes: 25 additions & 0 deletions .claude/skills/n8n-stop/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: n8n-stop
description: Stop the local n8n automation stack. Use when the user asks to stop, shut down, halt, or bring down n8n. Data in the n8n_data volume persists across stops.
---

# n8n-stop

Stops and removes the automation containers. The named volume `n8n_data` (workflows, credentials, settings) is preserved.

## Steps

1. **Run `down` from the workspace root:**
```bash
pnpm --filter automation n8n:down
```

2. **Confirm nothing is running:**
```bash
pnpm --filter automation n8n:ps
```

## Safety notes

- **Never pass `-v`** here. `down -v` deletes the `n8n_data` volume and all workflows/credentials would be lost. The `n8n:down` package script deliberately omits it.
- If the user asks to wipe state, confirm explicitly before running `./scripts/compose.sh down -v` from `apps/automation/`.
122 changes: 122 additions & 0 deletions .claude/skills/n8n-workflow-builder/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
name: n8n-workflow-builder
description: Domain-expertise guide for designing, building, validating, and modifying n8n workflows using the n8n-mcp tools. Use whenever the user asks to build, create, design, edit, or validate an n8n workflow. Requires the n8n-mcp server to be running (see n8n-start).
---

# n8n Workflow Builder (via n8n-mcp)

You are an n8n automation expert. Use the **n8n-mcp** tools to design, build, and validate workflows with maximum accuracy and minimum token cost.

## Core principles

1. **Silent execution.** Run tool calls without per-call commentary. Summarize only after the batch completes.
2. **Parallel when independent.** Fire off independent `search_*` / `get_node` / `validate_node` calls in a single tool-use block.
3. **Templates first.** With 2,700+ curated templates available, always try `search_templates` before building from scratch.
4. **Multi-level validation.** `validate_node(mode='minimal')` → `validate_node(mode='full')` → `validate_workflow`.
5. **Never trust defaults.** The #1 source of runtime failures. Explicitly set every parameter that controls node behavior.

## Process

1. **Bootstrap** — `tools_documentation()` once, to pull current best-practice guidance from the MCP server.

2. **Template discovery** (parallel when searching multiple axes):
- `search_templates({searchMode:'by_metadata', complexity:'simple', maxSetupMinutes:30})`
- `search_templates({searchMode:'by_task', task:'webhook_processing'})`
- `search_templates({searchMode:'by_nodes', nodeTypes:['n8n-nodes-base.slack']})`
- `search_templates({query:'slack notification'})` for keyword search.

3. **Node discovery** (if no suitable template):
- `search_nodes({query:'...', includeExamples:true})` — returns real configs from templates.
- Before configuring, present the intended architecture to the user for approval.

4. **Configuration** (parallel for multiple nodes):
- `get_node({nodeType, detail:'standard', includeExamples:true})` — default.
- `detail:'minimal'` (~200 tokens) for quick metadata, `detail:'full'` (~3-8k tokens) only when needed.
- `mode:'search_properties', propertyQuery:'auth'` to locate a specific property.
- `mode:'docs'` for the human-readable node docs.

5. **Node validation** (parallel):
- `validate_node({nodeType, config, mode:'minimal'})` — quick required-fields check.
- `validate_node({nodeType, config, mode:'full', profile:'runtime'})` — full with auto-fixes.
- Fix every error before continuing.

6. **Build:**
- Using a template: `get_template(id, {mode:'full'})`. **Attribution is mandatory** — always cite the template author and link: `Based on template by **<author.name>** (@<username>). View: <url>`.
- Set every meaningful parameter explicitly. Wire nodes correctly. Add error handling. Use n8n expression syntax (`$json`, `$node["Name"].json`).
- Avoid the **Code node** unless no standard node fits.
- Remember: any node can be used as an AI agent tool, not just nodes marked as such.

7. **Workflow validation** (before deployment):
- `validate_workflow(workflow)` — full sweep.
- `validate_workflow_connections(workflow)` / `validate_workflow_expressions(workflow)` for targeted checks.

8. **Deployment** (if the n8n API is configured and the user wants it pushed):
- `n8n_create_workflow(workflow)` to deploy.
- `n8n_validate_workflow({id})` to post-check.
- `n8n_update_partial_workflow({id, operations:[...]})` — **always batch** multiple operations into one call.
- `n8n_test_workflow({workflowId})` to run it.

## Critical pitfalls

### `addConnection` requires four **separate string** parameters

```json
{
"type": "addConnection",
"source": "Source Node",
"target": "Target Node",
"sourcePort": "main",
"targetPort": "main"
}
```

Not an object, not a tuple — four discrete string fields. See [n8n-mcp issue #327](https://github.com/czlonkowski/n8n-mcp/issues/327).

### IF-node branches

`addConnection` on an IF node must specify `branch: "true"` or `branch: "false"`. Without it, both connections may land on the same output and the logic silently breaks.

```json
{ "type":"addConnection", "source":"If", "target":"OnTrue", "sourcePort":"main", "targetPort":"main", "branch":"true" }
{ "type":"addConnection", "source":"If", "target":"OnFalse", "sourcePort":"main", "targetPort":"main", "branch":"false" }
```

### Batch partial updates

One `n8n_update_partial_workflow` with an array of operations beats N calls. Don't split.

### Explicit parameters

```
BAD: { resource:"message", operation:"post", text:"hi" }
GOOD: { resource:"message", operation:"post", select:"channel", channelId:"C123", text:"hi" }
```

The "BAD" form fails at runtime because default selections aren't filled in.

## Popular node types (exact IDs)

Use `n8n-nodes-base.` for core nodes and `@n8n/n8n-nodes-langchain.` for LangChain nodes.

- `n8n-nodes-base.code` — JS/Python (avoid when possible)
- `n8n-nodes-base.httpRequest`
- `n8n-nodes-base.webhook`, `n8n-nodes-base.respondToWebhook`
- `n8n-nodes-base.set`, `n8n-nodes-base.merge`, `n8n-nodes-base.splitInBatches`
- `n8n-nodes-base.if`, `n8n-nodes-base.switch`
- `n8n-nodes-base.manualTrigger`, `n8n-nodes-base.scheduleTrigger`, `n8n-nodes-base.executeWorkflowTrigger`
- `n8n-nodes-base.googleSheets`, `n8n-nodes-base.gmail`, `n8n-nodes-base.telegram`
- `n8n-nodes-base.stickyNote` — documentation inside the canvas
- `@n8n/n8n-nodes-langchain.agent`, `@n8n/n8n-nodes-langchain.lmChatOpenAi`

## Response format

After a batch of tool calls, report concisely:

```
Created workflow: Webhook → Validate → Slack
- Trigger: POST /webhook/contact-form
- Validation: If email present → Slack #support
- All nodes validated (0 errors, 0 warnings)
```

Defer long explanations until asked.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ yarn-error.log*
# Misc
.DS_Store
*.pem

# Local scratch (specs, plans, ad-hoc notes — not committed)
tmp/

# Claude Code personal settings (permissions, env, hooks — not shared)
.claude/settings.json
.claude/settings.local.json
Loading
Loading