agentsclimarketplace

Configure agent pr attestation

Skill harness/harness-skills/skills/configure-agent-pr-attestation

A collection of structured AI agent skills that enable Claude Code, Cursor, GitHub Copilot, and other AI coding assistants to create, operate, debug, and govern Harness CI/CD workflows through natural language.

Install
npx -y skills add harness/harness-skills --skill configure-agent-pr-attestation

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Use when asked to set up PR attestation, install harness-scs attestation hook, configure agent attestor, troubleshoot why agent attestation isn't uploading, or reconfigure an existing attestation hook (different SCM, new cosign key, updated Harness identity). Trigger phrases: set up PR attestation, install harness-scs attestation hook, configure agent attestor, why isn't my agent attestation uploading, set up agent attestation, configure PR signing, install attestation hook, configure claude attestation.

The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

8.0 KB, as published. Nobody here has run it

Configure Agent PR Attestation

Sets up a PostToolUse hook that signs and uploads an in-toto attestation to the Harness Evidence Vault every time an AI coding agent creates a PR/MR.

Instructions

Follow these steps in exact order. Do NOT skip steps or reorder them.

Step 1: Check Prerequisites

Run these checks and report what's missing. Do not proceed until all are installed.

command -v harness-scs
command -v jq
command -v git
command -v cosign

If harness-scs is missing, tell the user:

task compile-harness-scs && sudo mv harness-scs /usr/local/bin/

Step 2: Ask for SCM

Ask the user which tool they use to create PRs/MRs. Use AskUserQuestion.

Options:

Choicecommand_filterurl_pattern
Harness CLI (codepulse pr create)codepulse pr createhttps://[^/]*\.harness\.io/.*/pulls/[0-9]+(/.*)?
GitHub CLI (gh pr create)gh pr createhttps://github\.com/[^ ]+/pull/[0-9]+
GitLab CLI (glab mr create)glab mr createhttps://[^ ]+/-/merge_requests/[0-9]+
Bitbucket CLI (bb pr create)bb pr createhttps://[^ ]+/pull-requests/[0-9]+
Azure DevOps CLI (az repos pr create)az repos pr createhttps://[^ ]+/_git/[^ ]+/pullrequest/[0-9]+
Gitea / Forgejo (tea pr create)tea pr createhttps://[^ ]+/pulls/[0-9]+

If user picks GitLab, Bitbucket, Gitea, or Custom — also ask if self-hosted. If self-hosted, ask for hostname and replace the generic [^ ]+ host in the url_pattern with their specific escaped hostname.

If user picks "Other / custom":

  1. Ask for the exact command they run.
  2. Ask for an example PR URL their tool prints.
  3. Derive command_filter and url_pattern, show to user, confirm.

Step 3: Set up Harness Identity (auth.json)

Check if ~/.harness/auth.json already exists:

test -r ~/.harness/auth.json && jq -e '.token and .account_id' ~/.harness/auth.json >/dev/null 2>&1

If auth.json exists and is valid: Tell the user "Found existing ~/.harness/auth.json" and move to Step 4.

