Tired of double-clicking a .txt
file only to have it open in TextEdit when you'd rather use your preferred editor? On macOS, you can use duti
(a command-line utility) to programmatically set default applications for specific file types. This is especially useful for developers who want their preferred editor to handle all text files by default.
What is duti?
duti
is a command-line tool that allows you to set default applications for document types and URL schemes on macOS. It's particularly useful for developers who want to script their environment setup or make bulk changes to file associations.
Installation
The easiest way to install duti is via Homebrew:
brew install duti
Alternatively, you can download it from the official repository.
Finding Your Editor's Bundle Identifier
Before setting file associations, you need to find your editor's bundle identifier. Here are several methods:
Method 1: Using AppleScript
osascript -e 'id of app "Zed"'
# -> dev.zed.Zed
Method 2: Using mdls (metadata lookup)
mdls -name kMDItemCFBundleIdentifier -r /Applications/Zed.app
# -> dev.zed.Zed
Method 3: Common Editor Bundle IDs
Here are bundle identifiers for popular editors:
- Zed:
dev.zed.Zed
- Visual Studio Code:
com.microsoft.VSCode
- Vim:
org.vim.MacVim
- Neovim:
com.qvacua.VimR
- TextEdit:
com.apple.TextEdit
- Sublime Text:
com.sublimetext.4
- Nova:
com.panic.Nova
For other editors, replace the app name or path in the commands above accordingly.
Understanding Uniform Type Identifiers (UTIs)
On macOS, file associations are defined by Uniform Type Identifiers (UTIs) rather than just file extensions. UTIs provide a hierarchical system for identifying file types. Here are the most important UTIs for text files:
public.plain-text
— plain text files (.txt, .text)public.text
— generic text content (broader category)public.source-code
— source code filesnet.daringfireball.markdown
— Markdown files (.md, .markdown)
Setting Your Default Editor
The basic syntax for duti is:
duti -s <bundle-identifier> <uti> <role>
Where:
is your editor's ID (e.g.,dev.zed.Zed
)
is the file type identifier
is typicallyall
(handles opening, editing, etc.)
Basic Text Files
To set Zed as the default editor for basic text files:
# Set Zed for plain text files
duti -s dev.zed.Zed public.plain-text all
# Set Zed for generic text content
duti -s dev.zed.Zed public.text all
Source Code and Markdown
For development work, you'll likely want to handle source code and Markdown files:
# Markdown files
duti -s dev.zed.Zed net.daringfireball.markdown all
# Source code files (covers many programming languages)
duti -s dev.zed.Zed public.source-code all
Specific File Extensions
You can also set associations for specific file extensions:
# Set for .txt files specifically
duti -s dev.zed.Zed txt all
# Set for .md files
duti -s dev.zed.Zed md all
# Set for .js files
duti -s dev.zed.Zed js all
Quick Setup Script
Here's a comprehensive script to set Zed as your default editor for most text-based files:
#!/bin/bash
EDITOR_ID="dev.zed.Zed"
# Basic text types
duti -s $EDITOR_ID public.plain-text all
duti -s $EDITOR_ID public.text all
duti -s $EDITOR_ID public.source-code all
# Markdown
duti -s $EDITOR_ID net.daringfireball.markdown all
# Common file extensions
extensions=("txt" "md" "markdown" "js" "ts" "py" "go" "rs" "c" "cpp" "h" "hpp" "css" "html" "json" "yaml" "yml" "xml" "sh" "zsh" "bash")
for ext in "${extensions[@]}"; do
duti -s $EDITOR_ID $ext all
done
echo "Default editor associations updated!"
Verify Your Associations
After making changes, you can verify which applications are set to handle specific file types:
Check by File Extension
# Which app opens .txt files?
duti -x txt
# Which app opens .md files?
duti -x md
# Which app opens .js files?
duti -x js
Check by UTI
# List all apps that can handle plain text
duti -l public.plain-text
# List all apps that can handle Markdown
duti -l net.daringfireball.markdown
Test Your Settings
Create a test file and double-click it to verify:
# Create a test file
echo "Hello, World!" > ~/Desktop/test.txt
# Double-click the file in Finder to test
Switching to Another Editor
To change to a different editor, simply substitute another bundle identifier. For example, to switch to Visual Studio Code:
# Switch to VS Code
duti -s com.microsoft.VSCode public.plain-text all
duti -s com.microsoft.VSCode public.text all
duti -s com.microsoft.VSCode net.daringfireball.markdown all
To revert back to the system default (TextEdit):
# Revert to TextEdit
duti -s com.apple.TextEdit public.plain-text all
duti -s com.apple.TextEdit public.text all
Advanced Usage
Using Configuration Files
You can create a duti configuration file for easier management:
# Create a duti settings file
cat > ~/.duti << EOF
dev.zed.Zed public.plain-text all
dev.zed.Zed public.text all
dev.zed.Zed net.daringfireball.markdown all
dev.zed.Zed public.source-code all
EOF
# Apply the settings
duti ~/.duti
Integration with Dotfiles
Add duti commands to your shell configuration or dotfiles setup script:
# In your ~/.zshrc or setup script
setup_editor_associations() {
local editor_id="dev.zed.Zed"
duti -s "$editor_id" public.plain-text all
duti -s "$editor_id" public.text all
duti -s "$editor_id" net.daringfireball.markdown all
echo "Editor associations configured"
}
Troubleshooting
Changes Don't Take Effect
If your changes don't appear immediately:
- Quit and relaunch the target applications and Finder
- Log out and back in to refresh the system
- Clear Launch Services cache (advanced):
# Rebuild Launch Services database (use with caution)
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister \
-kill -r -domain local -domain system -domain user
A logout/login may be necessary after rebuilding the cache.
Finding the Right UTI
If a file type isn't responding to the standard UTIs, investigate what UTI your system uses:
# Check what UTI a specific file has
mdls -name kMDItemContentType /path/to/your/file.ext
# Example: Check a Python file
mdls -name kMDItemContentType example.py
Common Issues
- File still opens in wrong app: Some applications register their own UTIs. You may need to set associations for both the standard UTI and the app-specific one.
- System overrides your settings: Some system updates or application installations may reset file associations.
- Permissions issues: Ensure duti has the necessary permissions to modify system settings.
Useful duti Commands Reference
# Display help
duti -h
# List all UTIs for an extension
duti -l txt
# Show what app handles an extension
duti -x py
# Set default app for a UTI
duti -s com.app.bundle uti.identifier all
# Set default app for an extension
duti -s com.app.bundle ext all
# Apply settings from a file
duti /path/to/settings/file