Skip to content

DevShedLabs/mac-sethandler

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

sethandler

A tiny macOS CLI that sets the default app for a file type — the thing System Settings → General → Login Items & Extensions → Default web browser does, but for any file extension or Uniform Type Identifier (UTI), and scriptable.

Useful when you want .csv (or .log, .env, whatever) to always open in a specific app without hunting through Finder's "Get Info" → "Open with" → "Change All..." dialog by hand.

How it works

macOS decides which app opens a file type via LaunchServices, using a UTI (Uniform Type Identifier) — a reverse-DNS-style string like public.plain-text or com.microsoft.excel.csv — rather than the file extension directly. sethandler resolves the extension you give it to a UTI, then calls the same LaunchServices API (LSSetDefaultRoleHandlerForContentType) that Finder uses, registering your chosen app's bundle ID as the default handler for that type.

This changes a systemwide, persistent setting (stored by LaunchServices, not by this tool) — the same thing Finder's "Change All..." does. It affects every file of that type for your macOS user account, not just files opened through this CLI.

Requirements

  • macOS
  • The target app must already be installed (LaunchServices needs to know its bundle ID exists — see Finding a bundle ID below)

Build

swiftc sethandler.swift -o sethandler

No dependencies beyond the Swift toolchain that ships with Xcode / Xcode Command Line Tools (xcode-select --install if swiftc isn't found).

Usage

sethandler <bundle_id> <extension_or_uti> [more extensions/UTIs...]

Arguments starting with . are treated as file extensions and resolved to a UTI automatically. Anything else is assumed to already be a UTI.

Examples

Make an app the default handler for .csv and .tsv files:

sethandler com.devshed.coder .csv .tsv

✅ Set handler for UTI: public.comma-separated-values-text
✅ Set handler for UTI: public.tab-separated-values-text

Set a default handler across several extensions at once:

sethandler com.microsoft.VSCode .js .ts .tsx .json

Target a UTI directly instead of an extension:

sethandler com.devshed.coder public.comma-separated-values-text

Output

✅ Set handler for UTI: public.comma-separated-values-text
❌ Failed for UTI: .foobar (-54)

A ❌ usually means the extension didn't resolve to a known UTI, or the bundle ID isn't registered with LaunchServices (the app has never been launched, or isn't installed).

Finding a bundle ID

osascript -e 'id of app "Coder"'

or read it directly from the app bundle:

defaults read /Applications/Coder.app/Contents/Info.plist CFBundleIdentifier

Verifying it worked

Right-click any file of that type in Finder → Get Info → "Open with:" should now show your app selected. Alternatively, if you have duti installed (brew install duti):

duti -x csv

Caveats

  • Changes are systemwide for your user account — there's no per-tool or per-folder scoping.
  • Some apps re-register themselves as the default handler for their own file types on launch (common with editors/IDEs). If your setting reverts, that's the other app reclaiming it, not a bug in sethandler — rerun it after opening the other app, or check that app's settings for an "always reopen as default" preference.
  • Requires the target extension to resolve to a UTI that Apple's system or an installed app has already declared. Fully custom/unregistered extensions may need the owning app to declare a UTExportedTypeDeclarations entry in its own Info.plist before sethandler can target them.

License

MIT © DevShed Labs — see LICENSE.

About

Lets you to set almost any file extension on Mac to open in the app of your choice by default.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages