Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.dovetail.com/llms.txt

Use this file to discover all available pages before exploring further.

Dovetail CLI

The Dovetail CLI (dt) is a command-line tool for importing content into your Dovetail workspace from external sources — Notion, Confluence, Google Drive, Airtable, Productboard, EnjoyHQ, Marvin, Condens, and local files. Use it when you want to bulk-migrate historical research, run repeatable imports from a scriptable workflow, or stage a migration locally before sending data to Dovetail.

What can you do with the Dovetail CLI?

  • Bulk import from 9+ sources — Notion, Confluence, Google Drive, Airtable, Marvin, Condens, EnjoyHQ, Productboard, and local files
  • Preserve formatting and metadata — Headings, lists, tables, code blocks, attachments, author info, dates, and tags come through intact
  • Preview before committing — See exactly what will be imported before data touches your workspace
  • Resume interrupted imports — If an import fails partway through, pick up where you left off—no re-processing needed
  • Batch multiple sources — Configure migrations from Notion and Confluence in one config file, run them together
  • Filter and limit — Import only records matching specific titles, dates, or file types
  • Test connections — Validate API credentials and workspace permissions before running the full migration

Security and permissions

The CLI authenticates to Dovetail using a personal API key from your workspace settings. It only has write access to the destinations you configure — it cannot read or modify anything else in your workspace. Source credentials (Notion token, Confluence API token, etc.) are stored locally in your dt.yaml or as environment variables and are never transmitted anywhere except the source service itself.

Prerequisites

Before you install, make sure you have:
  • A Dovetail workspace and an API key. Generate one in your workspace settings.
  • What plans support the CLI?
    • All plans except plans that have HIIPA enabled.
  • Your workspace URL — for example, https://yourcompany.dovetail.com.
  • One of the supported install paths:
    • npm install: Node.js and npm. 
  • Build from source: Go 1.25 or later, plus make.
  • The credentials for each source you plan to import from. These vary by source — see Authenticate below.
The CLI runs on macOS, Linux, and Windows. The published npm package ships per-platform binaries (@heydovetail/dt-darwin-arm64, @heydovetail/dt-linux-x64, and so on) and npm install only downloads the binary for your machine.\

Install

You can install the CLI in two ways. Most people should use npm.

Install via npm

npm install -g @heydovetail/dt
Verify the install:
dt --version
You should see a version number print to your terminal. If dt isn’t found, your global npm bin directory may not be on your PATH — run npm prefix -g to see where npm installs global binaries and add that path’s bin subdirectory to your shell profile.

Build from source

You’ll need Go 1.25 or later.
git clone https://github.com/dovetail/cli.git
cd cli
make install
make install builds the dt binary and installs it to~/.local/bin/dt.If ~/.local/bin isn’t on your PATH, add it:
export PATH="$HOME/.local/bin:$PATH"
Other make targets you may need:
  • make build — compile the binary without installing it.
  • make test — run the test suite.
  • make lint — run golangci-lint.

Install shell completions

After installing, you can turn on autocompletion for dt subcommands and flags:
dt completions install
This supports bash, zsh, and fish.

Authenticate

Authentication happens at two levels: the CLI authenticates to your Dovetail workspace, and each source you connect authenticates separately to its own provider.

Authenticate to Dovetail

