From c970f07caa0cf46d6cbe9eb08c72d5bf9e41daf0 Mon Sep 17 00:00:00 2001 From: danciaclara Date: Thu, 4 Jun 2026 14:46:39 +0530 Subject: [PATCH 1/4] Send webhook in Automations --- docs/automations/custom-automations.md | 108 +++++++++++++++++++------ 1 file changed, 83 insertions(+), 25 deletions(-) diff --git a/docs/automations/custom-automations.md b/docs/automations/custom-automations.md index b42bfb6..1ee887f 100644 --- a/docs/automations/custom-automations.md +++ b/docs/automations/custom-automations.md @@ -27,8 +27,8 @@ Project automations apply to work items within a single project. 2. In the **Custom automations** section, click **Create automation**. 3. Give your automation a descriptive name and an optional description, then save. 4. Click **Add trigger** and choose the event that should start the automation. -5. Optionally click **Add condition** to narrow when the automation runs. You can add multiple conditions — the automation only fires when all conditions are met. -6. Click **Add action** to define what happens. Choose from **Add comment**, **Change property**, or **Run Script**. You can add multiple actions — they execute in sequence. +5. Optionally click **Add condition** to narrow when the automation runs. You can add multiple conditions - the automation only fires when all conditions are met. +6. Click **Add action** to define what happens. Choose from **Add comment**, **Change property**, or **Run Script**. You can add multiple actions - they execute in sequence. 7. Click **Confirm**. 8. Click **Enable** when you're ready for it to go live. @@ -44,7 +44,7 @@ Workspace automations can span your entire workspace or a specific set of projec 1. Go to **Workspace Settings → Automations**. 2. Click **Create automation**. -3. Choose which projects the automation should apply to — all projects in the workspace, or a specific subset. +3. Choose which projects the automation should apply to - all projects in the workspace, or a specific subset. 4. Follow the same steps as a project automation: name → trigger → conditions → actions. 5. Enable when ready. @@ -72,15 +72,16 @@ Conditions filter which work items an automation acts on. Without them, the auto 4. Choose an operator (is, in, contains, etc.) and set the value. 5. Add more conditions as needed. -Multiple conditions use **AND** logic by default — all of them must match. You can also create **OR** groups where only one condition in the group needs to match. +Multiple conditions use **AND** logic by default - all of them must match. You can also create **OR** groups where only one condition in the group needs to match. ## Add actions 1. Open the automation and go to the **Action** tab. 2. Click **Add action** and choose a type: - - **Change property** — update a field on the work item - - **Add comment** — post a comment on the work item - - **Run script** — execute a saved script via the Runner + - **Change property** - update a field on the work item + - **Add comment** - post a comment on the work item + - **Run script** - execute a saved script via the Runner + - **Send webhook** - POST a payload to an external URL when the automation fires 3. Configure the action details (see [Actions](#actions) for parameters). 4. Add more actions if needed. They run in the order listed. @@ -91,7 +92,7 @@ Multiple conditions use **AND** logic by default — all of them must match. You - **Enable**: open the automation and click **Enable**. The automation must have at least one trigger and one action. - **Disable**: open the automation and click **Disable** or toggle the status off. -You can't delete an enabled automation — disable it first. +You can't delete an enabled automation - disable it first. ### Check automation run history @@ -168,7 +169,7 @@ Updates a field on the work item. Posts a comment on the work item. You write the comment text in a rich text editor. The comment is always internal and appears as coming from Automation Bot in the activity log. -You can include dynamic values in the comment using template variables — for example, inserting the current priority or state name into the comment text. +You can include dynamic values in the comment using template variables - for example, inserting the current priority or state name into the comment text. **Example:** Say you have an automation that triggers when a work item's state changes. You want to leave a note with context each time that happens. Your comment template might look like: @@ -176,6 +177,63 @@ You can include dynamic values in the comment using template variables — for e This item has been moved to a new state. Current priority: {{priority}}. Please check if the due date needs updating. ``` +#### Send webhook + +Posts an HTTP payload to a URL you specify whenever the automation fires. Use this to push automation events into external systems - trigger a deployment, open a ticket in another tool, post to a custom service, or sync data outside of Plane. + +This is different from workspace webhooks, which fire on any matching event across your workspace. A Send webhook action fires only when this specific automation runs - you control the trigger, conditions, and timing. + +**Configuration** + +| Field | Required | Notes | +|---|---|---| +| URL | Yes | Must be a publicly reachable `http://` or `https://` address. Local and private network addresses are not accepted. | +| Secret key | Auto-generated | Generated when you save the action. Shown once in plain text - copy it before leaving. After that it appears masked as `plane_wh_••••XXXX`. | +| Custom headers | No | Up to 20 headers. Mark a header as secret to store its value encrypted - the value won't be returned in subsequent reads. | + +**The secret key** + +Plane generates a secret key when you first save the Send webhook action. It is shown in plain text once - copy and store it before navigating away. After that, it is masked and cannot be retrieved. + +If your key is compromised or you lose it, open the action in the automation editor and click **Regenerate secret**. The old key stops working immediately. Update your server before regenerating or your signature verification will fail. + +**What Plane sends** + +Every request includes these headers: + +| Header | Value | +|---|---| +| `Content-Type` | `application/json` | +| `User-Agent` | `Autopilot` | +| `X-Plane-Delivery` | Unique ID for this delivery attempt | +| `X-Plane-Event` | The automation event that triggered the action | +| `X-Plane-Signature` | HMAC-SHA256 signature of the request body | + +Custom headers you add are merged in. You cannot override the reserved headers listed above. + +**Verifying the payload** + +Use the `X-Plane-Signature` header to confirm the request came from Plane and wasn't tampered with. Compute an HMAC-SHA256 digest of the raw request body bytes using your secret key and compare it to the header value. + +```python +import hashlib +import hmac + +def verify_webhook(request_body_bytes: bytes, secret: str, signature_header: str) -> bool: + expected = hmac.new( + secret.encode("utf-8"), + request_body_bytes, + hashlib.sha256, + ).hexdigest() + return hmac.compare_digest(expected, signature_header) +``` + +Use raw request body bytes - not a parsed or re-serialized version - or the signature will not match. + +**Delivery behavior** + +Plane makes a single attempt with a 30-second timeout. If the request fails or times out, it is not retried. Check your automation's Activity log to see whether the delivery succeeded and what response your server returned. + #### Run script Runs a saved script from your [Plane Runner](/automations/plane-runner) library. You pick the script from a dropdown. This is the only action available when using a scheduled trigger. @@ -184,9 +242,9 @@ Runs a saved script from your [Plane Runner](/automations/plane-runner) library. ### How automations run -Every time something changes in Plane — a work item is created, a state changes, a comment is posted — Plane checks whether any of your enabled automations should respond. If a trigger matches, Plane evaluates any conditions you've set. If those pass, it runs the actions in order. +Every time something changes in Plane - a work item is created, a state changes, a comment is posted - Plane checks whether any of your enabled automations should respond. If a trigger matches, Plane evaluates any conditions you've set. If those pass, it runs the actions in order. -That's the whole flow: something happens → conditions are checked → actions run. If a condition doesn't match, nothing happens and the automation sits quietly. If an action runs into a problem, Plane stops there and marks that run as failed — you can see exactly what happened in the Activity tab. +That's the whole flow: something happens → conditions are checked → actions run. If a condition doesn't match, nothing happens and the automation sits quietly. If an action runs into a problem, Plane stops there and marks that run as failed - you can see exactly what happened in the Activity tab. Each event is only processed once per automation, so you won't end up with the same action firing twice on the same work item. @@ -194,15 +252,15 @@ Each event is only processed once per automation, so you won't end up with the s The distinction comes down to scope and reuse. -**Project automations** are the right choice when the rule is specific to one project. They're simpler to configure — the states, labels, and members you pick from are all scoped to that project. +**Project automations** are the right choice when the rule is specific to one project. They're simpler to configure - the states, labels, and members you pick from are all scoped to that project. -**Workspace automations** are the right choice when you want the same behavior across multiple projects. Instead of recreating the same automation in five different places, you define it once and choose which projects it applies to — all of them, or just a specific subset. +**Workspace automations** are the right choice when you want the same behavior across multiple projects. Instead of recreating the same automation in five different places, you define it once and choose which projects it applies to - all of them, or just a specific subset. -Either way, automations always act on individual work items. Workspace automations aren't doing anything different — they're just defined once and applied more broadly. +Either way, automations always act on individual work items. Workspace automations aren't doing anything different - they're just defined once and applied more broadly. ### Automation bot -Every custom automation acts through its own dedicated bot account. When an automation changes a field or posts a comment, the activity log shows it came from "Automation Bot" — not from any person on your team. +Every custom automation acts through its own dedicated bot account. When an automation changes a field or posts a comment, the activity log shows it came from "Automation Bot" - not from any person on your team. There are two reasons this matters: @@ -212,32 +270,32 @@ There are two reasons this matters: ### Why scheduled automations only run scripts -Most automations respond to something happening — a trigger gives them a specific work item to act on. Scheduled automations are different. They fire at a time you set, not because of any particular event. +Most automations respond to something happening - a trigger gives them a specific work item to act on. Scheduled automations are different. They fire at a time you set, not because of any particular event. -Since there's no work item that kicked off the run, Plane has nothing to apply a property change or comment to. That's why the only available action for scheduled automations is Run script. The script defines the logic — what to look for, which items to act on, and what to do with them. +Since there's no work item that kicked off the run, Plane has nothing to apply a property change or comment to. That's why the only available action for scheduled automations is Run script. The script defines the logic - what to look for, which items to act on, and what to do with them. Scheduled automations check whether they're due roughly every 5 minutes. The time you configure follows your project's timezone, falling back to the workspace timezone, then UTC. ### Why your trigger isn't enough on its own -Triggers tell Plane _what type of event_ to watch for — not which work items to care about. A "state changed" trigger fires for every single state change in the project, across every work item, regardless of type, priority, or who it's assigned to. +Triggers tell Plane _what type of event_ to watch for - not which work items to care about. A "state changed" trigger fires for every single state change in the project, across every work item, regardless of type, priority, or who it's assigned to. Without conditions, an action like "set priority to Urgent" would run on every state change in the project. That's almost never what you want. -Conditions are what make an automation surgical. They let you say "only run this when the work item is a Bug, assigned to this person, with no due date set" — whatever combination of criteria actually defines the case you're building for. +Conditions are what make an automation surgical. They let you say "only run this when the work item is a Bug, assigned to this person, with no due date set" - whatever combination of criteria actually defines the case you're building for. -One thing worth knowing: when a work item is first created, some fields like assignees and labels can take a moment to register, even if someone filled them in during creation. Plane handles this — it checks the latest state of those fields before evaluating your conditions, so a filter like "assignee is X" on a creation trigger will work as expected. +One thing worth knowing: when a work item is first created, some fields like assignees and labels can take a moment to register, even if someone filled them in during creation. Plane handles this - it checks the latest state of those fields before evaluating your conditions, so a filter like "assignee is X" on a creation trigger will work as expected. ## Common use cases Some common things people use automations for. -- **State management.** Automatically move work items through your workflow when something changes — for example, transition a work item to "In Review" when an assignee is added, or back to "Backlog" when an assignee is removed. +- **State management.** Automatically move work items through your workflow when something changes - for example, transition a work item to "In Review" when an assignee is added, or back to "Backlog" when an assignee is removed. -- **Triage and routing.** Make sure new work lands in the right place without manual intervention — for example, assign a default owner whenever a specific work item type is created, or apply a label to every incoming bug so nothing slips through untagged. +- **Triage and routing.** Make sure new work lands in the right place without manual intervention - for example, assign a default owner whenever a specific work item type is created, or apply a label to every incoming bug so nothing slips through untagged. -- **Priority escalation.** React to signals that indicate urgency — for example, automatically mark a work item as Urgent when a specific label is applied, or raise priority when it gets reassigned to a senior team member. +- **Priority escalation.** React to signals that indicate urgency - for example, automatically mark a work item as Urgent when a specific label is applied, or raise priority when it gets reassigned to a senior team member. -- **Contextual reminders.** Surface the right information at the right moment — for example, post an internal comment with a checklist when a work item enters "Ready for QA," or flag missing information when a work item is created without an assignee. +- **Contextual reminders.** Surface the right information at the right moment - for example, post an internal comment with a checklist when a work item enters "Ready for QA," or flag missing information when a work item is created without an assignee. -- **Scheduled operations.** Run scripts on a timer to handle things that don't map to a single event — for example, sweep stale items weekly, sync data to an external tool nightly, or generate a status comment on open items every Monday morning. +- **Scheduled operations.** Run scripts on a timer to handle things that don't map to a single event - for example, sweep stale items weekly, sync data to an external tool nightly, or generate a status comment on open items every Monday morning. From a0830056d72218e5b915c42e42e9021c48481827 Mon Sep 17 00:00:00 2001 From: danciaclara Date: Thu, 4 Jun 2026 21:37:41 +0530 Subject: [PATCH 2/4] Cursor integration --- docs/integrations/cursor.md | 179 ++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 docs/integrations/cursor.md diff --git a/docs/integrations/cursor.md b/docs/integrations/cursor.md new file mode 100644 index 0000000..20ef99b --- /dev/null +++ b/docs/integrations/cursor.md @@ -0,0 +1,179 @@ +--- +title: Cursor integration +description: Connect Plane to Cursor AI to assign coding tasks directly from work items. Cursor reads your spec, writes the code, and opens a pull request in your linked GitHub repository. +--- + +# Cursor integration + +The Cursor integration connects Plane to [Cursor](https://cursor.com), an AI-powered code editor. Once set up, anyone on your workspace can hand a coding task to Cursor's AI agent directly from a work item - either by assigning Cursor as a work item assignee or by mentioning `@cursor` in a comment. + +Either way, Cursor reads the work item, writes the code, and opens a pull request in the linked GitHub repository. The work item becomes the spec; Cursor does the implementation. + +The integration works through Plane's work item interface - no IDE required on the person's end to trigger the task. The PR appears in GitHub once Cursor completes the work. + +Two things need to be true before anyone can use Cursor from a work item: + +1. A workspace admin has installed and configured the integration, including mapping at least one Plane project to a GitHub repository. +2. Depending on how the admin has configured authentication, either the workspace has a shared Cursor API key or the individual member has connected their own Cursor account. + +## Set up the integration + +This section is for workspace admins. You'll install the integration, provide a Cursor API key, and map your Plane projects to GitHub repositories. + +### Install the Cursor integration + +1. Go to **Workspace Settings → Integrations**. +2. Find **Cursor** and click **Connect**. +3. Follow the installation prompts. + +Once installed, the configuration panel appears on the same page. + +## Configure the API key + +After installation, you need to provide a Cursor API key so the integration can communicate with Cursor on your workspace's behalf. By default, the integration runs in shared mode - one key for the whole workspace. + +1. Go to **Workspace Settings → Integrations → Cursor**. +2. Under **Configuration**, find the **API Key** field. +3. Paste your Cursor API key and click **Save API key**. + +Your key is encrypted at rest and masked after saving. To replace it, paste a new key into the same field. + +You can get your Cursor API key from [cursor.com/settings](https://cursor.com/settings). + +### Set up project mappings + +Project mappings tell Cursor which GitHub repository to push code to when someone uses `@cursor` on a work item in a given Plane project. You need at least one mapping before anyone can use the integration. + +1. Go to **Workspace Settings → Integrations → Cursor**. +2. Scroll to **Project Mappings**. +3. Click the **+** button to add a mapping. +4. Select a **Plane project** from the dropdown. +5. Select the **GitHub repository** to link it to. If your repositories don't appear in the list, type `owner/repo` manually. +6. Optionally enter a **Branch** to specify which branch Cursor should target. Defaults to your repository's default branch. +7. Click **Save**. + +A project can be mapped to more than one repository. If a project has multiple mappings, users need to specify which repository they want Cursor to work in when they use `@cursor`. See [Using @cursor on work items](#use-cursor-on-work-items). + +### Edit or delete a project mapping + +1. Go to **Workspace Settings → Integrations → Cursor**. +2. In the **Project Mappings** section, find the mapping you want to change. +3. Click the edit icon to modify it, or the delete icon to remove it. + +Deleting a mapping means `@cursor` will no longer work for that project until a new mapping is added. + +## Choose an authentication mode + +The integration has two modes that control how Cursor authenticates when creating pull requests. + +### Shared key mode + +In shared mode, all workspace members share one Cursor API key set by the admin. Pull requests are created by the Cursor bot - not on behalf of individual users. Usage is billed to the workspace's Cursor account. + +This is the default after installation. It's the simplest setup: the admin configures the key once and every member can immediately start using `@cursor`. + +### Per-user mode + +In per-user mode, each member connects their own Cursor account using their personal Cursor API key. Pull requests are opened on behalf of each individual, not the bot. Usage is tracked against each member's personal Cursor plan. + +This mode gives more visibility into who triggered which PR and is the right choice when your team members each have their own Cursor subscriptions. + +When per-user mode is on, members who haven't connected their account will see a warning in Plane and won't be able to use `@cursor` until they connect. Admins can see how many members have connected from the **Member connections** card on the integration settings page. + +### Switch to per-user mode + +1. Go to **Workspace Settings → Integrations → Cursor**. +2. Under **Configuration**, toggle on **Require each user to connect their Cursor account**. +3. Read the confirmation dialog - it explains what changes for your workspace - and confirm. + +What happens when you switch: +- Members must connect their own Cursor API key from the **Connections** page before they can use `@cursor`. +- PRs will be opened on each user's behalf instead of by the Cursor bot. +- Cursor usage is tracked against each member's individual plan. +- Your existing workspace API key becomes your personal Cursor connection - you don't need to re-paste it. +- The shared workspace key is retained but disabled. You can switch back at any time. + +### Switch back to shared key mode + +1. Go to **Workspace Settings → Integrations → Cursor**. +2. Toggle off **Require each user to connect their Cursor account**. +3. Confirm in the dialog. + +What happens when you switch back: +- All `@cursor` tasks will be created by the shared Cursor bot, regardless of who triggered them. +- Usage is billed to the workspace account. +- Members' personal connections are retained but ignored until per-user mode is re-enabled. + +## Connect your Cursor account + +This section is for individual workspace members when per-user mode is enabled. + +If your workspace admin has enabled per-user auth, you need to connect your own Cursor account before you can use `@cursor`. You'll see a "Required by admin" badge on the Cursor connection card if this applies to you. + +1. Go to your workspace's **Connections** page. +2. Find the **Cursor** card. +3. Click **Connect Cursor**. +4. In the **Cursor API key** field, paste your personal Cursor API key. + - Get your key from [cursor.com/settings](https://cursor.com/settings). + - The key format looks like `cursor_sk_••••••••••••••••`. +5. Click **Connect**. + +Plane verifies the key and saves it encrypted. Once connected, the card shows your connected email address and the last four characters of your key. You won't be able to see the full key after saving - generate a new one if you think it's been exposed. + +### Disconnect your Cursor account + +1. Go to the **Connections** page. +2. Find the **Cursor** card. +3. Click **Disconnect**. + +Disconnecting removes your key from Plane. You can reconnect at any time. + +## Use Cursor on work items + +Once the integration is set up and you're authenticated, there are two ways to hand a task to Cursor from a work item in a mapped project. + +### Assign Cursor as an assignee + +When you assign Cursor to a work item, Cursor picks up the task automatically - no comment needed. Cursor reads the work item's title and description as its spec, writes the code, and opens a pull request in the linked repository. + +1. Open a work item in a project that has a repository mapping. +2. In the **Assignees** field, search for and select **Cursor**. +3. That's it. Cursor begins working on the task using the work item title and description. + +Cursor appears in the assignee picker like any other team member once the integration is installed. The PR is created on your behalf in per-user mode, or by the Cursor bot in shared mode. + +If your project is mapped to more than one GitHub repository, Cursor needs to know which one to use. Add a comment with `[repo=owner/name]` after assigning: + +``` +[repo=acme/backend] +``` + +### Mention @cursor in a comment + +You can also trigger Cursor by posting a comment that includes `@cursor`. This is useful when you want to give Cursor a specific instruction beyond what's in the work item, or when you want to send a follow-up prompt to an already-active Cursor session. + +1. Open a work item in a project that has a repository mapping. +2. Add a comment describing the coding task you want Cursor to complete. +3. Include `@cursor` in the comment. +4. Post the comment. + +Cursor uses the comment - along with the work item's title and description - as its instructions. You can continue the conversation by posting additional comments with `@cursor` to give Cursor follow-up instructions. + +### Specify a repository when a project has multiple mappings + +If your project is mapped to more than one GitHub repository, you need to tell Cursor which one to use. Add `[repo=owner/name]` anywhere in your comment: + +``` +@cursor Fix the null pointer exception in the auth module [repo=acme/backend] +``` + +If you don't specify a repository and the project has multiple mappings, Cursor may not know where to push the code. + +### Write effective instructions + +Whether you're using the assignee or a comment, Cursor uses the work item's title and description as context. The clearer and more specific your work item (and comment), the better the result. + +Include: +- What needs to change and where +- Any constraints or requirements (don't break this test, match this pattern, etc.) +- The acceptance criteria if it's not already in the work item description \ No newline at end of file From 8edcc84c8879c6df62fd958d229a52c0ded01f4f Mon Sep 17 00:00:00 2001 From: danciaclara Date: Thu, 4 Jun 2026 21:40:00 +0530 Subject: [PATCH 3/4] formatting fixes --- docs/integrations/cursor.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/integrations/cursor.md b/docs/integrations/cursor.md index 20ef99b..e3e0e3e 100644 --- a/docs/integrations/cursor.md +++ b/docs/integrations/cursor.md @@ -87,6 +87,7 @@ When per-user mode is on, members who haven't connected their account will see a 3. Read the confirmation dialog - it explains what changes for your workspace - and confirm. What happens when you switch: + - Members must connect their own Cursor API key from the **Connections** page before they can use `@cursor`. - PRs will be opened on each user's behalf instead of by the Cursor bot. - Cursor usage is tracked against each member's individual plan. @@ -100,6 +101,7 @@ What happens when you switch: 3. Confirm in the dialog. What happens when you switch back: + - All `@cursor` tasks will be created by the shared Cursor bot, regardless of who triggered them. - Usage is billed to the workspace account. - Members' personal connections are retained but ignored until per-user mode is re-enabled. @@ -174,6 +176,7 @@ If you don't specify a repository and the project has multiple mappings, Cursor Whether you're using the assignee or a comment, Cursor uses the work item's title and description as context. The clearer and more specific your work item (and comment), the better the result. Include: + - What needs to change and where - Any constraints or requirements (don't break this test, match this pattern, etc.) -- The acceptance criteria if it's not already in the work item description \ No newline at end of file +- The acceptance criteria if it's not already in the work item description From 7bdc0f4e333270cc7671c187259e847107dfe61d Mon Sep 17 00:00:00 2001 From: danciaclara Date: Fri, 5 Jun 2026 13:38:35 +0530 Subject: [PATCH 4/4] added plan tag --- docs/integrations/cursor.md | 2 +- docs/integrations/draw-io.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/integrations/cursor.md b/docs/integrations/cursor.md index e3e0e3e..f70028b 100644 --- a/docs/integrations/cursor.md +++ b/docs/integrations/cursor.md @@ -3,7 +3,7 @@ title: Cursor integration description: Connect Plane to Cursor AI to assign coding tasks directly from work items. Cursor reads your spec, writes the code, and opens a pull request in your linked GitHub repository. --- -# Cursor integration +# Cursor integration The Cursor integration connects Plane to [Cursor](https://cursor.com), an AI-powered code editor. Once set up, anyone on your workspace can hand a coding task to Cursor's AI agent directly from a work item - either by assigning Cursor as a work item assignee or by mentioning `@cursor` in a comment. diff --git a/docs/integrations/draw-io.md b/docs/integrations/draw-io.md index 9e618b3..3eeb729 100644 --- a/docs/integrations/draw-io.md +++ b/docs/integrations/draw-io.md @@ -3,7 +3,7 @@ title: Connect Draw.io integration description: Connect Draw.io to your Plane workspace to create and edit diagrams and whiteboards directly inside Plane Pages. --- -# Draw.io Integration +# Draw.io Integration Connect Draw.io to create and edit powerful diagrams and whiteboards directly inside Plane Pages and Wiki.