skills/show-karma/skills/project-manager

project-manager

SKILL.md

Project Manager

Manage projects, grants, milestones, and updates on the Karma protocol. All actions create on-chain attestations via a single API.

Full API docs: https://gapapi.karmahq.xyz/v2/docs/static/index.html

BASE_URL="${KARMA_API_URL:-https://gapapi.karmahq.xyz}"
API_KEY="${KARMA_API_KEY}"
INVOCATION_ID=$(uuidgen)

CRITICAL: Every curl call must include these tracking headers:

-H "X-Source: skill:project-manager"
-H "X-Invocation-Id: $INVOCATION_ID"
-H "X-Skill-Version: 1.0.0"

Setup

If KARMA_API_KEY is already set, skip to Verify.

Otherwise use the AskUserQuestion tool with these options:

  • Question: "You need a Karma API key to continue. How would you like to set it up?"
  • Options: ["Quick start — Generate instantly (no account needed)", "Email login — Link to existing Karma account", "I already have a key"]

Quick Start (No Account Needed)

curl -s -X POST "${BASE_URL}/v2/agent/register" \
  -H "Content-Type: application/json" \
  -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0" \
  -d '{}'

Returns { "apiKey": "karma_..." } — shown only once.

Important: Always send -d '{}' — an empty body causes a 400 error.

Email Login

  1. Ask for email
  2. POST ${BASE_URL}/v2/api-keys/auth/init with { "email": "..." }
  3. Ask for code → POST ${BASE_URL}/v2/api-keys/auth/verify with { "email": "...", "code": "...", "name": "claude-agent" }
  4. Returns { "key": "karma_..." }
Error Action
400 Invalid or expired code Ask to recheck or request new code
409 Active key already exists Use existing key or revoke from website

Save API Key

After obtaining the key (from quick start, email login, or user pasting it), ask permission to save it permanently:

Would you like me to save your API key to your shell config so you don't have to paste it every time?

If yes, detect the user's shell and append the export:

# Detect shell config file
if [ -f "$HOME/.zshrc" ]; then
  SHELL_RC="$HOME/.zshrc"
elif [ -f "$HOME/.bashrc" ]; then
  SHELL_RC="$HOME/.bashrc"
fi

# Append only if not already present
grep -q 'KARMA_API_KEY' "$SHELL_RC" || echo '\n# Karma API Key\nexport KARMA_API_KEY="karma_..."' >> "$SHELL_RC"

# Also export for current session
export KARMA_API_KEY="karma_..."

If the key already exists in the file, replace the old value instead of appending a duplicate.

If the user declines, just set it for the current session:

export KARMA_API_KEY="karma_..."

Verify

curl -s "${BASE_URL}/v2/agent/info" \
  -H "x-api-key: ${API_KEY}" \
  -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0"

If response includes walletAddress and supportedActions → ready. Do NOT show wallet/chain details to the user. Tell them:

Your Karma agent is ready! You can now create projects, grants, milestones, and post updates.


Execute Endpoint

All actions use:

curl -s -X POST "${BASE_URL}/v2/agent/execute" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${API_KEY}" \
  -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0" \
  -d '{ "action": "<ACTION>", "params": { ... } }'

Success Output

[Action] completed successfully!

- Project: {title}
- Chain: {chainName} ({chainId})
- Transaction: {transactionHash}

Supported Chains

Chain ID
Arbitrum 42161
Base 8453
Celo 42220
Lisk 1135
Optimism 10
Polygon 137
Scroll 534352
Sei 1329
Testnets
Base Sepolia 84532
OP Sepolia 11155420

Default Chain Behavior

When the user does NOT specify a chain, default to Base (8453) and confirm:

Your project will be created on Base. Continue?

  • Yes
  • Choose another chain: Arbitrum, Base, Celo, Lisk, Optimism, Polygon, Scroll, Sei

Chain Inheritance

Child attestations must use the same chain as their parent:

  • Grant → uses project.chainId
  • Grant Update → uses grant.chainId
  • Milestone → uses grant.chainId
  • Complete Milestone → uses milestone.chainId
  • Project Update → uses project.chainId

Look up the parent's chain from the API — never ask the user for a chain on child attestations.


Actions

createProject

Param Required Description
chainId Yes Blockchain ID (default: Base 8453)
title Yes Project name (1-200 chars)
description Yes Project description (1-5000 chars)

Optional fields:

Param Description
imageURL Logo/image URL
links Array of { type, url } — github, website, twitter, discord
tags Array of strings (max 20) — e.g. "defi", "infrastructure"
problem What problem does this project solve? (1-5000 chars)
solution What is the solution? (1-5000 chars)
missionSummary Brief mission statement (1-1000 chars)
locationOfImpact Geographic or domain focus (1-1000 chars)
businessModel How does the project sustain itself? (1-1000 chars)
stageIn Development stage: Idea, MVP, Beta, Production, Growth, Mature (1-1000 chars)
raisedMoney Funding raised so far (1-1000 chars)
pathToTake Future roadmap (1-1000 chars)

Gathering Project Information

When the user wants to create a project, present all fields at once and let them fill in what they want:

To create your project, provide the following. Only title and description are required — the rest helps your project stand out:

  • Title: Project name
  • Description: What does the project do?
  • Problem: What problem are you solving?
  • Solution: How does your project solve it?
  • Mission: Sum up your mission in one sentence
  • Stage: Idea / MVP / Beta / Production / Growth / Mature
  • Location of Impact: Where or who does it impact?
  • Business Model: How do you sustain the project?
  • Funding Raised: What funding have you received?
  • Roadmap: What's your plan ahead?
  • Links: GitHub, website, Twitter, Discord URLs
  • Tags: Category tags (e.g. defi, infrastructure, public-goods)
  • Image: Logo or banner URL

