Complete reference for all MCP tools, parameters, workflows, and use cases.
- Tool Groups Overview
- Discovery Tools
- Configuration Tools
- Task CRUD Operations
- Task Query Operations
- Batch Operations
- CSV Import
- Document Management
- DartAI Loop Tools
- DartQL Reference
- Error Handling
- Performance Optimization
- Common Workflows
dart-query organizes 19 tools into 8 functional groups:
| Group | Tools | Purpose |
|---|---|---|
| discovery | info |
Progressive capability discovery |
| config | get_config |
Workspace configuration |
| task-crud | 5 tools | Single task operations (create, get, update, delete, comment) |
| task-query | 2 tools | Search and filter tasks (list, search) |
| task-batch | 3 tools | Bulk operations (batch update, batch delete, status) |
| import | 1 tool | CSV bulk import |
| doc-crud | 5 tools | Document management (create, get, update, delete, list) |
| dartai-loop | dartai_loop_snapshot |
Single-call loop startup aggregation |
Token Budget Summary:
- Discovery: ~150 tokens (overview)
- Config: ~400 tokens
- CRUD: ~200-300 tokens per operation
- Batch: ~400 tokens (summary, not full data)
- Import: ~500 tokens
Purpose: Explore dart-query capabilities without loading all schemas. Start here.
Input Schema:
{
level?: 'overview' | 'group' | 'tool' // default: 'overview'
target?: string // group name or tool name
}Output Schema:
{
level: string // echoed back
content: string // formatted documentation
next_steps: string[] // suggested follow-up queries
}Examples:
// Get overview of all tool groups
info()
// → Shows sparse table with 7 tool groups
// Explore batch operations
info({ level: 'group', target: 'task-batch' })
// → Shows 3 batch operation tools with descriptions
// Get full documentation for a specific tool
info({ level: 'tool', target: 'batch_update_tasks' })
// → Shows complete schema, examples, DartQL syntax guideToken Budget: ~150 tokens (overview), ~200 tokens (group), ~500 tokens (tool)
Performance: Instant (no API calls)
Purpose: Retrieve workspace configuration including dartboards, assignees, statuses, tags, priorities, sizes, and folders. Always call this before creating tasks or importing CSV.
Input Schema:
{
cache_bust?: boolean // default: false, force refresh cache
include?: string[] // limit to specific sections
}Valid include values:
"assignees"- User list with emails"dartboards"- Board names (Personal/test, Engineering/backend, etc.)"statuses"- Status names (To Do, Doing, Done, etc.)"tags"- Tag names"priorities"- Priority values ("critical", "high", "medium", "low")"sizes"- Size values ("xs", "small", "medium", "large", "xl")"folders"- Document folder names
Output Schema:
{
assignees: Array<{
dart_id: string
name: string
email: string
role?: string
}>
dartboards: string[] // e.g., ["Personal/test", "Engineering/backend"]
statuses: string[] // e.g., ["To Do", "Doing", "Done"]
tags: string[] // e.g., ["bug", "feature", "urgent"]
priorities: string[] // e.g., ["critical", "high", "medium", "low"]
sizes: string[] // e.g., ["xs", "small", "medium", "large", "xl"]
folders: string[] // doc folder names
cached_at: string // ISO8601 timestamp
cache_ttl_seconds: number // 300 (5 minutes)
}Examples:
// Get full workspace config (cached for 5 minutes)
get_config()
// Get only dartboards and assignees (token-efficient)
get_config({ include: ["dartboards", "assignees"] })
// Force refresh cached config
get_config({ cache_bust: true })Use Cases:
- Validate dartboard names before creating tasks
- Get assignee emails for CSV import
- Check available statuses, tags, priorities, sizes
- Discover valid reference values for batch updates
Token Budget: ~400 tokens for full config
Performance: Fast (cached) / Medium (API call on cache miss)
Relationship field naming (0.12.0+):
create_task,update_task, andlink_tasksaccept industry-standard Jira/Linear-style names —parent,subtasks,blocked_by,blocks,duplicates,related— alongside the legacy_ids-suffixed names. Responses dual-emit both shapes. The legacy names are deprecated and will be removed in 0.13.0. Prefer the canonical names in new code.Auto-mirror (0.12.0+): Setting a relationship on one side automatically patches the inverse side. Setting
parent: Pon a child also updatesP.subtasks. Settingblocked_by: [B]also updatesB.blocks. Best-effort — failures surface inmirror_warningson the response, never fail the primary write.Pseudo-edge tags rejected: Tags like
"needs:T-42","blocks:T-99","blocked-by:..."are rejected with a corrective error pointing at the right relationship field. Use relationship arrays, not tag prefixes.
Purpose: Create a new task with all metadata.
Input Schema:
{
title: string // REQUIRED, max 500 chars
dartboard: string // REQUIRED, dartboard name
description?: string // optional description
status?: string // e.g., "To Do", "Doing"
priority?: string // "critical", "high", "medium", "low"
size?: string // "xs", "small", "medium", "large", "xl"
assignees?: string[] // email addresses or names
tags?: string[] // tag names (no "needs:X"/"blocks:Y" — use relationship fields)
due_at?: string // ISO8601 date (e.g., "2026-02-01T00:00:00Z")
start_at?: string // ISO8601 date
// Relationship fields — canonical names (preferred)
parent?: string // parent task dart_id
subtasks?: string[] // child task dart_ids
blocked_by?: string[] // dart_ids of tasks blocking this one
blocks?: string[] // dart_ids of tasks this one blocks
duplicates?: string[] // dart_ids of duplicate tasks
related?: string[] // dart_ids of related tasks
// Legacy names (deprecated, removed in 0.13.0) — all accepted interchangeably
parent_task?: string
subtask_ids?: string[]
blocker_ids?: string[]
blocking_ids?: string[]
duplicate_ids?: string[]
related_ids?: string[]
}Output Schema:
{
dart_id: string // unique task ID
title: string
description?: string
status?: string
priority?: string
size?: string
assignees?: string[]
tags?: string[]
dartboard: string
due_at?: string
start_at?: string
completed_at?: string
created_at: string
updated_at: string
parent_task?: string
url?: string // web UI link
// Relationship fields
subtask_ids?: string[] // IDs of subtask (child) tasks
blocker_ids?: string[] // IDs of tasks that block this task
blocking_ids?: string[] // IDs of tasks blocked by this task
duplicate_ids?: string[] // IDs of duplicate tasks
related_ids?: string[] // IDs of related tasks
}Examples:
// Minimal task
create_task({
title: "Fix authentication bug",
dartboard: "Engineering/backend"
})
// Full task with all metadata
create_task({
title: "Implement OAuth2 login",
dartboard: "Engineering/backend",
description: "Add Google and GitHub OAuth providers",
status: "To Do",
priority: "high",
size: "large",
assignees: ["engineer@company.com"],
tags: ["feature", "auth"],
due_at: "2026-02-15T00:00:00Z"
})
// Task with relationships - creating a task that is blocked by another
create_task({
title: "Deploy OAuth2 to production",
dartboard: "Engineering/backend",
priority: "high",
blocker_ids: ["duid_oauth_impl"] // blocked by the OAuth implementation task
})
// Task with multiple relationships
create_task({
title: "Update user documentation",
dartboard: "Documentation",
related_ids: ["duid_oauth_impl", "duid_api_docs"],
blocking_ids: ["duid_release_v2"] // this task blocks the v2 release
})Errors:
ValidationError: Title empty, dartboard not found, invalid priority/sizeDartAPIError: Network errors, authentication failures
Token Budget: ~300 tokens
Purpose: Get full details of an existing task by its dart_id.
Input Schema:
{
dart_id: string // REQUIRED
detail_level?: 'minimal' | 'standard' | 'full' // default: 'standard'
include_relationships?: boolean // default: true, include relationship data
expand_relationships?: boolean // default: false, include titles of related tasks
}Output Schema:
{
// Core task fields (same as create_task output)
dart_id: string
title: string
description?: string
status?: string
priority?: string
size?: string
assignees?: string[]
tags?: string[]
dartboard: string
due_at?: string
start_at?: string
completed_at?: string
created_at: string
updated_at: string
parent_task?: string
url?: string
// Relationship IDs (when include_relationships=true)
subtask_ids?: string[]
blocker_ids?: string[]
blocking_ids?: string[]
duplicate_ids?: string[]
related_ids?: string[]
// Relationship counts (always included when include_relationships=true)
relationship_counts?: {
subtasks: number
blockers: number
blocking: number
duplicates: number
related: number
}
// Expanded relationships (when expand_relationships=true)
expanded_relationships?: {
subtasks?: Array<{ dart_id: string, title: string }>
blockers?: Array<{ dart_id: string, title: string }>
blocking?: Array<{ dart_id: string, title: string }>
duplicates?: Array<{ dart_id: string, title: string }>
related?: Array<{ dart_id: string, title: string }>
}
}Examples:
// Get full task details with relationships
get_task({ dart_id: "duid_task123" })
// Returns:
// {
// dart_id: "duid_task123",
// title: "Implement OAuth2",
// blocker_ids: ["duid_design_review"],
// blocking_ids: ["duid_deploy_prod"],
// relationship_counts: { subtasks: 0, blockers: 1, blocking: 1, duplicates: 0, related: 0 }
// }
// Get minimal details (fewer tokens)
get_task({ dart_id: "duid_task123", detail_level: "minimal" })
// Exclude relationship data for smaller response
get_task({ dart_id: "duid_task123", include_relationships: false })
// Get expanded relationships with task titles (useful for display)
get_task({ dart_id: "duid_task123", expand_relationships: true })
// Returns:
// {
// dart_id: "duid_task123",
// title: "Implement OAuth2",
// blocker_ids: ["duid_design_review"],
// expanded_relationships: {
// blockers: [{ dart_id: "duid_design_review", title: "Design review meeting" }],
// blocking: [{ dart_id: "duid_deploy_prod", title: "Deploy to production" }]
// }
// }Token Budget: ~200 tokens (minimal), ~300 tokens (standard), ~400+ tokens (with expanded relationships)
Purpose: Update one or more fields of an existing task.
Input Schema:
{
dart_id: string // REQUIRED
updates: { // REQUIRED, at least one field
title?: string
description?: string
status?: string
priority?: string
size?: string
assignees?: string[]
tags?: string[]
dartboard?: string
due_at?: string
start_at?: string
parent_task?: string
// Relationship fields (arrays of dart_id strings)
subtask_ids?: string[] // IDs of subtask (child) tasks
blocker_ids?: string[] // IDs of tasks that block this task
blocking_ids?: string[] // IDs of tasks blocked by this task
duplicate_ids?: string[] // IDs of duplicate tasks
related_ids?: string[] // IDs of related tasks
}
}Relationship Update Semantics:
- Full replacement: Providing a relationship array replaces ALL existing values
- Empty array
[]: Clears all relationships of that type - Omitting field: Leaves existing relationships unchanged
Output Schema: Same as get_task (updated task)
Examples:
// Update status only
update_task({
dart_id: "duid_task123",
updates: { status: "Doing" }
})
// Update multiple fields
update_task({
dart_id: "duid_task123",
updates: {
status: "Doing",
priority: "critical",
assignees: ["john@company.com"]
}
})
// Add blockers to a task (replaces any existing blockers)
update_task({
dart_id: "duid_deploy_task",
updates: {
blocker_ids: ["duid_testing", "duid_code_review"]
}
})
// Clear all blockers (task is no longer blocked)
update_task({
dart_id: "duid_deploy_task",
updates: {
blocker_ids: [] // empty array clears all blockers
}
})
// Link related tasks
update_task({
dart_id: "duid_task123",
updates: {
related_ids: ["duid_task456", "duid_task789"]
}
})
// Mark tasks as duplicates
update_task({
dart_id: "duid_original",
updates: {
duplicate_ids: ["duid_dup1", "duid_dup2"]
}
})
// Add subtasks to a parent task
update_task({
dart_id: "duid_parent_feature",
updates: {
subtask_ids: ["duid_subtask1", "duid_subtask2", "duid_subtask3"]
}
})Important: To add a single relationship without losing existing ones, first retrieve the current task with get_task, then include all existing IDs plus the new one in the update.
Purpose: Add a typed relationship between tasks, writing both sides of the link in one call. Prevents the common one-sided-graph failure mode where a planner sets parent_task on a child without updating the parent's subtasks.
Maps onto Linear's issueRelationCreate semantics. Internally delegates to update_task, so synonym normalization, pseudo-edge tag rejection, and auto-mirror diff logic apply transparently.
Input Schema:
{
type: 'parent' | 'subtasks' | 'blocks' | 'blocked_by' | 'duplicates' | 'related'
from: string // anchor task dart_id
to: string[] // target task dart_ids — length must be 1 for type='parent'
}Semantics:
parent: anchor getsparent = to[0];to[0].subtasks += anchor(auto-mirror)subtasks: anchor's subtasks +=to[]; eachto[i].parent = anchor(auto-mirror)blocks: anchor's blocks +=to[]; eachto[i].blocked_by += anchor(auto-mirror)blocked_by: anchor's blocked_by +=to[]; eachto[i].blocks += anchor(auto-mirror)duplicates/related: bidirectional symmetric mirror
Output Schema:
{
from: string
type: string
to: string[]
url: string
mirror_applied: string[] // inverse-side tasks successfully patched
mirror_warnings: string[] // inverse-side patches that failed (best-effort)
}Examples:
// Attach two subtasks to a parent — both sides linked in one call
link_tasks({ type: 'subtasks', from: 'duid_parent', to: ['duid_a', 'duid_b'] })
// Express a dependency
link_tasks({ type: 'blocks', from: 'duid_setup', to: ['duid_feat1', 'duid_feat2'] })
// Set parent on an existing task
link_tasks({ type: 'parent', from: 'duid_child', to: ['duid_epic'] })Why this exists: Dart's API does not auto-mirror parent↔subtask or blocker↔blocking. Most PM tools (Jira, Linear, Asana, ClickUp, GitHub sub-issues) do. link_tasks restores that intuition with a single verb. Use this over hand-rolling bidirectional updates.
Purpose: Move a task to trash (recoverable from Dart web UI).
Input Schema:
{
dart_id: string // REQUIRED
}Output Schema:
{
success: boolean
dart_id: string
message: string
}Examples:
delete_task({ dart_id: "duid_task123" })
// → Task moved to trash, recoverable from web UINote: Tasks are NOT permanently deleted - they move to trash and can be restored via Dart web UI.
Purpose: Add a text comment to an existing task.
Input Schema:
{
dart_id: string // REQUIRED
comment: string // REQUIRED, comment text
}Output Schema:
{
success: boolean
comment_id: string
dart_id: string
}Examples:
add_task_comment({
dart_id: "duid_task123",
comment: "Reviewed by security team - approved for deployment"
})Purpose: List tasks with optional filtering by assignee, status, dartboard, priority, tags, due dates, and relationships.
Input Schema:
{
assignee?: string // email or name
status?: string // status name
dartboard?: string // dartboard name
priority?: string // "critical", "high", "medium", "low"
tags?: string[] // array of tag names
due_before?: string // ISO8601 date
due_after?: string // ISO8601 date
limit?: number // max results, default 100
offset?: number // pagination offset, default 0
detail_level?: 'minimal' | 'standard' | 'full' // default: 'standard'
// Relationship filters
has_parent?: boolean // filter tasks that have/don't have a parent
// Note: Only has_parent is supported. Other relationship filters (has_subtasks,
// has_blockers, is_blocking) are not available because the list API doesn't
// return taskRelationships data.
}Output Schema:
{
tasks: DartTask[] // array of task objects (includes relationship fields)
total: number // total matching tasks
}Examples:
// List all tasks (max 100)
list_tasks()
// List high-priority tasks in Engineering dartboard
list_tasks({
dartboard: "Engineering/backend",
priority: "high"
})
// List overdue tasks
list_tasks({
due_before: "2026-01-18T00:00:00Z"
})
// List tasks by assignee with minimal details
list_tasks({
assignee: "john@company.com",
detail_level: "minimal"
})
// Pagination (get next 100 tasks)
list_tasks({ limit: 100, offset: 100 })
// List subtasks only (tasks with a parent)
list_tasks({
has_parent: true
})
// List root tasks only (tasks without a parent)
list_tasks({
has_parent: false
})
// Combine parent filter with other filters
list_tasks({
dartboard: "Engineering/backend",
has_parent: false,
priority: "high"
})
// Returns high-priority root tasks in the Engineering dartboardAPI Limitation: Only has_parent filter is supported because the list API returns parent_task but does not return taskRelationships data (subtask_ids, blocker_ids, etc.). To see full relationship data, use get_task() on individual tasks.
Token Budget: Variable based on result count (~200 tokens per 10 tasks)
Purpose: Search tasks by keywords with relevance ranking.
Input Schema:
{
query: string // REQUIRED, search keywords
dartboard?: string // filter to specific dartboard
limit?: number // max results, default 20
offset?: number // pagination offset, default 0
}Output Schema:
{
results: DartTask[] // ranked by relevance
total: number
query: string // echoed back
}Examples:
// Multi-term search
search_tasks({ query: "authentication security oauth" })
// Phrase search with dartboard filter
search_tasks({
query: "error handling database",
dartboard: "Engineering/backend"
})
// Pagination
search_tasks({
query: "bug fix",
limit: 20,
offset: 20
})How Search Works:
- Searches task titles and descriptions
- Ranks by relevance score (TF-IDF)
- Returns matches ordered by score (highest first)
Token Budget: Variable (~300 tokens per 10 results)
CRITICAL SAFETY RULES:
- ALWAYS use
dry_run: truefirst to preview matching tasks - Review preview before executing - verify selector is correct
- Test with small dataset first (< 10 tasks) before large batches
- Have rollback plan - tasks go to trash, recoverable via web UI
Purpose: Update multiple tasks matching a DartQL selector expression (SQL-like WHERE syntax).
Input Schema:
{
selector: string // REQUIRED, DartQL WHERE clause
updates: { // REQUIRED, fields to update
title?: string
description?: string
status?: string
priority?: string
size?: string
assignees?: string[]
tags?: string[]
dartboard?: string
due_at?: string
start_at?: string
// Relationship fields (arrays of dart_id strings)
subtask_ids?: string[] // IDs of subtask (child) tasks
blocker_ids?: string[] // IDs of tasks that block this task
blocking_ids?: string[] // IDs of tasks blocked by this task
duplicate_ids?: string[] // IDs of duplicate tasks
related_ids?: string[] // IDs of related tasks
}
dry_run?: boolean // default: false (RECOMMENDED: use true first!)
concurrency?: number // default: 5, range 1-20
}Relationship Update Semantics:
- Full replacement: Providing a relationship array replaces ALL existing values for ALL matched tasks
- Empty array
[]: Clears all relationships of that type on ALL matched tasks - Omitting field: Leaves existing relationships unchanged
Output Schema:
{
batch_operation_id: string
selector_matched: number // total tasks matching selector
dry_run: boolean
// If dry_run=true:
preview_tasks?: Array<{
dart_id: string
title: string
current_values: object // current values of fields being updated
new_values: object // values that will be applied (for relationships)
}> // max 10 tasks shown
// If dry_run=false:
successful_updates: number
failed_updates: number
successful_dart_ids: string[]
failed_items: Array<{
dart_id: string
error: string
reason: string
}>
execution_time_ms: number
}Examples:
// Step 1: ALWAYS preview first (dry_run=true by default)
batch_update_tasks({
selector: "dartboard = 'Engineering/backend' AND priority = 'high'",
updates: { status: "Doing" },
dry_run: true
})
// → Returns preview of up to 10 matching tasks
// Step 2: Review preview, verify selector matches ONLY intended tasks
// Step 3: Execute update (dry_run=false)
batch_update_tasks({
selector: "dartboard = 'Engineering/backend' AND priority = 'high'",
updates: { status: "Doing" },
dry_run: false
})
// → Updates all matching tasksComplex Examples:
// Update all overdue high-priority tasks
batch_update_tasks({
selector: "due_at < '2026-01-18T00:00:00Z' AND priority = 'high' AND status != 'Done'",
updates: {
priority: "critical",
assignees: ["manager@company.com"]
},
dry_run: true // ALWAYS preview first!
})
// Move completed Q4 tasks to archive
batch_update_tasks({
selector: "completed_at >= '2025-10-01T00:00:00Z' AND completed_at < '2026-01-01T00:00:00Z'",
updates: { dartboard: "Archive/2025-Q4" },
dry_run: false,
concurrency: 10 // faster with higher concurrency
})Relationship Batch Examples:
// Clear all blockers from tasks in a specific dartboard
batch_update_tasks({
selector: "dartboard = 'Engineering/backend' AND blocker_ids IS NOT NULL",
updates: {
blocker_ids: [] // empty array clears all blockers
},
dry_run: true // ALWAYS preview first!
})
// Mark all high-priority tasks as blocking the release task
batch_update_tasks({
selector: "priority = 'critical' AND status != 'Done'",
updates: {
blocking_ids: ["duid_release_v2"]
},
dry_run: true
})
// Link all security-tagged tasks as related to the audit task
batch_update_tasks({
selector: "tags CONTAINS 'security'",
updates: {
related_ids: ["duid_security_audit_2026"]
},
dry_run: true
})
// Clear duplicate relationships from resolved tasks
batch_update_tasks({
selector: "status = 'Done' AND duplicate_ids IS NOT NULL",
updates: {
duplicate_ids: []
},
dry_run: false
})Important: Batch relationship updates apply the SAME values to ALL matched tasks. Use this for scenarios like:
- Clearing relationships across many tasks
- Linking multiple tasks to a common blocker/release
- Resetting relationships during cleanup operations
Token Budget: ~400 tokens (returns summary, not full task data)
Performance: Depends on match count and concurrency (2-5 tasks/second typical)
Purpose: Delete (move to trash) multiple tasks matching a DartQL selector.
Input Schema:
{
selector: string // REQUIRED, DartQL WHERE clause
dry_run?: boolean // default: false (RECOMMENDED: use true first!)
confirm?: boolean // REQUIRED for dry_run=false (safety flag)
concurrency?: number // default: 5, range 1-20
}Output Schema: Same as batch_update_tasks (but no preview_tasks)
Examples:
// Step 1: Preview (dry_run=true)
batch_delete_tasks({
selector: "dartboard = 'Personal/test' AND status = 'Done'",
dry_run: true
})
// → Shows count of matching tasks
// Step 2: Execute (dry_run=false with confirm=true)
batch_delete_tasks({
selector: "dartboard = 'Personal/test' AND status = 'Done'",
dry_run: false,
confirm: true // REQUIRED safety flag
})
// → Moves all matching tasks to trashSAFETY NOTES:
- Tasks move to trash, NOT permanent deletion
- Recoverable via Dart web UI
confirm: truerequired for dry_run=false (prevents accidental deletion)- Triple-check selector specificity before executing
Purpose: Get status of a long-running batch operation.
Input Schema:
{
batch_operation_id: string // from batch_update_tasks or batch_delete_tasks
}Output Schema:
{
batch_operation_id: string
operation_type: 'update' | 'delete' | 'import'
status: 'pending' | 'in_progress' | 'completed' | 'failed'
total_items: number
successful_items: number
failed_items: number
started_at: string
completed_at?: string
}Examples:
get_batch_status({ batch_operation_id: "batch_abc123" })Purpose: Create hundreds of tasks from CSV data with validation, error recovery, and fuzzy matching.
Input Schema:
{
csv_data?: string // inline CSV content (first row = headers)
csv_file_path?: string // OR path to CSV file
dartboard: string // REQUIRED, default dartboard name
column_mapping?: object // custom column name mappings
validate_only?: boolean // default: true (RECOMMENDED: validate first!)
continue_on_error?: boolean // default: true
concurrency?: number // default: 5, range 1-20
}CSV Column Mapping:
{
// Map custom column names to dart-query field names
"Task Name": "title",
"Assigned To": "assignee",
"Issue Priority": "priority",
"Labels": "tags"
}Output Schema:
{
batch_operation_id: string
total_rows: number
valid_rows: number
invalid_rows: number
// Validation errors (if any)
validation_errors: Array<{
row_number: number
errors: string[] // list of errors for this row
}>
// If validate_only=true:
preview: Array<{
row_number: number
task_preview: object // what will be created
}> // max 10 rows
// If validate_only=false:
created_tasks: number
failed_tasks: number
created_dart_ids: string[]
failed_items: Array<{
row_number: number
error: string
row_data: object
}>
execution_time_ms: number
}CSV Format Guide:
Required Columns:
title- Task title (REQUIRED)
Optional Columns:
description- Task descriptionstatus- Status name (e.g., "To Do", "Doing")priority- Priority string ("critical", "high", "medium", "low")size- Size string ("xs", "small", "medium", "large", "xl")assignee- Email address or name (singular)dartboard- Override default dartboardtags- Comma-separated tag namesdue_date/due_at- ISO8601 date or recognizable formatstart_date/start_at- ISO8601 dateparent_task- Parent task dart_id
Relationship Columns (comma-separated dart_id values):
subtask_ids/subtasks/children- Comma-separated subtask IDsblocker_ids/blockers/blocked_by- Comma-separated blocker IDsblocking_ids/blocking/blocks- Comma-separated blocked task IDsduplicate_ids/duplicates- Comma-separated duplicate task IDsrelated_ids/related/related_tasks- Comma-separated related task IDs
Flexible Column Names (case-insensitive, fuzzy matched):
title=Title=Task Name=Taskassignee=Assigned To=Owner=Assigneetags=Labels=Tagspriority=Priority=Priblocker_ids=blockers=blocked_byblocking_ids=blocking=blocks
Example CSV (Basic):
title,description,assignee,priority,tags,due_at
"Fix login bug","Users can't login after password reset",john@company.com,critical,"bug,security",2026-02-01T00:00:00Z
"Update API docs","Document new authentication endpoints",writer@company.com,medium,documentation,2026-02-15T00:00:00Z
"Add rate limiting","Prevent API abuse",engineer@company.com,high,"feature,security",2026-02-10T00:00:00ZExample CSV (With Relationships):
title,priority,blocker_ids,related_ids,tags
"Deploy to production",critical,"duid_testing,duid_code_review",,deployment
"Write unit tests",high,,"duid_feature_impl","testing,quality"
"Code review",medium,"duid_feature_impl",,review
"Feature implementation",high,,,"feature,backend"CSV Relationship Format Notes:
- Use comma-separated dart_id values within a single cell
- Wrap in quotes if values contain commas:
"duid_task1,duid_task2" - Empty cell means no relationships of that type
- All dart_id values must be in valid format (e.g.,
duid_xxxxx)
Workflow:
// Step 1: Get config to understand valid values
get_config()
// → See available dartboards, priorities, sizes, tags
// Step 2: Validate CSV (validate_only=true)
import_tasks_csv({
csv_file_path: "./tasks.csv",
dartboard: "Engineering/backend",
validate_only: true
})
// → Returns validation errors and preview of first 10 tasks
// Step 3: Fix any validation errors in CSV
// Step 4: Execute import (validate_only=false)
import_tasks_csv({
csv_file_path: "./tasks.csv",
dartboard: "Engineering/backend",
validate_only: false
})
// → Creates all tasks (41 tasks in 17.4s typical)Advanced Example with Column Mapping:
import_tasks_csv({
csv_file_path: "./jira_export.csv",
dartboard: "Engineering/backend",
column_mapping: {
"Issue Summary": "title",
"Issue Description": "description",
"Assignee Email": "assignee",
"Issue Priority": "priority",
"Labels": "tags"
},
validate_only: true
})Error Recovery:
If > 50% of tasks fail, you'll get a rollback suggestion:
WARNING: 75% of tasks failed to create. Consider deleting created tasks and fixing errors.
Created task IDs: duid_task1, duid_task2, duid_task3
Use batch_delete_tasks to clean up:
// Delete failed import batch
batch_delete_tasks({
selector: "dart_id IN ('duid_task1', 'duid_task2', 'duid_task3')",
dry_run: false,
confirm: true
})Token Budget: ~500 tokens (returns summary + first 10 preview)
Performance: 2-4 tasks/second typical (41 tasks in 17.4s production tested)
dart-query includes full document (notes/docs) management. Documents are separate from tasks.
Input Schema:
{
folder?: string // filter by folder name
title_contains?: string // filter by title substring
text_contains?: string // filter by content substring
limit?: number // default 100
offset?: number // default 0
}Output Schema:
{
docs: Array<{
doc_id: string
title: string
folder?: string
created_at: string
updated_at: string
}>
total: number
}Input Schema:
{
title: string // REQUIRED
text: string // REQUIRED, markdown content
folder?: string // folder name
}Output Schema:
{
doc_id: string
title: string
text: string
folder?: string
created_at: string
updated_at: string
url?: string
}Input Schema:
{
doc_id: string // REQUIRED
}Output Schema: Same as create_doc
Input Schema:
{
doc_id: string // REQUIRED
title?: string
text?: string
folder?: string
}Output Schema: Same as get_doc (updated doc)
Input Schema:
{
doc_id: string // REQUIRED
}Output Schema:
{
success: boolean
doc_id: string
}Note: Docs move to trash (recoverable)
Purpose: Single-call snapshot for dartai loop startup. Returns dartboard config, claimable queue, runner-claimed tasks, and blocked tasks in one response. Replaces the 3-call sequence (get_config + list_tasks + client filter) with one aggregated call, saving 2 round-trips per loop iteration start.
Input Schema:
{
dartboard: string // REQUIRED — dartboard name or dart_id (e.g., "Personal/agnt")
runner_dart_id?: string // optional runner dart_id; populates runner_claimed when set
queue_limit?: number // max queue tasks returned (default: 20)
}Output Schema:
{
dartboard_id: string
config: {
statuses: string[] // dartboard's status names
assignees: { dart_id: string; email: string }[] // available assignees
}
queue: TaskSummary[] // Todo status, no `claimed:*` tag, not `loop-blocked` tagged
runner_claimed: TaskSummary[] // In Progress + assigned to runner_dart_id (empty when runner not provided)
blocked: TaskSummary[] // tasks tagged `loop-blocked` regardless of status
fetched_at: string // ISO-8601 timestamp of when the snapshot was assembled
}
// where:
type TaskSummary = {
dart_id: string
title: string
status: string
tags: string[]
assignees: string[]
}Examples:
// Minimal — just claimable queue + config
dartai_loop_snapshot({ dartboard: "Personal/agnt" })
// With runner partition — includes tasks already claimed by this runner
dartai_loop_snapshot({
dartboard: "Personal/agnt",
runner_dart_id: "ru_abc123",
queue_limit: 50
})Performance: Exactly one outbound listTasks call plus one cached get_config read. Designed to be the first call in dartai:start / workflow:start-loop skill flows.
DartQL uses SQL-92 WHERE clause syntax for batch operations.
field operator value [AND|OR field operator value ...]| Operator | Description | Example |
|---|---|---|
= |
Equals | status = 'To Do' |
!= / <> |
Not equals | priority != 'low' |
> |
Greater than | due_at > '2026-02-01' |
>= |
Greater or equal | priority >= 'high' |
< |
Less than | due_at < '2026-01-18' |
<= |
Less or equal | priority <= 'medium' |
IN |
In list | status IN ('To Do', 'Doing') |
NOT IN |
Not in list | priority NOT IN ('low') |
LIKE |
Pattern match (% = any chars, _ = single char, case-insensitive) |
title LIKE 'Task%' |
CONTAINS |
Array contains (aliases: INCLUDES, HAS) |
tags CONTAINS 'urgent' |
IS NULL |
Is null/undefined | due_at IS NULL |
IS NOT NULL |
Is not null | assignees IS NOT NULL |
BETWEEN |
Range | created_at BETWEEN '2026-01-01' AND '2026-01-31' |
| Operator | Description | Example |
|---|---|---|
AND |
Logical AND | status = 'To Do' AND priority = 'high' |
OR |
Logical OR | status = 'To Do' OR status = 'Doing' |
NOT |
Logical NOT | NOT (priority = 'low') |
( ) |
Grouping | (status = 'To Do' OR status = 'Doing') AND priority = 'high' |
Core Fields:
status- Task statuspriority- Priority stringsize- Size stringtitle- Task titledescription- Task descriptionassignee- Assignee emaildartboard- Dartboard nametags- Tag arraycreated_at- Creation timestampupdated_at- Update timestampdue_at- Due datestart_at- Start datecompleted_at- Completion timestampdart_id- Task ID
Relationship Fields:
parent_task- Parent task ID (string)subtask_ids- Subtask IDs (array)blocker_ids- Blocker task IDs (array)blocking_ids- Blocked task IDs (array)duplicate_ids- Duplicate task IDs (array)related_ids- Related task IDs (array)
Simple equality:
status = 'To Do'
dartboard = 'Engineering/backend'
priority = 'high'Multiple conditions (AND):
status = 'To Do' AND priority = 'high'
dartboard = 'Engineering/backend' AND assignee = 'john@company.com'OR conditions:
status = 'To Do' OR status = 'Doing'
priority = 'high' OR priority = 'critical'Range operators:
due_at < '2026-01-18T00:00:00Z'
due_at > '2026-02-01T00:00:00Z'IN operator:
status IN ('To Do', 'Doing', 'Blocked')
priority IN ('high', 'critical')Tag filtering:
tags CONTAINS 'urgent'
tags CONTAINS 'bug' AND tags CONTAINS 'security'Pattern matching (LIKE with SQL-92 wildcards):
title LIKE 'Task%' -- starts with "Task"
title LIKE '%authentication%' -- contains "authentication"
title LIKE '%fix' -- ends with "fix"
description LIKE 'API_%' -- starts with "API_" (underscore = single char)NULL checks:
due_at IS NULL
assignees IS NOT NULLComplex queries with grouping:
(status = 'To Do' OR status = 'Doing') AND priority = 'high'
dartboard = 'Engineering/backend' AND (priority = 'critical' OR tags CONTAINS 'urgent')BETWEEN operator:
created_at BETWEEN '2026-01-01T00:00:00Z' AND '2026-01-31T23:59:59Z'Find tasks with relationships:
-- Tasks that have blockers (are blocked by something)
blocker_ids IS NOT NULL
-- Tasks that are blocking other tasks
blocking_ids IS NOT NULL
-- Tasks with subtasks (parent tasks)
subtask_ids IS NOT NULL
-- Leaf tasks (no subtasks)
subtask_ids IS NULL
-- Tasks with related tasks
related_ids IS NOT NULL
-- Tasks marked as duplicates
duplicate_ids IS NOT NULLFind tasks blocked by a specific task:
-- Tasks blocked by the release blocker
blocker_ids CONTAINS 'duid_release_blocker'
-- Tasks blocking the deployment
blocking_ids CONTAINS 'duid_deployment'Find tasks related to a specific task:
related_ids CONTAINS 'duid_feature_spec'Combined relationship and field queries:
-- High-priority blocked tasks
blocker_ids IS NOT NULL AND priority = 'high'
-- Blocked tasks in Engineering dartboard
dartboard = 'Engineering/backend' AND blocker_ids IS NOT NULL
-- Critical tasks that are blocking releases
priority = 'critical' AND blocking_ids CONTAINS 'duid_release_v2'
-- Parent tasks with urgent tag
subtask_ids IS NOT NULL AND tags CONTAINS 'urgent'
-- Unblocked tasks ready to start
blocker_ids IS NULL AND status = 'To Do' AND priority = 'high'Note on IS NULL for relationship arrays:
blocker_ids IS NULLmatches tasks with NO blockers (empty array or undefined)blocker_ids IS NOT NULLmatches tasks with AT LEAST ONE blocker- Empty arrays
[]are treated as NULL for relationship fields
dart-query optimizes queries by using Dart API filters when possible, falling back to client-side filtering for complex queries.
API-Compatible (fast):
- Simple
=equality on: assignee, status, dartboard, priority, tags - Range operators on: due_at (
<,>,<=,>=) - AND logic only
Requires Client-Side Filtering (slower):
- OR logic
- NOT logic
!=operatorIN,NOT IN,LIKE,CONTAINS,IS NULL,BETWEEN- Range operators on priority/size
- Complex nested expressions
Example:
// API-compatible (fast)
batch_update_tasks({
selector: "dartboard = 'Engineering' AND priority = 'high'",
updates: { status: "Doing" }
})
// Requires client-side filtering (slower, fetches all tasks first)
batch_update_tasks({
selector: "status IN ('To Do', 'Doing') AND tags CONTAINS 'urgent'",
updates: { priority: "critical" }
})When client-side filtering is needed, you'll see a warning:
Query requires client-side filtering which may impact performance.
Consider using simpler queries with API-supported filters for better performance.
DartQL provides helpful error messages with suggestions:
Unknown field: 'priorty'. Did you mean 'priority'?
Unknown field: 'assignees'. Did you mean 'assignee'?
ValidationError - Input validation failures
{
message: string
field?: string // which field failed
suggestions?: string[] // fuzzy match suggestions
}Common causes:
- Missing required fields
- Invalid field values (priority not in config)
- Invalid date formats
- Empty strings where non-empty expected
DartAPIError - API communication errors
{
message: string
statusCode: number // HTTP status code
response?: object // API response body
}Common status codes:
401- Invalid or missing DART_TOKEN404- Resource not found (task, dartboard, etc.)429- Rate limit exceeded400- Bad request (malformed data)500- Server error
DartQLParseError - DartQL syntax errors
{
message: string
position: number // character position in query
token: string // token that caused error
}Common causes:
- Unterminated string literals
- Unknown operators
- Missing parentheses
- Invalid field names
Validation Errors:
try {
create_task({
title: "Test task",
dartboard: "Invalid Board"
});
} catch (error) {
if (error instanceof ValidationError) {
// Check suggestions
if (error.suggestions && error.suggestions.length > 0) {
console.log(`Did you mean: ${error.suggestions.join(', ')}?`);
}
// Get valid values from config
const config = await get_config();
console.log(`Valid dartboards: ${config.dartboards.join(', ')}`);
}
}Rate Limiting (429):
// Reduce concurrency
batch_update_tasks({
selector: "status = 'To Do'",
updates: { priority: "high" },
concurrency: 2 // Lower than default 5
})dart-query has automatic retry with exponential backoff for rate limits.
Network Errors:
try {
const config = await get_config();
} catch (error) {
if (error instanceof DartAPIError && error.statusCode >= 500) {
// Server error - retry after delay
await new Promise(resolve => setTimeout(resolve, 5000));
const config = await get_config({ cache_bust: true });
}
}CSV Import Errors:
// Always validate first
const validation = await import_tasks_csv({
csv_file_path: "./tasks.csv",
dartboard: "Engineering",
validate_only: true
});
if (validation.validation_errors.length > 0) {
// Show all errors
validation.validation_errors.forEach(err => {
console.log(`Row ${err.row_number}: ${err.errors.join('; ')}`);
});
// Fix CSV and retry
} else {
// Execute import
const result = await import_tasks_csv({
csv_file_path: "./tasks.csv",
dartboard: "Engineering",
validate_only: false
});
}// Good: Uses 5-minute cache
get_config()
// Bad: Forces API call every time
get_config({ cache_bust: true })// Minimal details (fewer tokens, faster)
list_tasks({ detail_level: "minimal" })
// Standard (default)
list_tasks({ detail_level: "standard" })
// Full (most tokens, slowest)
list_tasks({ detail_level: "full" })// Too low: slow
batch_update_tasks({
selector: "...",
updates: { ... },
concurrency: 1
})
// Default: balanced (5 concurrent)
batch_update_tasks({
selector: "...",
updates: { ... }
})
// Higher: faster but risks rate limits
batch_update_tasks({
selector: "...",
updates: { ... },
concurrency: 15 // Monitor for 429 errors
})// Fast: API-compatible
selector: "dartboard = 'Engineering' AND priority = 'high'"
// Slow: Client-side filtering required
selector: "status IN ('To Do', 'Doing') OR priority = 'critical'"// Get first 100 tasks
const page1 = await list_tasks({ limit: 100, offset: 0 });
// Get next 100 tasks
const page2 = await list_tasks({ limit: 100, offset: 100 });// Bad: 50 individual API calls, 25,000+ tokens
for (const task of tasks) {
await update_task({ dart_id: task.dart_id, updates: { status: "Done" } });
}
// Good: 1 batch operation, ~400 tokens
batch_update_tasks({
selector: "dartboard = 'Engineering' AND priority = 'high'",
updates: { status: "Done" }
})Token savings: 99% Time savings: 90% Context rot: Eliminated
// Bad: 100 create_task calls, 30,000+ tokens
for (const row of csvData) {
await create_task({ title: row.title, ... });
}
// Good: 1 CSV import, ~500 tokens
import_tasks_csv({
csv_file_path: "./tasks.csv",
dartboard: "Engineering",
validate_only: false
})// Step 1: Create parent task
const parent = await create_task({
title: "Implement OAuth2 authentication",
dartboard: "Engineering/backend",
priority: "high",
size: "xl",
due_at: "2026-03-01T00:00:00Z"
});
// Step 2: Create subtasks
await create_task({
title: "Add Google OAuth provider",
dartboard: "Engineering/backend",
priority: "high",
parent_task: parent.dart_id
});
await create_task({
title: "Add GitHub OAuth provider",
dartboard: "Engineering/backend",
priority: "high",
parent_task: parent.dart_id
});
// Step 3: Update all subtasks when starting work
await batch_update_tasks({
selector: `parent_task = '${parent.dart_id}'`,
updates: { status: "Doing" }
});// Step 1: Export from external system to CSV
// Create CSV: jira_export.csv
// Step 2: Get dart-query config
const config = await get_config();
console.log("Available dartboards:", config.dartboards);
console.log("Available priorities:", config.priorities);
// Step 3: Validate CSV
const validation = await import_tasks_csv({
csv_file_path: "./jira_export.csv",
dartboard: "Engineering/backend",
column_mapping: {
"Issue Summary": "title",
"Issue Description": "description",
"Assignee Email": "assignee",
"Issue Priority": "priority",
"Labels": "tags"
},
validate_only: true
});
if (validation.validation_errors.length > 0) {
console.error("Validation errors:", validation.validation_errors);
process.exit(1);
}
// Step 4: Execute import
const result = await import_tasks_csv({
csv_file_path: "./jira_export.csv",
dartboard: "Engineering/backend",
column_mapping: {
"Issue Summary": "title",
"Issue Description": "description",
"Assignee Email": "assignee",
"Issue Priority": "priority",
"Labels": "tags"
},
validate_only: false
});
console.log(`Created ${result.created_tasks} tasks in ${result.execution_time_ms}ms`);// Step 1: Find all unassigned high-priority tasks
const unassigned = await list_tasks({
priority: "high",
status: "To Do"
});
// Step 2: Assign to team members
await batch_update_tasks({
selector: "priority = 'high' AND status = 'To Do' AND tags CONTAINS 'backend'",
updates: { assignees: ["john@company.com"] }
});
await batch_update_tasks({
selector: "priority = 'high' AND status = 'To Do' AND tags CONTAINS 'frontend'",
updates: { assignees: ["jane@company.com"] }
});
// Step 3: Set sprint deadlines
await batch_update_tasks({
selector: "assignees IS NOT NULL AND status = 'To Do'",
updates: { due_at: "2026-02-01T00:00:00Z" }
});// Step 1: Archive completed tasks
await batch_update_tasks({
selector: "completed_at >= '2025-10-01' AND completed_at < '2026-01-01'",
updates: { dartboard: "Archive/2025-Q4" },
dry_run: true // Preview first
});
// Step 2: After reviewing preview, execute
await batch_update_tasks({
selector: "completed_at >= '2025-10-01' AND completed_at < '2026-01-01'",
updates: { dartboard: "Archive/2025-Q4" },
dry_run: false,
concurrency: 10
});
// Step 3: Delete abandoned low-priority tasks
await batch_delete_tasks({
selector: "priority = 'low' AND updated_at < '2025-10-01' AND status = 'To Do'",
dry_run: true
});
await batch_delete_tasks({
selector: "priority = 'low' AND updated_at < '2025-10-01' AND status = 'To Do'",
dry_run: false,
confirm: true
});// Step 1: Search for security-related tasks
const securityTasks = await search_tasks({
query: "security vulnerability authentication xss sql injection",
dartboard: "Engineering"
});
// Step 2: Tag all security tasks
await batch_update_tasks({
selector: "tags CONTAINS 'security'",
updates: {
priority: "critical",
tags: ["security", "audit-2026-q1"]
}
});
// Step 3: Track remediation
await add_task_comment({
dart_id: "duid_task123",
comment: "Reviewed by security team - CVSS 8.5, requires immediate patching"
});// Step 1: Create a release task that will be blocked by feature tasks
const release = await create_task({
title: "Release v2.0",
dartboard: "Engineering/releases",
priority: "high",
due_at: "2026-03-01T00:00:00Z"
});
// Step 2: Create feature tasks that block the release
const feature1 = await create_task({
title: "Implement OAuth2",
dartboard: "Engineering/backend",
priority: "high",
blocking_ids: [release.dart_id] // This task blocks the release
});
const feature2 = await create_task({
title: "Update user dashboard",
dartboard: "Engineering/frontend",
priority: "high",
blocking_ids: [release.dart_id] // This task also blocks the release
});
// Step 3: Update the release task with its blockers
await update_task({
dart_id: release.dart_id,
updates: {
blocker_ids: [feature1.dart_id, feature2.dart_id]
}
});
// Step 4: Check the release task for blockers
// Note: list_tasks doesn't support has_blockers filter (API limitation)
// Use get_task to see relationship data for individual tasks
const releaseTask = await get_task({ dart_id: release.dart_id });
const hasBlockers = releaseTask.blocker_ids?.length > 0;
// Step 5: When a feature is complete, update relationships
// Remove completed feature from blockers
const remainingBlockers = releaseTask.blocker_ids?.filter(
id => id !== feature1.dart_id
) || [];
await update_task({
dart_id: release.dart_id,
updates: {
blocker_ids: remainingBlockers
}
});
// Step 6: Check if release is ready (no more blockers)
const updatedRelease = await get_task({ dart_id: release.dart_id });
const isReady = !updatedRelease.blocker_ids || updatedRelease.blocker_ids.length === 0;// Step 1: Create a design spec task
const designSpec = await create_task({
title: "Design authentication system spec",
dartboard: "Engineering/design",
priority: "high"
});
// Step 2: Create implementation tasks related to the spec
const backendTask = await create_task({
title: "Implement auth backend",
dartboard: "Engineering/backend",
related_ids: [designSpec.dart_id]
});
const frontendTask = await create_task({
title: "Implement auth frontend",
dartboard: "Engineering/frontend",
related_ids: [designSpec.dart_id]
});
// Step 3: Update the spec to link back to implementations
await update_task({
dart_id: designSpec.dart_id,
updates: {
related_ids: [backendTask.dart_id, frontendTask.dart_id]
}
});
// Step 4: Batch link all auth-tagged tasks to the spec
await batch_update_tasks({
selector: "tags CONTAINS 'auth' AND dart_id != '" + designSpec.dart_id + "'",
updates: {
related_ids: [designSpec.dart_id]
},
dry_run: true // Preview first!
});
// Step 5: Find all tasks related to the spec
const relatedToSpec = await list_tasks({});
// Then filter client-side or use DartQL:
await batch_update_tasks({
selector: "related_ids CONTAINS '" + designSpec.dart_id + "'",
updates: { status: "In Review" },
dry_run: true
});// Step 1: Find potential duplicates via search
const searchResults = await search_tasks({
query: "authentication login bug"
});
// Step 2: Mark tasks as duplicates of the original
const originalTask = searchResults.results[0];
const duplicateTasks = searchResults.results.slice(1);
// Link duplicates to original
await update_task({
dart_id: originalTask.dart_id,
updates: {
duplicate_ids: duplicateTasks.map(t => t.dart_id)
}
});
// Step 3: Close duplicate tasks
await batch_update_tasks({
selector: `dart_id IN (${duplicateTasks.map(t => `'${t.dart_id}'`).join(', ')})`,
updates: {
status: "Duplicate",
duplicate_ids: [originalTask.dart_id] // Link back to original
},
dry_run: false
});
// Step 4: Find all tasks marked as duplicates
const allDuplicates = await list_tasks({});
// Use DartQL to find:
await batch_update_tasks({
selector: "duplicate_ids IS NOT NULL",
updates: { priority: "low" },
dry_run: true
});Error:
Error: Invalid DART_TOKEN
Solution:
- Get fresh token from https://app.dartai.com/?settings=account
- Ensure token starts with
dsa_ - Verify environment variable:
echo $DART_TOKEN - Restart MCP server after changing token
Error:
Error: Rate limit exceeded
Solution:
- Reduce
concurrencyparameter (try 2-3 instead of default 5) - Add delays between batch operations
- Use API-compatible DartQL (avoids client-side filtering)
- Contact Dart support if persistent
dart-query has automatic retry with exponential backoff.
Error:
Row 3, column 'priority': Invalid priority: "5". Available: critical, high, medium, low
Solution:
- Always use
validate_only: truefirst - Check
get_config()for available values - Use string priorities ("high") not numbers (3)
- Use string sizes ("medium") not numbers (3)
- Verify dartboard names exactly match config
- Check date formats (ISO8601: "2026-02-01T00:00:00Z")
Error:
Unknown field: priorty. Did you mean: priority?
Solution:
- Check field name spelling (fuzzy match suggestions provided)
- Valid fields: status, priority, size, title, description, assignee, dartboard, tags, dates, dart_id
- Use quotes for string values:
status = 'To Do'notstatus = To Do - Check operator syntax (SQL-92):
=,!=/<>,>,>=,<,<=,IN,NOT IN,LIKE,CONTAINS/INCLUDES/HAS,IS NULL,BETWEEN - For pattern matching use
LIKEwith%and_wildcards (notstarts_with,matches, etc.)
Error:
Accidentally updated 500 tasks instead of 50
Solution:
- ALWAYS use
dry_run: truefirst - Review preview carefully before executing
- Test selector with
list_tasks()first - Start with small batches (< 10 tasks) to verify selector
- Use more specific selectors (multiple AND conditions)
Recovery: Tasks move to trash (recoverable via Dart web UI)
Symptoms:
- Batch operations taking > 10s per task
- CSV imports timing out
- Context window filling up
Solutions:
- Use API-compatible DartQL (avoid OR, NOT, LIKE)
- Increase concurrency (try 10-15 instead of 5)
- Use
detail_level: "minimal"for large queries - Enable config cache (default 5 minutes)
- Paginate large result sets
- Use batch operations instead of individual CRUD
- ✅ Always use
dry_run: truefor batch operations - ✅ Always use
validate_only: truefor CSV imports - ✅ Test selectors with small datasets first (< 10 tasks)
- ✅ Review previews before executing
- ✅ Have rollback plan (tasks → trash, recoverable)
- ✅ Use
confirm: truefor batch deletes - ✅ Triple-check selector specificity
- ✅ Use batch operations for > 5 tasks
- ✅ Use CSV import for > 50 tasks
- ✅ Use config cache (don't bust unless needed)
- ✅ Use minimal detail levels when possible
- ✅ Use API-compatible DartQL selectors
- ✅ Adjust concurrency based on rate limits (2-15 range)
- ✅ Paginate large result sets (limit/offset)
- ✅ Call
get_config()before creating tasks - ✅ Validate all CSV data before import
- ✅ Use fuzzy match suggestions for typos
- ✅ Check field names in DartQL queries
- ✅ Use proper date formats (ISO8601)
- ✅ Use string priorities/sizes ("high", "medium") not numbers
- ✅ Batch operations return summaries (not full data)
- ✅ CSV import returns preview of first 10 (not all)
- ✅ Use
infotool for progressive discovery - ✅ Use
detail_level: "minimal"when appropriate - ✅ Result: 99% token reduction vs. traditional approach
For additional help:
- GitHub Issues: https://github.com/standardbeagle/dart-query/issues
- Dart AI Support: https://dartai.com/support
- MCP Documentation: https://modelcontextprotocol.io