Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .chezmoi.toml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ personal = true
rust = true
ohmyzsh = true
mise = true
emacs = true
elixir = true
erlang = true
lua = true
Expand Down Expand Up @@ -107,6 +108,51 @@ bright_magenta = "#ff7edb"
bright_cyan = "#36f9f6"
bright_white = "#ffffff"

# Synthwave84 Soft -- the variant Zed uses ("Synthwave84 Soft" in zed/settings.json).
# Lower contrast than the base palette above, and it carries the syntax roles the base
# block lacks. Consumed by the Emacs theme. Source of truth is the shipped Zed theme:
# ~/Library/Application Support/Zed/extensions/installed/synthwave84/themes/synthwave84.json
# ANSI/terminal colors are deliberately absent -- Zed's Soft variant reuses the base ANSI
# palette above, so terminal faces stay identical to Ghostty.
[data.theme.soft]
name = "Synthwave84 Soft"
bg = "#2e2a3e"
bg_dark = "#2a2139"
bg_light = "#332e42"
fg = "#f0f0f0"
# Flattened from Zed's alpha colors over bg: #f0f0f080 and #f0f0f073 respectively.
fg_dim = "#8f8d97"
fg_subtle = "#85838e"
accent = "#ff92e0"
accent2 = "#5af5f3"
cursor = "#ff92e0"
selection_bg = "#4e4570"
selection_fg = "#f0f0f0"
border = "#5a5f8d"
border_focus = "#9933aa"
comment = "#848bbd"
keyword = "#fee380"
string = "#ffa15a"
string_escape = "#85f3c3"
number = "#fa9890"
constant = "#fa9890"
function = "#5af5f3"
variable = "#ff92e0"
type = "#ff92e0"
property = "#ff92e0"
operator = "#fee380"
punctuation = "#f0f0f0"
preproc = "#ff92e0"
link = "#85f3c3"
error = "#fe6670"
warning = "#fee380"
info = "#33f0fc"
success = "#85f3c3"
hint = "#33f0fc"
git_added = "#85f3c3"
git_modified = "#fee380"
git_deleted = "#fe6670"

[git]
autoCommit = true
autoPush = false
Expand Down
5 changes: 5 additions & 0 deletions Brewfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

tap "hashicorp/tap"
# homebrew/services is now built-in, no tap needed
tap "d12frosted/emacs-plus"
tap "infisical/get-cli"
tap "kurtosis-tech/tap"

Expand Down Expand Up @@ -109,6 +110,10 @@ brew "osv-scanner" # Dependency CVE scanning
# =============================================================================

brew "neovim"
# emacs-plus over core emacs: native-comp, tree-sitter, and a real macOS GUI,
# all on by default in this formula -- do not pass args, they disable bottles.
# Config lives at ~/.config/emacs (see: make setup-emacs).
brew "d12frosted/emacs-plus/emacs-plus@30"
brew "autoconf"
brew "automake"
brew "libtool"
Expand Down
7 changes: 6 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,14 @@ make lazy-load-stats # Show lazy loading stats
```
# Identity: name, email, github, gpg_signing_key, age_recipient, brewPrefix
# Shell: starship, ohmyzsh, oh_my_zsh_theme, oh_my_zsh_plugins
# Tools: mise, rust, elixir, erlang, lua, direnv, devenv, nix
# Tools: mise, rust, elixir, erlang, lua, direnv, devenv, nix, emacs
# Services: tailscale, onepassword, aws, infisical, orbstack
# macOS: paperwm, raycast, llvm, postgres, psql
# Web3: foundry, huff, solana
# Apps: work, personal
# MCP: datadog, sentry, signoz, regen, coingecko, digest, recall, autoresearch, watchdog, prepper, sentinel, patchbot
# Theme: [data.theme] -- full Synthwave84 palette (bg, fg, accent, ANSI colors)
# [data.theme.soft] -- Synthwave84 Soft variant + syntax roles (Zed/Emacs)
```

Use in templates: `{{- if .rust -}}...{{- end -}}`. Use `{{- -}}` to trim whitespace.
Expand Down Expand Up @@ -108,6 +109,10 @@ Commits run: trailing-whitespace, end-of-file-fixer, check-yaml, check-added-lar

Single source of truth: `[data.theme]` in `chezmoi.toml` (Synthwave84 palette). Templates reference colors as `{{ .theme.bg }}`, `{{ .theme.accent }}`, etc. Applied to: fzf (`tools.zsh.tmpl`), Starship (`starship.toml.tmpl`), Hammerspoon alerts. Static theme files in `config/theme/synthwave84.toml` for tools that can't use chezmoi templates.

**Two variants.** `[data.theme]` is the base palette (Ghostty, tmux, fzf, Starship, btop, yazi). `[data.theme.soft]` is the lower-contrast **Synthwave84 Soft** variant that Zed uses, and it is the only block carrying syntax roles (`keyword`, `string`, `function`, `type`, ...) plus diagnostic and git colors. Emacs consumes `{{ .theme.soft.* }}` for UI and syntax, but reuses the base `{{ .theme.* }}` ANSI keys for terminal faces -- Zed's Soft variant leaves `terminal.ansi.*` at base values, so shell buffers match Ghostty exactly.

Authoritative source for both is the shipped Zed theme JSON (`~/Library/Application Support/Zed/extensions/installed/synthwave84/themes/synthwave84.json`), not `config/theme/synthwave84.toml`, which had drifted on `keyword` and `type`.

## Adding Features

**New alias**: Add to `home/dot_zsh/aliases/dev.zsh`
Expand Down
15 changes: 14 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help install update diff status backup clean doctor bootstrap sync sync-from-remote backup-full install-optional generate-template setup-age age-retrieve age-status setup-mise mise-status mise-upgrade mise-doctor setup-raycast raycast-export raycast-import raycast-status setup-signoz-mcp signoz-mcp-status signoz-mcp-update lint perf perf-report skills-status
.PHONY: help install update diff status backup clean doctor bootstrap sync sync-from-remote backup-full install-optional generate-template setup-age age-retrieve age-status setup-mise mise-status mise-upgrade mise-doctor setup-raycast raycast-export raycast-import raycast-status setup-emacs emacs-grammars emacs-restart emacs-status setup-signoz-mcp signoz-mcp-status signoz-mcp-update lint perf perf-report skills-status

# Configuration
DOTFILES_ROOT := $(shell pwd)
Expand Down Expand Up @@ -165,6 +165,19 @@ setup-paperwm: ## Install PaperWM.spoon for Hammerspoon
paperwm-status: ## Show PaperWM installation status
@$(SCRIPTS_DIR)/setup/setup-paperwm.sh status

# Emacs
setup-emacs: ## Install Emacs config, packages, and grammars
@$(SCRIPTS_DIR)/setup/setup-emacs.sh install

emacs-grammars: ## Compile missing tree-sitter grammars
@$(SCRIPTS_DIR)/setup/setup-emacs.sh grammars

emacs-restart: ## Restart the Emacs daemon
@$(SCRIPTS_DIR)/setup/setup-emacs.sh restart

emacs-status: ## Show Emacs installation status
@$(SCRIPTS_DIR)/setup/setup-emacs.sh status

# Raycast
setup-raycast: ## Verify Raycast installation
@$(SCRIPTS_DIR)/setup/setup-raycast.sh install
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ dotfiles/

Everything runs Synthwave84. The palette lives in `config/theme/synthwave84.toml` and gets templated into Ghostty, tmux, fzf, Neovim (mona.nvim), btop, yazi, fastfetch, Starship, and Hammerspoon.

Zed and Emacs run the lower-contrast **Synthwave84 Soft** variant, driven from `[data.theme.soft]` in `chezmoi.toml`. Emacs keeps the base ANSI palette for terminal buffers, so shells inside Emacs still match Ghostty.

## Forking

This is meant to be forked. On first `chezmoi init`, you get prompted for your name, email, and GitHub username. Everything adapts from there -- git config, SSH, encrypted secrets, the works.
Expand Down
46 changes: 46 additions & 0 deletions chezmoi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ personal = true
rust = true
ohmyzsh = true
mise = true
emacs = true
elixir = true
erlang = true
lua = true
Expand Down Expand Up @@ -80,6 +81,51 @@ bright_magenta = "#ff7edb"
bright_cyan = "#36f9f6"
bright_white = "#ffffff"