Include only the fields the user provides — all metadata fields are optional.

After Project Creation

After a successful project creation, display:

Your project has been created on {chainName}!

  • Project: {title}
  • Chain: {chainName} ({chainId})
  • Transaction: {transactionHash}

Want to post your first update? Share something you just built, a milestone you hit, or what's coming next.


updateProjectDetails

Update an existing project. Replaces all fields — fetch current details first for partial updates.

Param Required Description
chainId Yes Chain where the project lives
projectUID Yes Project attestation UID
title Yes Project name (1-200 chars)
description Yes Project description (1-5000 chars)

Plus all optional fields from createProject (imageURL, links, tags, problem, solution, missionSummary, locationOfImpact, businessModel, stageIn, raisedMoney, pathToTake).

Important: Always include existing fields alongside changes since the update replaces everything.


createProjectUpdate

Post a progress update on a project.

Param Required Description
chainId Yes Must match project's chain
projectUID Yes Project attestation UID
title Yes Update title (1-200 chars)
text Yes Update content (1-10000 chars)

createGrant

Add a grant (funding) to a project.

Param Required Description
chainId Yes Must match project's chain
projectUID Yes Project attestation UID
communityUID Yes Community attestation UID
title Yes Grant title (1-200 chars)
description No Grant description (1-5000 chars)
amount No Funding amount (e.g. "50000 USDC")
proposalURL No Link to grant proposal
programId No Program ID (look up via programs API)

createGrantUpdate

Post a progress update on a grant.

Param Required Description
chainId Yes Must match grant's chain
grantUID Yes Grant attestation UID
title Yes Update title (1-200 chars)
text Yes Update content (1-10000 chars)

createMilestone

Add a milestone to a grant.

Param Required Description
chainId Yes Must match grant's chain
grantUID Yes Grant attestation UID
title Yes Milestone title (1-200 chars)
description Yes What will be delivered (1-5000 chars)
endsAt Yes Deadline as Unix timestamp in seconds
priority No Priority level (0-4)

Date conversion: Math.floor(new Date("2025-06-30").getTime() / 1000)


completeMilestone

Mark a milestone as completed.

Param Required Description
chainId Yes Must match milestone's chain
milestoneUID Yes Milestone attestation UID
reason Yes Completion summary (1-5000 chars)
proofOfWork No URL to proof (PR, demo, report)

createProjectWithGrant

Create a project and grant in a single transaction (4 attestations).

All createProject params plus:

Param Required Description
communityUID Yes Community attestation UID
grant.title Yes Grant title (1-200 chars)
grant.description No Grant description
grant.amount No Funding amount
grant.proposalURL No Proposal link
grant.programId No Program ID

After success, use the same post-creation message as createProject.


Looking Up Data

Find a Project

curl -s -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0" \
  "${BASE_URL}/v2/projects?q=SEARCH_TERM&limit=5&page=1"

Each result has: uid, chainID, details.title, details.slug, details.description

Get Project by UID or Slug

curl -s -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0" \
  "${BASE_URL}/v2/projects/PROJECT_UID_OR_SLUG"

Get Project Grants

curl -s -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0" \
  "${BASE_URL}/v2/projects/PROJECT_UID_OR_SLUG/grants"

Each grant has: uid, details.title, milestones[]

Search Communities

curl -s -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0" \
  "${BASE_URL}/v2/communities/?limit=5&page=1"

Get Community Programs

curl -s -H "X-Source: skill:project-manager" -H "X-Invocation-Id: $INVOCATION_ID" -H "X-Skill-Version: 1.0.0" \
  "${BASE_URL}/communities/COMMUNITY_SLUG_OR_UID/programs"

Each program has: programId, metadata.title. Always include programId when the user mentions a specific program.


Natural Language Mapping

User says Action
"create a project", "new project" createProject — present all fields, default Base
"create a DeFi project on Optimism" createProject with tags: ["defi"], chainId: 10
"update project details", "rename project", "enrich my project" updateProjectDetails — fetch current details first
"post an update", "project progress" createProjectUpdate — look up projectUID, inherit chain
"add a grant", "record funding" createGrant — look up projectUID + communityUID, inherit chain
"grant update", "grant progress" createGrantUpdate — look up grantUID, inherit chain
"add milestone", "set deliverable" createMilestone — look up grantUID, inherit chain
"complete milestone", "mark done" completeMilestone — look up milestoneUID, inherit chain
"create project with grant" createProjectWithGrant

Error Handling

Status Meaning Action
400 Bad params Show error, help fix
401 Invalid API key Tell user to check KARMA_API_KEY or run setup
429 Rate limited (60/min) Wait and retry
500 Server error Retry once, then report

Edge Cases

Scenario Response
Missing required field Ask user for it
Chain not specified (root action) Default to Base, confirm with user
Chain not specified (child action) Inherit from parent — never ask
API key not set Run setup flow
Title too long (>200) Truncate and confirm
Need UID but user gave name Search API to find the UID
Partial project update Fetch current details, merge changes, then update
Multiple grants on project Show list, ask which one
Date given as string Convert to Unix timestamp in seconds
Weekly Installs
5
GitHub Stars
1
First Seen
7 days ago
Installed on
gemini-cli5
claude-code5
github-copilot5
codex5
kimi-cli5
cursor5