If auth.json does NOT exist: Ask the user for these values:

  • API key (PAT, format: pat.<account>.<random>.<random>)
  • API URL (default: https://app.harness.io)
  • Account ID (can be auto-derived from PAT if empty)
  • Org ID
  • Project ID

Then create ~/.harness/auth.json:

mkdir -p ~/.harness
cat > ~/.harness/auth.json << 'EOF'
{
  "token": "<API key>",
  "base_url": "<API URL>",
  "account_id": "<Account ID>",
  "org_id": "<Org ID>",
  "project_id": "<Project ID>"
}
EOF
chmod 600 ~/.harness/auth.json

Step 4: Set up Cosign Key and scs.env

Ask the user via AskUserQuestion:

Cosign signing key:
  - I already have one         → ask for absolute path
  - Generate a new one for me  → generate in ~/.harness/

If generating:

mkdir -p ~/.harness
cd ~/.harness && COSIGN_PASSWORD="" cosign generate-key-pair
chmod 600 ~/.harness/cosign.key

Set key_path="$HOME/.harness/cosign.key".

If existing key: Ask for the absolute path. Validate it's readable. Warn if password-protected — they'll need to set COSIGN_PASSWORD for unattended runs.

Then write ~/.harness/scs.env (do NOT ask where to put it — always this path):

cat > ~/.harness/scs.env << 'EOF'
export HARNESS_SIGNER_KEY_PATH="<key_path>"
export COSIGN_PASSWORD=""
EOF

scs.env contains ONLY cosign signer variables. Never put Harness identity here.

Step 5: Generate the Hook Script

Write to <project>/.claude/hooks/agent-pr-attestation.sh, substituting:

  • {{COMMAND_FILTER}} ← from Step 2
  • {{URL_REGEX}} ← from Step 2
  • {{KEY_PATH}} ← from Step 4

Then chmod +x the script.

#!/bin/bash
# Generated by configure-agent-pr-attestation skill.
# Captures a signed in-toto attestation when an AI agent creates a PR.
#
# To reconfigure: re-run /configure-agent-pr-attestation in your agent.

set -uo pipefail

[ -f ~/.harness/scs.env ] && source ~/.harness/scs.env

COMMAND_FILTER='{{COMMAND_FILTER}}'
URL_REGEX='{{URL_REGEX}}'

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if ! echo "$COMMAND" | grep -qE "$COMMAND_FILTER"; then
  exit 0
fi

TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path')
TOOL_STDOUT=$(echo "$INPUT" | jq -r '.tool_response.stdout // empty')
TOOL_STDERR=$(echo "$INPUT" | jq -r '.tool_response.stderr // empty')
CWD=$(echo "$INPUT" | jq -r '.cwd')

PR_URL=$(printf '%s\n%s\n' "$TOOL_STDOUT" "$TOOL_STDERR" | grep -oE "$URL_REGEX" | head -1)
COMMIT_SHA=$(cd "$CWD" && git rev-parse HEAD 2>/dev/null)

if [ -z "$PR_URL" ] || [ -z "$COMMIT_SHA" ]; then
  exit 0
fi

PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$')
EXECUTION_ID="harness-pr-attestor-${PR_NUMBER:-$(date +%s)}"

PASSPHRASE_FILE=$(mktemp -t harness-scs-passphrase.XXXXXX)
trap 'rm -f "$PASSPHRASE_FILE"' EXIT
chmod 600 "$PASSPHRASE_FILE"
printf '%s' "${COSIGN_PASSWORD:-}" >"$PASSPHRASE_FILE"

harness-scs attestation run \
  --step "agent-pull-request" \
  --attestations claudecode \
  --attestor-claudecode-session-file "$TRANSCRIPT_PATH" \
  --attestor-claudecode-include-thinking \
  --attestor-claudecode-commit-sha "$COMMIT_SHA" \
  --attestor-claudecode-pr-url "$PR_URL" \
  --signer-file-key-path "${HARNESS_SIGNER_KEY_PATH:-{{KEY_PATH}}}" \
  --signer-file-key-passphrase-path "$PASSPHRASE_FILE" \
  --enable-attestation-upload \
  --execution-id "$EXECUTION_ID" \
  >/dev/null 2>&1

exit 0

Step 6: Patch .claude/settings.json

Register the hook with Claude Code. Use project-scoped settings by default.

Read existing .claude/settings.json (create {} if absent), then merge in:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "$CLAUDE_PROJECT_DIR/.claude/hooks/agent-pr-attestation.sh"
          }
        ]
      }
    ]
  }
}

Make this idempotent — don't duplicate if already present.

After patching, confirm setup is complete and tell the user to verify by creating a test PR in a new session.

Troubleshooting

SymptomLikely causeFix
Hook never firesMatcher not registered, or settings.json malformedjq . .claude/settings.json to validate; re-run skill
No attestation after PR createdcommand_filter doesn't match the command, OR url_regex doesn't match the PR URLAdd echo "$COMMAND" > /tmp/debug-hook.txt to inspect; run PR command manually and compare URL against regex
harness-scs: command not foundBinary not on PATH for non-interactive shellsInstall to /usr/local/bin/ or hardcode absolute path
failed to load any signersMissing or unreadable cosign keyCheck $HARNESS_SIGNER_KEY_PATH is set and file is readable
Upload fails with 401/403Stale or wrong API keyCheck ~/.harness/auth.json token and account_id

Reconfiguration

If the user re-runs the skill, detect existing files and offer:

  • "An existing hook was found at <path>. Replace it?"
  • "Existing cosign key at <path> — keep it or regenerate?"
  • "Found ~/.harness/auth.json — keep or update?"

Never silently overwrite.

Limitations

Only cosign file keys are supported for signing. If the user asks about keyless signing (Fulcio), KMS signers, or non-Claude-Code agent runtimes, tell them these are not yet available.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.