Skip to main content

CLI Reference

The UnderControl CLI (ud) is a command-line tool for managing tasks from the terminal. It supports both direct commands and an interactive TUI mode with vim-style keybindings.

Installation

# Global install
npm install -g @oatnil/ud

# Or run directly without installing
npx @oatnil/ud --help

Homebrew (macOS/Linux)

brew tap oatnil-top/ud
brew install ud

Install Script

curl -fsSL https://get.oatnil.com/ud | bash

Manual Download

Download the appropriate version for your platform:

PlatformFilename
macOS (Apple Silicon)ud_x.x.x_darwin_arm64.tar.gz
macOS (Intel)ud_x.x.x_darwin_amd64.tar.gz
Linux (x64)ud_x.x.x_linux_amd64.tar.gz
Linux (ARM64)ud_x.x.x_linux_arm64.tar.gz
Windowsud_x.x.x_windows_amd64.zip

macOS / Linux:

# Extract
tar -xzf ud_x.x.x_darwin_arm64.tar.gz

# Move to PATH
sudo mv ud /usr/local/bin/ud

# Verify
ud --version

Windows:

  1. Extract the .zip file
  2. Move ud.exe to a directory in your PATH
  3. Or add the extracted directory to your system PATH

Authentication

Login

ud login

You'll be prompted for:

  • Server URL: Your UnderControl server (e.g., https://api.undercontrol.app)
  • Username: Your account email
  • Password: Your account password

Credentials are saved to ~/.config/ud/config.yaml.

Multi-Context Support

The CLI supports kubectl-style contexts for managing multiple accounts. See CLI Multi-Context Authentication for details.

# List contexts
ud config get-contexts

# Switch context
ud config use-context work

# Login to specific context
ud login --context work --api-url https://ud.company.com

Resource Commands (kubectl-style)

The CLI supports kubectl-style top-level verbs for managing resources. These are the recommended way to interact with resources.

Get Resources

ud get task [id] [--status <status>]

Display one or many tasks in a table format.

Options:

  • --status: Filter by status (todo, in-progress, pending, stale, done, archived)

Examples:

# List all tasks
ud get task

# List only todo tasks
ud get task --status todo

# Show a single task in table format
ud get task abc123

Describe Resource

ud describe task <id>

Show detailed information about a specific task, including title, description, status, tags, deadline, timestamps, linked tasks, attachments, and notes.

Examples:

# View full task details
ud describe task abc123

# Using short prefix
ud describe task 3de
Short ID Support

All commands that accept a task ID support prefix matching. You can use the 8-character short IDs shown in get task output, or even shorter prefixes as long as they're unique.

ud describe task 3de9f82b    # Full short ID from list
ud describe task 3de # Shorter prefix (if unique)
ud describe task 3de9f82b-fc49-4e84-b288-9ae3174f69ae # Full UUID also works

If a prefix matches multiple tasks, you'll see an error listing the matches:

Error: ambiguous ID prefix '3' matches 2 tasks:
3de9f82b (Task title one)
3fbf7c24 (Task title two)
Please use a longer prefix

Apply Resource from File

ud apply -f <file>       # .md for tasks/notes, .yaml for other resources
ud apply -f - # Read from stdin (auto-detects format)

Create or update resources declaratively from files (kubectl-style). Supports all resource types:

FormatResourcesAuto-detection
.mdTask (default), Note (when task_id in frontmatter)task_id present → Note
.yaml / .ymlBoard, Budget, Account, Expense, Incomekind field in YAML

Quick examples:

# Task
echo '---
title: New Task
status: todo
---
Description here.' | ud apply -f -

# Note (auto-detected by task_id)
echo '---
task_id: abc123
---
Progress update.' | ud apply -f -

# Board (YAML)
ud apply -f board.yaml

# Multi-document YAML (multiple resources in one file)
ud apply -f setup.yaml

For the full schema reference, all supported fields, and YAML resource format details, see the Apply & Resource Schema guide.

Delete Resource

ud delete task <id>

Delete a task by ID.

Examples:

ud delete task abc123
ud delete task 3de9f82b

Task Commands

Deprecated Commands

The following ud task subcommands are deprecated and will be removed in a future release. They still work but print a deprecation warning. Use the kubectl-style commands instead:

DeprecatedUse instead
ud task listud get task
ud task view <id>ud describe task <id>
ud task apply -f <file>ud apply -f <file>
ud task delete <id>ud delete task <id>

Create Task

ud task create <title> [flags]
ud task create -f <file>

Flags:

  • -d, --description: Task description
  • -s, --status: Initial status (default: todo)
  • -f, --file: Create from file (first line = title, rest = description)

Examples:

# Simple task
ud task create "Fix login bug"

# With description
ud task create "Refactor API" -d "Update to v2 endpoints"

# With initial status
ud task create "Review PR" -s in-progress

# From file
ud task create -f requirements.md

File format for -f:

Task title goes here
The rest of the file
becomes the description.

Mark Task Done

ud task done <id>

Shortcut to set task status to done.

Edit Task

ud task edit <id>

Opens the task in your $EDITOR (defaults to vi). The file format is:

  • First line: title
  • Blank line
  • Rest: description

Query Tasks

ud query "<query>" [flags]

Query tasks using SQL-like syntax.

Flags:

  • --page: Page number (default: 1)
  • --limit: Items per page (default: 50)
  • --sort: Sort field (title, deadline, created_at, updated_at)
  • --order: Sort direction (asc, desc)

Examples:

# Find todo tasks
ud query "status = 'todo'"

# Search by title
ud query "title ILIKE '%api%'"

# Find tasks due this week
ud query "deadline BETWEEN 'today' AND '+7d'"

# Find tagged tasks
ud query "tags = 'urgent'"

# Complex query
ud query "(status = 'todo' OR status = 'in-progress') AND deadline <= 'today'"

Note Commands

Notes allow you to add comments, progress updates, and context to tasks. They're useful for tracking work history and AI agent collaboration.

Add Note

ud task note add <task-id> "<content>"
ud task note add <task-id> -f <file>
echo "content" | ud task note add <task-id> -

Flags:

  • -f, --file: Read note content from file

Examples:

# Add inline note
ud task note add abc123 "Started implementation"

# Add progress update
ud task note add abc123 "✓ Auth middleware done"

# From file
ud task note add abc123 -f progress.md

# From stdin
echo "Completed review" | ud task note add abc123 -

List Notes

ud task note list <task-id>
ud task note ls <task-id> # Alias

Output format:

[4223db11] 2025-01-31 11:08
✓ Auth middleware done
---
[3150c5ce] 2025-01-31 10:45
Started implementation

Delete Note

ud task note delete <task-id> <note-id>
ud task note rm <task-id> <note-id> # Alias

Example:

ud task note delete abc123 4223db11

AI Agent Workflow

Notes enable seamless collaboration between humans and AI agents:

# AI creates task from plan
ud task create -f plan.md
# Created task: abc12345

# Human reviews in UI, adds context via notes

# AI fetches task and logs progress
ud task view abc123
ud task note add abc123 "✓ Completed step 1: Database schema"
ud task note add abc123 "✓ Completed step 2: API endpoints"
ud task note add abc123 "⚠️ Blocked: Need API key for external service"

# Human sees progress, unblocks AI

# AI continues and completes
ud task note add abc123 "✓ All steps completed"
ud task done abc123

File Upload & Attachment Commands

Upload files as resources and optionally attach them to entities like tasks or expenses. Files are uploaded via presigned URLs directly to cloud storage.

Upload a File

ud upload resource <file-path> [flags]

Upload a file as a resource. Optionally attach it to an entity in a single step.

Flags:

  • -t, --entity-type: Entity type to attach to (e.g., todolist, expense)
  • -e, --entity-id: Entity ID to attach to (supports prefix matching for tasks)

Examples:

# Upload a standalone file
ud upload resource ./receipt.png

# Upload and attach to a task
ud upload resource ./design.pdf --entity-type todolist --entity-id abc123

# Short flags
ud upload resource ./photo.jpg -t todolist -e abc123

# Upload a document to a task (partial ID)
ud upload resource ./notes.txt -t todolist -e 3de

Output:

Uploading ./receipt.png...
Uploaded: receipt.png
ID: 2a2e542e-0711-4e7f-aafb-09a432e71860
Type: image
Size: 102.4 KB
MIME: image/png
MIME Type Detection

The CLI automatically detects MIME types from file extensions. Common mappings:

  • Images: .png, .jpg, .gif, .webp, .svgimage
  • Documents: .pdf, .doc, .docx, .txt, .csvdocument
  • Diagrams: .drawio, .drawio.pngdiagram
  • Other: all other extensions → other

Attach Existing Resource

ud attach resource <resource-id> --entity-type <type> --entity-id <id>

Link an already-uploaded resource to an entity. Both --entity-type and --entity-id are required.

Flags:

  • -t, --entity-type: Entity type (required)
  • -e, --entity-id: Entity ID (required, supports prefix matching for tasks)

Supported entity types:

Entity TypeDescription
todolistTasks
expenseExpenses
budgetBudgets
accountAccounts

Examples:

# Attach resource to a task
ud attach resource 2a2e542e-0711-4e7f-aafb-09a432e71860 -t todolist -e abc123

# Attach to an expense
ud attach resource 2a2e542e -t expense -e def456

Download a Resource

To download a resource, use ud entity get to retrieve the presigned download URL, then download with curl:

# Get resource details (includes presigned download URL)
ud entity get 2a2e542e-0711-4e7f-aafb-09a432e71860

# Download using the presigned URL from the response
curl -o receipt.png "https://storage.example.com/...?signature=..."

Upload Workflow Example

A typical workflow for attaching files to tasks:

# 1. Find the task
ud get task --status in-progress

# 2. Upload and attach a file
ud upload resource ./screenshot.png -t todolist -e 3de9f82b

# 3. Verify the attachment
ud describe task 3de9f82b
# Shows: [2a2e542e] screenshot.png (image/png, 102.4 KB)

# 4. Later, download the file
ud entity get 2a2e542e
# Copy the presignedUrl from the output
curl -o screenshot.png "<presigned-url>"

TUI Mode

Run ud without arguments to enter the interactive terminal UI.

List View Keybindings

KeyAction
j / kMove down/up
ggJump to top
GJump to bottom
EnterView task details
iCreate new task
eEdit task (uses $EDITOR)
xToggle task status
ddDelete task
/Search
n / NNext/previous search result
rRefresh list
fOpen file picker
qQuit
?Show help

Detail View Keybindings

KeyAction
j / kScroll content
xToggle task status
eEdit task
ddDelete task
Esc / qReturn to list

File Picker

Press f in list view to open an fzf-like file picker:

  • Fuzzy search files in current directory
  • Select file to create task
  • First line = title, rest = description
  • Binary files are skipped

Configuration Commands

View Configuration

ud config view

Shows the full configuration with tokens partially masked.

List Contexts

ud config get-contexts

Switch Context

ud config use-context <name>

Show Current Context

ud config current-context

Create/Update Context

ud config set-context <name> [flags]

Flags:

  • --api-url: API server URL
  • --api-key: API key (for CI/CD)

Delete Context

ud config delete-context <name>

Rename Context

ud config rename-context <old-name> <new-name>

Environment Variables

VariableDescription
UD_CONTEXTOverride current context
UD_API_URLOverride API URL
UD_API_KEYOverride API key
UD_TOKENOverride auth token
EDITOREditor for task edit command

Examples:

# Use different context for one command
UD_CONTEXT=staging ud task list

# Override API URL
UD_API_URL=http://localhost:4000 ud task list

# Set editor
export EDITOR=vim

Common Workflows

AI Agent Integration

Create .claude/instructions.md or .cursorrules in your project:

# Task Management

Use UnderControl CLI to manage project tasks:

- List tasks: `ud get task`
- View task details: `ud describe task <id>`
- Create task: `ud task create "title" -d "description"`
- Complete task: `ud task done <id>`
- Update task: `ud apply -f task.md`
- Delete task: `ud delete task <id>`

Before implementing features, check related tasks for context.

Batch Updates with Apply

Create a template file and apply to multiple tasks:

# Create status update template for each task
for id in abc123 def456 ghi789; do
echo "---
id: $id
status: done
---" | ud apply -f -
done

Export and Edit Workflow

# View task, copy content
ud describe task abc123

# Create markdown file with updates (include id for update)
cat > update.md << 'EOF'
---
id: abc123
title: Updated Title
status: in-progress
tags:
- reviewed
- approved
---

Updated description with new requirements.
EOF

# Apply changes
ud apply -f update.md

Troubleshooting

Login Failed

Problem: API error: Invalid credentials

Solutions:

  1. Verify username and password
  2. Check server URL is correct
  3. Try logging in via web to verify account

Connection Timeout

Problem: connection timeout

Solutions:

  1. Check network connection
  2. Verify server URL is accessible
  3. Check firewall settings

Token Expired

Problem: API error: Token expired

Solution: Run ud login to re-authenticate.

Editor Not Working

Problem: task edit has no effect

Solution: Set the EDITOR environment variable:

export EDITOR=vim  # or nano, code, etc.

Invalid Status Error

Problem: API error: An unexpected error occurred when using apply

Solution: Ensure status is one of: todo, in-progress, pending, stale, done, archived

Context Not Found

Problem: context "work" not found

Solution: Create the context first:

ud config set-context work --api-url https://ud.company.com
ud login --context work