Authentication
Chucky uses JWT (JSON Web Tokens) for authentication. Tokens are created server-side with your HMAC secret and include budget limits for each user.
Token Architecture
Request Token
Your client (browser) requests a token from your backend server
Create JWT
Your server creates a JWT signed with your HMAC secret, including user ID and budget limits
Return Token
Server returns the signed JWT to the client
Use SDK
Client uses the token to connect to Chucky Cloud via the SDK
Never expose your HMAC secret to clients. Always create tokens on your server.
Creating Tokens
Basic Token
Get your Project ID and HMAC Secret from your project settings at app.chucky.cloud .
TypeScript (Server)
Python (Server)
import { createToken , createBudget } from '@chucky.cloud/sdk' ;
const token = await createToken ({
userId: 'user-123' ,
projectId: process . env . CHUCKY_PROJECT_ID , // From portal project settings
secret: process . env . CHUCKY_HMAC_SECRET , // From portal project settings
budget: createBudget ({
aiDollars: 1.00 ,
computeHours: 1 ,
window: 'day' ,
}),
});
The Project ID and HMAC Secret are separate values found in your project settings at app.chucky.cloud .
The Project ID is used in JWT tokens, while the HMAC Secret is used for signing (never exposed in tokens).
Token Options
Option Type Required Description userIdstringYes Unique identifier for the user projectIdstringYes Your project ID from portal settings secretstringYes Your HMAC secret from portal settings budgetTokenBudgetYes Budget configuration expiresInnumberNo Token validity in seconds (default: 3600) permissionsobjectNo Optional permission constraints sdkConfigobjectNo SDK configuration overrides
Budget Configuration
Budgets control how much each user can spend. Two types of limits:
AI Budget : Cost limit for Claude API calls (in dollars)
Compute Budget : Time limit for sandbox execution (in hours)
Budget Helper
import { createBudget } from '@chucky.cloud/sdk' ;
const budget = createBudget ({
aiDollars: 5.00 , // $5 AI budget
computeHours: 2 , // 2 hours compute
window: 'day' , // Reset window
windowStart: new Date () // Optional: when window started
});
Budget Windows
Window Description hourResets every hour dayResets every 24 hours weekResets every 7 days monthResets on billing anchor day
If you need more control, you can specify the raw budget format:
const token = await createToken ({
userId: 'user-123' ,
projectId: process . env . CHUCKY_PROJECT_ID ,
secret: process . env . CHUCKY_HMAC_SECRET ,
budget: {
ai: 5_000_000 , // 5 USD in microdollars
compute: 7200 , // 2 hours in seconds
window: 'day' ,
windowStart: new Date (). toISOString (),
},
});
AI budget is specified in microdollars (1 USD = 1,000,000 microdollars) for precision.
Token Permissions
Restrict what users can do with their token:
const token = await createToken ({
userId: 'user-123' ,
projectId: process . env . CHUCKY_PROJECT_ID ,
secret: process . env . CHUCKY_HMAC_SECRET ,
budget: createBudget ({ aiDollars: 1 , computeHours: 1 , window: 'day' }),
permissions: {
tools: [ 'search' , 'calculator' ], // Only these tools allowed
blockedTools: [ 'shell' , 'write' ], // These tools blocked
maxTurns: 10 , // Max conversation turns
model: 'claude-sonnet-4-5-20250929' , // Force specific model
},
});
Permission Options
Option Type Description toolsstring[]Whitelist of allowed tool names blockedToolsstring[]Blacklist of blocked tool names maxTurnsnumberMaximum conversation turns modelstringForce a specific model
SDK Config Overrides
Override client-side SDK options from the token (server-enforced):
const token = await createToken ({
userId: 'user-123' ,
projectId: process . env . CHUCKY_PROJECT_ID ,
secret: process . env . CHUCKY_HMAC_SECRET ,
budget: createBudget ({ aiDollars: 1 , computeHours: 1 , window: 'day' }),
sdkConfig: {
model: 'claude-sonnet-4-5-20250929' ,
systemPrompt: 'You are a helpful assistant.' ,
maxTurns: 5 ,
maxBudgetUsd: 0.50 ,
allowedTools: [ 'safe_tool' ],
disallowedTools: [ 'dangerous_tool' ],
},
});
SDK config overrides take precedence over any options passed by the client.
Token Utilities
Decode Token (No Verification)
import { decodeToken } from '@chucky.cloud/sdk' ;
const decoded = decodeToken ( token );
console . log ( decoded . sub ); // User ID
console . log ( decoded . iss ); // Project ID
console . log ( decoded . budget ); // Budget config
Verify Token
import { verifyToken } from '@chucky.cloud/sdk' ;
const isValid = await verifyToken ( token , process . env . HMAC_SECRET );
if ( ! isValid ) {
throw new Error ( 'Invalid token signature' );
}
Check Expiration
import { isTokenExpired } from '@chucky.cloud/sdk' ;
if ( isTokenExpired ( token )) {
// Token has expired, create a new one
const newToken = await createToken ({ ... });
}
Token Payload Structure
The JWT payload contains:
interface TokenPayload {
// Standard JWT claims
sub : string ; // User ID
iss : string ; // Project/Issuer ID
exp : number ; // Expiry timestamp (Unix seconds)
iat : number ; // Issued at timestamp
// Chucky-specific
budget : {
ai : number ; // AI budget in microdollars
compute : number ; // Compute budget in seconds
window : string ; // Budget window type
windowStart : string ; // ISO 8601 timestamp
};
// Optional
permissions ?: { ... };
sdkConfig ?: { ... };
}
Best Practices
Use short expiration times (1 hour or less) and refresh tokens as needed. This limits exposure if a token is compromised.
Create a new token for each user session rather than reusing tokens. This provides better audit trails and security.
Start with small budgets and increase based on user needs. You can always create a new token with a larger budget.
Restrict tools and models based on user trust level. Free users might get limited tools, while premium users get full access.
Example: Token Endpoint
Here’s a complete example of a token endpoint:
// pages/api/token.ts (Next.js example)
import { createToken , createBudget } from '@chucky.cloud/sdk' ;
export async function POST ( req : Request ) {
// Verify user is authenticated (your auth system)
const user = await getCurrentUser ( req );
if ( ! user ) {
return new Response ( 'Unauthorized' , { status: 401 });
}
// Get user's tier for budget limits
const tier = user . subscriptionTier || 'free' ;
const budgets = {
free: { ai: 0.10 , compute: 0.1 },
pro: { ai: 5.00 , compute: 2 },
enterprise: { ai: 50.00 , compute: 10 },
};
const { ai , compute } = budgets [ tier ];
const token = await createToken ({
userId: user . id ,
projectId: process . env . CHUCKY_PROJECT_ID ,
secret: process . env . CHUCKY_HMAC_SECRET ,
expiresIn: 3600 ,
budget: createBudget ({
aiDollars: ai ,
computeHours: compute ,
window: 'day' ,
}),
permissions: tier === 'free' ? {
maxTurns: 5 ,
blockedTools: [ 'shell' , 'write_file' ],
} : undefined ,
});
return Response . json ({ token });
}