Install Alkahest Developer
Pick your agent. Every command is ready to paste.
npx skills add internet-court/internet-court-skill --skill alkahest-developerThe open skills CLI detects your agents (Claude Code, Cursor, Codex and 70+ more) and installs to the right folder. Add -g to install globally.
01
Install it
Run the command above, or upload the folder in Claude.
02
Ask naturally
Describe the task. Your agent loads alkahest-developer when the request matches its description.
03
Name it if needed
If it does not trigger, say “use the alkahest-developer skill”. In Codex, type $alkahest-developer.
Alkahest Developer Skill
When to Use
Use this skill when a developer wants to write code that interacts with Alkahest escrow contracts. This covers:
- Integrating Alkahest into an application
- Writing bots/agents that create escrows, fulfill obligations, or arbitrate
- Building custom arbiters or obligation contracts
- Understanding SDK patterns and APIs
SDK Overview
| SDK | Language | Package | Foundation |
|---|---|---|---|
| TypeScript | TypeScript/JavaScript | @alkahest/ts-sdk |
viem |
| Rust | Rust | alkahest-rs |
alloy |
| Python | Python | alkahest-py |
PyO3 wrapper around Rust SDK |
Client Setup
TypeScript
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";
import { makeClient } from "@alkahest/ts-sdk";
const walletClient = createWalletClient({
account: privateKeyToAccount("0xPRIVATE_KEY"),
chain: baseSepolia,
transport: http("https://rpc-url"),
});
// Full client with all extensions
const client = makeClient(walletClient);
// Custom addresses (optional)
const client = makeClient(walletClient, customAddresses);
// Minimal client for custom extension patterns
const minimal = makeMinimalClient(walletClient);
const extended = minimal.extend((base) => ({
custom: makeErc20Client(base.viemClient, pickErc20Addresses(base.contractAddresses)),
}));
Rust
use alkahest_rs::AlkahestClient;
// Full client with all extensions (Base Sepolia default)
let client = AlkahestClient::with_base_extensions(
"0xPRIVATE_KEY",
"https://rpc-url",
None, // uses Base Sepolia addresses
).await?;
// Custom addresses
use alkahest_rs::{DefaultExtensionConfig, ETHEREUM_SEPOLIA_ADDRESSES};
let client = AlkahestClient::with_base_extensions(
"0xPRIVATE_KEY",
"https://rpc-url",
Some(ETHEREUM_SEPOLIA_ADDRESSES),
).await?;
// Bare client + custom extensions
let bare = AlkahestClient::new("0xPRIVATE_KEY", "https://rpc-url").await?;
let extended = bare.extend::<Erc20Module>(Some(erc20_config)).await?;
Python
from alkahest_py import PyAlkahestClient
# Full client with all extensions (Base Sepolia default)
client = PyAlkahestClient("0xPRIVATE_KEY", "https://rpc-url")
# Custom addresses
from alkahest_py import DefaultExtensionConfig, PyErc20Addresses, ...
config = DefaultExtensionConfig(erc20_addresses=..., ...)
client = PyAlkahestClient("0xPRIVATE_KEY", "https://rpc-url", config)
Core Patterns
Creating an Escrow
TypeScript:
// 1. Approve token
await client.erc20.util.approve({ address: TOKEN, value: amount }, "escrow");
// 2. Create escrow
const { hash, attested } = await client.erc20.escrow.default.doObligation(
client.erc20.escrow.default.encodeObligationRaw({
token: TOKEN, amount, arbiter: ARBITER, demand: DEMAND_BYTES,
}),
);
const escrowUid = attested.uid;
Rust:
// 1. Approve
client.erc20().approve(&Erc20Data { address: token, value: amount }, ApprovalPurpose::Escrow).await?;
// 2. Create escrow
let receipt = client.erc20().escrow().default().make_statement(
token, amount, arbiter, demand_bytes, expiration,
).await?;
let attested = client.get_attested_event(receipt)?;
Python:
# 1. Approve
await client.erc20.util.approve(token_address, amount, "escrow")
# 2. Create escrow
uid = await client.erc20.escrow.default.create(
token=token_address, amount=amount,
arbiter=arbiter_address, demand=demand_bytes,
expiration=expiration,
)
Fulfilling with StringObligation
TypeScript:
const { attested } = await client.stringObligation.doObligation(
"fulfillment content",
undefined, // schema
escrowUid, // refUID
);
Rust:
let receipt = client.string_obligation().do_obligation(
"fulfillment content", None, Some(escrow_uid),
).await?;
Python:
uid = await client.string_obligation.do_obligation(
"fulfillment content",
ref_uid=escrow_uid,
)
Collecting Escrow
TypeScript:
const { hash } = await client.erc20.escrow.default.collectObligation(
escrowUid,
fulfillmentUid,
);
Rust:
let receipt = client.erc20().escrow().default().collect_payment(
escrow_uid, fulfillment_uid,
).await?;
Python:
tx_hash = await client.erc20.escrow.default.collect(escrow_uid, fulfillment_uid)
Waiting for Fulfillment
TypeScript:
const result = await client.waitForFulfillment(
client.contractAddresses.erc20EscrowObligation,
escrowUid,
);
Rust:
let log = client.wait_for_fulfillment(
client.erc20_address(Erc20Contract::EscrowObligation),
escrow_uid,
None, // from_block
).await?;
Python:
result = await client.wait_for_fulfillment(
escrow_contract_address,
escrow_uid,
)
Encoding Demands
TypeScript:
// Trusted oracle
const demand = client.arbiters.general.trustedOracle.encodeDemand({
oracle: ORACLE, data: "0x",
});
// Logical composition
const demand = client.arbiters.logical.all.encodeDemand({
arbiters: [ARBITER_A, ARBITER_B],
demands: [DEMAND_A, DEMAND_B],
});
// Attestation properties
const demand = client.arbiters.attestationProperties.attester.encodeDemand({
attester: REQUIRED_ATTESTER,
});
Rust:
// Trusted oracle (ABI encoding)
use alloy::sol_types::SolValue;
let demand = TrustedOracleArbiter::DemandData { oracle, data: Bytes::new() }.abi_encode();
// Decode arbiter demand (auto-detects)
let decoded = client.arbiters().decode_arbiter_demand(arbiter_addr, &demand_bytes)?;
Python:
# Trusted oracle
demand = client.arbiters.trusted_oracle.encode_demand(oracle=ORACLE, data=b"")
# Logical composition
demand = client.arbiters.logical.all.encode(
arbiters=[ARBITER_A, ARBITER_B],
demands=[DEMAND_A, DEMAND_B],
)
Commit-Reveal Pattern
TypeScript:
// 1. Compute commitment
const commitment = await client.commitReveal.computeCommitment(
escrowUid, claimerAddress, { payload, salt, schema },
);
// 2. Commit (sends bond as ETH)
await client.commitReveal.commit(commitment, bondAmount, commitDeadline);
// 3. Wait 1+ blocks, then reveal. The matching bond is reclaimed on reveal.
await client.commitReveal.doObligation(
{ payload, salt, schema }, escrowUid,
);
Rust:
let commitment = client.commit_reveal().compute_commitment(
escrow_uid, claimer, &obligation_data,
).await?;
client.commit_reveal().commit(commitment, bond_amount, commit_deadline).await?;
// wait 1+ blocks; the matching bond is reclaimed on reveal
let receipt = client.commit_reveal().do_obligation(&obligation_data, Some(escrow_uid)).await?;
Python:
commitment = await client.commit_reveal.compute_commitment(
escrow_uid, claimer, payload, salt, schema,
)
await client.commit_reveal.commit(commitment, bond_amount, commit_deadline)
# wait 1+ blocks; the matching bond is reclaimed on reveal
uid = await client.commit_reveal.do_obligation(payload, salt, schema, ref_uid=escrow_uid)
Atomic Payment Utilities
Atomic payment utilities provide single-transaction payment and collection for existing escrows:
TypeScript:
await client.erc20.payment.payErc20AndCollect(escrowUid);
Rust:
client.erc20().payment().pay_erc20_and_collect(escrow_uid).await?;
Key Type Differences
| Concept | TypeScript | Rust | Python |
|---|---|---|---|
| Addresses | `0x${string}` |
Address |
str (hex) |
| Big integers | bigint |
U256 |
str (decimal) |
| Bytes | `0x${string}` |
Bytes / FixedBytes<32> |
bytes / str (hex) |
| Receipts | { hash, attested } |
TransactionReceipt |
str (tx hash or uid) |
| Attestations | Attestation object |
IEAS::Attestation |
PyAttestation |
Reference Documentation
references/typescript-api.md— full TS SDK API treereferences/rust-api.md— full Rust SDK API treereferences/python-api.md— full Python SDK API treereferences/contracts.md— contract addresses and data schemasdocs/website/Escrow Flow/Token Trading.mdx— token trading walkthroughdocs/website/Escrow Flow/Job Trading.mdx— oracle arbitration walkthroughdocs/drafts/Escrow Flow (pt 2b - Frontrunning Protection).md— commit-reveal frontrunning protectiondocs/website/Escrow Flow/Composing Demands.mdx— composing demands with logical arbitersdocs/website/Writing Arbiters/— custom arbiter developmentdocs/website/Writing Escrow Contracts.mdanddocs/website/Writing Fulfillment Contracts.md— custom escrow/obligation developmentdocs/mcp-server/— MCP server for looking up contract details
Tips for Alkahest Developer
- • Start a fresh session after installing so your agent picks up the new skill.
- • It bundles reference files. The agent reads them only when needed, so they cost no context until then.
- • It is part of a pack with 30 skills. Install only the ones you need with --skill to keep triggers precise.
- • If two skills overlap, mention the one you want by name.
Questions about Alkahest Developer
What does the Alkahest Developer skill do?
Help developers write code that interacts with Alkahest escrow contracts using the TypeScript, Rust, or Python SDK
How do I install Alkahest Developer?
Run "npx skills add internet-court/internet-court-skill --skill alkahest-developer" in your project. The skills CLI installs it for Claude Code, Cursor, Codex and 70+ other agents. In Claude on the web, upload the skill folder as a ZIP under Customize > Skills.
Does Alkahest Developer work in Cursor and Codex?
Yes. Alkahest Developer uses the open SKILL.md format, so it works in Claude Code, Claude, Cursor, OpenAI Codex, Gemini CLI, GitHub Copilot and other agents that support agent skills.
Is Alkahest Developer free?
Alkahest Developer is open source on GitHub. It is free to install; check the license before commercial use.
Who made Alkahest Developer?
Alkahest Developer is published by internet-court in the internet-court/internet-court-skill repository, together with 29 other skills.




