Ecosystem

grapes CLI

Universal Grant Management CLI — request, approve, delegate, and execute.

grapes

The universal CLI for the OpenApe grant lifecycle. Handles authentication, grant requests, approvals, delegations, and integrates with escapes for privilege elevation.

Installation

npm install -g @openape/grapes

Authentication

Human Login (Browser-based)

grapes login --idp https://id.example.com

Opens a browser for Passkey authentication. The IdP redirects back to a local callback server on port 9876.

Agent Login (Key-based)

grapes login --idp https://id.example.com \
  --key ~/.ssh/agent_key \
  --email agent+deploy@example.com

Uses Ed25519 challenge-response authentication. No browser needed.

Session Management

grapes whoami        # Show current identity, IdP, token expiry
grapes logout        # Clear stored credentials

Credentials are stored in ~/.config/grapes/auth.json (mode 0600).

Grant Requests

Request a Command Grant

grapes request "systemctl restart nginx" \
  --audience escapes \
  --reason "Deploy hotfix #42"

Request with Options

FlagDescriptionDefault
--audienceService identifier (e.g., escapes, proxy)Required
--hostTarget hostSystem hostname
--approvalGrant type: once, timed, alwaysonce
--durationDuration for timed grants (e.g., 30m, 1h, 7d)
--reasonHuman-readable reason
--run-asExecute as specific user
--waitBlock until approved/denied (5 min timeout)false

Request a Capability Grant

For use with Shapes adapters:

grapes request-capability kubectl \
  --resource pods \
  --selector default \
  --action delete \
  --approval once \
  --wait

Grant Execution

Run (Request + Execute in One Step)

The run command combines request, approval-wait, and execution:

# Request grant, wait for approval, execute via escapes
grapes run escapes "systemctl restart nginx" --reason "Deploy"

# With timed approval
grapes run escapes "apt-get upgrade" --approval timed --duration 1h

# For non-escapes audiences, outputs the JWT to stdout
TOKEN=$(grapes run proxy "test" 2>/dev/null)
curl -H "Authorization: Bearer $TOKEN" https://api.example.com/action
FlagDescriptionDefault
--approvalGrant typeonce
--reasonHuman-readable reason
--run-asExecute as specific user
--hostTarget hostSystem hostname
--escapes-pathPath to escapes binaryescapes

Get Token for Existing Grant

# Get the AuthZ-JWT for an already-approved grant
grapes token <grant-id>

# Pipe to another command
JWT=$(grapes token abc123)
escapes --grant "$JWT" -- systemctl restart nginx

Grant Management

List Grants

grapes list                      # All grants
grapes list --status pending     # Only pending
grapes list --limit 50           # Up to 50 results
grapes list --json               # JSON output

Check Grant Status

grapes status <grant-id>
grapes status <grant-id> --json

Approve / Deny (as Approver)

grapes approve <grant-id>
grapes deny <grant-id>
You must be logged in as the agent's owner or designated approver to approve/deny grants.

Revoke a Grant

grapes revoke <grant-id>

Revokes an approved grant immediately. The AuthZ-JWT will fail verification after revocation.

Delegations

Delegations allow a user to grant another identity the ability to act on their behalf at a specific service.

Create a Delegation

grapes delegate \
  --to agent+bot@example.com \
  --at escapes \
  --approval always

# With scopes and expiry
grapes delegate \
  --to alice@example.com \
  --at proxy \
  --scopes "read,exec" \
  --expires "2026-12-31T23:59:59Z"
FlagDescriptionRequired
--toDelegate emailYes
--atService/audienceYes
--scopesComma-separated scopesNo
--approvalonce, timed, alwaysNo (default: once)
--expiresISO 8601 expiration dateNo

List Delegations

grapes delegations
grapes delegations --json

Configuration

Config File (Optional)

Create ~/.config/grapes/config.toml:

[defaults]
idp = "https://id.example.com"

[agent]
key = "~/.ssh/agent_key"
email = "agent+deploy@example.com"

With a config file, you can skip the --idp, --key, and --email flags.

Environment Variables

VariableDescription
GRAPES_IDPOverride IdP URL

Endpoint Discovery

All API endpoints are discovered automatically via OIDC .well-known/openid-configuration:

Discovery KeyEndpoint
openape_grants_endpoint/api/grants
openape_delegations_endpoint/api/delegations
ddisa_agent_challenge_endpoint/api/agent/challenge
ddisa_agent_authenticate_endpoint/api/agent/authenticate