Set your Dovetail API key as an environment variable, then run the setup wizard:
export DOVETAIL_API_KEY="your-api-key"
dt init
dt init is an interactive wizard that:
  1. Confirms your workspace URL (for example, https://yourcompany.dovetail.com).
  2. Stores your API key.
  3. Walks you through adding your first source.
Re-run with dt init --force to overwrite an existing configuration. You can also set your workspace URL persistently in your config under dovetail.base_url. This is important — it ensures every link the CLI generates points to the right workspace.

Authenticate each source

Every source has its own credential. Most use a personal access token set via environment variable; Google Drive uses OAuth or a service account.
SourceStatusAuth methodEnvironment variable
NotionGAInternal integration tokenNOTION_TOKEN
ConfluenceGAAPI token + email + base URLCONFLUENCE_API_TOKEN, CONFLUENCE_EMAIL, CONFLUENCE_BASE_URL
Google DriveGAOAuth (personal) or service account (org)GOOGLE_APPLICATION_CREDENTIALS (service account only)
AirtableGAPersonal access token with data.records:read and schema.bases:readAIRTABLE_TOKEN
ProductboardGAPublic API access tokenPRODUCTBOARD_API_TOKEN
EnjoyHQExperimentalWorkspace API tokenENJOYHQ_API_TOKEN
MarvinExperimentalNone (local export folder)
CondensExperimentalNone (local zip export)
Local filesGANone

Supported sources & field mapping

Notion

What gets migrated:
  • Pages and database entries with all formatting (headings, lists, tables, code blocks, callouts, toggles)
  • Inline attachments and cover images
  • Metadata: author, creation date, last-modified date, tags, properties
  • Child pages (up to 3 levels of nesting, configurable)
Field mapping to Dovetail: | Notion | Dovetail | |--------|----------| | Page title | Record title | | Page content (HTML) | Record body | | Database properties | Custom fields or tags | | Attachments & images | Attachments | | Author & dates | Data metadata | | Page link | Source URL | Requirements:
  • Notion Integration created at https://www.notion.so/my-integrations
  • All databases you want to migrate must be explicitly shared with the integration
  • Integration must have “Read” permissions at minimum
Setup:
export NOTION_TOKEN="ntn_xxxxxxxxxxxx"
dt source add notion
dt source validate notion
Field mapping configuration (optional): You can map Notion database properties to Dovetail custom fields. If not configured, properties are stored as tags.

Confluence

What gets migrated:
  • Cloud pages and blog posts with full HTML content and formatting
  • Attachments (PDFs, images, Word docs, etc.)
  • Labels and metadata (author, creation/modification dates, space key)
  • Parent-child page relationships preserved
  • Comments (available as metadata)
Field mapping to Dovetail: | Confluence | Dovetail | |------------|----------| | Page/post title | Record title | | Page content (HTML) | Record body | | Attachments | Attachments | | Labels | Tags | | Author & dates | Data metadata | | Space | Project or folder (configurable) | Requirements: Setup:
export CONFLUENCE_API_TOKEN="your-api-token"
export CONFLUENCE_EMAIL="you@company.com"
export CONFLUENCE_BASE_URL="https://mycompany.atlassian.net/wiki"
dt source add confluence
dt source validate confluence
Rate limits:
  • 300 requests per minute per API token (Atlassian limit)
  • The CLI automatically retries with exponential backoff; no action needed

Google Drive

What gets migrated:
  • Google Docs (exported as HTML with formatting)
  • Google Sheets (optionally, as CSV)
  • PDFs, images, and other files (as attachments)
  • Folder structure and hierarchy preserved
  • File metadata (owner, creation/modification dates)
Field mapping to Dovetail: | Google Drive | Dovetail | |--------------|----------| | Document title | Record title | | Document content (HTML) | Record body | | Spreadsheet rows | Records (one per row) or single attachment | | Files | Attachments | | Folder structure | Organize into projects/folders | | Shared metadata | Source info & timestamps | Requirements: Choose one authentication method:
  1. OAuth (personal/shared drives, recommended for most users)
  • Google Cloud project with Drive API enabled
  • OAuth 2.0 Desktop client ID created
  • dt source add gdrive opens your browser to sign in
  • No credential file needed; token is stored securely
  1. Service account (org/shared drives)
  • Service account created in Google Cloud
  • JSON key file downloaded
  • Drive folder explicitly shared with the service account email
  • Set GOOGLE_APPLICATION_CREDENTIALS environment variable
Setup:
# OAuth (most common)
dt source add gdrive
dt source validate gdrive

# Service account (shared drives)
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"
dt source add gdrive
dt source validate gdrive
Rate limits:
  • 10 million read requests per day (per project)
  • 600 requests per minute per user
  • The CLI automatically retries rate-limited requests
Technical details:
  • Large files (>50 MB) may take longer to transfer; no timeout
  • Empty files are skipped
  • Google Sheets are converted to CSV format

Airtable

What gets migrated:
  • Records from all tables/views
  • All field values (text, numbers, attachments, linked records, etc.)
  • Attachment files uploaded as Dovetail attachments
  • Linked record metadata (record name, ID)
  • Field names and types preserved
Field mapping to Dovetail: | Airtable | Dovetail | |----------|----------| | Record ID | Record ID (preserved for deduplication) | | Field values | Custom fields or record body | | Attachments | Attachments | | Linked records | Cross-reference data or tags | | Field types | Mapped to Dovetail field types | Requirements:
  • Airtable personal access token from https://airtable.com/create/tokens
  • Required scopes: data.records:read and schema.bases:read
  • Read access to the base(s) you’re migrating
Setup:
export AIRTABLE_TOKEN="your-token"
dt source add airtable
dt source validate airtable
Rate limits:
  • 5 requests per second (Airtable limit)
  • The CLI respects this automatically; no backoff needed
Technical details:
  • Linked records are imported as metadata; you can later link them in Dovetail
  • Attachment metadata is preserved (file name, size, URL)

Marvin

What gets migrated:
  • Video/audio recordings → uploaded as data with automatic transcription
  • Insights (reports) → imported as docs with markdown content
  • Interview metadata (date, duration, tags, participant info)
Field mapping to Dovetail: | Marvin | Dovetail | |--------|----------| | Recording file | Data record with attachment | | Recording metadata | Record metadata (date, tags, participants) | | Insight markdown | Doc with full formatting | | Insight tags | Project tags | | Project | Project or folder | Requirements:
  • Manual export from Marvin (no public API), or use Claude Code /marvin-download skill
  • Folder structure:
marvin-export/
  Project Name/
    files/
      Interview 1.mp4
      Interview 2.mp4
    insights/
      My Report/
        content.md
        metadata.json
Setup: Option A: Automated export (recommended)
# In Claude Code, run: /marvin-download
# Downloads all recordings and insights automatically
# Then configure the CLI:
dt source add marvin
dt migrate run --source marvin --preview
Option B: Manual export
  1. In Marvin, go to each project → All Actions → Download Video
  2. Copy insight markdown into content.md files in the folder structure above
  3. Run:
dt source add marvin
Technical details:
  • Video/audio files are uploaded as attachments; Dovetail generates transcripts automatically
  • Transcription typically completes within 10 minutes for 1-hour recordings
  • Insights are imported as plain markdown docs; no special formatting required
  • Maximum file size: 5 GB per recording

Condens

What gets migrated:
  • Sessions (interview notes, transcripts, video) → data records
  • Artifacts (reports, deliverables) → docs
  • Video attachments automatically included
  • Session metadata (date, participants, tags)
Field mapping to Dovetail: | Condens | Dovetail | |---------|----------| | Session | Data record | | Video/transcript | Attachment + auto-transcription | | Artifact | Doc | | Metadata | Tags, dates | Requirements:
  • Condens export ZIP file from Project → Settings → Export data
  • No API credentials needed
Setup:
dt source add condens
# When prompted, provide the path to your .zip file
dt migrate run --source condens --preview
dt migrate run --source condens
Technical details:
  • ZIP is processed locally; never uploaded to Dovetail servers
  • Large projects (>1 GB) may take 5–10 minutes to process
  • Video formats supported: MP4, WebM, MOV (same as Dovetail)

EnjoyHQ

What gets migrated:
  • Stories (customer feedback) with HTML content → data records
  • Projects (plans + summaries) → docs
  • Documents (feedback text) → data records
  • Labels, state, customer info preserved
Field mapping to Dovetail: | EnjoyHQ | Dovetail | |---------|----------| | Story | Data record | | Project | Doc | | Document | Data record | | Labels | Tags | | Customer info | Record metadata | Requirements:
  • EnjoyHQ API token from workspace settings
  • Read access to stories, projects, and documents
Setup:
export ENJOYHQ_API_TOKEN="your-token"
dt source add enjoyhq
dt source validate enjoyhq
dt migrate run --source enjoyhq --preview
Rate limits:
  • 100 requests per minute
  • The CLI automatically respects this limit

Productboard

What gets migrated:
  • Notes (customer feedback, research) → data records
  • Features (with descriptions, metadata) → docs
  • Linked data (initiatives, objectives)
  • Metadata (date, priority, status, owner)
Field mapping to Dovetail: | Productboard | Dovetail | |--------------|----------| | Note | Data record | | Feature | Doc | | Field values | Custom fields or tags | | Attachments | Attachments | | Metadata | Record metadata | Requirements:
  • Productboard API token from Settings → Integrations → Public API
  • Read access to notes and features
Setup:
export PRODUCTBOARD_API_TOKEN="your-token"
dt source add productboard
dt source validate productboard
dt migrate run --source productboard --preview
Rate limits:
  • 60 requests per minute (Productboard public API)
  • The CLI automatically queues and retries

Local files

What gets migrated:
  • Markdown (.md) → record body
  • Text files (.txt, .html) → record body
  • PDFs, images, videos, Word docs → attachments
  • Folder structure preserved
Field mapping to Dovetail: | File | Dovetail | |------|----------| | File name | Record title | | File content (text) | Record body | | File (binary) | Attachment | | Folder | Project or folder | Requirements:
  • Local folder with files you want to import
  • No credentials needed
Setup:
dt source add local
# When prompted, provide the path to your folder
dt migrate run --source local --preview
dt migrate run --source local
Options:
extensions: ".md,.pdf,.mp4"  # Import only these file types (optional)
Technical details:
  • File permissions: must have read access
  • Symlinks are followed
  • Hidden files (starting with .) are skipped
  • Maximum file size: 5 GB

Configuration

Configuration file structure (dt.yaml)

The CLI uses a YAML configuration file to manage migrations:
dovetail:
  base_url: "https://mycompany.dovetail.com"
  api_key: "${DOVETAIL_API_KEY}"  # Or paste key directly (not recommended)

sources:
  notion:
    token: "${NOTION_TOKEN}"
    child_pages: "true"

  confluence:
    base_url: "https://mycompany.atlassian.net/wiki"
    email: "you@company.com"
    token: "${CONFLUENCE_API_TOKEN}"

migrations:
  # Notion database to project data
  - source: notion
    content:
      - "notion-database-id-here"
    destination:
      type: "data"
      parent:
        type: "project"
        name: "Customer Research"

  # Confluence space to project docs
  - source: confluence
    content:
      - "PROD"  # Space key
    destination:
      type: "doc"
      parent:
        type: "project"
        name: "Product Knowledge Base"

  # Google Drive folder to data
  - source: gdrive
    content:
      - "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs"  # Folder ID
    destination:
      type: "data"
      parent:
        type: "project"
        name: "UX Research Archive"
    options:
      recursive: "true"
      include_binary: "true"

  # Local files to data
  - source: local
    content:
      - "/path/to/your/folder"
    destination:
      type: "data"
      parent:
        type: "project"
        name: "Research Files"
    options:
      extensions: ".md,.pdf,.mp4"

Configuration resolution order

The CLI resolves configuration from (highest to lowest priority):
  1. CLI flagsdt migrate run --source notion --limit 100
  2. Environment variablesexport NOTION_TOKEN="..."
  3. dt.yaml filesources.notion.token
  4. Defaults — Built-in sensible defaults

Environment variables reference

VariableUsed byPurpose
DOVETAIL_API_KEYAll sourcesDovetail workspace authentication
NOTION_TOKENNotionNotion integration token
CONFLUENCE_API_TOKENConfluenceConfluence API authentication
CONFLUENCE_EMAILConfluenceConfluence account email
CONFLUENCE_BASE_URLConfluenceConfluence workspace URL
GOOGLE_APPLICATION_CREDENTIALSGoogle DrivePath to service account JSON key
AIRTABLE_TOKENAirtableAirtable personal access token
ENJOYHQ_API_TOKENEnjoyHQEnjoyHQ API token
PRODUCTBOARD_API_TOKENProductboardProductboard API token

Running migrations

Preview before importing

Always preview first to see exactly what will be imported:
dt migrate run --source notion --preview
This shows:
  • Number of records that will be imported
  • Size of attachments
  • Any records that will be skipped (and why)
  • Estimated import time
No data is sent to Dovetail in preview mode.

Run the migration

dt migrate run --source notion
The CLI will:
  1. Fetch records from the source
  2. Transform them into Dovetail format
  3. Upload in batches with progress updates
  4. Show a summary of imported records and any errors

Advanced migration options

# Run migrations for multiple sources at once
dt migrate run

# Run only specific migrations by source
dt migrate run --source notion
dt migrate run --source confluence

# Limit the number of records processed (useful for testing)
dt migrate run --source notion --limit 10

# Filter by title or date
dt migrate run --source notion --filter "title:Interview"
dt migrate run --source notion --filter "date:2024-01-01:2024-12-31"

# Dry-run: fetch and transform, but don't upload
dt migrate run --source notion --dry-run

# Re-run without creating duplicates (uses record IDs for deduplication)
dt migrate run --source notion --upsert

# Minimal output (errors and summary only)
dt migrate run --source notion --quiet

# Detailed progress logs
dt migrate run --source notion --verbose

# Machine-readable JSON output
dt migrate run --source notion --output json

# Use a specific config file
dt migrate run --config /path/to/custom-dt.yaml

# Resume an interrupted migration
dt migrate resume

Duplicate handling & upsert behavior

By default, running a migration multiple times creates duplicate records. To prevent duplicates on re-runs:
dt migrate run --source notion --upsert
How it works:
  • Records are matched by source ID (Notion page ID, Confluence page ID, etc.)
  • If a record with the same source ID exists in Dovetail, it’s updated (not duplicated)
  • New records are created if they don’t exist
  • The upsert feature works with all sources except local files
    Important: If you delete a record in Dovetail, running —upsert again will re-create it from the source.

Testing & validation

Validate a source connection

Before running a full migration, test that your credentials work:
dt source validate notion
This checks:
  • API token is valid and not expired
  • Token has necessary permissions
  • You have access to at least one database/page
  • Network connectivity to the source API

Validate migration configuration

Check your dt.yaml syntax and workspace connectivity:
dt migrate validate

Workspace health check

See what’s already in your Dovetail workspace:
dt status
Shows:
  • Workspace name and URL
  • Number of projects, docs, records
  • Configured migrations
  • Any incomplete or failed imports

Workspace statistics

Quick count of content:
dt stats

Diagnostic check

Full system diagnostics:
dt doctor
Checks:
  • Configuration file validity
  • Dovetail API connectivity
  • Source credentials
  • Staging directory available
  • Disk space

Troubleshooting

Run dt doctor first whenever something is wrong. It checks your config, your network connection to Dovetail, every configured source credential, and the staging directory. Most issues show up there before you have to debug deeper.
SymptomLikely causeWhat to do
401 UnauthorizedYour Dovetail API key or a source token is invalid or expired.Regenerate the token, update the relevant environment variable, and re-run dt source validate.
403 ForbiddenYour Dovetail API key lacks permission, or the source account can’t read the content you’re asking for.Confirm your Dovetail role includes API access. For sources, check that the source account has read access to the database, folder, space, or base in question.
no records fetchedThe source can authenticate, but it can’t see the content.Source-specific: in Notion, share the database with your integration; in Google Drive, share the folder with your service account email; in Confluence, check that the space allows your account to read pages; in Airtable, confirm the token hasdata.records:read and schema.bases:read scopes.
rate limitedThe source’s API has thrown a rate-limit error.No action needed — the CLI retries automatically with exponential backoff. If it keeps happening, lower —limit or run fewer migrations in parallel.
Migration interrupted (network drop, terminal closed)The CLI exited before finishing.Run dt migrate resume to pick up where it left off.
Migration appears stuck or silentDefault output is quiet.Re-run with —verbose (or -v) for per-record progress.
dt: command not found after installYour shell can’t find the binary on PATH.For npm installs, add the global npm bin directory to PATH. For source builds, add ~/.local/bin to PATH.
dt --version shows an old version after upgradingA stale binary is shadowing the new one.Run which dt to find the active binary. Remove or rename the old one, or reinstall.
For verbose logs across any command:
dt migrate run --verbose
To get structured output that’s easier to parse from scripts or pipelines:
dt migrate status --output json
If you’ve tried dt doctor, checked the table above, and you’re still stuck, capture the output of dt doctor and dt migrate run --verbose and contact Dovetail support via support@dovetail.com or the Support in-app chat.

Uninstall

How you uninstall depends on how you installed.

If you installed via npm

npm uninstall -g @heydovetail/dt

If you built from source

Remove the binary:
rm ~/.local/bin/dt
If you added ~/.local/bin to your PATH only for the CLI, you can revert that change in your shell profile.

Clean up configuration and staging

Uninstalling the binary doesn’t remove your config file or any staging directories from completed migrations. To remove them:
  • Delete your config file (dt.yaml in whichever directories you ran the CLI from).
  • Run dt clean before uninstalling to remove staging directories. After uninstall, remove any remaining staging directories manually.
  • Unset the environment variables you exported (DOVETAIL_API_KEY, NOTION_TOKEN, and so on) from your shell profile.

Revoke credentials

Uninstalling the CLI doesn’t revoke the tokens or OAuth grants it used. For a complete cleanup:
  • Delete your Dovetail API key in your workspace settings.
  • Revoke each source token from the source’s own settings (Notion integrations page, Atlassian API tokens, Airtable tokens page, Productboard public API, and so on).
  • For Google Drive OAuth, revoke access at myaccount.google.com/permissions. For service accounts, delete the JSON key from your Google Cloud project.

Need a source the CLI doesn’t yet support, or hitting something the troubleshooting table doesn’t cover? Let us know.