# Cursor agent - Signed commits

**URL:** <https://forum.cursor.com/t/cursor-agent-signed-commits/119822>\
**Category:** Feature Requests\
**Created:** [July 18, 2025, 2:53pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822 "2025-07-18T14:53:38Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ArthurSens](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/arthursens/32/71626_2.png) [@ArthurSens](https://forum.cursor.com/u/ArthurSens)\
**Post date:** [July 18, 2025, 2:53pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/1 "2025-07-18T14:53:38Z")

</div>

Hey 👋 - I’ve been using the Cursor agent every single day since it was released, and loving it! The only issue I’ve found so far is contributing to open-source projects that require signed commits due to legal reasons.

Usually, big OSS projects require all commits to be signed appropriately, and in our first contribution, further automation asks contributors to sign digitally an authorization to use the code they wrote (see [exporter/prometheus: Promote `EnableNativeHistograms` feature flag to beta. by ArthurSens · Pull Request #41105 · open-telemetry/opentelemetry-collector-contrib · GitHub](https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/41105) as an example).

While using the agent, the cursor does not sign commits by default, and I’m having trouble making this work even after I tell it to. When I tell cursor to sign all commits with my email, it runs `git config-- global user.email "my email"` and then hangs forever!

Has anyone faced this before? Any workaround that worked?

---

<div class="post-metadata">

**Author:** ![pasevin](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/pasevin/32/244_2.png) [@pasevin](https://forum.cursor.com/u/pasevin)\
**Post date:** [August 8, 2025, 1:09pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/2 "2025-08-08T13:09:08Z")

</div>

Hey @ArthurSens have you resolved this issue? Did Cursor team address it?

---

<div class="post-metadata">

**Author:** ![ArthurSens](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/arthursens/32/71626_2.png) [@ArthurSens](https://forum.cursor.com/u/ArthurSens)\
**Post date:** [August 8, 2025, 5:32pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/3 "2025-08-08T17:32:39Z")

</div>

Nop, not really… I can just copy the code manually and commit stuff myself, but I was hoping for something less manual

---

<div class="post-metadata">

**Author:** ![pasevin](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/pasevin/32/244_2.png) [@pasevin](https://forum.cursor.com/u/pasevin)\
**Post date:** [August 11, 2025, 8:48am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/4 "2025-08-11T08:48:36Z")

</div>

Yeah, I had to resign the commits myself.

---

<div class="post-metadata">

**Author:** ![richard-tensor](https://avatars.discourse-cdn.com/v4/letter/r/dfb087/32.png) [@richard-tensor](https://forum.cursor.com/u/richard-tensor)\
**Post date:** [September 4, 2025, 2:37am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/5 "2025-09-04T02:37:42Z")

</div>

+1!

---

<div class="post-metadata">

**Author:** ![Jon\_Ator](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/jon_ator/32/78844_2.png) [@Jon\_Ator](https://forum.cursor.com/u/Jon_Ator)\
**Post date:** [September 4, 2025, 4:32pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/6 "2025-09-04T16:32:26Z")

</div>

BTW our pipeline requires signed commits. It’s a significant slowdown to the team wanting to use cursor agents having to go in and force push signed commits for each branch before merging. Would be great if we could somehow have agents sign their commits and whitelist the agent as a contributor.

---

<div class="post-metadata">

**Author:** ![andrews](https://avatars.discourse-cdn.com/v4/letter/a/898d66/32.png) [@andrews](https://forum.cursor.com/u/andrews)\
**Post date:** [October 4, 2025, 6:19pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/7 "2025-10-04T18:19:56Z")

</div>

👍 +1 to this

---

<div class="post-metadata">

**Author:** ![Vif](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/vif/32/86339_2.png) [@Vif](https://forum.cursor.com/u/Vif)\
**Post date:** [November 7, 2025, 9:05am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/8 "2025-11-07T09:05:41Z")

</div>

➕ to this

---

<div class="post-metadata">

**Author:** ![jordipaddle](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@jordipaddle](https://forum.cursor.com/u/jordipaddle)\
**Post date:** [November 7, 2025, 9:26am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/9 "2025-11-07T09:26:36Z")

</div>

➕ to this

---

<div class="post-metadata">

**Author:** ![hadavies](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/hadavies/32/86337_2.png) [@hadavies](https://forum.cursor.com/u/hadavies)\
**Post date:** [November 7, 2025, 9:26am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/10 "2025-11-07T09:26:42Z")

</div>

➕ 🙏

---

<div class="post-metadata">

**Author:** ![goncalo.raposo](https://avatars.discourse-cdn.com/v4/letter/g/f17d59/32.png) [@goncalo.raposo](https://forum.cursor.com/u/goncalo.raposo)\
**Post date:** [November 7, 2025, 10:49am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/11 "2025-11-07T10:49:43Z")

</div>

+1 🙏

---

<div class="post-metadata">

**Author:** ![scupit](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/scupit/32/74266_2.png) [@scupit](https://forum.cursor.com/u/scupit)\
**Post date:** [November 7, 2025, 12:39pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/12 "2025-11-07T12:39:00Z")

</div>

**Edit:** This explains how to configure GPG in the local environment because I misinterpreted the post. _See my next answer for how to set this up in the cloud environment_. You’ll still need to generate a GPG key for that, but you won’t have to do all this manual setup.

* * *

First let me clarify something real quick: Your name and email are attached to a commit automatically as long as you have configured them globally in git (more on that later in this answer). The _[signing](https://stackoverflow.com/questions/454048/what-is-the-difference-between-encrypting-and-signing-in-asymmetric-encryption)_ is actually done using an [asymmetric key pair](https://www.ibm.com/think/topics/asymmetric-encryption), usually through GPG. Your name and email are also associated with the GPG key (and are automatically attached alongside the signature), so a signed commit technically contains that information twice - once from git, and once from GPG. Keep that in mind when configuring the two; ideally use the same name and email for both to eliminate any potential confusion. I won’t get into that too much, but what you want to accomplish is this: When you make a commit, you want git to invoke GPG to make a [cryptographic signature](https://www.cisa.gov/news-events/news/understanding-digital-signatures) on the commit, so that someone else can check the signature later using a “public key” you give them.

I’m going to assume you’re talking about signing commits with [GPG](https://www.gnupg.org/) here, since it’s the most common method. I’ll also assume you already have a GPG key pair for your name and email address, and that you have already added the public key to your GitHub account. If you don’t, download GPG using one of the following methods:

- Linux: GPG is pre-installed already on most distros (probably all the common ones). If you don’t have it for some reason (i.e. the `gpg` command is missing), install it using your system’s package manager.
- MacOS: [Install it using homebrew](https://formulae.brew.sh/formula/gnupg).
- Windows: Download it from [gpg4win](https://www.gpg4win.org/). That is the official windows download - the [GPG homepage links to it](https://www.gnupg.org/index.html).

Once you have `gpg` installed, follow the great GitHub guides on [generating a new GPG key pair](https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key) and [adding the public key to your GitHub account](https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account). (They also have a [short doc on signing commits](https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits) if you want a starting point for some additional reading). Adding the _public_ key to your GitHub account is an important step. If you don’t do that, GitHub won’t be able to verify that your commits are properly signed. Quick note for those guides: _**Make sure you use the same email address as your GitHub account when generating the keys. If you don’t, you’ll probably encounter an issue where GitHub fails to verify your commits because it looks for a GPG key under a different email (the one your signing key specified).**_

Apparently you can also sign commits using an SSH or S/MIME key as well. However, I’ve never seen anyone do that nor had to do it myself in practice, so I’d stick with GPG unless specifically instructed otherwise.

Also, make sure you [(globally) configure Git to use your name and email address for commits](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration#_git_config):

```sh
git config --global user.name 'Yourfirstname Yourlastname'
git config --global user.email 'your_email@example.com'

```

At this point, verify that your configuration is correct. In the terminal, run:

```sh
git config --global user.name
# ^ should output your full name

git config --global user.email
# ^ should output your email address

gpg -k
# ^ should output something like:
#
# pub ed25519 2025-07-15 [C] [expires: 2027-07-15]
# ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890101
# uid [ultimate] Yourfirstname Yourlastname <your_email@example.com>
# sub cv25519 2025-07-15 [E] [expires: 2027-07-15]
# sub ed25519 2025-07-15 [S] [expires: 2027-07-15]

```

Take note of the string of random characters like `ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890101`. That’s your GPG key ID. You’ll need it in the next step.

Now that we have a key pair and the basic git info in place, we’ll configure git to sign commits by default. In the terminal, run:

```sh
# This is where you should use your GPG key ID from the previous step.
# Don't use this one - it's just a placeholder.
git config --global user.signingKey 'ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890101'

# Configure git to sign commits by default
git config --global commit.gpgsign true

```

As an added bonus, you can also have git sign tags by default:

```sh
git config --global tag.gpgSign true

```

You can verify that all this has taken effect by viewing your `~/.gitconfig` file (`$env:USERPROFILE\.gitconfig` if accessed from PowerShell on Windows). It should look something like this:

```toml
[user]
	name = Yourfirstname Yourlastname
	email = your_email@example.com
	signingKey = ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890101
[commit]
	gpgsign = true
[tag]
	gpgSign = true

```

Now try making a commit the same way you always do, either through the terminal or through Cursor’s UI. GPG may ask you to input a password if you assigned one to your key. Once the commit succeeds, verify that the signature actually happened by running

```sh
git log --show-signature

```

in the repository. If it succeeded, your output should look something like this:

```txt
commit 9a3fca344fc4fa18dd23b6762deed51254f4ad80 (HEAD -> main)
gpg: Signature made Fri Nov 7 04:27:14 2025 CST
gpg: using EDDSA key ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890101
gpg: Good signature from "Yourfirstname Yourlastname <your_email@example.com>" [ultimate]
Author: Yourfirstname Yourlastname <your_email@example.com>
Date: Fri Nov 7 04:27:14 2025 -0600

```

where a successful signature and verification is denoted by the `Good signature from "Yourfirstname ...` message.

## If your commit/signature failed

While debugging the signing process, you can use `echo 'test' | gpg --clearsign` to see whether GPG actually runs properly. If your GPG is set up and working properly, you’ll get an output like this:

```txt
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

test
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRI3DqE2xJF0MxyuA+WQUVgYGHLGQUCaQ3g/QAKCRCWQUVgYGHL
GfW2AQCyiLYY3vc7/zH+kE0whMLYvterztOhJl/+MsCIJ2pLVwEA0vjZkuVXgbyw
MURbaOiJ59dPXvj0z5GyHP5lr7NX0QE=
=UrJF
-----END PGP SIGNATURE-----

```

And if you think maybe git isn’t invoking `gpg` automatically, you can manually tell it to sign a commit using the `-S` flag:

```sh
git commit -S -m 'Awesome commit message'

```

### Failed On MacOS

Signing commits will fail by default on Macbooks and MacOS because it doesn’t have a _pinentry_ program installed by default. When Git invokes GPG to sign a commit, GPG has no way to prompt the user for a password, and fails with this message:

`error: gpg failed to sign the data fatal: failed to write commit object`

Follow these steps to resolve:

1. `brew install pinentry-mac`
2. Add this line to _~/.gnupg/gpg-agent.conf_ :

```txt
pinentry-program /opt/homebrew/bin/pinentry-mac

```

1. Kill GPG agent: `killall gpg-agent`, then try the commit/signature again. It should work.

### Failed On Windows

The gpg4win installation ([official GPG distribution for Windows](https://www.gpg4win.org/about.html)) is finicky because it can conflict a bit with the GPG that comes preinstalled with “Git Bash”, the bash shell that ships with the Git Windows installation for some reason. For me, the issue is usually that the GPG agent doesn’t launch properly on startup. I don’t know exactly why that is, but you can fix it by running these commands:

```powershell
gpgconf --launch gpg-agent
gpg-connect-agent.exe /bye
gpgconf --reload gpg-agent

```

and if that still doesn’t work, just launch the program called **Kleopatra**. [It’s part of the gpg4win distribution](https://www.gpg4win.org/about.html). Once Kleopatra finishes loading, your commit should work.

Trying these two things should solve the issue 100% of the time.

### Failed On Linux through SSH

Add this to your _.bashrc_, _.zshrc_, or whatever config file you use for your shell:

```sh
export GPG_TTY=$(tty)

```

Then either restart the SSH session (log out then log back in), or reload the shell with a command like `exec bash`, `exec zsh`, etc. (whichever shell you use). Once you’re back in the reloaded session, install `pinentry-curses` using your distro’s package manager, and add this line to _~/.gnupg/gpg-agent.conf_:

```auto
pinentry-program /usr/bin/pinentry-curses

```

That gives you a nice full-terminal password entry experience. You can probably use `pinentry-tty` instead if you want - I just like `pinentry-curses` better.

### Failed on Linux Desktop environment

I have no idea how to solve this one, sorry. Never seen `gpg` fail on Linux outside an SSH session.

---

<div class="post-metadata">

**Author:** ![ArthurSens](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/arthursens/32/71626_2.png) [@ArthurSens](https://forum.cursor.com/u/ArthurSens)\
**Post date:** [November 7, 2025, 1:24pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/13 "2025-11-07T13:24:21Z")

</div>

I meant the background agents

---

<div class="post-metadata">

**Author:** ![scupit](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/scupit/32/74266_2.png) [@scupit](https://forum.cursor.com/u/scupit)\
**Post date:** [November 9, 2025, 6:58am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/14 "2025-11-09T06:58:01Z")

</div>

@ArthurSens The [cloud agents are working for me again](https://forum.cursor.com/t/background-agent-stuck-on-loading-with-small-prompt/140122), so I was finally able to test this. Here’s a working system you can use to have cursor cloud agents sign every commit (at least, when launched from the editor. I don’t think this will work if the agents are launched from Slack or GitHub).

The idea is:

1. Put needed user-specific information (email, GPG private key, etc.) in cloud agent user secrets.
2. Write a bash script to handle the GPG configuration I described above.
3. Configure [.cursor/environment.json](https://cursor.com/docs/cloud-agent#base-environment-setup) to run the script during the cloud agent install step (initialization).

_This solution is set up so that the shell scripts are downloaded on the fly, so they don’t have to be saved in a repository_ (that way you can use this when contributing to other projects). I ended up splitting this into two scripts just so I had a simpler mental model of the variable scopes. It can probably be condensed into one script, but this works. You can copy these exactly as they are without change - they’re configured using cursor secrets (environment variables in the cloud env).

* * *

> **setup.sh: This runs the init-gpg.sh script then unsets sensitive environment variables so they aren't accessible in the project's actual install/init command.**
>
> ```bash
> #!/bin/bash
> # This script is designed to be SOURCED in Cursor Cloud Agent environments
> # Usage: source <(curl -fsSL "$SCRIPT_DOWNLOAD_ROOT_URL/setup.sh")
> 
> set -euo pipefail
> 
> # Validate that the repository URL is set
> if [[-z "${SCRIPT_DOWNLOAD_ROOT_URL:-}"]]; then
> echo "ERROR: SCRIPT_DOWNLOAD_ROOT_URL environment variable not set" >&2
> echo "Please add it as a secret in Cursor Dashboard" >&2
> echo "Example: https://raw.githubusercontent.com/YOUR_USERNAME/your-repo/main" >&2
> return 1
> fi
> 
> echo "[Setup] Using repository: $SCRIPT_DOWNLOAD_ROOT_URL"
> echo "[Setup] Downloading GPG init script from: $SCRIPT_DOWNLOAD_ROOT_URL/init-gpg.sh"
> 
> # Download and execute init-gpg.sh directly without saving to disk
> if ! curl -fsSL "$SCRIPT_DOWNLOAD_ROOT_URL/init-gpg.sh" | bash; then
> echo "ERROR: GPG initialization failed" >&2
> return 1
> fi
> 
> # Security: Clear sensitive environment variables to prevent exposure to subsequent
> # commands in the Cloud agent "install" step (e.g., npm install). This protects
> # against malicious dependencies.
> echo "[Setup] Clearing sensitive environment variables..."
> unset SCRIPT_DOWNLOAD_ROOT_URL
> unset GPG_PRIVATE_KEY_BASE64
> unset GPG_PRIVATE_KEY_PASSPHRASE
> unset MY_GIT_EMAIL
> unset MY_FULL_NAME
> 
> echo "[Setup] GPG configuration complete"
> 
> ```

* * *

> **init-gpg.sh: This does the full GPG setup I described earlier, but for the headless environment. It configures the cloud agent environment to automatically sign every commit with your GPG private key without requiring any human intervention.**
>
> ```sh
> #!/bin/bash
> set -euo pipefail
> 
> # Safety check: Only run in Cursor Cloud Agent environments
> # Set IS_RUNNING_CURSOR_CLOUD_AGENT=1 as a secret in Cursor Dashboard
> if [[-z "${IS_RUNNING_CURSOR_CLOUD_AGENT:-}"]]; then
> echo "ERROR: This script is designed for Cursor Cloud Agents only." >&2
> echo "Skipping GPG setup to avoid breaking your local configuration." >&2
> echo "If you are seeing this error message within a Cursor Cloud Agent environment, please set IS_RUNNING_CURSOR_CLOUD_AGENT=1 in the Cursor dashboard. It should work afterwards." >&2
> exit 1
> fi
> 
> # Required environment variables (from Cursor Secrets)
> : "${GPG_PRIVATE_KEY_BASE64:?Error: GPG_PRIVATE_KEY_BASE64 not set in Cursor Secrets}"
> : "${GPG_PRIVATE_KEY_PASSPHRASE:?Error: GPG_PRIVATE_KEY_PASSPHRASE not set in Cursor Secrets}"
> : "${MY_GIT_EMAIL:?Error: MY_GIT_EMAIL not set in Cursor Secrets}"
> : "${MY_FULL_NAME:?Error: MY_FULL_NAME not set in Cursor Secrets}"
> 
> echo "Setting up GPG signing for $MY_FULL_NAME..."
> 
> # Initialize GPG home with proper permissions
> export GNUPGHOME="${GNUPGHOME:-$HOME/.gnupg}"
> mkdir -p "$GNUPGHOME"
> chmod 700 "$GNUPGHOME"
> 
> # Configure gpg-agent for non-interactive operation. Allowing a preset passphrase allows
> # us to enter the password during cloud agent initialization, so it doesn't have to be entered
> # after each commit.
> cat > "$GNUPGHOME/gpg-agent.conf" <<EOF
> allow-preset-passphrase
> default-cache-ttl 28800
> max-cache-ttl 86400
> EOF
> 
> # Ensure the above configuration is applied.
> gpgconf --kill gpg-agent 2>/dev/null || true
> gpgconf --launch gpg-agent
> 
> # Decode and import private key (base64 -> ASCII-armored GPG key)
> echo "$GPG_PRIVATE_KEY_BASE64" | base64 -d | gpg --batch --import 2>/dev/null
> 
> KEY_INFO=$(gpg --with-colons --with-keygrip --list-secret-keys "$MY_GIT_EMAIL" 2>/dev/null)
> KEYGRIPS=$(echo "$KEY_INFO" | awk -F: '/^grp:/ {print $10}')
> FINGERPRINT=$(echo "$KEY_INFO" | awk -F: '/^fpr:/ {print $10; exit}')
> 
> if [[-z "$KEYGRIPS"]] || [[-z "$FINGERPRINT"]]; then
> echo "Error: Failed to extract keygrip(s) or fingerprint for $MY_GIT_EMAIL" >&2
> echo "Available keys:" >&2
> gpg --list-secret-keys >&2
> exit 1
> fi
> 
> # Find and use gpg-preset-passphrase (Ubuntu typically has it in /usr/lib/gnupg).
> # This is what allows us to preload the passphrase, to ensure the agent doesn't require any
> # user interaction for signing.
> GPG_PRESET=""
> for preset_path in \
> "/usr/lib/gnupg/gpg-preset-passphrase" \
> "/usr/lib/gnupg2/gpg-preset-passphrase" \
> "/usr/libexec/gpg-preset-passphrase" \
> "$(command -v gpg-preset-passphrase 2>/dev/null || echo '')"; do
> if [[-x "$preset_path"]]; then
> GPG_PRESET="$preset_path"
> break
> fi
> done
> 
> if [[-z "$GPG_PRESET"]]; then
> echo "Error: gpg-preset-passphrase not found. Installing gnupg2..." >&2
> # gpg-preset-passphrase is only supported in GPG 2.0 or later. I think Ubuntu will have this
> # by default, but if they don't, we'll install it.
> sudo apt-get update && sudo apt-get install -y gnupg2
> GPG_PRESET="/usr/lib/gnupg/gpg-preset-passphrase"
> fi
> 
> # Load the passphrase into gpg-agent cache for all keygrips (primary + subkeys).
> # This ensures gpg will never ask for the passphrase, regardless of which key it uses.
> # As a result, also ensures it works with non-default GPG key setups like using
> # a subkey for signing instead of the primary key.
> for KEYGRIP in $KEYGRIPS; do
> printf '%s' "$GPG_PRIVATE_KEY_PASSPHRASE" | "$GPG_PRESET" --preset "$KEYGRIP"
> done
> 
> # Configure Git globally for automatic signing
> git config --global user.name "$MY_FULL_NAME"
> git config --global user.email "$MY_GIT_EMAIL"
> git config --global user.signingkey "$FINGERPRINT"
> git config --global commit.gpgsign true
> git config --global gpg.program "gpg"
> 
> # Quick double check to make sure we can actually sign things without additional interaction.
> if echo "test" | gpg --batch --yes \
> --local-user "$FINGERPRINT" --clearsign >/dev/null 2>&1; then
> echo "[OK] GPG signing configured successfully"
> echo " Name: $MY_FULL_NAME"
> echo " Email: $MY_GIT_EMAIL"
> echo " Fingerprint: $FINGERPRINT"
> else
> echo "ERROR: GPG signing verification failed!" >&2
> echo "Debugging information:" >&2
> gpg --list-secret-keys "$MY_GIT_EMAIL" >&2
> echo "" >&2
> echo "Attempting test signature with verbose output:" >&2
> echo "test" | gpg --batch --yes \
> --local-user "$FINGERPRINT" --clearsign 2>&2 || true
> exit 1
> fi
> 
> ```

* * *

> **Example .cursor/environment.json**
>
> ```json
> {
> "install": "{ [[-n \"${SCRIPT_DOWNLOAD_ROOT_URL:-}\"]] || { echo \"ERROR: SCRIPT_DOWNLOAD_ROOT_URL not set in Cursor Secrets\" >&2; false; }; } && { echo \"[Setup] Downloading from: $SCRIPT_DOWNLOAD_ROOT_URL/setup.sh\" && _setup_script=$(curl -fsSL \"$SCRIPT_DOWNLOAD_ROOT_URL/setup.sh\") && source /dev/stdin <<< \"$_setup_script\"; } && npm install",
> "terminals": [
> {
> "name": "Dev Server",
> "command": "npm run dev"
> }
> ]
> }
> 
> ```

* * *

- _setup.sh_ and _init-gpg.sh_ have to be put in their own separate repository, or somewhere on the web where they can be freely downloaded from the same base URL.

- _.cursor/environment.json_ has to be put in the repository you’re working on. I imagine many open source projects wouldn’t appreciate you adding this to their repo, so I recommend adding it to your local, private ignore file instead of .gitignore: `echo ".cursor/environment.json" >> .git/info/exclude`

Once those are all ready, configure these user secrets in cursor’s cloud agent dashboard (or the editor settings):

- `IS_RUNNING_CURSOR_CLOUD_AGENT`: Flag to safeguard against running this script in a local environment. Set it to `1` in secrets.
- `SCRIPT_DOWNLOAD_ROOT_URL`: Base URL for downloading setup scripts. For example, if your scripts repository is hosted on github and called _my-scripts-repo_ and the scripts you want are available on the _main_ branch, your root URL will be `https://raw.githubusercontent.com/YOUR_GITHUB_USERNAME/my-scripts-repo/main`
- `GPG_PRIVATE_KEY_BASE64`: base64 encoded ASCII-armored GPG private key.
- `GPG_PRIVATE_KEY_PASSPHRASE`: Password for your private key.
- `MY_GIT_EMAIL`: Email address associated with your GPG key and Git commits.
- `MY_FULL_NAME`: Your full name (also associated with commits and GPG key).

The private key is base64 encoded just so I can guarantee nothing breaks when I put it in the single-line secret input. Use this to export the key in that way:

```bash
# List your GPG keys to find the key ID
gpg --list-secret-keys --keyid-format=long

# Export the private key (replace YOUR_KEY_ID with your actual key ID)
# The 'tr -d' command removes newlines to create a single-line string
gpg --armor --export-secret-keys YOUR_KEY_ID | base64 | tr -d '\n'; echo

```

And a quick note about the cloud agent environment file, the `&& npm install` is the actual init command for the project. Everything before that is part of the setup to call _setup.sh_ properly. Feel free to change that and the terminal list as needed to fit your project.

* * *

To summarize, here’s the expected setup:

1. You have the two shell scripts saved in an external repository or hosted on a server so that you can download them with an HTTP request (hosting in a github repo is fine). Make sure the names are exactly _setup.sh_ and _init-gpg.sh_.
2. You have a _.cursor/environment.json_ file **in your locally cloned copy of the project** , ensured git ignores it by specifying it in your private, local _.git/info/exclude_ file.
3. All 6 user SECRETS are properly configured.

Auto-signing for all commits should work once you have all that in place.

---

<div class="post-metadata">

**Author:** ![Raul\_Catalan](https://avatars.discourse-cdn.com/v4/letter/r/8e8cbc/32.png) [@Raul\_Catalan](https://forum.cursor.com/u/Raul_Catalan)\
**Post date:** [December 12, 2025, 3:25pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/15 "2025-12-12T15:25:33Z")

</div>

I test your solution @scupit and it is workin fine. The issue still as you mentioned, signed commits are not workin with the Slack integration, so it needs to be local. It would be good if we can just configure a GPG key that the cloud agent can take to signed the commits.

---

<div class="post-metadata">

**Author:** ![dtorres-spear-ai](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/dtorres-spear-ai/32/95961_2.png) [@dtorres-spear-ai](https://forum.cursor.com/u/dtorres-spear-ai)\
**Post date:** [January 26, 2026, 3:03pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/16 "2026-01-26T15:03:58Z")

</div>

I don’t think that secrets are available in the install command. Is the `setup.sh` script still working for everyone?

---

<div class="post-metadata">

**Author:** ![Carlos\_Tamulonis](https://avatars.discourse-cdn.com/v4/letter/c/b9e5f3/32.png) [@Carlos\_Tamulonis](https://forum.cursor.com/u/Carlos_Tamulonis)\
**Post date:** [February 10, 2026, 6:28pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/17 "2026-02-10T18:28:42Z")

</div>

+1 to supporting cloud agents signing with GPG. Our org requires signed commits. This one gap is breaking what would otherwise be a nearly seamless workflow from Slack/Linear to merge.

---

<div class="post-metadata">

**Author:** ![evsasse](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/evsasse/32/85688_2.png) [@evsasse](https://forum.cursor.com/u/evsasse)\
**Post date:** [March 3, 2026, 4:42pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/18 "2026-03-03T16:42:00Z")

</div>

Would highly appreciate this too…

Currently I put the Cloud Agent to work, and later I need to pull its branch, and rebase it myself, to re-sign the commits…

---

<div class="post-metadata">

**Author:** ![michaelrshannon](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/michaelrshannon/32/100472_2.png) [@michaelrshannon](https://forum.cursor.com/u/michaelrshannon)\
**Post date:** [March 5, 2026, 10:20am UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/19 "2026-03-05T10:20:29Z")

</div>

Echoing others here - lack of cloud agents being able to sign commits is a real blocker for us being able to leverage cloud agents as our repositories require signed commits.

---

<div class="post-metadata">

**Author:** ![v0id-user](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/v0id-user/32/100839_2.png) [@v0id-user](https://forum.cursor.com/u/v0id-user)\
**Post date:** [March 7, 2026, 11:57pm UTC](https://forum.cursor.com/t/cursor-agent-signed-commits/119822/20 "2026-03-07T23:57:00Z")

</div>

Wish they give this priority

[Next page](https://forum.cursor.com/t/cursor-agent-signed-commits/119822.md?page=2)
