@n8n-as-code/n8nac 2.0.0-next.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,42 @@
1
+ # @n8n-as-code/n8nac
2
+
3
+ ## [2026.5.0](https://github.com/EtienneLescot/n8n-as-code/compare/@n8n-as-code/n8nac@v2026.4.1...@n8n-as-code/n8nac@v2026.5.0) (2026-03-31)
4
+
5
+ ### Features
6
+
7
+ * add integration tests for CLI instance management and update AI functionality ([f3131de](https://github.com/EtienneLescot/n8n-as-code/commit/f3131de6f74c28875e8264c5ac929291046cee7b))
8
+ * add agent-friendly instance management flows ([3d63571](https://github.com/EtienneLescot/n8n-as-code/commit/3d63571e1c5243e58a51a93b0c0b927946be86bf))
9
+ * extend instance library to plugins docs and integration tests ([3f97f54](https://github.com/EtienneLescot/n8n-as-code/commit/3f97f54869ddf99cd8c9b3837cf7ec94d35dccb5))
10
+
11
+ ### Bug Fixes
12
+
13
+ * address PR review feedback for instance config flows ([06f0298](https://github.com/EtienneLescot/n8n-as-code/commit/06f029828969da738b154cf65f64461c8bda5571))
14
+
15
+ ### Documentation
16
+
17
+ * align config flows across product surfaces ([d961f78](https://github.com/EtienneLescot/n8n-as-code/commit/d961f783e1b95022acdbf3f13ca0982520026619))
18
+
19
+ ## [2026.4.1](https://github.com/EtienneLescot/n8n-as-code/compare/@n8n-as-code/n8nac@v2026.4.0...@n8n-as-code/n8nac@v2026.4.1) (2026-03-30)
20
+
21
+ ### Bug Fixes
22
+
23
+ * make agent workflow testing and sync state resilient ([5850d07](https://github.com/EtienneLescot/n8n-as-code/commit/5850d07d8136ffb24c5106c7391b2d49d4dd2e5d))
24
+
25
+ ## [2026.4.0](https://github.com/EtienneLescot/n8n-as-code/compare/@n8n-as-code/n8nac@v2026.3.1...@n8n-as-code/n8nac@v2026.4.0) (2026-03-17)
26
+
27
+ ### Features
28
+
29
+ * scope OpenClaw n8n context via bundled skill ([abf1501](https://github.com/EtienneLescot/n8n-as-code/commit/abf15012e2d5f5cab9bd04fc930fe27b4fd48802))
30
+
31
+ ### Bug Fixes
32
+
33
+ * tighten getChildEnv() allowlist + add unit tests ([2846414](https://github.com/EtienneLescot/n8n-as-code/commit/28464143bfb3390d51db6303bb377783a2994cfb))
34
+ * prevent credential forwarding to child processes via explicit env filtering ([283d005](https://github.com/EtienneLescot/n8n-as-code/commit/283d0059a1fcf33d70ec27d4485333e4441be240))
35
+ * refresh generated OpenClaw skill output ([b1f1eac](https://github.com/EtienneLescot/n8n-as-code/commit/b1f1eacb7bf1a988e19f42bdc86bb9088691cbae))
36
+ * generate OpenClaw skill from shared SSOT ([b6678bd](https://github.com/EtienneLescot/n8n-as-code/commit/b6678bd45c7da338b5ea4b6d5082be8b6d5105d4))
37
+
38
+ ## [2026.3.1](https://github.com/EtienneLescot/n8n-as-code/compare/@n8n-as-code/n8nac@v2026.3.0...@n8n-as-code/n8nac@v2026.3.1) (2026-03-13)
39
+
40
+ ### Documentation
41
+
42
+ * align editor and integration release messaging ([e1d6198](https://github.com/EtienneLescot/n8n-as-code/commit/e1d6198c3c6c942afe024f34b4ad419005ed991c))
package/README.md ADDED
@@ -0,0 +1,170 @@
1
+ # @n8n-as-code/n8nac
2
+
3
+ **OpenClaw access to the standard `n8n-as-code` skills and workflow stack.**
4
+
5
+ Use OpenClaw to build, update, validate, and manage n8n workflows with the same `n8nac` CLI and AI context model used across the wider `n8n-as-code` project.
6
+
7
+ ## v2 migration note
8
+
9
+ Version 2 removes the facade-specific OpenClaw runtime tool path. The plugin now delegates instance, auth, project, tunnel, credential, and presentation operations to `n8n-manager`, while workspace sync context is stored through `n8nac workspace` in `~/.openclaw/n8nac/`.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ openclaw plugins install @n8n-as-code/n8nac
15
+ ```
16
+
17
+ If you previously installed `@n8n-as-code/openclaw-plugin`, remove the old install first so OpenClaw re-registers the plugin cleanly under `n8nac`:
18
+
19
+ ```bash
20
+ openclaw plugins uninstall n8nac
21
+ openclaw plugins install @n8n-as-code/n8nac
22
+ ```
23
+
24
+ Restart the gateway. Runtime access, project selection, workspace sync, and
25
+ workflow guidance are handled by the bundled `n8n-manager` and `n8n-architect`
26
+ skills through their documented shell commands.
27
+
28
+ ## Usage
29
+
30
+ Once the runtime and workspace are configured through the skills, talk to OpenClaw:
31
+
32
+ > "Create an n8n workflow that sends a Slack message when a GitHub issue is opened"
33
+
34
+ > "Pull workflow 42 and add an error handler to it"
35
+
36
+ > "What operations does the Google Sheets node support?"
37
+
38
+ The plugin keeps its prompt hook lightweight. OpenClaw uses the bundled
39
+ `n8n-manager` and `n8n-architect` skills for explicit n8n sessions. Those
40
+ skills use the same shell commands as Claude, Codex, Cursor, VS Code, and other
41
+ agents: `n8n-manager ...` and `n8nac ...`.
42
+
43
+ ## CLI commands
44
+
45
+ | Command | Description |
46
+ |---|---|
47
+ | `openclaw n8nac:status` | Show workspace status |
48
+
49
+ ## Workspace
50
+
51
+ All files live in `~/.openclaw/n8nac/`:
52
+
53
+ ```
54
+ ~/.openclaw/n8nac/
55
+ n8nac-config.json ← workspace project/sync overrides only
56
+ AGENTS.md ← lightweight agent bootstrap (written by n8nac update-ai)
57
+ .agents/skills/ ← portable n8n-manager + n8n-architect skills
58
+ workflows/ ← .workflow.ts files (your n8n workflows)
59
+ ```
60
+
61
+ Instances and API keys are not stored in this workspace. They live in the global
62
+ `n8n-manager` configuration under `~/.n8n-manager`.
63
+
64
+ ## Agent skills
65
+
66
+ The plugin does not register a facade-specific agent tool. Agents should use
67
+ the portable skills and shell commands directly:
68
+
69
+ ```bash
70
+ n8n-manager instances list
71
+ n8nac workspace status --json
72
+ n8nac list
73
+ n8nac pull <workflowId>
74
+ n8nac push <path-to-workflow.workflow.ts> --verify
75
+ n8nac skills node-info <nodeName>
76
+ ```
77
+
78
+ `AGENTS.md` is not a configuration source of truth. It points agents to the
79
+ local skills and to `n8nac workspace status --json`, which resolves the
80
+ effective context through the backend.
81
+
82
+ ## Local development
83
+
84
+ This section covers how to load the plugin from source during development so
85
+ that changes take effect immediately without an npm publish cycle.
86
+
87
+ ### 1. Link the plugin directory
88
+
89
+ OpenClaw's `--link` flag registers a local path instead of installing a copy.
90
+ jiti is used to run TypeScript directly, so no build step is needed.
91
+
92
+ ```bash
93
+ openclaw plugins install --link \
94
+ /home/etienne/repos/n8n-as-code/plugins/openclaw/n8n-as-code
95
+ ```
96
+
97
+ What this does:
98
+ - Adds the path to `plugins.load.paths` in `~/.openclaw/openclaw.json`
99
+ - Registers a `source: "path"` install record bound to the plugin ID `n8nac`
100
+ - No file copy — OpenClaw loads `index.ts` directly from the source tree
101
+
102
+ ### 2. Verify the plugin is registered
103
+
104
+ ```bash
105
+ openclaw plugins info n8nac
106
+ ```
107
+
108
+ You should see status `loaded`, the bundled skills, and the `n8nac:status` CLI
109
+ command. The plugin intentionally does not register a
110
+ facade-specific agent tool.
111
+
112
+ ### 3. Configure runtime access through skills
113
+
114
+ ```bash
115
+ n8n-manager auth set --url <url> --api-key-stdin
116
+ n8n-manager projects list
117
+ n8n-manager projects select <project-id-or-name>
118
+ n8nac workspace set-sync-folder workflows
119
+ n8nac update-ai
120
+ ```
121
+
122
+ The OpenClaw plugin does not own setup orchestration. It exposes lightweight
123
+ context and lets the portable skills manage global instances, secrets, projects,
124
+ workspace overrides, `AGENTS.md`, and `.agents/skills`.
125
+
126
+ ### 4. Iterate on the code
127
+
128
+ - Edit any `.ts` file in `plugins/openclaw/n8n-as-code/`
129
+ - **Restart the gateway** to reload: `openclaw stop && openclaw start` (or the
130
+ equivalent service restart on your setup)
131
+ - The `before_prompt_build` hook and CLI commands reload on
132
+ gateway start
133
+
134
+ ### 5. Check gateway logs
135
+
136
+ ```bash
137
+ tail -f ~/.openclaw/logs/openclaw-$(date +%Y-%m-%d).log | grep n8nac
138
+ ```
139
+
140
+ The plugin prefixes all `api.logger` calls with `[n8nac]`.
141
+
142
+ ### 6. Inspect the n8nac workspace
143
+
144
+ ```
145
+ ~/.openclaw/n8nac/
146
+ n8nac-config.json ← workspace project/sync overrides only
147
+ AGENTS.md ← lightweight bootstrap written by update-ai
148
+ .agents/skills/ ← portable skills written by update-ai
149
+ workflows/ ← .workflow.ts files
150
+ ```
151
+
152
+ To reset and redo setup from scratch:
153
+
154
+ ```bash
155
+ rm -rf ~/.openclaw/n8nac
156
+ n8nac workspace set-sync-folder workflows
157
+ n8nac update-ai
158
+ ```
159
+
160
+ ### 7. Unlink when done
161
+
162
+ ```bash
163
+ openclaw plugins uninstall n8nac
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Source
169
+
170
+ Part of the [n8n-as-code](https://github.com/EtienneLescot/n8n-as-code) monorepo.
package/index.ts ADDED
@@ -0,0 +1,137 @@
1
+ import { accessSync, constants, mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { N8N_FACADE_SETUP_MODES } from "@n8n-as-code/workflow-core";
4
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
5
+ import { registerN8nAcCli } from "./src/cli.js";
6
+ import { getWorkspaceDir, isWorkspaceInitialized, readWorkspaceBinding } from "./src/workspace.js";
7
+
8
+ // ---------------------------------------------------------------------------
9
+ // Lightweight prompt context
10
+ // ---------------------------------------------------------------------------
11
+
12
+ const SETUP_MODE_CONTEXT = N8N_FACADE_SETUP_MODES
13
+ .map((mode) => `- \`${mode.id}\`: ${mode.description}`)
14
+ .join("\n");
15
+
16
+ const BOOTSTRAP_CONTEXT = `\
17
+ ## n8n-as-code — Bootstrap
18
+
19
+ The n8n-as-code plugin is installed but the workspace has not been initialized yet.
20
+
21
+ **Tell the user:**
22
+ > "To start building n8n workflows, choose whether I should connect to your existing n8n access, let n8n-manager prepare runtime access, or stay in generation-only mode."
23
+
24
+ Supported facade runtime modes:
25
+ ${SETUP_MODE_CONTEXT}
26
+
27
+ For agent-driven flows, use the installed \`n8n-manager\` and \`n8n-architect\`
28
+ skills and their documented shell commands. Instance/auth/project management
29
+ belongs to \`n8n-manager\`; context-root overrides and workflow sync belong
30
+ to \`n8nac workspace\` and the n8n-as-code skills.
31
+ `;
32
+
33
+ function buildStatusHeader(workspaceDir: string): string {
34
+ const cfg = readWorkspaceBinding(workspaceDir);
35
+ return [
36
+ "## n8n-as-code Context Root Status",
37
+ "",
38
+ "**The context root is initialized. Do NOT infer effective n8n config from this prompt.**",
39
+ "",
40
+ `- Context root: \`${workspaceDir}\``,
41
+ `- Local overrides file: \`${join(workspaceDir, "n8nac-config.json")}\``,
42
+ `- Bootstrap file: \`${join(workspaceDir, "AGENTS.md")}\``,
43
+ "",
44
+ "Before n8n work, run `n8nac workspace status --json` from the context root and use the backend-resolved result.",
45
+ cfg.activeInstanceId || cfg.projectId || cfg.projectName || cfg.syncFolder
46
+ ? "The local overrides file exists, but n8n-manager plus n8nac backend resolution remains the only source of effective state."
47
+ : "The local overrides file is present but incomplete.",
48
+ ].join("\n");
49
+ }
50
+
51
+ function hasAgentsContext(workspaceDir: string): boolean {
52
+ const agentsPath = join(workspaceDir, "AGENTS.md");
53
+ try {
54
+ accessSync(agentsPath, constants.R_OK);
55
+ return true;
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+
61
+ export function buildPromptContext(workspaceDir: string): string {
62
+ if (!isWorkspaceInitialized(workspaceDir)) {
63
+ return BOOTSTRAP_CONTEXT;
64
+ }
65
+
66
+ const agentsPath = join(workspaceDir, "AGENTS.md");
67
+ const guidanceLines = hasAgentsContext(workspaceDir)
68
+ ? [
69
+ "",
70
+ "Detailed workflow-authoring guidance is intentionally scoped to the `n8n-architect` skill.",
71
+ "Only use that deeper n8n workflow context when the request is clearly about n8n workflow work.",
72
+ `When that happens, read \`${agentsPath}\` and the local \`${join(workspaceDir, ".agents", "skills")}\` skills.`,
73
+ ]
74
+ : [
75
+ "",
76
+ "Detailed workflow-authoring guidance is intentionally scoped to the `n8n-architect` skill, but the generated workspace AI context file (`AGENTS.md`) is missing.",
77
+ "If the user starts explicit n8n workflow work, use the n8n-manager and n8n-architect skills to configure access and regenerate `AGENTS.md` with `npx --yes n8nac update-ai` when needed.",
78
+ ];
79
+
80
+ return [
81
+ buildStatusHeader(workspaceDir),
82
+ ...guidanceLines,
83
+ "",
84
+ "For unrelated requests, ignore this plugin context.",
85
+ ].join("\n");
86
+ }
87
+
88
+ // ---------------------------------------------------------------------------
89
+ // Plugin
90
+ // ---------------------------------------------------------------------------
91
+
92
+ const n8nAcPlugin = {
93
+ id: "n8nac",
94
+ name: "n8n-as-code",
95
+ description:
96
+ "Create and manage n8n workflows from OpenClaw using n8n-as-code (n8nac). " +
97
+ "Guides through workspace initialization, workflow CRUD, and AI-powered node schema lookup.",
98
+
99
+ register(api: OpenClawPluginApi) {
100
+ const workspaceDir = getWorkspaceDir();
101
+
102
+ // Ensure the plugin workspace directory always exists.
103
+ mkdirSync(workspaceDir, { recursive: true });
104
+
105
+ // -- Context injection ---------------------------------------------------
106
+ // Keep default context lightweight; full workflow-authoring guidance lives
107
+ // in the bundled skills and the context-root AGENTS.md file.
108
+ api.on("before_prompt_build", () => {
109
+ return { prependContext: buildPromptContext(workspaceDir) };
110
+ });
111
+
112
+ // -- CLI status ----------------------------------------------------------
113
+ api.registerCli(
114
+ ({ program }) => registerN8nAcCli({ program, workspaceDir }),
115
+ { commands: ["n8nac:status"] },
116
+ );
117
+
118
+ // -- Service -------------------------------------------------------------
119
+ api.registerService({
120
+ id: "n8nac-context",
121
+ start: async () => {
122
+ if (isWorkspaceInitialized(workspaceDir)) {
123
+ if (hasAgentsContext(workspaceDir)) {
124
+ api.logger.info("[n8nac] Workspace ready — lightweight prompt context enabled; n8n skill available.");
125
+ } else {
126
+ api.logger.warn("[n8nac] Workspace ready, but AGENTS.md is missing or unreadable.");
127
+ }
128
+ } else {
129
+ api.logger.info("[n8nac] Workspace not initialized. Use the n8n-manager and n8n-architect skills to configure it.");
130
+ }
131
+ },
132
+ stop: async () => {},
133
+ });
134
+ },
135
+ };
136
+
137
+ export default n8nAcPlugin;
@@ -0,0 +1,19 @@
1
+ {
2
+ "id": "n8nac",
3
+ "name": "n8n-as-code",
4
+ "description": "Create and manage n8n workflows from OpenClaw. Uses n8n-manager for runtime setup and n8nac for workspace/workflow tools.",
5
+ "skills": [
6
+ "skills"
7
+ ],
8
+ "configSchema": {
9
+ "type": "object",
10
+ "additionalProperties": false,
11
+ "properties": {
12
+ "enabled": {
13
+ "type": "boolean",
14
+ "default": false,
15
+ "description": "Enable the n8n-as-code integration"
16
+ }
17
+ }
18
+ }
19
+ }
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@n8n-as-code/n8nac",
3
+ "version": "2.0.0-next.56",
4
+ "description": "OpenClaw plugin for n8n-as-code — create and manage n8n workflows from OpenClaw",
5
+ "keywords": [
6
+ "n8n",
7
+ "workflow",
8
+ "automation",
9
+ "openclaw",
10
+ "openclaw-plugin",
11
+ "n8nac"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/EtienneLescot/n8n-as-code.git",
16
+ "directory": "plugins/openclaw/n8n-as-code"
17
+ },
18
+ "license": "MIT",
19
+ "type": "module",
20
+ "scripts": {
21
+ "build": "npm run typecheck",
22
+ "clean": "rm -rf node_modules/.vitest",
23
+ "test": "vitest run",
24
+ "typecheck": "tsc --noEmit"
25
+ },
26
+ "dependencies": {
27
+ "@n8n-as-code/workflow-core": "0.1.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.0.0",
31
+ "openclaw": "^2026.2.26",
32
+ "typescript": "^5.8.0",
33
+ "vitest": "^1.6.1"
34
+ },
35
+ "files": [
36
+ "CHANGELOG.md",
37
+ "README.md",
38
+ "index.ts",
39
+ "openclaw.plugin.json",
40
+ "skills/",
41
+ "src/",
42
+ "tsconfig.json"
43
+ ],
44
+ "peerDependencies": {
45
+ "openclaw": ">=2026.2.0"
46
+ },
47
+ "openclaw": {
48
+ "extensions": [
49
+ "./index.ts"
50
+ ]
51
+ }
52
+ }
@@ -0,0 +1,379 @@
1
+ ---
2
+ name: n8n-architect
3
+ description: Use when the user explicitly wants to create, edit, validate, sync, or troubleshoot n8n workflows, asks about n8n nodes or automation, or wants to use n8n-as-code in the current context root.
4
+ ---
5
+
6
+ # n8n Architect
7
+
8
+ Use this skill for workflow engineering. Use the `n8n-manager` skill for instance, auth, runtime, tunnel, project-default, credential infrastructure, or workflow presentation work.
9
+
10
+ ## Context Root Protocol
11
+
12
+ - Treat the current context root as the directory containing `n8nac-config.json`, `AGENTS.md`, `.agents/skills`, and the workflow sync folder.
13
+ - Generated context root hint: not embedded. Use the shell launch directory or the workspace path explicitly given by the user.
14
+ - Before any n8n work, first run `npx --yes n8nac update-ai` from the context root, then read `AGENTS.md`. `update-ai` is designed to create or refresh the n8n-as-code block without destroying existing user or agent instructions.
15
+ - Use the exact `n8nac command` and `n8n-manager command` listed in `AGENTS.md`. Those context-root commands override the portable examples in this skill.
16
+ - Run every `npx --yes n8nac workspace ...`, `npx --yes n8nac list`, `pull`, `push`, `validate`, `test`, and `update-ai` command from the context root unless the user explicitly gives another context root.
17
+ - `AGENTS.md` is bootstrap context only, not a source of configuration truth.
18
+ - Do not infer instance, project, sync folder, or workflow directory from `AGENTS.md`.
19
+ - Before n8n work, resolve the effective context from the backend:
20
+
21
+ ```bash
22
+ npx --yes n8nac workspace status --json
23
+ ```
24
+
25
+ - Use the returned `workflowDir` for workflow files. Do not reconstruct it from `syncFolder`, `instanceIdentifier`, or `projectName`.
26
+ - Never write `n8nac-config.json` by hand. Use `npx --yes n8nac workspace ...` commands.
27
+
28
+ ## Bootstrap Order
29
+
30
+ 1. `cd` to the context root.
31
+ 2. Run `npx --yes n8nac update-ai`, then read `AGENTS.md`.
32
+ 3. Run `npx --yes n8nac workspace status --json`.
33
+ 4. If the context root is not ready, inspect instances with `n8n-manager instances list`.
34
+ 5. Reuse an existing instance when suitable.
35
+ 6. If no suitable instance exists, stop and ask the user whether they want to reuse/configure an existing instance, create a managed local n8n instance, or connect an existing/remote n8n instance. Do not create infrastructure by default. If the user chooses a managed local instance, ask separately whether they want a public tunnel.
36
+ 7. Ask for host/API key only for an explicitly remote or existing n8n instance.
37
+ 8. Configure context-root overrides with:
38
+
39
+ ```bash
40
+ npx --yes n8nac workspace pin-instance --instance-id <id>
41
+ npx --yes n8nac workspace set-sync-folder workflows
42
+ npx --yes n8nac workspace set-project --project-id <id> --project-name <name>
43
+ ```
44
+
45
+ For self-hosted n8n instances where the projects API is unavailable or returns 401/403, do not keep retrying project discovery. Use the standard personal project override unless the user gave another project:
46
+
47
+ ```bash
48
+ npx --yes n8nac workspace set-project --project-id personal --project-name Personal
49
+ ```
50
+
51
+ 9. Run `npx --yes n8nac update-ai` after changing context-root overrides when the facade does not do it automatically.
52
+
53
+ ## Sync Discipline
54
+
55
+ - Pull before reading or modifying an existing workflow.
56
+ - Push after every modification.
57
+ - Use `list` to inspect workflow IDs, file paths, and sync status.
58
+
59
+ ```bash
60
+ npx --yes n8nac list
61
+ npx --yes n8nac pull <workflowId>
62
+ npx --yes n8nac push <path-to-workflow.workflow.ts> --verify
63
+ ```
64
+
65
+ - `push` requires the full workflow file path, either absolute or context-root-relative. Do not pass a bare filename.
66
+ - For a new workflow, create the file inside the `workflowDir` returned by `workspace status --json`, then confirm it with `npx --yes n8nac list --local`.
67
+ - If push/pull reports a conflict, use explicit resolution commands. Do not overwrite remote changes blindly.
68
+ - `pull` and conflict resolution operate on a single workflow ID.
69
+ - `list` is the lightweight command that covers all workflows at once.
70
+ - If you skip pull, a later push can be rejected by optimistic concurrency control when the remote changed.
71
+
72
+ ## Conflict Handling
73
+
74
+ If push or pull reports a conflict, stop and inspect the conflict. Use explicit resolution commands only after choosing the intended direction:
75
+
76
+ ```bash
77
+ npx --yes n8nac resolve <workflowId> --mode keep-current
78
+ npx --yes n8nac resolve <workflowId> --mode keep-incoming
79
+ ```
80
+
81
+ - `keep-current` force-pushes the local version.
82
+ - `keep-incoming` force-pulls the remote version.
83
+ - Never silently force-push over a remote change.
84
+
85
+ ## Schema-First Research
86
+
87
+ Never guess n8n node parameters.
88
+
89
+ ```bash
90
+ npx --yes n8nac skills examples search "<workflow pattern>"
91
+ npx --yes n8nac skills search "<node or capability>"
92
+ npx --yes n8nac skills node-info <nodeName>
93
+ npx --yes n8nac skills validate <workflow.workflow.ts>
94
+ ```
95
+
96
+ - Use exact node `type` and valid `typeVersion` values from `node-info`.
97
+ - Use exact resource, operation, option, and parameter names from schema output.
98
+ - Do not invent parameters, operations, credential types, or CLI flags.
99
+ - Treat schema output as the absolute source of truth even if examples or memory disagree.
100
+ - Prefer the highest valid `typeVersion` returned by schema output.
101
+ - For fixed collections such as Switch/If rules, Wait form fields, or nested options, read the full `node-info` output before writing values.
102
+
103
+ ## Knowledge Commands
104
+
105
+ Use these commands instead of guessing:
106
+
107
+ ```bash
108
+ npx --yes n8nac skills search "<node or capability>"
109
+ npx --yes n8nac skills node-info <nodeName>
110
+ npx --yes n8nac skills node-schema <nodeName>
111
+ npx --yes n8nac skills docs "<topic>"
112
+ npx --yes n8nac skills guides "<topic>"
113
+ npx --yes n8nac skills examples search "<workflow pattern>"
114
+ npx --yes n8nac skills examples info <id>
115
+ npx --yes n8nac skills examples download <id>
116
+ ```
117
+
118
+ - Start with `examples search` when the user asks for a common automation pattern.
119
+ - Use examples to learn patterns, not as authority over current node schemas.
120
+ - If a command or flag is unfamiliar, run `npx --yes n8nac <subcommand> --help`; do not invent flags.
121
+
122
+ ## Workflow Authoring Rules
123
+
124
+ - Use TypeScript decorators from `@n8n-as-code/transformer`.
125
+ - Regular nodes connect with `source.out(0).to(target.in(0))`.
126
+ - AI sub-nodes connect with `.uses()`, never `.out().to()`.
127
+ - `ai_tool` and `ai_document` connections are arrays: `ai_tool: [this.Tool.output]`.
128
+ - Other AI connection types are single refs, such as `ai_languageModel: this.Model.output`.
129
+ - Check `node-info` for connection-dependent boolean flags before declaring `.uses()` connections.
130
+
131
+ Every `.workflow.ts` file starts with a `<workflow-map>` block. Read that map first, locate the property name you need, then read only the relevant class section.
132
+
133
+ ### Minimal Workflow Structure
134
+
135
+ ```typescript
136
+ import { workflow, node, links } from '@n8n-as-code/transformer';
137
+
138
+ @workflow({
139
+ name: 'Workflow Name',
140
+ active: false
141
+ })
142
+ export class MyWorkflow {
143
+ @node({
144
+ name: 'Descriptive Name',
145
+ type: '/* exact type from node-info */',
146
+ version: 4,
147
+ position: [250, 300]
148
+ })
149
+ MyNode = {
150
+ /* parameters from node-info */
151
+ };
152
+
153
+ @node({
154
+ name: 'Next Node',
155
+ type: '/* exact type from node-info */',
156
+ version: 3,
157
+ position: [520, 300]
158
+ })
159
+ NextNode = {};
160
+
161
+ @links()
162
+ defineRouting() {
163
+ this.MyNode.out(0).to(this.NextNode.in(0));
164
+ }
165
+ }
166
+ ```
167
+
168
+ ### Expression Syntax
169
+
170
+ - Prefer modern expressions: `{{ $json.fieldName }}`.
171
+ - Use specific-node expressions when needed: `{{ $('Node Name').item.json.field }}`.
172
+ - Avoid legacy `$node["Name"].json.field` unless you are preserving an existing workflow and have a reason.
173
+ - In Switch/If comparisons, `value1` is the expression being evaluated and `value2` is the literal comparison value.
174
+
175
+ ### Node Naming
176
+
177
+ - Use descriptive names such as `Get Customers`, `Send Slack Alert`, or `Normalize Payload`.
178
+ - Avoid names like `Node1`, `HTTP Request`, or `Code` when a more specific name is available.
179
+ - Connection references must match the exact node property names in the TypeScript class.
180
+
181
+ ## Reading Workflow Files Efficiently
182
+
183
+ Use the `<workflow-map>` block as the index before loading large workflow files.
184
+
185
+ ```typescript
186
+ // <workflow-map>
187
+ // Workflow : My Workflow
188
+ // Nodes : 12 | Connections: 14
189
+ //
190
+ // NODE INDEX
191
+ // Property name Node type (short) Flags
192
+ // ScheduleTrigger scheduleTrigger
193
+ // AgentGenerateApplication agent [AI] [creds]
194
+ // OpenaiChatModel lmChatOpenAi [creds] [ai_languageModel]
195
+ // Memory memoryBufferWindow [ai_memory]
196
+ // GithubCheckBranchRef httpRequest [onError->out(1)]
197
+ //
198
+ // ROUTING MAP
199
+ // ScheduleTrigger
200
+ // -> Configuration
201
+ // -> BuildProfileSources -> LoopOverProfileSources
202
+ //
203
+ // AI CONNECTIONS
204
+ // AgentGenerateApplication.uses({ ai_languageModel: OpenaiChatModel, ai_memory: Memory })
205
+ // </workflow-map>
206
+ ```
207
+
208
+ Navigation rule:
209
+
210
+ 1. Read `<workflow-map>` first.
211
+ 2. Locate the property name you need.
212
+ 3. Search for that property in the file.
213
+ 4. Read only the relevant node or routing section unless broader context is required.
214
+
215
+ ## AI And LangChain Node Rules
216
+
217
+ AI sub-nodes are not regular data-flow nodes.
218
+
219
+ ```typescript
220
+ @links()
221
+ defineRouting() {
222
+ this.ChatTrigger.out(0).to(this.AiAgent.in(0));
223
+
224
+ this.AiAgent.uses({
225
+ ai_languageModel: this.OpenaiModel.output,
226
+ ai_memory: this.Memory.output,
227
+ ai_outputParser: this.OutputParser.output,
228
+ ai_tool: [this.SearchTool.output],
229
+ });
230
+ }
231
+ ```
232
+
233
+ - Use `.uses()` for language models, memory, tools, parsers, embeddings, vector stores, retrievers, and other AI sub-nodes.
234
+ - Never connect AI sub-nodes with `.out().to()`.
235
+ - `ai_tool` and `ai_document` must be arrays.
236
+ - Most other AI connection types are single refs.
237
+ - Some nodes require boolean flags to expose AI ports or gated parameters. Check `node-info` before declaring `.uses()`.
238
+
239
+ ## Common Mistakes To Avoid
240
+
241
+ - Wrong node type: use the exact full type returned by schema output, including package prefix when provided.
242
+ - Outdated or non-existent typeVersion: use a value from the schema output.
243
+ - Invalid operation/resource value: use exact option values from the schema.
244
+ - Mismatched resource and operation: each resource enables its own operations.
245
+ - Guessing nested structures: fixed collections have exact shapes.
246
+ - Wrong connection names: match TypeScript property names exactly.
247
+ - Inventing nodes, credentials, operations, or parameters.
248
+ - Connecting AI sub-nodes with `.out().to()`.
249
+ - Using `ai_tool: this.Tool.output` instead of `ai_tool: [this.Tool.output]`.
250
+ - Inverting Switch/If `value1` and `value2`.
251
+ - Using old Wait form structures such as `formFieldsUi.fieldItems` when the current schema expects `formFields: { values: [...] }`.
252
+ - Passing a bare filename to `push`.
253
+ - Treating Class A runtime/config gaps as workflow-code bugs.
254
+
255
+ ## Verify, Test, And Present
256
+
257
+ After pushing:
258
+
259
+ ```bash
260
+ npx --yes n8nac verify <workflowId>
261
+ npx --yes n8nac test-plan <workflowId> --json
262
+ ```
263
+
264
+ For webhook, chat, or form workflows, prefer the production test sequence:
265
+
266
+ ```bash
267
+ npx --yes n8nac workflow activate <workflowId>
268
+ npx --yes n8nac test <workflowId> --prod
269
+ ```
270
+
271
+ - Class A configuration gaps require user/config action, not workflow rewrites.
272
+ - Runtime-state issues such as unarmed test webhooks are not workflow-code bugs.
273
+ - Class B wiring errors are fixable in the workflow file.
274
+ - Stop after two repeated failures with the same diagnostic.
275
+
276
+ ## Workflow Presentation Contract
277
+
278
+ `presentWorkflowResult` is the standard way to show a workflow to the user. It is part of the workflow authoring loop, even though the command lives in n8n-manager.
279
+
280
+ Run it whenever one of these is true:
281
+
282
+ - you created a workflow;
283
+ - you modified and pushed a workflow;
284
+ - you ran or tested a workflow and the user needs to inspect it;
285
+ - the user asks to show, open, present, display, or give the URL/link for a workflow.
286
+
287
+ ```bash
288
+ n8n-manager presentWorkflowResult --workflow-id <workflowId> --workspace-root <contextRoot>
289
+ ```
290
+
291
+ Rules:
292
+
293
+ - Do not manually construct n8n workflow URLs.
294
+ - Do not return an internal local n8n URL when a presentation URL is available.
295
+ - Use the `url` returned by `presentWorkflowResult` as the user-facing URL.
296
+ - If you do not know the workflow ID, run `npx --yes n8nac list` first and select the matching workflow.
297
+ - If `presentWorkflowResult` fails, report the backend diagnostic and then provide the best direct n8n URL only as a fallback.
298
+ - Do this before the final response when the task created, changed, pushed, ran, or explicitly asks to show a workflow.
299
+
300
+ ### Testability Protocol
301
+
302
+ For webhook, chat, or form workflows:
303
+
304
+ 1. Push with verification when possible.
305
+ 2. Run `test-plan` to inspect trigger type, endpoint, and suggested payload.
306
+ 3. Activate the workflow.
307
+ 4. Test with `--prod` by default.
308
+
309
+ ```bash
310
+ npx --yes n8nac push <path-to-workflow.workflow.ts> --verify
311
+ npx --yes n8nac test-plan <workflowId> --json
312
+ npx --yes n8nac workflow activate <workflowId>
313
+ npx --yes n8nac test <workflowId> --prod
314
+ ```
315
+
316
+ Use bare `npx --yes n8nac test <workflowId>` only when a test URL was intentionally armed in the n8n editor.
317
+
318
+ For GET/HEAD webhooks that read from `$json.query`, prefer:
319
+
320
+ ```bash
321
+ npx --yes n8nac test <workflowId> --query '{"key":"value"}' --prod
322
+ ```
323
+
324
+ ## Execution Debugging
325
+
326
+ If a webhook returns success but the workflow behavior is wrong, inspect executions instead of guessing:
327
+
328
+ ```bash
329
+ npx --yes n8nac execution list --workflow-id <workflowId> --limit 5 --json
330
+ npx --yes n8nac execution get <executionId> --include-data --json
331
+ ```
332
+
333
+ - A successful HTTP trigger only means n8n accepted the request.
334
+ - The execution can still fail later inside the workflow.
335
+ - Use execution data to identify the failing node and real payload shape.
336
+
337
+ ## Credential Workflow
338
+
339
+ When a workflow is blocked by missing credentials, resolve the credential gap without rewriting unrelated workflow logic.
340
+
341
+ ```bash
342
+ npx --yes n8nac workflow credential-required <workflowId> --json
343
+ npx --yes n8nac credential schema <type>
344
+ npx --yes n8nac credential list --json
345
+ npx --yes n8nac credential create --type <type> --name <name> --file cred.json --json
346
+ npx --yes n8nac workflow activate <workflowId>
347
+ ```
348
+
349
+ - `workflow credential-required` exits non-zero when at least one credential is missing. Treat that as a signal to act, not as a workflow-code failure.
350
+ - Use `credential schema` to discover required fields.
351
+ - Ask the user for secret values when needed.
352
+ - Prefer `--file` for credential creation. Do not pass secrets inline in shell arguments.
353
+ - Do not print API keys or credential secret values back to the user.
354
+ - If credential creation fails, read the validation message and change the payload before retrying.
355
+
356
+ ## Operating Loop
357
+
358
+ For most workflow tasks:
359
+
360
+ 1. Resolve context with `workspace status --json`.
361
+ 2. Read `workflowDir` from the backend response.
362
+ 3. Inspect existing workflows with `list`.
363
+ 4. Pull before editing an existing workflow.
364
+ 5. Search examples and schemas.
365
+ 6. Edit or create the `.workflow.ts` file.
366
+ 7. Validate locally.
367
+ 8. Push with `--verify`.
368
+ 9. Test if the workflow is HTTP-triggered.
369
+ 10. Inspect executions when behavior is unclear.
370
+ 11. Present the final workflow link with `presentWorkflowResult`.
371
+
372
+ ## Response Discipline
373
+
374
+ - Explain concrete actions and command results, not generic capability.
375
+ - When the user asks for an URL or visual inspection of a workflow, run `presentWorkflowResult` instead of composing a URL manually.
376
+ - If setup is missing, use `n8n-manager` for instance/auth/runtime and `n8nac workspace ...` for context-root overrides.
377
+ - Do not ask for host/API key until existing n8n-manager instances have been inspected.
378
+ - Do not tell the user to run setup commands when you can run non-interactive commands yourself.
379
+ - Stop after two repeated failures with the same diagnostic and report the backend error clearly.
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: n8n-manager
3
+ description: Use when the user needs n8n instance, runtime, tunnel, auth, project, credential, or workflow presentation management through n8n-manager.
4
+ ---
5
+
6
+ # n8n Manager
7
+
8
+ Use this skill for global n8n instance management. `n8n-manager` is the source of truth for instances, runtime state, tunnels, API keys, managed owner credentials, default projects, and workflow presentation links.
9
+
10
+ ## Responsibility Boundary
11
+
12
+ - Generated context root hint: not embedded. Use the shell launch directory or the workspace path explicitly given by the user.
13
+ - If `n8nac` is available, first run `npx --yes n8nac update-ai` from the context root, then read `AGENTS.md`. `update-ai` is designed to create or refresh the n8n-as-code block without destroying existing user or agent instructions.
14
+ - Use the exact `n8n-manager command` and `n8nac command` listed in `AGENTS.md` when present. Those context-root commands override the portable examples in this skill.
15
+ - Use `n8n-manager` for global instance, auth, runtime, tunnel, project-default, credential, and workflow-presentation operations.
16
+ - Use `npx --yes n8nac workspace ...` only for context-root overrides such as pinned instance, sync folder, and project override.
17
+ - Use `npx --yes n8nac` workflow commands only after the effective context is ready.
18
+ - Never edit `n8nac-config.json`, `~/.n8n-manager`, or n8n-manager secret files by hand.
19
+
20
+ ## Core Commands
21
+
22
+ Inspect existing instances before changing state:
23
+
24
+ ```bash
25
+ n8n-manager instances list
26
+ n8n-manager instances --help
27
+ n8n-manager config get
28
+ ```
29
+
30
+ Do not invent n8n-manager subcommands. In particular, `instances create` and `--type local` are not valid. Use `instances add --mode ...` exactly as documented by `instances --help`.
31
+
32
+ ## Unconfigured Context Root
33
+
34
+ When the context root is not configured and no suitable existing instance is available, stop and ask the user to choose. Do not create infrastructure by default.
35
+
36
+ Present these choices clearly:
37
+
38
+ - use an existing n8n-manager instance if one is available;
39
+ - create a new managed local Docker n8n instance;
40
+ - connect an existing or remote n8n instance with user-provided credentials.
41
+
42
+ If the user chooses a managed local Docker instance, ask the tunnel question separately:
43
+
44
+ - without public tunnel: local n8n only, suitable for normal UI/API workflow work;
45
+ - with public tunnel: exposes the instance through a public URL, useful for webhooks/forms/chat triggers and remote callbacks.
46
+
47
+ Do not enable, refresh, or start a public tunnel unless the user explicitly requested public access, webhook testing, or approved the tunnel option. If public access is not needed, create/start the managed instance without `--tunnel`.
48
+
49
+ ## Confirmed Setup Commands
50
+
51
+ Only run these commands after the user has explicitly chosen the corresponding option.
52
+
53
+ Managed local Docker without public tunnel:
54
+
55
+ ```bash
56
+ n8n-manager instances add --name <name> --mode managed-local-docker
57
+ n8n-manager instances setup <id-or-name>
58
+ n8n-manager instances start <id-or-name>
59
+ n8n-manager instances status <id-or-name>
60
+ ```
61
+
62
+ Managed local Docker with public tunnel:
63
+
64
+ ```bash
65
+ n8n-manager instances add --name <name> --mode managed-local-docker --tunnel
66
+ n8n-manager instances setup <id-or-name> --tunnel
67
+ n8n-manager instances start <id-or-name>
68
+ n8n-manager instances tunnel status <id-or-name>
69
+ ```
70
+
71
+ Remote or existing instances require user-provided credentials. Prefer stdin for API keys:
72
+
73
+ ```bash
74
+ n8n-manager auth set --url <url> --api-key-stdin --name <name>
75
+ n8n-manager auth test --instance <id-or-name>
76
+ ```
77
+
78
+ Project selection is instance-level unless the context root explicitly needs a workspace override:
79
+
80
+ ```bash
81
+ n8n-manager projects list --instance <id-or-name>
82
+ n8n-manager projects select <project-id-or-name> --instance <id-or-name>
83
+ ```
84
+
85
+ Self-hosted n8n may not expose the projects API or may return 401/403. In that case, do not retry project discovery. Use the n8n-architect workspace override path with the standard personal project unless the user gave another project:
86
+
87
+ ```bash
88
+ npx --yes n8nac workspace set-project --project-id personal --project-name Personal
89
+ ```
90
+
91
+ Runtime and tunnel operations are per instance:
92
+
93
+ ```bash
94
+ n8n-manager instances start <id-or-name>
95
+ n8n-manager instances stop <id-or-name>
96
+ n8n-manager instances restart <id-or-name>
97
+ n8n-manager instances tunnel status <id-or-name>
98
+ n8n-manager instances tunnel start <id-or-name>
99
+ n8n-manager instances tunnel refresh <id-or-name>
100
+ ```
101
+
102
+ Present workflow results after creating, modifying, pushing, or running a workflow:
103
+
104
+ ```bash
105
+ n8n-manager presentWorkflowResult --workflow-id <workflowId> --workspace-root <contextRoot>
106
+ ```
107
+
108
+ ## Guardrails
109
+
110
+ - Do not ask for host/API key before checking `instances list`.
111
+ - Do not ask for host/API key when the user wants a managed local Docker instance.
112
+ - Do not print API keys back to the user.
113
+ - Do not delete runtime data unless the user explicitly asks for destructive deletion.
114
+ - If Docker is unavailable or the daemon is stopped, report the backend diagnostic and stop. Do not loop.
115
+ - If a command fails repeatedly, stop after two attempts and explain the backend diagnostic.
116
+ - For workflow credentials, inspect the required credential type before asking for secret values.
package/src/cli.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
2
+ import { isWorkspaceInitialized } from "./workspace.js";
3
+
4
+ type CliProgram = Parameters<Parameters<OpenClawPluginApi["registerCli"]>[0]>[0]["program"];
5
+
6
+ type CliOpts = {
7
+ program: CliProgram;
8
+ workspaceDir: string;
9
+ };
10
+
11
+ export function registerN8nAcCli({ program, workspaceDir }: CliOpts): void {
12
+ program
13
+ .command("n8nac:status")
14
+ .description("Show n8n-as-code workspace status")
15
+ .action(() => {
16
+ const initialized = isWorkspaceInitialized(workspaceDir);
17
+ console.log(`\nn8n-as-code workspace: ${workspaceDir}`);
18
+ console.log(`Status: ${initialized ? "✓ Initialized" : "✗ Not initialized"}`);
19
+ if (!initialized) {
20
+ console.log("\nUse the n8n-manager and n8n-architect skills to configure runtime access and workflow guidance.");
21
+ }
22
+ console.log();
23
+ });
24
+ }
@@ -0,0 +1,53 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+
5
+ export type WorkspaceBinding = {
6
+ projectId?: string;
7
+ projectName?: string;
8
+ syncFolder?: string;
9
+ activeInstanceId?: string;
10
+ };
11
+
12
+ /**
13
+ * Fixed context-root directory for V1.
14
+ * All n8nac context files (n8nac-config.json, AGENTS.md, .agents/skills, workflows/) live here.
15
+ * n8n instances and credentials are stored globally by n8n-manager.
16
+ */
17
+ export function getWorkspaceDir(): string {
18
+ return join(homedir(), ".openclaw", "n8nac");
19
+ }
20
+
21
+ function readString(value: unknown): string {
22
+ return typeof value === "string" ? value.trim() : "";
23
+ }
24
+
25
+ export function readWorkspaceBinding(workspaceDir: string): WorkspaceBinding {
26
+ const configPath = join(workspaceDir, "n8nac-config.json");
27
+ if (!existsSync(configPath)) {
28
+ return {};
29
+ }
30
+
31
+ try {
32
+ const raw = readFileSync(configPath, "utf-8");
33
+ const config = JSON.parse(raw) as Record<string, unknown>;
34
+
35
+ return {
36
+ projectId: readString(config.projectId) || undefined,
37
+ projectName: readString(config.projectName) || undefined,
38
+ syncFolder: readString(config.syncFolder) || undefined,
39
+ activeInstanceId: readString(config.activeInstanceId) || undefined,
40
+ };
41
+ } catch {
42
+ return {};
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Returns true when n8nac has been initialized in the given directory,
48
+ * meaning the config exists and contains a selected project + sync folder.
49
+ */
50
+ export function isWorkspaceInitialized(workspaceDir: string): boolean {
51
+ const binding = readWorkspaceBinding(workspaceDir);
52
+ return Boolean(binding.projectId && binding.projectName && binding.syncFolder);
53
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowImportingTsExtensions": true,
4
+ "allowSyntheticDefaultImports": true,
5
+ "esModuleInterop": true,
6
+ "forceConsistentCasingInFileNames": true,
7
+ "lib": ["DOM", "DOM.Iterable", "ES2023"],
8
+ "module": "NodeNext",
9
+ "moduleResolution": "NodeNext",
10
+ "noEmit": true,
11
+ "resolveJsonModule": true,
12
+ "skipLibCheck": true,
13
+ "strict": true,
14
+ "target": "es2023"
15
+ },
16
+ "include": ["index.ts", "src/**/*", "tests/**/*.ts"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }