Skip to content
jnunemakerPublic

About

Some of my dotfiles, nothing fancy or worthwhile

Resources

Stars

31 stars

Watchers

3 watching

Forks

Repository files navigation

My Dot Files

Clone the repository and run setup.

git clone https://github.com/jnunemaker/dotfiles.git ~/.dotfiles
~/.dotfiles/script/setup

After that, run dotfiles from any directory. Setup links it and the other commands in bin/ into ~/.local/bin.

  • dotfiles sync offers to save changed T3 Code settings, pulls ~/.dotfiles, then runs setup on this Mac. Run it on each Mac.
  • dotfiles setup runs setup without pulling, such as after a local edit.
  • dotfiles help lists the commands.

Setup is silent when everything works. If a step fails, it prints what it was doing and that step's full output, then stops. Only steps that need you, such as the Homebrew installer's password prompt or Codex's Cloudflare, Honeybadger, Help Scout, and Flare sign-ins and the one-time Jelly, Fireside, and Ahrefs token prompts, show their output as they run. If setup replaces existing files, it says where it moved them.

Setup also adds air and pro SSH hosts for my two Macs, by their Tailscale names, so ssh air and ssh pro work. They live in ssh/config, which setup links to ~/.ssh/dotfiles_config and includes from the top of ~/.ssh/config, leaving the rest of that file alone.

Setup installs Bun, Claude Code, Codex, and the T3 Code CLI (t3) with their official user-local installers when they are missing. It then installs Homebrew when needed, installs missing packages from the Brewfile (including Git) without upgrading existing packages, and symlinks the managed configuration files.

The Brewfile also declares the desktop apps and developer tools used on each Mac. Setup preserves existing installations and uses Homebrew for software that does not have a suitable first-party, user-local installer. Apps still require their normal first-run sign-in and macOS permission prompts.

Gstack is installed from its official Git repository after its Homebrew dependencies are available.

Setup also clones Cloudflare's security-audit skill to ~/.local/share/security-audit-skill and links it into both Claude Code and Codex. Ask either agent to "security audit this codebase" to run it; reports go to ~/security-audit-skill/<repo>/run-N. Run git pull in the clone to update.

Setup also clones Jason Cohen's asb skills (positioning, ideal customer, customer interviews, pricing) to ~/.local/share/asb-skills, pulls updates on each run, and links every asb-* skill into both Claude Code (~/.claude/skills) and Codex (~/.agents/skills).

My own skills live in skills/, and setup links them into both Claude Code (~/.claude/skills) and Codex (~/.agents/skills):

  • nunebot-review runs simplify, QA, a review by the other model, up to three rounds of reviewing only the fixes, then performance, compatibility, security, and proof. Pass unattended when nobody is watching.
  • nunebot-pr commits what's left, pushes, and creates or updates the pull request in my format, using the ledger nunebot-review left in the worktree's ignored .nunebot/ folder.
  • nunebot-next answers "what's next?" with where things stand, what's been reviewed, the one next step, and any decisions only I can make.
  • nunebot-land merges a ready pull request once CI is green, watches the deploy, checks production, and cleans up the branch.
  • nunebot-run runs one Nunebot pass from nunebot/PROMPT.md in my brain repo, optionally limited to some repos or a different PR cap.
  • simplify is linked into Codex only, because Claude Code has it built in.

So these skills can commit, push, and check deploys from Codex without asking, setup merges codex/config.toml and the work permission profile in codex/permissions.toml into ~/.codex/config.toml (see script/codex-config). Codex may write anywhere in ~/github and its current workspace, and reach only the hosts listed there. Writes to ~/.dotfiles from another repo ask the guardian reviewer first, because setup links those files live. A command that needs another host fails with "domain is not on the allowlist"; add the host and rerun setup.

Setup installs the Cloudflare and PlanetScale Claude Code plugins, which bring their hosted MCP servers, and adds the same Cloudflare and PlanetScale MCP servers to Codex. It also installs the pstack Claude Code plugin from Cursor's marketplace, which has no Codex version, and links its per-role model choices from claude/rules/pstack-models.md into ~/.claude/rules/. It also installs Matt Pocock's skills as a plugin in both Claude Code and Codex. Setup also adds the hosted Honeybadger, Help Scout (read-only), and Flare MCP servers to both Claude Code and Codex. Each signs in with OAuth the first time it is used. A Honeybadger sign-in grants a single account and all its projects, so there is one server per account: honeybadger-boxout (Box Out Sports), honeybadger-nunes (Nunes), and honeybadger-verygood (Very Good Software). Pick the matching account when each one signs in.