# Synthwave84 Soft -- the variant Zed uses ("Synthwave84 Soft" in zed/settings.json).
# Lower contrast than the base palette above, and it carries the syntax roles the base
# block lacks. Consumed by the Emacs theme. Source of truth is the shipped Zed theme:
# ~/Library/Application Support/Zed/extensions/installed/synthwave84/themes/synthwave84.json
# ANSI/terminal colors are deliberately absent -- Zed's Soft variant reuses the base ANSI
# palette above, so terminal faces stay identical to Ghostty.
[data.theme.soft]
name = "Synthwave84 Soft"
bg = "#2e2a3e"
bg_dark = "#2a2139"
bg_light = "#332e42"
fg = "#f0f0f0"
# Flattened from Zed's alpha colors over bg: #f0f0f080 and #f0f0f073 respectively.
fg_dim = "#8f8d97"
fg_subtle = "#85838e"
accent = "#ff92e0"
accent2 = "#5af5f3"
cursor = "#ff92e0"
selection_bg = "#4e4570"
selection_fg = "#f0f0f0"
border = "#5a5f8d"
border_focus = "#9933aa"
comment = "#848bbd"
keyword = "#fee380"
string = "#ffa15a"
string_escape = "#85f3c3"
number = "#fa9890"
constant = "#fa9890"
function = "#5af5f3"
variable = "#ff92e0"
type = "#ff92e0"
property = "#ff92e0"
operator = "#fee380"
punctuation = "#f0f0f0"
preproc = "#ff92e0"
link = "#85f3c3"
error = "#fe6670"
warning = "#fee380"
info = "#33f0fc"
success = "#85f3c3"
hint = "#33f0fc"
git_added = "#85f3c3"
git_modified = "#fee380"
git_deleted = "#fe6670"

[age]
command = "~/.config/chezmoi/age-op-decrypt.sh"
recipient = "age1alqwmllzqv8pjmmn6yfjdwm0d8jz7x459clralv2xeefactyv5nq7wze36"
4 changes: 2 additions & 2 deletions config/theme/synthwave84.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ comment = "#848bbd"
line_highlight = "#2a2139"

# Syntax colors
keyword = "#ff7edb" # Pink - keywords, operators
keyword = "#fede5d" # Yellow - keywords, operators
string = "#ff8b39" # Orange - strings
number = "#f97e72" # Coral - numbers
function = "#36f9f6" # Cyan - functions
variable = "#ff7edb" # Pink - variables
type = "#72f1b8" # Green - types
type = "#ff7edb" # Pink - types
constant = "#f97e72" # Coral - constants
parameter = "#fe4450" # Red - parameters

Expand Down
6 changes: 6 additions & 0 deletions home/dot_zsh/aliases/dev.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ alias ......="cd ../../../.."
alias v="nvim"
alias nv="nvim"

# Emacs via the daemon (brew services runs it). The -a fallback starts a
# standalone Emacs if the daemon is down, so these never fail outright.
alias e="emacsclient -nw -a emacs" # terminal frame in this shell
alias eg="emacsclient -c -n -a emacs" # new GUI frame, returns immediately
alias ekill="emacsclient -e '(kill-emacs)'"

# Network utilities
alias myip="curl -s https://ipinfo.io/ip"
alias speedtest="curl -s https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py | python3 -"
Expand Down
7 changes: 7 additions & 0 deletions home/private_dot_config/emacs/banner.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
██████╗ ██████╗ ██████╗ ██████╗
██╔══██╗██╔══██╗██╔═══██╗██╔═══██╗
██║ ██║██████╔╝██║ ██║██║ ██║
██║ ██║██╔══██╗██║ ██║██║ ██║
██████╔╝██║ ██║╚██████╔╝╚██████╔╝
╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝
═══════════════════════════════════
86 changes: 86 additions & 0 deletions home/private_dot_config/emacs/early-init.el.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
;;; early-init.el --- Pre-frame initialization -*- lexical-binding: t; -*-

;; Generated by chezmoi. Edit home/private_dot_config/emacs/early-init.el.tmpl,
;; not this file. Only the frame colors are templated, from [data.theme.soft].

;;; Commentary:

;; Runs before the first frame is created and before package.el initializes.
;; Two jobs here:
;;
;; 1. Keep ~/.config/emacs free of runtime state. This directory is
;; chezmoi-managed, so anything Emacs writes into it shows up as drift in
;; `chezmoi verify' and `make test'. Packages, the native-comp cache,
;; tree-sitter grammars, and customize output all go to XDG dirs instead.
;;
;; 2. Paint the frame in the theme background immediately, so startup does not
;; flash white before init.el gets around to `load-theme'.

;;; Code:

;; Startup only: a huge threshold avoids dozens of collections while loading.
;; droo-defaults restores a sane steady-state value on `emacs-startup-hook'.
(setq gc-cons-threshold most-positive-fixnum
gc-cons-percentage 0.6)

;; package.el is initialized explicitly in init.el, not implicitly before it.
(setq package-enable-at-startup nil)

;; Skip the X resource lookup and the implied frame resize during startup.
(setq inhibit-x-resources t
frame-inhibit-implied-resize t)

;;; XDG state redirection

(defconst droo/xdg-data
(or (getenv "XDG_DATA_HOME") (expand-file-name "~/.local/share"))
"Base XDG data directory.")

(defconst droo/xdg-cache
(or (getenv "XDG_CACHE_HOME") (expand-file-name "~/.cache"))
"Base XDG cache directory.")

(defconst droo/xdg-state
(or (getenv "XDG_STATE_HOME") (expand-file-name "~/.local/state"))
"Base XDG state directory.")

(defconst droo/data-dir (expand-file-name "emacs/" droo/xdg-data)
"Durable Emacs data: installed packages, tree-sitter grammars.")

(defconst droo/cache-dir (expand-file-name "emacs/" droo/xdg-cache)
"Regenerable Emacs data: native-comp cache, backups, auto-saves.")

(defconst droo/state-dir (expand-file-name "emacs/" droo/xdg-state)
"Emacs state that should survive a cache wipe: history, places, custom.el.")

(dolist (dir (list droo/data-dir droo/cache-dir droo/state-dir))
(make-directory dir t))

(setq package-user-dir (expand-file-name "elpa" droo/data-dir)
custom-file (expand-file-name "custom.el" droo/state-dir))

;; Native compilation writes a lot; keep it out of the managed tree.
(when (fboundp 'startup-redirect-eln-cache)
(startup-redirect-eln-cache (expand-file-name "eln-cache/" droo/cache-dir)))

(setq native-comp-async-report-warnings-errors 'silent)

;;; Frame appearance

;; Set before the first frame exists so there is no white flash on startup.
(dolist (param '((background-color . "{{ .theme.soft.bg }}")
(foreground-color . "{{ .theme.soft.fg }}")
(cursor-color . "{{ .theme.soft.cursor }}")
(tool-bar-lines . 0)
(vertical-scroll-bars . nil)
(ns-transparent-titlebar . t)
(ns-appearance . dark)))
(push param default-frame-alist))

;; macOS keeps its system menu bar (it costs no frame real estate); elsewhere drop it.
(unless (eq system-type 'darwin)
(push '(menu-bar-lines . 0) default-frame-alist))

(provide 'early-init)

;;; early-init.el ends here
60 changes: 60 additions & 0 deletions home/private_dot_config/emacs/init.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
;;; init.el --- Personal Emacs configuration -*- lexical-binding: t; -*-

;; Managed by chezmoi: home/private_dot_config/emacs/init.el

;;; Commentary:

;; Vanilla Emacs 30 with package.el and the built-in use-package. Runtime state
;; lives under XDG directories (see early-init.el); this tree stays read-only as
;; far as Emacs is concerned.
;;
;; The theme loads before any module so that a broken package still leaves a
;; correctly themed Emacs. `custom-theme-set-faces' records specs for faces that
;; do not exist yet, so magit/corfu/eglot faces are themed when those load later.

;;; Code:

(add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory))
(add-to-list 'custom-theme-load-path (expand-file-name "themes" user-emacs-directory))

(load-theme 'synthwave84-soft t)

;;; Packages

(require 'package)

(setq package-archives
'(("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa" . "https://melpa.org/packages/"))
;; Prefer the curated archives; fall back to MELPA for everything else.
package-archive-priorities
'(("gnu" . 3) ("nongnu" . 2) ("melpa" . 1)))

(package-initialize)

(unless package-archive-contents
(package-refresh-contents))

(require 'use-package)

(setq use-package-always-ensure t
use-package-expand-minimally t
;; `M-x use-package-report' to find slow packages.
use-package-compute-statistics t)

;;; Modules

(require 'droo-defaults)
(require 'droo-ui)
(require 'droo-completion)
(require 'droo-git)
(require 'droo-lang)
(require 'droo-lsp)

;; Written by `customize'; kept out of the chezmoi-managed tree. Nothing here is
;; authoritative -- prefer editing the modules above.
(when (file-exists-p custom-file)
(load custom-file nil t))

;;; init.el ends here
Loading