Charge customer
Skill MauricioPerera/agent-skills/examples/skills/charge-customer
Creates a one-time charge against an existing Stripe customer using the Stripe Charges API. Reads the secret key from the shell environment so it never reaches the LLM context.From its SKILL.md
npx -y skills add MauricioPerera/agent-skills --skill charge-customerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. 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
7.2 KB, 969 tokens by cl100k_base, as published. Nobody here has run it
Charge a Customer
Creates a one-time charge against an existing Stripe customer. The customer must already exist in your Stripe account.
Privacy property — the credential isolation invariant
This skill demonstrates SPEC.md §8 P1:
- The
command_templatereferences$STRIPE_SECRET_KEYas a shell variable, not as a{placeholder}. - The bank does NOT substitute
$STRIPE_SECRET_KEY. The bank's substitution only handles{placeholder}patterns. - When the bank emits the (substituted) command to the shell for execution, the shell sees
$STRIPE_SECRET_KEYas a normal variable reference and expands it from the environment at exec time, after the LLM is no longer involved. - The LLM receives only
command_template(with$STRIPE_SECRET_KEYliteral) — it never sees the key's value.
For this skill to work, the operator must have set $STRIPE_SECRET_KEY in the shell environment before the agent runs. Common mechanisms:
# Option A: dotenv-style file sourced at agent start
source ~/.stripe-credentials
# Option B: direnv per-project
echo 'export STRIPE_SECRET_KEY=sk_test_xxx' > .envrc
direnv allow
# Option C: 1Password CLI on demand
export STRIPE_SECRET_KEY=$(op read 'op://vault/Stripe/api-key')
The skill does NOT include a "set the key" step intentionally — credential bootstrap is the operator's responsibility, not the agent's.
When to use this
- The user has explicitly named a customer (with
cus_*ID) and an amount. - The intent is a one-off charge, not a subscription or invoice.
- The Stripe account is configured to accept the currency requested.
When NOT to use this
- The user wants a subscription (use
create-subscriptioninstead). - The user wants to charge a card directly without an existing customer (use
create-charge-with-card, although this is generally discouraged). - The user wants to refund (use
refund-charge). - The amount or customer ID is uncertain — the agent should confirm with the user first.
idempotent: false
Creating a charge is intrinsically non-idempotent: re-running this skill with the same args creates a second charge. Operators using chains MUST NOT auto-retry this skill (the chain executor checks idempotent before deciding). To make a charge retry-safe, add a --data idempotency_key=<UUID> to the template (see Stripe's docs on idempotency keys).
A future version of this skill may add an idempotency_key arg and flip to idempotent: true. That would be a MINOR version bump (it relaxes a constraint without breaking existing usage).
Input validation
Before substitution, the bank validates:
amount: positive integer ≤ 99,999,999.currency: one of the listed ISO codes.customer_id: matches^cus_[a-zA-Z0-9]+$— prevents injection of arbitrary URLs.description: matches the safe-character pattern, length ≤ 256.
Validation failure produces exit code 5 (validation error) with a clear stderr message. The skill is never invoked with bad args.
Output
Stdout: the JSON response from Stripe's /v1/charges endpoint. Notable fields:
id: the charge ID (ch_*).status:succeeded,pending, orfailed.amount,currency,customer: echoed back.failure_code,failure_message: present ifstatus == "failed".
Errors
- HTTP 401 Unauthorized:
$STRIPE_SECRET_KEYis invalid or empty. Re-check the env. - HTTP 402 Payment Required: card declined;
failure_codeexplains why. - HTTP 404 Not Found:
customer_iddoes not exist in this Stripe account. - HTTP 429 Too Many Requests: hit Stripe's rate limit; retry with backoff.
Audit considerations
Every successful charge is recorded in Stripe's dashboard. To make agent-emitted charges identifiable in the dashboard, consider extending the template with --data 'metadata[source]=agent-skills' — Stripe metadata is searchable.
The skill bank's local audit log (per SPEC.md §4.5) is a complementary record but not a substitute for Stripe's canonical activity log.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.