The hosted Jelly (jelly), Fireside (fireside), Crisp (crisp), Box Out (boxout), and Flipper Cloud (flipper-cloud) MCP servers have no OAuth and take an API token instead (in Jelly, Settings → API Tokens; Fireside's start with fire_; in Crisp, Settings → Workspace Settings → Advanced configuration → MCP Server Token, which also regenerates the workspace's REST API tokens; in Box Out, the profile menu → API Keys, which start with boxout_; in Flipper Cloud, the key shown under Connect an assistant). Setup reads each from that Mac's login Keychain (jelly-api-token, fireside-api-token, crisp-mcp-token, boxout-api-key, flipper-cloud-api-key), then from JELLY_API_TOKEN, FIRESIDE_API_TOKEN, CRISP_MCP_TOKEN, BOXOUT_API_KEY, or FLIPPER_CLOUD_API_KEY, then asks when run in a terminal, and saves it to the Keychain. With no token it skips that server with a note instead of waiting, so setup never hangs on it. Setup then gives it to Claude Code and Codex as a bearer header in their local configs, never in this repo. To change a token, delete the Keychain item and the server from both tools, then rerun setup.

The hosted Ahrefs MCP server (ahrefs) signs in with OAuth in Claude Code (run /mcp and pick your Ahrefs workspace the first time). Codex refuses Ahrefs' OAuth sign-in, so Codex uses an Ahrefs MCP key instead (an MCP key, not an API v3 key). Setup handles it like the Jelly and Fireside tokens, using the Keychain item ahrefs-mcp-key or AHREFS_MCP_KEY.

Setup adds john_fireside (the default) and jnunemaker profiles to ~/.config/linode-cli, each with a personal access token from cloud.linode.com/profile/tokens. It reads tokens the same way, from the Keychain items linode-token-john_fireside and linode-token-jnunemaker, then LINODE_TOKEN_JOHN_FIRESIDE or LINODE_TOKEN_JNUNEMAKER, then asks. Profiles already in the config are left alone, so to change a token, edit the config and update the Keychain item.

mise manages language versions and is installed with its official installer (mise.run) into ~/.local/bin; setup replaces a Homebrew mise if one is present. Global versions live in mise/config.toml, which setup links to ~/.config/mise/config.toml before running mise install. A leftover ~/.tool-versions is moved to the backup so it cannot override them. Projects still pick their own versions from .tool-versions or .ruby-version.

T3 Code's settings live in t3/settings.json (server settings such as the default model and enabled providers) and t3/client-settings.json (interface preferences), and shortcuts live in t3/keybindings.json. Cmd+T opens the in-app browser when the right panel is closed, and the right panel's new-tab menu when it is open. T3 Code replaces these files when it saves, so setup copies them into ~/.t3/userdata/ rather than linking them, backing up any that differ. When the app's settings changed since setup installed them, dotfiles sync offers to save them here (after a gitleaks scan, since this repo is public) and push them before setting up. Sign-ins, secrets, and threads stay on each Mac.

Git and the external tools referenced by .gitconfig are managed by the Brewfile, including Delta (the pager), hunk (for reviewing agent changes), Git LFS, GitHub CLI, Heroku CLI, and GnuPG. Diffity is installed globally through npm.

Preferred microphone

Setup compiles preferred-mic and loads it as a LaunchAgent. Whenever a Shure MV7 is connected, it stays the default microphone, even after AirPods or other Bluetooth headphones connect and macOS switches input to them. Audio output is left alone, so headphones keep playing sound.

When the Shure is unplugged, it still keeps input off Bluetooth headphones. Using AirPods as a mic (for dictation, say) switches them from stereo music to low-quality call audio, so it uses the MacBook's mic instead, or a wired mic like a monitor's or a headset on the headphone jack when the lid is closed. If there's no other mic, AirPods stay (or become) the input, since a closed lid mutes the MacBook's mic.

Apps that pick a specific microphone in their own settings ignore the system default; set them to "System default" to follow it.

Switches are logged to ~/Library/Logs/preferred-mic.log. To prefer a different microphone, change the name prefix in preferred-mic/com.jnunemaker.preferred-mic.plist and rerun setup. To pause it until the next login:

launchctl bootout gui/$(id -u)/com.jnunemaker.preferred-mic

About

Some of my dotfiles, nothing fancy or worthwhile

Resources

Stars

31 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages