Dart Cloud CLI#
Command-line interface for deploying and managing Dart serverless functions.
Overview#
dart_cloud_cli is a powerful CLI tool that enables developers to:
- Deploy Dart cloud functions with a single command
- Validate function structure and security automatically
- Manage deployed functions (list, invoke, delete)
- View function logs and metrics
- Authenticate with the Dart Cloud platform using access and refresh tokens
Installation#
From Source#
cd dart_cloud_cli
dart pub get
dart pub global activate --source path .
Now you can use dart_cloud from anywhere.
Quick Start#
1. Login#
dart_cloud login
You'll be prompted for your email and password. Upon successful login, you'll receive:
- Access Token - Short-lived token (1 hour) for API requests
- Refresh Token - Long-lived token (30 days) for obtaining new access tokens
Both tokens are securely stored in ~/.dart_cloud/config.json.
2. Create a Function#
mkdir my-function
cd my-function
dart create -t console-simple .
3. Initialize Function#
dart_cloud init
This:
- Validates function structure (pubspec.yaml, entry point)
- Creates function on backend with status
initand generates UUID - Stores UUID in
.dart_tool/function_config.json - Returns the function UUID for deployment
You can also generate an API key during initialization:
# Generate API key valid for 1 day
dart_cloud init --apikey 1d
# Generate API key with forever validity
dart_cloud init --apikey
# Revoke existing key and generate new one
dart_cloud init --apikey 1w --revoke
4. Add dart_cloud_function Dependency#
Edit pubspec.yaml:
dependencies:
dart_cloud_function: ^1.0.0
5. Write Your Function#
Create main.dart:
import 'package:dart_cloud_function/dart_cloud_function.dart';
@cloudFunction
class MyFunction extends CloudDartFunction {
@override
Future<CloudResponse> handle({
required CloudRequest request,
Map<String, String>? env,
}) async {
return CloudResponse.json({
'message': 'Hello, World!',
'path': request.path,
});
}
}
6. Deploy#
dart_cloud deploy ./my-function
Commands#
init#
Initialize function configuration in the current directory.
dart_cloud init
Creates a .dart_tool/function_config.json file that stores:
function_name- The project name frompubspec.yamlfunction_id- Cached after deployment (auto-populated)created_at- Timestamp of initialization
This file is used as a cache for function metadata, allowing you to:
- Update functions without specifying the ID
- Invoke functions locally using the cached ID
- Track function metadata in your project
Output:
✓ Successfully initialized function config
✓ Config file created at: .dart_tool/function_config.json
✓ Function name: my_function
login#
Authenticate with the Dart Cloud platform.
dart_cloud login
Authentication Flow:
- Enter email and password
- Backend validates credentials
- Receives access token (1 hour expiry) and refresh token (30 days expiry)
- Tokens stored securely in
~/.dart_cloud/config.json
Token Storage:
{
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc...",
"serverUrl": "http://localhost:8080"
}
logout#
Logout from the platform and invalidate tokens.
dart_cloud logout
Logout Flow:
- Sends access token and refresh token to backend
- Backend blacklists both tokens
- Removes tokens from local storage
- User must login again to access platform
deploy#
Deploy a Dart function from a directory.
dart_cloud deploy [--force|-f]
Requirements:
- Function must be initialized first (run
dart_cloud init) - Function directory must contain
pubspec.yaml - Function must have entry point (
main.dartorbin/main.dart)
Options:
--force, -f- Force deployment even if no changes detected
What it does:
- Validates function is initialized (has UUID in config)
- Validates function structure and code
- Creates archive of function code
- Uploads to backend with function UUID
- Backend changes status from
init→building→active
Validation Phases:
Phase 1 - Deployment Restrictions:
- Function size < 5 MB
- No forbidden directories (
.git,node_modules, etc.) - No forbidden files (
.env,secrets.json, etc.) - Required files present (
pubspec.yaml,main.dart)
Phase 2 - Code Analysis:
- Exactly one
CloudDartFunctionclass @cloudFunctionannotation present- No
main()function - Security checks (no process execution, FFI, mirrors)
Post-Deployment:
- Function deployment hash is stored in
.dart_tool/function_config.json - Deployment version is tracked for updates
list#
List all deployed functions.
dart_cloud list
logs#
View logs for a specific function.
dart_cloud logs <function-id>
apikey#
Manage API keys for function signing and secure invocation.
dart_cloud apikey <subcommand> [options]
Subcommands:
generate
Generate a new API key for a function.
dart_cloud apikey generate [--function-id <uuid>] [--validity <duration>] [--name <name>]
Options:
--function-id, -f- Function UUID (uses current directory config if not provided)-
--validity, -v- Key validity:1h,1d,1w,1m, orforever(default:1d) --name, -n- Optional friendly name for the key
Validity Options:
1h- 1 hour1d- 1 day (default)1w- 1 week1m- 1 monthforever- Never expires
Examples:
dart_cloud apikey generate --validity 1d
dart_cloud apikey generate --function-id <uuid> --validity 1w --name "Production Key"
What it does:
- Generates a public/private key pair
- Stores public key on backend
- Returns private key (only shown once!)
- Stores private key in Hive database (
~/.containerpub/api_keys/) - Updates function config with API key metadata
info
Get API key info for a function.
dart_cloud apikey info [--function-id <uuid>]
revoke
Revoke an API key.
dart_cloud apikey revoke [--key-id <uuid>] [--revoke]
list
List all API keys for a function.
dart_cloud apikey list [--function-id <uuid>]
roll
Extend an API key's expiration by its validity period.
dart_cloud apikey roll [--key-id <uuid>]
Options:
--key-id, -k- API key UUID to roll (uses current directory config if not provided)
What it does:
- Extends the API key's expiration by its validity period
- For example, if validity is
1d, it adds 1 day to the current expiration - Useful for extending active keys without regenerating them
Examples:
# Roll key from current directory config
dart_cloud apikey roll
# Roll specific key
dart_cloud apikey roll --key-id <api-key-uuid>
invoke#
Invoke a deployed function with optional data and optional signature.
dart_cloud invoke <function-id> [--data '{"key": "value"}'] [--sign]
Options:
--data- JSON data to pass to the function--sign- Sign the request with stored API key
Basic Invocation:
# Invoke without data
dart_cloud invoke <function-id>
# Invoke with JSON data
dart_cloud invoke <function-id> --data '{"key": "value"}'
Signed Invocation (with API Key):
If your function has an API key configured, use the --sign flag to sign the request:
dart_cloud invoke <function-id> --sign
# With data and signature
dart_cloud invoke <function-id> --data '{"key": "value"}' --sign
This will:
- Load the secret key from Hive database
- Create a timestamp and HMAC-SHA256 signature
- Send request with
X-SignatureandX-Timestampheaders - Backend validates signature before executing function
See API Key Signing & Secure Invocation for detailed signing documentation.
apikey#
Manage API keys for function signing. API keys provide an additional layer of security using HMAC-SHA256 signatures.
Generate a new API key:
# From function directory
dart_cloud apikey generate --validity 1d
# With custom name
dart_cloud apikey generate --validity 1w --name "Production Key"
# For specific function
dart_cloud apikey generate --function-id <uuid> --validity 1m
Validity options: 1h (1 hour), 1d (1 day), 1w
(1 week), 1m (1 month), forever
View API key info:
dart_cloud apikey info
dart_cloud apikey info --function-id <uuid>
List all keys:
dart_cloud apikey list
dart_cloud apikey list --function-id <uuid>
Roll an API key (extend expiration):
dart_cloud apikey roll
dart_cloud apikey roll --key-id <api-key-uuid>
Revoke an API key:
dart_cloud apikey revoke
dart_cloud apikey revoke --key-id <api-key-uuid>
See API Keys & Signing for detailed documentation.
delete#
Delete a deployed function.
dart_cloud delete <function-id>
help#
Show help information.
dart_cloud help
version#
Show CLI version.
dart_cloud version
Authentication System#
Token Types#
Access Token:
- Short-lived (1 hour)
- Used for API requests
- Automatically refreshed when expired
- Stored in
~/.dart_cloud/config.json
Refresh Token:
- Long-lived (30 days)
- Used to obtain new access tokens
- Invalidated on logout
- Stored in
~/.dart_cloud/config.json
Token Refresh Flow#
When an access token expires:
- CLI detects 401 Unauthorized response
- Automatically sends refresh token to
/api/auth/refresh - Receives new access token
- Retries original request with new token
- Updates local token storage
Security Features#
- Token Encryption - Tokens stored with encryption at rest
- Automatic Expiry - Access tokens expire after 1 hour
- Blacklisting - Tokens invalidated on logout
- Secure Storage - Tokens stored in user home directory with restricted permissions
Deployment Validation#
The CLI performs comprehensive validation before deployment:
Size Limits#
- Maximum: 5 MB
- Warning: 4 MB
Forbidden Directories#
.git- Version control.github- GitHub workflows.vscode,.idea- IDE configsnode_modules- Node dependencies.dart_tool- Dart build artifactsbuild,.gradle,.cocoapods- Build directories
Forbidden Files#
.env,.env.local- Environment filessecrets.json,credentials.json- Credentials*.pem,*.key,*.p12,*.pfx- Private keys
Code Validation#
- Exactly one
CloudDartFunctionclass @cloudFunctionannotation required- No
main()function - No dangerous imports (dart:mirrors, dart:ffi)
- No process execution (Process.run, Shell, etc.)
Configuration#
Global CLI Configuration#
The CLI configuration is stored at ~/.dart_cloud/config.json:
{
"accessToken": "your-access-token",
"refreshToken": "your-refresh-token",
"serverUrl": "http://localhost:8080"
}
You can manually edit this file to change the server URL.
Function Configuration#
Each function directory contains a .dart_tool/function_config.json file:
{
"function_name": "my_function",
"function_id": "abc123xyz789",
"created_at": "2025-11-16T23:34:00.000Z",
"function_path": "/path/to/function",
"last_deploy_hash": "abc123def456...",
"last_deployed_at": "2025-12-15T02:00:00.000Z",
"deploy_version": 3,
"api_key_uuid": "key-uuid-if-configured",
"api_key_public_key": "base64-public-key",
"api_key_validity": "1d",
"api_key_expires_at": "2025-12-16T02:00:00.000Z"
}
This file is:
- Created by
dart_cloud init -
Updated automatically after
dart_cloud deployanddart_cloud apikey generate - Used for caching function metadata locally
- Optional but recommended for better developer experience
API Key Storage#
When you generate an API key, the private key is stored separately:
-
Private Key:
.dart_tool/api_key.secret(auto-added to.gitignore) - Public Key Info: Stored in
function_config.json
Examples#
Simple Echo Function#
import 'package:dart_cloud_function/dart_cloud_function.dart';
@cloudFunction
class EchoFunction extends CloudDartFunction {
@override
Future<CloudResponse> handle({
required CloudRequest request,
Map<String, String>? env,
}) async {
return CloudResponse.json({
'method': request.method,
'path': request.path,
'query': request.query,
'body': request.body,
});
}
}
JSON Processing Function#
import 'package:dart_cloud_function/dart_cloud_function.dart';
@cloudFunction
class ProcessorFunction extends CloudDartFunction {
@override
Future<CloudResponse> handle({
required CloudRequest request,
Map<String, String>? env,
}) async {
try {
final data = request.body as Map<String, dynamic>;
final result = {
'processed': true,
'input': data,
'timestamp': DateTime.now().toIso8601String(),
};
return CloudResponse.json(result);
} catch (e) {
return CloudResponse.json(
{'error': e.toString()},
statusCode: 400,
);
}
}
}
Troubleshooting#
Authentication Issues#
dart_cloud login
Token Expired#
The CLI automatically refreshes expired access tokens. If refresh fails, login again:
dart_cloud logout
dart_cloud login
Deployment Size Exceeded#
Remove unnecessary files:
rm -rf .git .dart_tool build node_modules
Missing @cloudFunction Annotation#
Add annotation to your class:
@cloudFunction
class MyFunction extends CloudDartFunction { ... }
main() Function Not Allowed#
Remove the main function - the platform handles invocation.
Connection Issues#
Verify the backend server is running and accessible at the configured URL.