Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Alloy CLI Reference

Alloy is a headless, API-first project management tool. The CLI (alloy) lets you manage organizations, projects, tickets, sprints, time entries, and more from your terminal. For the HTTP API, see the API Reference. New to Alloy? Start with the Getting Started guide.

Global Flags

Every command accepts:

FlagEnv VarDefaultDescription
--format <json|table|plain>ALLOY_FORMATauto-detectOutput format
--api-url <URL>ALLOY_API_URLhttp://localhost:3000API server URL

Output Formats

The --format flag controls how results are displayed:

FormatDescription
jsonMachine-readable JSON (pretty-printed)
tableHuman-readable columns with headers
plainMinimal output suitable for scripting

TTY auto-detection: When output goes to an interactive terminal, format defaults to table. When piped or redirected, it defaults to json. Override with --format or the ALLOY_FORMAT environment variable.

The NO_COLOR environment variable suppresses ANSI color codes when set to any non-empty value.


Commands

health

Check API server connectivity and status.

alloy health [--format <FORMAT>]
FlagDescription
--formatOutput format (json, table, plain)

Examples:

# Quick status check
alloy health

# Machine-readable health check for monitoring
alloy health --format json

migrate

Run database migrations against the configured database.

alloy migrate

Uses ALLOY_DATABASE_URL (default: sqlite://alloy.db). Migrations are embedded in the binary — no external migration files needed at runtime.

Env VarDefaultDescription
ALLOY_DATABASE_URLsqlite://alloy.dbDatabase connection URL

Examples:

# Run migrations against default SQLite database
alloy migrate

# Run migrations against PostgreSQL
ALLOY_DATABASE_URL=postgres://localhost/alloy alloy migrate

serve

Start the Alloy API server.

alloy serve [--db <URL>] [--port <PORT>]
FlagEnv VarDefaultDescription
--db <URL>ALLOY_DATABASE_URLsqlite://alloy.dbDatabase URL
--port <PORT>PORT3000Listen port

Examples:

# Start with defaults (SQLite on port 3000)
alloy serve

# Start with PostgreSQL on a custom port
alloy serve --db postgres://localhost/alloy --port 8080

auth

Authenticate with the Alloy API and manage API keys.

auth login

Log in with email and password. Stores credentials locally.

alloy auth login --email <EMAIL> --password <PASSWORD>
FlagDescription
--email <EMAIL>Account email address
--password <PASSWORD>Account password

Credentials are saved to ~/.config/alloy/credentials.toml and include the access token, refresh token, user ID, and email. The CLI automatically refreshes expired tokens on 401 responses.

Examples:

# Log in and save credentials
alloy auth login --email admin@example.com --password s3cret

# Log in and capture just the user ID
alloy auth login --email admin@example.com --password s3cret --format plain

auth token

Display the currently stored authentication token (masked for security).

alloy auth token

Shows the first 12 and last 4 characters of the token with the middle masked.

Examples:

# Check which account is logged in
alloy auth token

# Get token info as JSON
alloy auth token --format json

auth api-key create

Create a new API key with optional scope and project restrictions.

alloy auth api-key create --name <NAME> [--scopes <SCOPES>] [--projects <PROJECT_IDS>]
FlagDefaultDescription
--name <NAME>(required)Human-readable key name
--scopes <SCOPES>read,writeComma-separated: read, write, admin
--projects <IDS>all projectsComma-separated project UUIDs to restrict access

API keys are prefixed alloy_live_ (production) or alloy_test_ (testing). The full key is shown only once at creation time.

Scopes:

  • read — Read-only access to resources
  • write — Create, update, and delete resources
  • admin — Full access including user and org management

Examples:

# Create a read-write key for CI
alloy auth api-key create --name "CI Pipeline"

# Create a read-only key restricted to one project
alloy auth api-key create --name "Dashboard" --scopes read --projects 550e8400-e29b-41d4-a716-446655440000

# Create an admin key and capture it for scripting
alloy auth api-key create --name "Admin Script" --scopes read,write,admin --format plain

auth api-key list

List all API keys for the current user.

alloy auth api-key list

Examples:

# View all API keys
alloy auth api-key list

# List keys as JSON for automation
alloy auth api-key list --format json

auth api-key revoke

Revoke an API key by its ID.

alloy auth api-key revoke <ID>

Examples:

# Revoke a specific key
alloy auth api-key revoke 550e8400-e29b-41d4-a716-446655440000

# List keys then revoke one
alloy auth api-key list --format json | jq '.[0].id' -r | xargs alloy auth api-key revoke

org

Manage organizations (tenants).

org create

alloy org create --name <NAME> --slug <SLUG>
FlagDescription
--name <NAME>Organization display name
--slug <SLUG>URL-friendly identifier (e.g. acme-corp)

Examples:

# Create a new organization
alloy org create --name "Acme Corp" --slug acme-corp

# Create and capture org ID
ORG_ID=$(alloy org create --name "Acme Corp" --slug acme-corp --format json | jq -r '.id')

org list

alloy org list

Examples:

# List all organizations
alloy org list

# Get org IDs for scripting
alloy org list --format json | jq '.[].id'

org switch

Set the active organization for subsequent commands.

alloy org switch <ID>

Examples:

# Switch active organization
alloy org switch 550e8400-e29b-41d4-a716-446655440000

# Switch to the first org
alloy org switch $(alloy org list --format json | jq -r '.data[0].id')

project

Manage projects within an organization.

project create

alloy project create --org-id <ORG_ID> --key <KEY> --name <NAME> [--description <DESC>] [--team-id <TEAM_ID>]
FlagDescription
--org-id <ORG_ID>Organization UUID
--key <KEY>Short project key, 1-10 chars (e.g. BACK, MOBILE)
--name <NAME>Project display name
--description <DESC>Optional description
--team-id <TEAM_ID>Optional team UUID

Examples:

# Create a backend project
alloy project create --org-id $ORG_ID --key BACK --name "Backend Services"

# Create with description
alloy project create --org-id $ORG_ID --key WEB --name "Web Frontend" --description "React SPA and design system"

project list

alloy project list --org-id <ORG_ID> [--cursor <CURSOR>] [--limit <LIMIT>]
FlagDefaultDescription
--org-id <ORG_ID>(required)Organization UUID
--cursor <CURSOR>Pagination cursor from previous response
--limit <LIMIT>20Results per page

Examples:

# List all projects in an org
alloy project list --org-id $ORG_ID

# Page through results
alloy project list --org-id $ORG_ID --limit 5 --cursor "next_cursor_value"

project get

alloy project get <ID>

Examples:

# Get project details
alloy project get 550e8400-e29b-41d4-a716-446655440000

# Get project as JSON
alloy project get $PROJECT_ID --format json

project update

alloy project update <ID> [--name <NAME>] [--description <DESC>] [--team-id <ID|none>] [--cap-type <capex|opex|none>] [--phase <preliminary|app-development|post-implementation|none>] [--cost-center-id <ID|none>] [--amortization-months <INT|none>]

Pass none to any optional field to unset it.

Examples:

# Rename a project
alloy project update $PROJECT_ID --name "Backend API v2"

# Set capitalization type for time tracking
alloy project update $PROJECT_ID --cap-type capex --phase app-development --amortization-months 36

project delete

alloy project delete <ID>

Examples:

# Delete a project
alloy project delete $PROJECT_ID

# Delete by key lookup
alloy project delete $(alloy project get $PROJECT_ID --format json | jq -r '.id')

project use

Set a default project context. This enables bare ticket number resolution (e.g., alloy ticket get 42 resolves to PROJ-42).

alloy project use <KEY_OR_ID>

Accepts either a project key (like BACK) or a UUID. The project ID and key are saved to ~/.config/alloy/credentials.toml.

Examples:

# Set default project by key
alloy project use BACK

# Set default project by UUID
alloy project use 550e8400-e29b-41d4-a716-446655440000

# Now bare numbers work everywhere
alloy ticket get 42     # resolves to BACK-42
alloy ticket list       # lists tickets in BACK

ticket

Create, list, update, and manage tickets. Supports smart ID resolution.

Smart ID Resolution: Ticket commands accept three reference formats:

FormatExampleResolution
UUID550e8400-...Used directly
KEY-NUMBERBACK-42Resolved via API (/api/v1/tickets/resolve?ref=BACK-42)
Bare number42Requires project context; resolves as {PROJECT_KEY}-42

Set project context with alloy project use <KEY> to enable bare number references.

ticket create

alloy ticket create [--project <PROJECT_ID>] [--title <TITLE>] [--description <DESC>] [--priority <PRIORITY>] [--status <STATUS>] [--assignee-id <UUID>] [--reporter-id <UUID>]
FlagDefaultDescription
--project <ID>credentials projectProject UUID (prompted interactively if omitted)
--title <TITLE>Ticket title (prompted interactively if omitted)
--description <DESC>Detailed description
--priority <PRIORITY>mediumnone, low, medium, high, urgent
--status <STATUS>backlogbacklog, todo, in_progress, in_review, done, cancelled
--assignee-id <UUID>Assignee user UUID (fuzzy selector in interactive mode)
--reporter-id <UUID>logged-in userReporter user UUID

In interactive mode (TTY), missing fields are prompted with fuzzy selectors for projects, users, and priorities.

Examples:

# Create a ticket interactively (prompts for missing fields)
alloy ticket create

# Create a ticket non-interactively
alloy ticket create --project $PROJECT_ID --title "Fix login timeout" --priority high --status todo

# Create and capture the ticket ID
TICKET_ID=$(alloy ticket create --project $PROJECT_ID --title "Add caching" --format json | jq -r '.id')

ticket list

alloy ticket list [--project <PROJECT_ID>] [--status <STATUS>] [--priority <PRIORITY>] [--assignee-id <UUID>] [--cursor <CURSOR>] [--limit <LIMIT>]
FlagDefaultDescription
--project <ID>credentials projectProject UUID
--status <STATUS>Filter by status (comma-separated)
--priority <PRIORITY>Filter by priority
--assignee-id <UUID>Filter by assignee
--cursor <CURSOR>Pagination cursor
--limit <LIMIT>20Results per page

Examples:

# List tickets in the default project
alloy ticket list

# Filter by status
alloy ticket list --status todo,in_progress

# List high-priority tickets as JSON
alloy ticket list --priority high --format json

# Page through results
alloy ticket list --limit 10 --cursor "next_cursor_value"

ticket get

alloy ticket get <ID>

Accepts UUID, KEY-NUMBER, or bare number.

Examples:

# Get by project-qualified reference
alloy ticket get BACK-42

# Get by bare number (uses default project)
alloy ticket get 42

# Get by UUID
alloy ticket get 550e8400-e29b-41d4-a716-446655440000

ticket update

alloy ticket update <ID> [--title <TITLE>] [--description <DESC>] [--status <STATUS>] [--priority <PRIORITY>] [--assignee-id <UUID|none>] [--add-label <LABEL_ID>] [--remove-label <LABEL_ID>]

In interactive mode with no flags, a multi-select dialog prompts for which fields to update with fuzzy selectors for users and labels.

Examples:

# Move a ticket to in-progress
alloy ticket update BACK-42 --status in_progress

# Assign and add a label
alloy ticket update 42 --assignee-id $USER_ID --add-label $LABEL_ID

# Interactive update (prompts for fields to change)
alloy ticket update BACK-42

ticket batch-update

alloy ticket batch-update --ticket-ids <UUID,UUID,...> [--title <TITLE>] [--description <DESC>] [--status <STATUS>] [--priority <PRIORITY>] [--assignee-id <UUID>] [--sprint-id <UUID>]

Apply the same field updates to multiple tickets at once. At least one field flag must be provided.

FlagDescription
--ticket-ids <IDs>Comma-separated ticket UUIDs
--title <TITLE>New title for all tickets
--description <DESC>New description for all tickets
--status <STATUS>New status for all tickets
--priority <PRIORITY>New priority (none, low, medium, high, urgent)
--assignee-id <UUID>Assignee UUID for all tickets
--sprint-id <UUID>Sprint UUID for all tickets

Examples:

# Set all tickets to high priority
alloy ticket batch-update --ticket-ids "$ID1,$ID2" --priority high

# Move multiple tickets to Done
alloy ticket batch-update --ticket-ids "$ID1,$ID2" --status Done

ticket batch-transition

alloy ticket batch-transition --ticket-ids <UUID,UUID,...> --to-status <STATUS>

Transition multiple tickets to the same target status. Each ticket is validated against its project’s workflow. Reports successes and failures individually.

FlagDescription
--ticket-ids <IDs>Comma-separated ticket UUIDs
--to-status <STATUS>Target status to transition all tickets to

Examples:

# Transition all sprint tickets to Done
alloy ticket batch-transition --ticket-ids "$ID1,$ID2" --to-status Done

comment

Add and manage comments on tickets.

comment add

alloy comment add --ticket <TICKET_REF> --body <BODY> --author-id <UUID> [--parent-id <COMMENT_ID>]
FlagDescription
--ticket <REF>Ticket reference (UUID, KEY-NUMBER, or bare number)
--body <BODY>Comment text
--author-id <UUID>Author’s user UUID
--parent-id <ID>Parent comment UUID for threading

Examples:

# Add a comment to a ticket
alloy comment add --ticket BACK-42 --body "Deployed to staging" --author-id $USER_ID

# Reply to an existing comment (threaded)
alloy comment add --ticket 42 --body "Confirmed fixed" --author-id $USER_ID --parent-id $PARENT_COMMENT_ID

comment list

alloy comment list --ticket <TICKET_REF> [--cursor <CURSOR>] [--limit <LIMIT>]

Examples:

# List comments on a ticket
alloy comment list --ticket BACK-42

# Get comments as JSON
alloy comment list --ticket 42 --format json

comment get

alloy comment get <ID>

Examples:

# Get a specific comment
alloy comment get $COMMENT_ID

# Get comment as JSON
alloy comment get $COMMENT_ID --format json

comment update

alloy comment update <ID> --body <BODY>

Examples:

# Edit a comment
alloy comment update $COMMENT_ID --body "Updated: deployed to production"

# Update and verify
alloy comment update $COMMENT_ID --body "Fixed in v2.1" && alloy comment get $COMMENT_ID

comment delete

alloy comment delete <ID>

Examples:

# Delete a comment
alloy comment delete $COMMENT_ID

label

Manage labels for organizing tickets.

label create

alloy label create --org <ORG_ID> --name <NAME> --color <COLOR>
FlagDescription
--org <ORG_ID>Organization UUID
--name <NAME>Label name (e.g. bug, feature)
--color <COLOR>Hex color code (e.g. #FF0000)

Examples:

# Create a bug label
alloy label create --org $ORG_ID --name bug --color "#FF0000"

# Create a feature label
alloy label create --org $ORG_ID --name feature --color "#00FF00"

label list

alloy label list --org <ORG_ID> [--cursor <CURSOR>] [--limit <LIMIT>]

Examples:

# List all labels
alloy label list --org $ORG_ID

# Get labels as JSON
alloy label list --org $ORG_ID --format json

label get

alloy label get <ID>

Examples:

# Get label details
alloy label get $LABEL_ID

label update

alloy label update <ID> [--name <NAME>] [--color <COLOR>]

Examples:

# Change label color
alloy label update $LABEL_ID --color "#0000FF"

# Rename a label
alloy label update $LABEL_ID --name "critical-bug"

label delete

alloy label delete <ID>

Examples:

# Delete a label
alloy label delete $LABEL_ID

workflow

Define custom workflows with statuses and allowed transitions.

workflow create

alloy workflow create --org-id <ORG_ID> --name <NAME> --statuses <JSON> --transitions <JSON>
FlagDescription
--org-id <ORG_ID>Organization UUID
--name <NAME>Workflow name
--statuses <JSON>JSON array of status definitions
--transitions <JSON>JSON array of allowed transitions

Examples:

# Create a simple workflow
alloy workflow create --org-id $ORG_ID --name "Standard" \
  --statuses '[{"name":"Backlog","category":"todo"},{"name":"In Progress","category":"in_progress"},{"name":"Done","category":"done"}]' \
  --transitions '[{"from":"Backlog","to":"In Progress"},{"from":"In Progress","to":"Done"}]'

# Create a workflow with review step
alloy workflow create --org-id $ORG_ID --name "With Review" \
  --statuses '[{"name":"Todo","category":"todo"},{"name":"Working","category":"in_progress"},{"name":"Review","category":"in_progress"},{"name":"Done","category":"done"}]' \
  --transitions '[{"from":"Todo","to":"Working"},{"from":"Working","to":"Review"},{"from":"Review","to":"Done"},{"from":"Review","to":"Working"}]'

workflow list

alloy workflow list --org-id <ORG_ID> [--cursor <CURSOR>] [--limit <LIMIT>]

Examples:

# List workflows
alloy workflow list --org-id $ORG_ID

# Get workflow details as JSON
alloy workflow list --org-id $ORG_ID --format json

workflow show

alloy workflow show <ID>

Examples:

# Show workflow with statuses and transitions
alloy workflow show $WORKFLOW_ID

# Get workflow as JSON for editing
alloy workflow show $WORKFLOW_ID --format json

workflow update

alloy workflow update <ID> [--name <NAME>] [--statuses <JSON>] [--transitions <JSON>]

Examples:

# Rename a workflow
alloy workflow update $WORKFLOW_ID --name "Engineering Flow"

# Add a new status and transition
alloy workflow update $WORKFLOW_ID \
  --statuses '[{"name":"Todo","category":"todo"},{"name":"In Progress","category":"in_progress"},{"name":"QA","category":"in_progress"},{"name":"Done","category":"done"}]' \
  --transitions '[{"from":"Todo","to":"In Progress"},{"from":"In Progress","to":"QA"},{"from":"QA","to":"Done"}]'

workflow delete

alloy workflow delete <ID>

Examples:

# Delete a workflow
alloy workflow delete $WORKFLOW_ID

tag

Manage key-value tags on entities (projects, tickets, users, teams, time entries).

tag set

Set one or more key-value tags on an entity (upsert — creates or updates).

alloy tag set --org <ORG_ID> --entity-type <TYPE> --entity-id <ID> --tag <KEY=VALUE>...
FlagDescription
--org <ORG_ID>Organization UUID
--entity-type <TYPE>Entity type: project, ticket, user, team, time_entry
--entity-id <ID>Entity UUID
--tag <KEY=VALUE>Tag key-value pair (repeatable)

Examples:

# Tag a project with environment and team
alloy tag set --org $ORG_ID --entity-type project --entity-id $PROJECT_ID \
  --tag env=production --tag team=backend

# Tag a ticket with a priority label
alloy tag set --org $ORG_ID --entity-type ticket --entity-id $TICKET_ID --tag sprint=12

tag get

Get all tags for an entity.

alloy tag get --org <ORG_ID> --entity-type <TYPE> --entity-id <ID>
FlagDescription
--org <ORG_ID>Organization UUID
--entity-type <TYPE>Entity type
--entity-id <ID>Entity UUID

Examples:

# Get tags for a project
alloy tag get --org $ORG_ID --entity-type project --entity-id $PROJECT_ID

# Get tags as JSON
alloy tag get --org $ORG_ID --entity-type ticket --entity-id $TICKET_ID --format json

tag delete

Delete a tag by key from an entity.

alloy tag delete --org <ORG_ID> --entity-type <TYPE> --entity-id <ID> --key <KEY>
FlagDescription
--org <ORG_ID>Organization UUID
--entity-type <TYPE>Entity type
--entity-id <ID>Entity UUID
--key <KEY>Tag key to delete

Examples:

# Remove the "env" tag from a project
alloy tag delete --org $ORG_ID --entity-type project --entity-id $PROJECT_ID --key env

Search for entities by tag key-value pair.

alloy tag search --org <ORG_ID> --key <KEY> --value <VALUE> [--cursor <CURSOR>] [--limit <LIMIT>]
FlagDefaultDescription
--org <ORG_ID>(required)Organization UUID
--key <KEY>(required)Tag key to search for
--value <VALUE>(required)Tag value to search for
--cursor <CURSOR>Pagination cursor
--limit <LIMIT>20Results per page

Examples:

# Find all entities tagged env=production
alloy tag search --org $ORG_ID --key env --value production

# Search with pagination
alloy tag search --org $ORG_ID --key team --value backend --limit 10 --format json

team

Manage teams within an organization.

team create

alloy team create --name <NAME> [--description <DESC>]
FlagDescription
--name <NAME>Team name
--description <DESC>Optional team description

Examples:

# Create a team
alloy team create --name "Backend"

# Create with description
alloy team create --name "Platform" --description "Infrastructure and DevOps"

team list

alloy team list

Examples:

# List all teams
alloy team list

# Get teams as JSON
alloy team list --format json

team delete

alloy team delete <ID> [--cascade] [--dry-run]
FlagDescription
--cascadeCascade-delete all dependents (members, projects)
--dry-runPreview what would be deleted (requires --cascade)

Examples:

# Delete a team
alloy team delete $TEAM_ID

# Preview cascade delete
alloy team delete $TEAM_ID --cascade --dry-run

# Cascade delete team and all dependents
alloy team delete $TEAM_ID --cascade

project member

Manage project membership. Nested under project.

project member add

alloy project member add --project-id <PROJECT_ID> --user-id <USER_ID>
FlagDescription
--project-id <ID>Project UUID
--user-id <ID>User UUID to add

Examples:

# Add a user to a project
alloy project member add --project-id $PROJECT_ID --user-id $USER_ID

project member remove

alloy project member remove --project-id <PROJECT_ID> --user-id <USER_ID>
FlagDescription
--project-id <ID>Project UUID
--user-id <ID>User UUID to remove

Examples:

# Remove a user from a project
alloy project member remove --project-id $PROJECT_ID --user-id $USER_ID

project member list

alloy project member list --project-id <PROJECT_ID>
FlagDescription
--project-id <ID>Project UUID

Examples:

# List project members
alloy project member list --project-id $PROJECT_ID

# Get members as JSON
alloy project member list --project-id $PROJECT_ID --format json

report

Generate capitalization and finance reports.

report capitalization

Generate a capitalization report as JSON with optional grouping and filters.

alloy report capitalization --period <YYYY-MM> [--group-by <GROUP>] [--include-users] [--include-budget] [--team-id <ID>] [--user-id <ID>] [--cost-center-id <ID>] [--activity-type <TYPE>] [--tag <KEY:VALUE>]
FlagDefaultDescription
--period <YYYY-MM>(required)Reporting month
--group-by <GROUP>Group by team or user
--include-usersfalseInclude individual user breakdowns
--include-budgetfalseInclude budget data
--team-id <ID>Filter by team UUID
--user-id <ID>Filter by user UUID
--cost-center-id <ID>Filter by cost center UUID
--activity-type <TYPE>Filter by activity type
--tag <KEY:VALUE>Tag filter (repeatable)

Examples:

# Basic capitalization report
alloy report capitalization --period 2026-03

# Report grouped by team with user breakdowns
alloy report capitalization --period 2026-03 --group-by team --include-users

# Filtered report
alloy report capitalization --period 2026-03 --team-id $TEAM_ID --activity-type development

report export

Export a capitalization report as CSV to stdout.

alloy report export --period <YYYY-MM> [--team-id <ID>] [--user-id <ID>] [--cost-center-id <ID>] [--activity-type <TYPE>] [--tag <KEY:VALUE>]
FlagDefaultDescription
--period <YYYY-MM>(required)Reporting month
--team-id <ID>Filter by team UUID
--user-id <ID>Filter by user UUID
--cost-center-id <ID>Filter by cost center UUID
--activity-type <TYPE>Filter by activity type
--tag <KEY:VALUE>Tag filter (repeatable)

Examples:

# Export March report as CSV
alloy report export --period 2026-03

# Save CSV to file
alloy report export --period 2026-03 > march-2026.csv

# Export filtered by team
alloy report export --period 2026-03 --team-id $TEAM_ID

export

Export complete project data as portable JSON or SQLite. Uses human-readable keys (emails, project keys, label names) instead of UUIDs.

alloy export [--org <ORG_ID>] [--project <KEY>] [--export-format <FORMAT>] [--output <FILE>]
FlagDefaultDescription
--org <ORG_ID>stored orgOrganization UUID (defaults to org from login)
--project <KEY>Filter to a single project by key
--export-format <FORMAT>jsonExport format: json or sqlite
-o, --output <FILE>alloy-export.dbOutput file path (for sqlite format)

Examples:

# Export everything as JSON (uses stored org from login)
alloy export

# Export with explicit org ID
alloy export --org $ORG_ID

# Export a single project
alloy export --project PROJ

# Save to file
alloy export --project PROJ > proj-backup.json

# Export as SQLite database
alloy export --export-format sqlite --output alloy-export.db

import

Import data from an Alloy JSON export file, a Jira JSON export, or a Linear JSON export. Reads from a file path or stdin. Supports --dry-run to preview what would be imported without making changes. Use --from jira or --from linear to import from external tools.

alloy import [FILE] [--org <ORG_ID>] [--from <SOURCE>] [--dry-run]
Argument/FlagDefaultDescription
[FILE]stdinPath to JSON export file (reads stdin if omitted)
--org <ORG_ID>stored orgOrganization UUID (defaults to org from login)
--from <SOURCE>alloySource format: alloy (native), jira (Jira export), or linear (Linear export)
--dry-runPreview import without making changes

Examples:

# Import from an Alloy export file
alloy import backup.json

# Preview what would be imported
alloy import backup.json --dry-run

# Import from stdin (e.g. pipe from export)
alloy export --project PROJ | alloy import

# Import with explicit org ID
alloy import backup.json --org $ORG_ID

# Import from a Jira JSON export
alloy import jira-export.json --from jira

# Preview a Jira import without making changes
alloy import jira-export.json --from jira --dry-run

# Import from a Linear JSON export
alloy import linear-export.json --from linear

# Preview a Linear import without making changes
alloy import linear-export.json --from linear --dry-run

Jira import mapping:

Jira conceptAlloy conceptNotes
ProjectsProjectsKey and name preserved
IssuesTicketsNumber extracted from issue key
Issue typesLabelsMapped as type:<IssueType> labels
PrioritiesPrioritiesBlocker/Highest→Urgent, High/Major→High, etc.
StatusesWorkflow statusesGrouped into a “Jira Import” workflow
VersionsSprintsReleased versions become Completed sprints
ComponentsLabelsMapped to labels with a warning
CommentsCommentsAuthor and body preserved
WorklogsTime entriesDuration converted from seconds to minutes
LabelsLabelsPreserved as-is
LinksSkipped with a warning
Custom fieldsSkipped with a warning
ResolutionsLogged as warnings (status preserved)

Linear import mapping:

Linear conceptAlloy conceptNotes
TeamsProjectsKey and name preserved
IssuesTicketsNumber extracted from identifier
PrioritiesPriorities1=Urgent, 2=High, 3=Medium, 4=Low, 0=None
StatesWorkflow statusesGrouped into a “Linear Import” workflow
CyclesSprintsCompleted cycles become Completed sprints
LabelsLabelsColor preserved from Linear
CommentsCommentsAuthor and body preserved
UsersUsersEmail preserved; display name used
ProjectsSkipped with a warning (teams used instead)
RelationsSkipped with a warning
EstimatesSkipped with a warning
Sub-issuesTicketsImported as top-level tickets with a warning

board

Show the sprint board — tickets organized by workflow status columns.

alloy board <SPRINT_ID> [--format <FORMAT>]
Argument/FlagDescription
<SPRINT_ID>Sprint UUID
--formatOutput format (json, table, plain)

Table output shows the sprint header, then each status column with its ticket count and the tickets listed with priority, title, and assignee.

Examples:

# View the sprint board
alloy board $SPRINT_ID

# Get board as JSON for scripting
alloy board $SPRINT_ID --format json

# Pipe plain output for processing
alloy board $SPRINT_ID --format plain

burndown

Show sprint burndown chart data — daily progress with total, completed, and remaining ticket counts.

alloy burndown <SPRINT_ID> [--format <FORMAT>]
Argument/FlagDescription
<SPRINT_ID>Sprint UUID
--formatOutput format (json, table, plain)

Table output shows a dated table with total, completed, and remaining columns.

Examples:

# View burndown data
alloy burndown $SPRINT_ID

# Get burndown as JSON
alloy burndown $SPRINT_ID --format json

# Export for a spreadsheet
alloy burndown $SPRINT_ID --format plain > burndown.tsv

sprint

Manage sprints within projects. Sprints have a lifecycle: planningactivecompleted.

Use alloy board <sprint-id> to view the sprint board and alloy burndown <sprint-id> to view the burndown chart.

sprint create

alloy sprint create --project <PROJECT_ID> --name <NAME> --start-date <DATE> --end-date <DATE> [--goal <GOAL>]
FlagDescription
--project <ID>Project UUID (fuzzy selector in interactive mode)
--name <NAME>Sprint name (e.g. Sprint 12)
--start-date <DATE>Start date (YYYY-MM-DD)
--end-date <DATE>End date (YYYY-MM-DD)
--goal <GOAL>Optional sprint goal

Examples:

# Create a two-week sprint
alloy sprint create --project $PROJECT_ID --name "Sprint 12" \
  --start-date 2026-03-25 --end-date 2026-04-08 \
  --goal "Ship authentication and onboarding"

# Create a sprint and capture its ID
SPRINT_ID=$(alloy sprint create --project $PROJECT_ID --name "Sprint 13" \
  --start-date 2026-04-08 --end-date 2026-04-22 --format json | jq -r '.id')

sprint list

alloy sprint list --project <PROJECT_ID> [--cursor <CURSOR>] [--limit <LIMIT>]

Examples:

# List sprints for a project
alloy sprint list --project $PROJECT_ID

# Get sprints as JSON
alloy sprint list --project $PROJECT_ID --format json

sprint start

Transition a sprint from planning to active.

alloy sprint start <ID>

Examples:

# Start a sprint
alloy sprint start $SPRINT_ID

# Start and verify status
alloy sprint start $SPRINT_ID && alloy sprint list --project $PROJECT_ID

sprint complete

Transition a sprint from active to completed.

alloy sprint complete <ID>

Examples:

# Complete a sprint
alloy sprint complete $SPRINT_ID

time

Log and manage time entries for capitalization tracking. Entries follow a lifecycle: draftsubmittedapproved.

time log

alloy time log [--user-id <UUID>] [--ticket <TICKET_REF>] [--project <PROJECT_ID>] [--date <DATE>] [--duration <MINUTES>] [--description <DESC>] [--activity-type <TYPE>]
FlagDefaultDescription
--user-id <UUID>logged-in userUser UUID
--ticket <REF>Ticket reference (prompted if missing)
--project <ID>from ticketProject UUID
--date <DATE>todayDate in YYYY-MM-DD format
--duration <MINUTES>Duration in minutes (prompted if missing)
--description <DESC>What was done
--activity-type <TYPE>Activity category (prompted if missing)

Activity types: Coding, Testing, CodeReview, Design, Documentation, Meeting, Planning, DevOps, BugFix, Refactoring, Research, Support, Other

Examples:

# Log time interactively (prompts for missing fields)
alloy time log

# Log 90 minutes of coding against a ticket
alloy time log --ticket BACK-42 --duration 90 --activity-type Coding --description "Implemented auth middleware"

# Log time for yesterday
alloy time log --ticket 42 --duration 60 --activity-type CodeReview --date 2026-03-24

time list

alloy time list --ticket <TICKET_REF> [--cursor <CURSOR>] [--limit <LIMIT>]

Examples:

# List time entries for a ticket
alloy time list --ticket BACK-42

# Get time entries as JSON
alloy time list --ticket 42 --format json

time get

alloy time get <ID>

Examples:

# Get time entry details
alloy time get $TIME_ENTRY_ID

time submit

Move a time entry from draft to submitted for approval.

alloy time submit <ID>

Examples:

# Submit a time entry for approval
alloy time submit $TIME_ENTRY_ID

# Log and submit in one flow
ENTRY=$(alloy time log --ticket 42 --duration 60 --activity-type Coding --format json | jq -r '.id')
alloy time submit $ENTRY

time approve

Approve a submitted time entry (manager action).

alloy time approve <ID>

Examples:

# Approve a time entry
alloy time approve $TIME_ENTRY_ID

time report

Generate capitalization reports for a given month.

alloy time report --period <YYYY-MM> [--output <csv|json>]
FlagDefaultDescription
--period <YYYY-MM>(required)Reporting month
--output <csv|json>csvReport format

Examples:

# Export March 2026 as CSV
alloy time report --period 2026-03

# Get report as JSON
alloy time report --period 2026-03 --output json

# Save CSV report to file
alloy time report --period 2026-03 > march-2026.csv

invite

Create and manage organization invitations.

invite create

alloy invite create --org-id <ORG_ID> [--email <EMAIL>] [--role <ROLE>]
FlagDefaultDescription
--org-id <ORG_ID>(required)Organization UUID
--email <EMAIL>Invitee email (omit for open invite link)
--role <ROLE>MemberOwner, Admin, Member, Viewer

Examples:

# Invite a specific person
alloy invite create --org-id $ORG_ID --email dev@example.com --role Member

# Create an open invite link for the team
alloy invite create --org-id $ORG_ID --role Member

# Get just the invite code for scripting
alloy invite create --org-id $ORG_ID --email new@example.com --format plain

invite list

alloy invite list --org-id <ORG_ID>

Examples:

# List pending invitations
alloy invite list --org-id $ORG_ID

# List invites as JSON
alloy invite list --org-id $ORG_ID --format json

onboard

First-run setup wizard. Creates the initial admin user, organization, and API key. Only works when no organizations exist in the system.

alloy onboard --email <EMAIL> --password <PASSWORD> --org-name <NAME> --org-slug <SLUG>
FlagDescription
--email <EMAIL>Admin email address
--password <PASSWORD>Admin password (min 8 characters)
--org-name <NAME>Organization display name
--org-slug <SLUG>URL-friendly organization identifier

Returns an API key that is shown only once — save it immediately.

Examples:

# Set up a fresh Alloy instance
alloy onboard --email admin@example.com --password mysecretpw --org-name "Acme Corp" --org-slug acme

# Capture the API key for automation
API_KEY=$(alloy onboard --email admin@example.com --password mysecretpw \
  --org-name "Acme" --org-slug acme --format plain)

completions

Generate shell completion scripts.

alloy completions <SHELL>

Supported shells: bash, zsh, fish, powershell, elvish.

Examples:

# Generate Zsh completions
alloy completions zsh > ~/.zfunc/_alloy

# Generate Bash completions
alloy completions bash > /etc/bash_completion.d/alloy

usage

Print agent-optimized self-documentation (<1500 tokens). Useful for LLM agents that need to discover available commands.

alloy usage [SUBCOMMAND]
ArgumentDescription
SUBCOMMANDOptional command name for detailed help

Examples:

# Get concise overview of all commands
alloy usage

# Get detailed help for a specific command
alloy usage ticket

Credential Storage

Credentials are stored at ~/.config/alloy/credentials.toml (platform-specific via the directories crate). The file contains:

access_token = "eyJ..."
refresh_token = "abc123..."
user_id = "550e8400-..."
email = "admin@example.com"
org_id = "660e8400-..."          # set by `alloy org switch`
project_id = "770e8400-..."      # set by `alloy project use`
project_key = "BACK"             # set by `alloy project use`

The CLI auto-refreshes expired tokens: on a 401 response, it calls /api/v1/auth/refresh with the stored refresh token, updates credentials on disk, and retries the original request.


Common Workflows

Create an organization and invite your team

# First-time setup
alloy onboard --email admin@acme.com --password s3cretpw \
  --org-name "Acme Corp" --org-slug acme

# Log in
alloy auth login --email admin@acme.com --password s3cretpw

# Create a project
alloy project create --org-id $ORG_ID --key BACK --name "Backend"
alloy project use BACK

# Invite team members
alloy invite create --org-id $ORG_ID --email dev1@acme.com --role Member
alloy invite create --org-id $ORG_ID --email dev2@acme.com --role Member
alloy invite create --org-id $ORG_ID --email lead@acme.com --role Admin

Sprint planning

# Create a sprint
alloy sprint create --project $PROJECT_ID --name "Sprint 12" \
  --start-date 2026-03-25 --end-date 2026-04-08 \
  --goal "Ship user authentication"

# Create tickets for the sprint
alloy ticket create --project $PROJECT_ID --title "Implement login endpoint" --priority high
alloy ticket create --project $PROJECT_ID --title "Add password reset flow" --priority medium
alloy ticket create --project $PROJECT_ID --title "Write auth integration tests" --priority medium

# Start the sprint
alloy sprint start $SPRINT_ID

# Check sprint status
alloy sprint list --project $PROJECT_ID

Time tracking for a week

# Set your default project
alloy project use BACK

# Log daily entries
alloy time log --ticket 42 --duration 120 --activity-type Coding --date 2026-03-24 --description "Auth middleware"
alloy time log --ticket 42 --duration 90 --activity-type Testing --date 2026-03-25 --description "Auth tests"
alloy time log --ticket 43 --duration 60 --activity-type CodeReview --date 2026-03-25 --description "PR review"
alloy time log --ticket 44 --duration 45 --activity-type Meeting --date 2026-03-26 --description "Sprint planning"
alloy time log --ticket 42 --duration 180 --activity-type Coding --date 2026-03-27 --description "Token refresh"

# Submit all entries
alloy time list --ticket 42 --format json | jq -r '.data[].id' | xargs -I{} alloy time submit {}

# Generate monthly report
alloy time report --period 2026-03

Bulk ticket updates with JSON output piping

# Close all done tickets
alloy ticket list --status done --format json | jq -r '.data[].id' | \
  xargs -I{} alloy ticket update {} --status cancelled

# Reassign all tickets from one user to another
alloy ticket list --assignee-id $OLD_USER --format json | jq -r '.data[].id' | \
  xargs -I{} alloy ticket update {} --assignee-id $NEW_USER

# Export all high-priority tickets
alloy ticket list --priority high --format json | jq '.data[] | {id, title, status}'

Shell Completions

Alloy can generate shell completion scripts for tab-completion of commands, subcommands, flags, and enum values.

alloy completions <SHELL>
ArgumentValuesDescription
SHELLbash, zsh, fishShell to generate completions for

Bash

Add to your ~/.bashrc:

# Generate and source completions
eval "$(alloy completions bash)"

Or install persistently:

# Create completions directory if needed
mkdir -p ~/.local/share/bash-completion/completions

# Generate the completion script
alloy completions bash > ~/.local/share/bash-completion/completions/alloy

# Reload your shell
source ~/.bashrc

Zsh

Add to your ~/.zshrc:

# Generate and source completions
eval "$(alloy completions zsh)"

Or install persistently:

# Ensure completions directory is in fpath (add to ~/.zshrc before compinit)
mkdir -p ~/.zfunc
echo 'fpath=(~/.zfunc $fpath)' >> ~/.zshrc

# Generate the completion script
alloy completions zsh > ~/.zfunc/_alloy

# Rebuild completion cache
rm -f ~/.zcompdump && compinit

Fish

# Generate and install completions
alloy completions fish > ~/.config/fish/completions/alloy.fish

Fish automatically loads completions from ~/.config/fish/completions/, so no additional configuration is needed.

Verifying Completions

After installation, restart your shell (or source the relevant config file) and test by typing:

alloy <TAB>

You should see all available subcommands (health, project, ticket, sprint, time, team, completions, etc.) as completion suggestions.