housectl is the command-line interface for the housecarl authorization system. It provides comprehensive tools for managing tenants, users, domains, policies, API keys, and performing authorization checks.
Build with Bazel:
./bzsh build //housecarl/src/bin:housectl
Or use the Makefile shortcut:
make cli
Binary location: ./bazel-bin/housecarl/src/bin/housectl
# 1. Login to a housecarl server
housectl config login https://housecarl.example.com admin --tenant system
# 2. Check your connection
housectl config ping
# 3. Explore available commands
housectl <COMMAND> --help
These options are available for all commands:
| Option | Description |
|---|---|
--context <NAME> | Use a specific context for this command (overrides HOUSECARL_CONTEXT) |
--config <FILE> | Path to configuration file (overrides default location) |
--log-level <LEVEL> | Logging verbosity: 0=error, 1=warn, 2=info, 3=debug, 4=trace |
-o, --format <FORMAT> | Output format: pretty (default), table, or json |
--interface-version | Print interface version and exit (for scripting compatibility) |
--help | Display help information |
--version | Display version information |
| Variable | Description | Priority |
|---|---|---|
HOUSECARL_ENDPOINT | Direct endpoint override (requires HOUSECARL_TOKEN) | Highest |
HOUSECARL_TOKEN | Direct token override (requires HOUSECARL_ENDPOINT) | Highest |
HOUSECARL_CONTEXT | Context name to use (overrides config default) | Medium |
HOUSECARL_CONFIG_PATH | Custom config file path (must be absolute) | N/A |
HOUSECTL_PASSWORD | Password for login (avoids interactive prompt) | N/A |
Precedence Order (highest to lowest):
HOUSECARL_ENDPOINT + HOUSECARL_TOKEN (direct connection, bypasses config)--context CLI flagHOUSECARL_CONTEXT environment variablecurrent context from config fileAll Platforms: ~/.config/housecarl.toml
current = "admin@acme@localhost"
[contexts.admin@acme@localhost]
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
endpoint = "http://localhost:50051"
user_id = "7c9e6679-7425-40de-944b-e07fc1f90ae7"
username = "admin"
tenant_id = "550e8400-e29b-41d4-a716-446655440000"
[contexts.devuser@staging@staging-server]
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
endpoint = "https://staging.example.com:50051"
user_id = "8c9e6679-7425-40de-944b-e07fc1f90ae8"
username = "devuser"
tenant_id = "660e8400-e29b-41d4-a716-446655440001"
Configuration Fields:
current: Name of the currently active contextcontexts: Map of context configurations by name
username@tenant@hosttoken: JWT authentication token (obtained from login)tenant_id: UUID of the tenant (optional for system tenant)user_id: UUID of the authenticated userendpoint: gRPC endpoint URLusername: Username for display purposesAuthentication and connection configuration commands.
Authenticate with a housecarl server and establish a session.
Usage:
housectl config login <ENDPOINT> <USERNAME> [OPTIONS]
Arguments:
<ENDPOINT> - Server URL (gRPC endpoint, e.g., https://housecarl.example.com or http://localhost:50051)<USERNAME> - Username for authenticationOptions:
--tenant <TENANT> - Tenant ID or name to authenticate against--password <PASSWORD> - Password (or set HOUSECTL_PASSWORD env var; will prompt if not provided)--duration <SECONDS> - Session token validity in seconds (default: 43200 = 12 hours)--as <CONTEXT_NAME> - Use custom context name instead of auto-generated oneExamples:
# Login with interactive password prompt
housectl config login https://housecarl.example.com admin --tenant system
# Login with password from environment variable
export HOUSECTL_PASSWORD=secret123
housectl config login http://localhost:50051 alice --tenant acme-corp
# Login with password flag
housectl config login http://localhost:50051 alice --tenant acme-corp --password secret123
# Login with custom token duration (24 hours)
housectl config login https://housecarl.example.com admin --tenant system --duration 86400
# Login with custom context name
housectl config login http://localhost:50051 admin --tenant acme --as my-local-dev
Notes:
Clear stored credentials and end the current session.
Usage:
housectl config logout
Example:
housectl config logout
Display current authentication status and configuration details.
Usage:
housectl config status
Example:
housectl config status
Output includes:
Verify connection to the server with current credentials.
Usage:
housectl config ping
Example:
housectl config ping
Notes:
Check server health status.
Usage:
housectl config health [OPTIONS]
Options:
--watch - Continuously monitor health status (stream updates until Ctrl+C)Examples:
# Single health check
housectl config health
# Continuous health monitoring
housectl config health --watch
Health Status Codes:
0 - UNKNOWN1 - SERVING2 - NOT_SERVING3 - SERVICE_UNKNOWNList all available contexts.
Usage:
housectl config list
Example:
housectl config list
Output:
CONTEXT NAME ENDPOINT CURRENT
admin@acme@localhost http://localhost:50051 *
devuser@staging@staging-server https://staging.example.com:50051
Show the current active context name.
Usage:
housectl config current
Example:
housectl config current
Output:
admin@acme@localhost
Switch to a different context.
Usage:
housectl config use <CONTEXT_NAME>
Arguments:
<CONTEXT_NAME> - Name of the context to switch toExample:
housectl config use devuser@staging@staging-server
Notes:
housectl config list to see available contextsShow details of a specific context.
Usage:
housectl config show <CONTEXT_NAME>
Arguments:
<CONTEXT_NAME> - Name of the context to show details forExample:
housectl config show admin@acme@localhost
Output:
Context: admin@acme@localhost
Endpoint: http://localhost:50051
Username: admin
User ID: 7c9e6679-7425-40de-944b-e07fc1f90ae7
Tenant: 550e8400-e29b-41d4-a716-446655440000
Remove a context from the configuration.
Usage:
housectl config remove <CONTEXT_NAME>
Arguments:
<CONTEXT_NAME> - Name of the context to removeExample:
housectl config remove old-context
Notes:
housectl config use to switch contexts firstUser account management commands.
Create a new user account.
Usage:
housectl user create <USERNAME> <PASSWORD> <EMAIL>
Arguments:
<USERNAME> - Unique username for the account<PASSWORD> - Password (min 8 characters, must include uppercase, lowercase, number, and special character)<EMAIL> - Email address for the accountExample:
housectl user create alice Secret123! alice@example.com
Password Requirements:
Retrieve user details by ID or username.
Usage:
housectl user get <USER>
Arguments:
<USER> - User ID (UUID format) or usernameExamples:
# Get by username
housectl user get alice
# Get by UUID
housectl user get 550e8400-e29b-41d4-a716-446655440000
Modify user account properties.
Usage:
housectl user update <USER> [OPTIONS]
Arguments:
<USER> - User ID (UUID format) or usernameOptions:
--username <USERNAME> - New username--email <EMAIL> - New email address--active <BOOL> - Set active status (true to enable, false to disable)Example:
housectl user update alice --email newemail@example.com --active true
Change a user's password.
Usage:
housectl user change-password <USER> <PASSWORD>
Arguments:
<USER> - User ID (UUID format) or username<PASSWORD> - New password (must meet password requirements)Example:
housectl user change-password alice NewSecret123!
Permanently delete a user account.
Usage:
housectl user delete <USER> [OPTIONS]
Arguments:
<USER> - User ID (UUID format) or username to deleteOptions:
-y, --yes - Skip confirmation prompt (use with caution)Example:
housectl user delete alice --yes
Warning: This action is irreversible.
Tenant management and user association commands.
Retrieve tenant details by ID or name.
Usage:
housectl tenant get <ID>
Arguments:
<ID> - Tenant ID (UUID) or unique nameExamples:
# Get by name
housectl tenant get acme-corp
# Get by UUID
housectl tenant get 550e8400-e29b-41d4-a716-446655440000
Display the tenant associated with your current login session.
Usage:
housectl tenant current
Example:
housectl tenant current
Modify tenant properties.
Usage:
housectl tenant update <ID> [OPTIONS]
Arguments:
<ID> - Tenant ID (UUID) or name to updateOptions:
--name <NAME> - New display name for the tenant--description <DESCRIPTION> - New description for the tenant--subscription <PLAN> - Subscription plan identifier (e.g., 'free', 'pro', 'enterprise')--active <BOOL> - Set active status (true to enable, false to disable)Example:
housectl tenant update acme-corp --name "Acme Corporation" --description "Updated description"
Permanently delete a tenant and all associated resources.
Usage:
housectl tenant delete <ID> [OPTIONS]
Arguments:
<ID> - Tenant ID (UUID) or name to deleteOptions:
-y, --yes - Skip confirmation prompt (use with extreme caution)Example:
housectl tenant delete acme-corp --yes
Warning: This action is irreversible and will delete all domains, policies, and user associations.
Disable a specific domain within a tenant.
Usage:
housectl tenant disable-domain <DOMAIN> [OPTIONS]
Arguments:
<DOMAIN> - Domain ID (UUID) or name to disableOptions:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)Example:
housectl tenant disable-domain billing-domain --tenant acme-corp
Grant a user access to a tenant.
Usage:
housectl tenant associate-user <TENANT> <USERNAME>
Arguments:
<TENANT> - Tenant ID (UUID) or name to associate the user with<USERNAME> - Username to associateExamples:
# Associate by tenant name
housectl tenant associate-user acme-corp alice@example.com
# Associate by tenant UUID
housectl tenant associate-user 550e8400-e29b-41d4-a716-446655440000 alice@example.com
Remove a user's access from a tenant.
Usage:
housectl tenant disassociate-user <TENANT> <USERNAME>
Arguments:
<TENANT> - Tenant ID (UUID) or name to remove the user from<USERNAME> - Username to removeExamples:
housectl tenant disassociate-user acme-corp alice@example.com
housectl tenant disassociate-user 550e8400-e29b-41d4-a716-446655440000 alice@example.com
Check if a user is associated with a tenant.
Usage:
housectl tenant is-user-associated <TENANT> <USERNAME>
Arguments:
<TENANT> - Tenant ID (UUID) or name to check<USERNAME> - Username to checkExamples:
housectl tenant is-user-associated acme-corp alice@example.com
housectl tenant is-user-associated 550e8400-e29b-41d4-a716-446655440000 alice@example.com
List all users associated with a tenant.
Usage:
housectl tenant all-associated-users [TENANT]
Arguments:
[TENANT] - Tenant ID (UUID) or name (defaults to your current tenant)Examples:
# List users in current tenant
housectl tenant all-associated-users
# List users in specific tenant by name
housectl tenant all-associated-users acme-corp
# List users in specific tenant by UUID
housectl tenant all-associated-users 550e8400-e29b-41d4-a716-446655440000
Create a service account for automated systems and integrations.
Usage:
housectl tenant service-account create <NAME> <DESCRIPTION> [OPTIONS]
Arguments:
<NAME> - Service account name (will be automatically prefixed with 'svc:')<DESCRIPTION> - Human-readable description of the service account's purposeOptions:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)--expiration-days <DAYS> - API key expiration period in days (default: 365)Example:
housectl tenant service-account create billing-webhook "Handles billing webhooks" --expiration-days 90
List all service accounts for a tenant.
Usage:
housectl tenant service-account list [OPTIONS]
Options:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)--active-only - Filter to show only active service accountsExample:
housectl tenant service-account list --active-only
Retrieve details of a specific service account.
Usage:
housectl tenant service-account get <ID>
Arguments:
<ID> - Service account ID (UUID format)Example:
housectl tenant service-account get 550e8400-e29b-41d4-a716-446655440000
Update a service account's status.
Usage:
housectl tenant service-account update <ID> [OPTIONS]
Arguments:
<ID> - Service account ID (UUID format)Options:
--active <BOOL> - Set active status (true to enable, false to disable)Example:
housectl tenant service-account update 550e8400-e29b-41d4-a716-446655440000 --active false
Permanently delete a service account and revoke its access.
Usage:
housectl tenant service-account delete <ID> [OPTIONS]
Arguments:
<ID> - Service account ID (UUID format)Options:
-y, --yes - Skip confirmation prompt (use with caution)Example:
housectl tenant service-account delete 550e8400-e29b-41d4-a716-446655440000 --yes
Warning: This action is irreversible and will revoke all access for this service account.
System administration commands (requires admin privileges).
Create a new tenant organization.
Usage:
housectl admin create <NAME> <DESCRIPTION>
Arguments:
<NAME> - Unique name for the tenant organization (≤100 characters)<DESCRIPTION> - Human-readable description of the tenant (≤500 characters)Example:
housectl admin create "Acme Corp" "Enterprise customer"
Input Validation:
Disable a tenant (suspends all access for that organization).
Usage:
housectl admin disable [TENANT_ID] [OPTIONS]
Arguments:
[TENANT_ID] - Tenant ID (UUID) to disable; defaults to current tenant if omittedOptions:
-y, --yes - Skip confirmation promptExample:
housectl admin disable 550e8400-e29b-41d4-a716-446655440000
Enable a previously disabled tenant.
Usage:
housectl admin enable [TENANT_ID] [OPTIONS]
Arguments:
[TENANT_ID] - Tenant ID (UUID) to enable; defaults to current tenant if omittedOptions:
-y, --yes - Skip confirmation promptExample:
housectl admin enable 550e8400-e29b-41d4-a716-446655440000
Set tenant enabled/disabled status explicitly.
Usage:
housectl admin tenant-set-enabled <STATUS> [TENANT_ID] [OPTIONS]
Arguments:
<STATUS> - Target status: true (enabled) or false (disabled)[TENANT_ID] - Tenant ID (UUID); defaults to current tenant if omittedOptions:
-y, --yes - Skip confirmation promptExample:
housectl admin tenant-set-enabled true 550e8400-e29b-41d4-a716-446655440000
List all tenants in the system.
Usage:
housectl admin list
Example:
housectl admin list
List all users across all tenants.
Usage:
housectl admin list-users
Example:
housectl admin list-users
Reset API call limit counters for all tenants.
Usage:
housectl admin refresh-tenants
Example:
housectl admin refresh-tenants
Notes:
Domain management commands (authorization policy containers).
Create a new authorization domain with policies.
Usage:
housectl domain create <NAME> [TENANT] [POLICIES...]
Arguments:
<NAME> - Unique name for the domain[TENANT] - Tenant ID or name (defaults to your current tenant)[POLICIES...] - Policy files or directories to include in the domainExamples:
# Create domain with single policy file
housectl domain create billing-domain ./policies/billing.hcl
# Create domain with policy directory
housectl domain create api-access my-tenant ./policies/
# Create domain with multiple policy files
housectl domain create production-access acme-corp policy1.hcl policy2.hcl
Notes:
Retrieve domain details by ID or name.
Usage:
housectl domain get <DOMAIN> [OPTIONS]
Arguments:
<DOMAIN> - Domain ID (UUID) or nameOptions:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)Examples:
# Get by name
housectl domain get billing-domain
# Get by UUID with specific tenant
housectl domain get 550e8400-e29b-41d4-a716-446655440000 --tenant acme-corp
List all domains in a tenant.
Usage:
housectl domain list [OPTIONS]
Options:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)Examples:
# List domains in current tenant
housectl domain list
# List domains in specific tenant
housectl domain list --tenant acme-corp
Modify domain properties.
Usage:
housectl domain update <DOMAIN> [OPTIONS]
Arguments:
<DOMAIN> - Domain ID (UUID) or name to updateOptions:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)--name <NAME> - New name for the domain--active <BOOL> - Set active status (true to enable, false to disable)Example:
housectl domain update billing-domain --name new-billing-domain --active true
Permanently delete a domain and its policies.
Usage:
housectl domain delete <DOMAIN> [OPTIONS]
Arguments:
<DOMAIN> - Domain ID (UUID) or name to deleteOptions:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)-y, --yes - Skip confirmation prompt (use with caution)Example:
housectl domain delete billing-domain --yes
Warning: This action is irreversible.
Replace all policies in a domain.
Usage:
housectl domain put-policies <DOMAIN> <POLICIES...>
Arguments:
<DOMAIN> - Domain ID (UUID) or name to update<POLICIES...> - Policy files or directories to deployExamples:
# Replace with policy directory
housectl domain put-policies billing-domain ./policies/
# Replace with specific policy files
housectl domain put-policies api-domain policy1.hcl policy2.hcl
Notes:
List all policies in a domain.
Usage:
housectl domain list-policies <DOMAIN> [OPTIONS]
Arguments:
<DOMAIN> - Domain ID (UUID) or nameOptions:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)Examples:
# List policies by domain name
housectl domain list-policies billing-domain
# List policies by domain UUID
housectl domain list-policies 550e8400-e29b-41d4-a716-446655440000
Get a specific policy from a domain by name.
Usage:
housectl domain get-policy <DOMAIN> <POLICY_NAME> [OPTIONS]
Arguments:
<DOMAIN> - Domain ID (UUID) or name<POLICY_NAME> - Policy name to retrieveOptions:
--tenant <TENANT> - Tenant ID or name (defaults to your current tenant)Examples:
housectl domain get-policy billing-domain admin-access
housectl domain get-policy api-domain read-only-policy
Authorization checks and policy management commands.
Check if a request is authorized against server policies.
Usage:
housectl authz can-i <REQUEST_FILE>
Arguments:
<REQUEST_FILE> - Path to JSON file containing the authorization requestExample:
housectl authz can-i request.json
Request File Format (request.json):
{
"subject": "user:alice",
"action": "read",
"object": {
"type": "document",
"id": "doc-123"
}
}
Response:
ALLOW or DENY with the matching policy (if any)Test authorization with custom policies (speculative check).
Usage:
housectl authz can-i-maybe <REQUEST> <POLICIES...>
Arguments:
<REQUEST> - Request to check (use 'file://' prefix for file path, or inline JSON)<POLICIES...> - Policy files or directories to evaluate against (in addition to server policies)Examples:
# Test with policy directory
housectl authz can-i-maybe request.json ./policies/
# Test with file URI
housectl authz can-i-maybe file://request.json policy1.hcl policy2.hcl
Notes:
Evaluate authorization locally without server connection.
Usage:
housectl authz can-i-local --request <FILE> [OPTIONS] <POLICIES...>
Arguments:
<POLICIES...> - Policy files or directories to evaluate againstOptions:
--request <FILE> - Path to JSON file containing the authorization request--tenant <UUID> - Tenant ID to simulate (equivalent to JWT tenant_id claim)--domain <DOMAIN> - Domain name or ID to evaluate againstExamples:
# Local evaluation with policy directory
housectl authz can-i-local --request request.json ./policies/
# Local evaluation with tenant context
housectl authz can-i-local --request request.json --tenant 550e8400-e29b-41d4-a716-446655440000 ./policies/
Notes:
Parse and validate policy files without executing them.
Usage:
housectl authz parse-policies <POLICIES...>
Arguments:
<POLICIES...> - Policy files or directories to validateExamples:
# Validate policy directory
housectl authz parse-policies ./policies/
# Validate specific policy files
housectl authz parse-policies policy1.hcl policy2.hcl
Exit Codes:
0 - All policies are valid1 - One or more policies have errorsNotes:
API key management for programmatic access.
Create a new API key for programmatic access.
Usage:
housectl api-key create <USER_ID>
Arguments:
<USER_ID> - User ID (UUID format) to create key forExample:
housectl api-key create 550e8400-e29b-41d4-a716-446655440000
Retrieve details of an existing API key.
Usage:
housectl api-key get <USER_ID> <KEY_ID>
Arguments:
<USER_ID> - User ID (UUID format) who owns the key<KEY_ID> - API key ID (UUID format) to retrieveExample:
housectl api-key get 550e8400-e29b-41d4-a716-446655440000 660e8400-e29b-41d4-a716-446655440001
Delete an API key (revokes programmatic access).
Usage:
housectl api-key delete <USER_ID> <KEY_ID> [OPTIONS]
Arguments:
<USER_ID> - User ID (UUID format) who owns the key<KEY_ID> - API key ID (UUID format) to deleteOptions:
-y, --yes - Skip confirmation prompt (use with caution)Example:
housectl api-key delete 550e8400-e29b-41d4-a716-446655440000 660e8400-e29b-41d4-a716-446655440001 --yes
| Code | Meaning |
|---|---|
0 | Success or operation cancelled |
1 | Generic error |
2 | Invalid input |
3 | Not authenticated |
4 | API error |
5 | Client error |
6 | IO error |
7 | Invalid state |
Not Logged In:
Error: NotLoggedInError
Please run: housectl config login
Solution: Run housectl config login <ENDPOINT> <USERNAME> --tenant <TENANT>
Token Expired:
Error: Your token will expire in less than 5 minutes
Solution: housectl automatically attempts to refresh tokens. If this fails, re-login.
Connection Error:
Error: Cannot connect to the server
Solutions:
Invalid Configuration:
Error: ConfigurationError
Solution: Check configuration file exists and has correct permissions (chmod 600)
Human-readable output with formatting:
housectl user get alice
User: alice
ID: 550e8400-e29b-41d4-a716-446655440000
Email: alice@example.com
Active: true
Machine-parsable output:
housectl user get alice --format json
{
"username": "alice",
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "alice@example.com",
"active": true
}
Tabular output for list commands:
housectl admin list --format table
ID NAME ACTIVE
550e8400-e29b-41d4-a716-446655440000 acme-corp true
660e8400-e29b-41d4-a716-446655440001 beta-corp true
#!/bin/bash
# Extract user emails
housectl admin list-users --format json | jq -r '.users[].email'
#!/bin/bash
# Automated login
export HOUSECTL_PASSWORD=secret123
housectl config login https://housecarl.example.com admin --tenant system
#!/bin/bash
# Create multiple users from CSV
while IFS=, read -r username email password; do
housectl user create "$username" "$password" "$email"
done < users.csv
#!/bin/bash
# Check exit codes
if housectl config ping; then
echo "Server is reachable"
else
echo "Server is unreachable (exit code: $?)"
exit 1
fi
chmod 600 ~/.config/housecarl.toml--yes flag only in automated scriptsauthz parse-policies in CI/CD pipelinesauthz can-i-local# Login to different environments (each creates a context)
housectl config login https://dev.housecarl.example.com admin --tenant system
housectl config login https://prod.housecarl.example.com admin --tenant system
# List all available contexts
housectl config list
# Switch between environments
housectl config use admin@system@dev.housecarl.example.com
housectl config use admin@system@prod.housecarl.example.com
# Use environment variable for scripts
HOUSECARL_CONTEXT=admin@system@prod.housecarl.example.com housectl user list-users
# Use --context flag for one-off commands
housectl --context admin@system@prod.housecarl.example.com user list-users
# 1. Parse policies locally
housectl authz parse-policies ./policies/
# 2. Test locally without server
housectl authz can-i-local --request test-request.json ./policies/
# 3. Test speculatively with server
housectl authz can-i-maybe test-request.json ./policies/
# 4. Deploy to server
housectl domain put-policies production ./policies/
# 5. Verify with real authorization check
housectl authz can-i test-request.json
# Example GitHub Actions workflow
- name: Validate Policies
run: |
./housectl authz parse-policies ./policies/
if [ $? -ne 0 ]; then
echo "Policy validation failed"
exit 1
fi
# Check server is running
curl http://localhost:50051
# Verify configuration
housectl config status
# Test connection
housectl config ping
# Check token status
housectl config status
# Re-login to get new token
housectl config login <ENDPOINT> <USERNAME> --tenant <TENANT>
Ensure the authenticated user has appropriate permissions:
# Check file exists
ls -la ~/.config/housecarl.toml
# Check permissions
chmod 600 ~/.config/housecarl.toml
# List available contexts
housectl config list
# Recreate config with login
rm ~/.config/housecarl.toml
housectl config login <ENDPOINT> <USERNAME> --tenant <TENANT>
If you get a "Context not found" error:
# List available contexts
housectl config list
# Switch to an existing context
housectl config use <context-name>
# Or login again to create a new context
housectl config login <ENDPOINT> <USERNAME> --tenant <TENANT>
For issues, bug reports, or feature requests, visit: