Function bodies 96 total
init function · go · L27-L29 (3 LOC)cmd/doctor.go
func init() {
rootCmd.AddCommand(doctorCmd)
}init function · go · L22-L30 (9 LOC)cmd/install.go
func init() {
installCmd.Flags().BoolVar(&flagDryRun, "dry-run", false, "Show what would be done without making changes")
installCmd.Flags().BoolVar(&flagForce, "force", false, "Overwrite existing configs without prompting")
installCmd.Flags().BoolVar(&flagVerbose, "verbose", false, "Show detailed output")
installCmd.Flags().BoolVar(&flagSkipBackup, "skip-backup", false, "Skip backing up existing configs")
installCmd.Flags().BoolVar(&flagNamedWorkspaces, "named-workspaces", false, "Use named workspaces (D/W/M/E/S) with app-to-workspace rules instead of numbered 1-9")
installCmd.Flags().BoolVar(&flagQuiet, "quiet", false, "Run without the TUI (log to stdout)")
rootCmd.AddCommand(installCmd)
}Execute function · go · L15-L17 (3 LOC)cmd/root.go
func Execute() error {
return rootCmd.Execute()
}init function · go · L31-L33 (3 LOC)cmd/status.go
func init() {
rootCmd.AddCommand(statusCmd)
}shortPath function · go · L91-L97 (7 LOC)cmd/status.go
func shortPath(path string) string {
home, _ := os.UserHomeDir()
if len(path) > len(home) && path[:len(home)] == home {
return "~" + path[len(home):]
}
return path
}init function · go · L20-L26 (7 LOC)cmd/uninstall.go
func init() {
uninstallCmd.Flags().BoolVar(&uninstallDryRun, "dry-run", false, "Show what would be done without making changes")
uninstallCmd.Flags().BoolVar(&uninstallKeepConfigs, "keep-configs", false, "Keep deployed config files")
uninstallCmd.Flags().BoolVar(&uninstallKeepPkgs, "keep-packages", false, "Keep installed packages")
uninstallCmd.Flags().BoolVar(&uninstallQuiet, "quiet", false, "Run without the TUI (log to stdout)")
rootCmd.AddCommand(uninstallCmd)
}init function · go · L9-L11 (3 LOC)cmd/version.go
func init() {
rootCmd.AddCommand(versionCmd)
}Same scanner, your repo: https://repobility.com — Repobility
Run function · go · L15-L69 (55 LOC)internal/backup/backup.go
func Run(destPaths []string, onLine func(string)) (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
// Check which paths actually exist
var toBackup []string
for _, dest := range destPaths {
expanded := expandHome(dest, home)
if _, err := os.Stat(expanded); err == nil {
toBackup = append(toBackup, expanded)
}
}
if len(toBackup) == 0 {
onLine(" No existing configs to back up")
return "", nil
}
// Create backup directory
ts := time.Now().Format("20060102-150405")
backupDir := filepath.Join(home, ".omachy", "backups", ts)
if err := os.MkdirAll(backupDir, 0755); err != nil {
return "", fmt.Errorf("create backup dir: %w", err)
}
onLine(fmt.Sprintf("==> Backup directory: %s", backupDir))
for _, src := range toBackup {
// Preserve relative structure from home
rel, _ := filepath.Rel(home, src)
dest := filepath.Join(backupDir, rel)
info, err := os.Stat(src)
if err != nil {
continue
}
if info.IsDir() {
iexpandHome function · go · L71-L76 (6 LOC)internal/backup/backup.go
func expandHome(path, home string) string {
if strings.HasPrefix(path, "~/") {
return filepath.Join(home, path[2:])
}
return path
}copyFile function · go · L78-L101 (24 LOC)internal/backup/backup.go
func copyFile(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
if _, err := io.Copy(out, in); err != nil {
return err
}
info, err := in.Stat()
if err == nil {
os.Chmod(dst, info.Mode())
}
return nil
}copyDir function · go · L103-L117 (15 LOC)internal/backup/backup.go
func copyDir(src, dst string) error {
return filepath.WalkDir(src, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
rel, _ := filepath.Rel(src, path)
target := filepath.Join(dst, rel)
if d.IsDir() {
return os.MkdirAll(target, 0755)
}
return copyFile(path, target)
})
}Tap function · go · L11-L19 (9 LOC)internal/brew/brew.go
func Tap(name string, onLine func(string)) error {
if IsTapped(name) {
onLine(fmt.Sprintf(" Already tapped: %s", name))
return nil
}
onLine(fmt.Sprintf("==> Tapping %s", name))
return shell.RunStreaming("brew", []string{"tap", name}, onLine)
}IsTapped function · go · L22-L33 (12 LOC)internal/brew/brew.go
func IsTapped(name string) bool {
result, err := shell.Run("brew", "tap")
if err != nil {
return false
}
for _, line := range strings.Split(result.Stdout, "\n") {
if strings.TrimSpace(line) == name {
return true
}
}
return false
}Install function · go · L36-L60 (25 LOC)internal/brew/brew.go
func Install(name string, cask bool, onLine func(string)) error {
if IsInstalled(name, cask) {
onLine(fmt.Sprintf(" Already installed: %s", name))
return nil
}
args := []string{"install"}
if cask {
args = append(args, "--cask")
}
args = append(args, name)
onLine(fmt.Sprintf("==> Installing %s", name))
if err := shell.RunStreaming("brew", args, onLine); err != nil {
// brew install exits 1 when the package installs but linking fails
// (e.g. another formula owns the symlinks). The package is still
// usable in the Cellar, so treat this as a warning, not a failure.
if IsInstalled(name, cask) {
onLine(fmt.Sprintf(" Warning: %s installed but not linked (conflicting package)", name))
return nil
}
return err
}
return nil
}IsInstalled function · go · L63-L72 (10 LOC)internal/brew/brew.go
func IsInstalled(name string, cask bool) bool {
args := []string{"list"}
if cask {
args = append(args, "--cask")
}
args = append(args, name)
_, err := shell.Run("brew", args...)
return err == nil
}Repobility analyzer · published findings · https://repobility.com
StartService function · go · L75-L78 (4 LOC)internal/brew/brew.go
func StartService(name string, onLine func(string)) error {
onLine(fmt.Sprintf("==> Starting service: %s", name))
return shell.RunStreaming("brew", []string{"services", "start", name}, onLine)
}StopService function · go · L81-L84 (4 LOC)internal/brew/brew.go
func StopService(name string, onLine func(string)) error {
onLine(fmt.Sprintf("==> Stopping service: %s", name))
return shell.RunStreaming("brew", []string{"services", "stop", name}, onLine)
}Uninstall function · go · L87-L101 (15 LOC)internal/brew/brew.go
func Uninstall(name string, cask bool, onLine func(string)) error {
if !IsInstalled(name, cask) {
onLine(fmt.Sprintf(" Not installed: %s", name))
return nil
}
args := []string{"uninstall"}
if cask {
args = append(args, "--cask")
}
args = append(args, name)
onLine(fmt.Sprintf("==> Uninstalling %s", name))
return shell.RunStreaming("brew", args, onLine)
}Path function · go · L12-L40 (29 LOC)internal/checksum/checksum.go
func Path(path string) (string, error) {
info, err := os.Stat(path)
if err != nil {
return "", err
}
if info.IsDir() {
h := sha256.New()
filepath.WalkDir(path, func(p string, d fs.DirEntry, err error) error {
if err != nil || d.IsDir() {
return err
}
data, err := os.ReadFile(p)
if err != nil {
return err
}
h.Write([]byte(p))
h.Write(data)
return nil
})
return fmt.Sprintf("%x", h.Sum(nil)), nil
}
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
return fmt.Sprintf("%x", sha256.Sum256(data)), nil
}runPackages function · go · L13-L82 (70 LOC)internal/installer/brew.go
func runPackages(p *tea.Program, opts Options) error {
log := func(text string) {
p.Send(tui.LogLine{Text: text})
}
state, err := LoadState()
if err != nil {
return fmt.Errorf("load state: %w", err)
}
// Add taps — track which ones Omachy added
for _, tap := range manifest.Taps() {
if opts.DryRun {
log(fmt.Sprintf("==> Would tap %s", tap))
continue
}
alreadyTapped := brew.IsTapped(tap)
if err := brew.Tap(tap, log); err != nil {
return fmt.Errorf("tap %s: %w", tap, err)
}
if !alreadyTapped {
state.InstalledTaps = appendUnique(state.InstalledTaps, tap)
}
}
// Install packages — only record ones Omachy actually installed
pkgs := manifest.Packages()
for i, pkg := range pkgs {
if pkg.SkipIfBinary != "" {
if _, found := shell.Which(pkg.SkipIfBinary); found {
log(fmt.Sprintf(" Skipping %s (%s already on PATH)", pkg.Name, pkg.SkipIfBinary))
pct := 40 + ((i+1)*20)/len(pkgs)
p.Send(tui.ProgressUpdate{Percent: pct})
continue
}runBackup function · go · L23-L74 (52 LOC)internal/installer/config.go
func runBackup(p *tea.Program, opts Options) error {
log := func(text string) {
p.Send(tui.LogLine{Text: text})
}
if opts.SkipBackup {
log("==> Skipping backup (--skip-backup)")
return nil
}
state, err := LoadState()
if err != nil {
return fmt.Errorf("load state: %w", err)
}
// Only back up once — the pre-Omachy state. If a backup already exists
// in state, the user's originals are already saved.
if state.BackupPath != "" {
log(fmt.Sprintf("==> Original backup already exists: %s", state.BackupPath))
log(" Skipping backup (originals are preserved)")
return nil
}
log("==> Backing up existing configs (pre-Omachy state)")
// Collect destination paths from manifest
var destPaths []string
for _, cfg := range manifest.Configs() {
destPaths = append(destPaths, cfg.Dest)
}
if opts.DryRun {
for _, d := range destPaths {
log(fmt.Sprintf(" Would back up %s (if exists)", d))
}
return nil
}
backupPath, err := backup.Run(destPaths, log)
if errunConfigs function · go · L76-L220 (145 LOC)internal/installer/config.go
func runConfigs(p *tea.Program, opts Options) error {
log := func(text string) {
p.Send(tui.LogLine{Text: text})
}
home, err := os.UserHomeDir()
if err != nil {
return err
}
state, err := LoadState()
if err != nil {
return fmt.Errorf("load state: %w", err)
}
configs := manifest.Configs()
// Swap to named workspace configs if requested
if opts.NamedWorkspaces {
for i := range configs {
if configs[i].Source == "aerospace/aerospace.toml" {
configs[i].Source = "aerospace/aerospace-named.toml"
}
}
}
for i, cfg := range configs {
dest := expandHome(cfg.Dest, home)
// Skip configs marked NeverOverwrite if destination already exists
// Use Lstat to detect symlinks (even broken ones) as "exists"
if cfg.NeverOverwrite && !opts.Force {
if _, err := os.Lstat(dest); err == nil {
log(fmt.Sprintf("==> Skipping %s (existing config found, use --force to overwrite)", cfg.Dest))
pct := 60 + ((i+1)*20)/len(configs)
p.Send(tui.ProgressUpdate{PerupdateZshrcBlock function · go · L242-L295 (54 LOC)internal/installer/config.go
func updateZshrcBlock(path string, log func(string)) error {
// Read existing content, or start with empty
existing := ""
if data, err := os.ReadFile(path); err == nil {
existing = string(data)
}
// Remove existing managed block so we can rebuild it with all integrations
cleaned := removeManagedBlock(existing)
// Check for orphaned markers — if only one marker exists, don't add a new block
// to avoid duplicates. Warn the user instead.
if strings.Contains(cleaned, zshrcMarkerStart) || strings.Contains(cleaned, zshrcMarkerEnd) {
log(" Warning: found orphaned Omachy markers in .zshrc — please fix manually")
return nil
}
// Build the managed block. Skip integrations that already exist outside
// the managed block (i.e. the user set them up themselves).
var lines []string
for _, si := range shellIntegrations {
if strings.Contains(cleaned, si.check) {
log(fmt.Sprintf(" Already present outside managed block: %s", si.check))
} else {
lines = append(linesRepobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
removeManagedBlock function · go · L297-L309 (13 LOC)internal/installer/config.go
func removeManagedBlock(content string) string {
startIdx := strings.Index(content, zshrcMarkerStart)
endIdx := strings.Index(content, zshrcMarkerEnd)
if startIdx == -1 || endIdx == -1 || endIdx < startIdx {
return content
}
before := content[:startIdx]
after := content[endIdx+len(zshrcMarkerEnd):]
if len(after) > 0 && after[0] == '\n' {
after = after[1:]
}
return before + after
}deployFile function · go · L311-L322 (12 LOC)internal/installer/config.go
func deployFile(source, dest string, mode fs.FileMode) error {
data, err := EmbeddedConfigs.ReadFile(filepath.Join("configs", source))
if err != nil {
return fmt.Errorf("read embedded %s: %w", source, err)
}
if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
return err
}
return os.WriteFile(dest, data, mode)
}deployDir function · go · L324-L360 (37 LOC)internal/installer/config.go
func deployDir(source, dest string, mode uint32) error {
if err := os.MkdirAll(dest, 0755); err != nil {
return err
}
srcDir := filepath.Join("configs", source)
return fs.WalkDir(EmbeddedConfigs, srcDir, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
// Skip .gitkeep files
if d.Name() == ".gitkeep" {
return nil
}
rel, _ := filepath.Rel(srcDir, path)
target := filepath.Join(dest, rel)
if d.IsDir() {
return os.MkdirAll(target, 0755)
}
data, err := EmbeddedConfigs.ReadFile(path)
if err != nil {
return err
}
fileMode := fs.FileMode(mode)
// Scripts get 0755
if strings.HasSuffix(d.Name(), ".sh") || strings.HasPrefix(d.Name(), "plugin.") {
fileMode = 0755
}
return os.WriteFile(target, data, fileMode)
})
}expandHome function · go · L362-L367 (6 LOC)internal/installer/config.go
func expandHome(path, home string) string {
if strings.HasPrefix(path, "~/") {
return filepath.Join(home, path[2:])
}
return path
}runSystem function · go · L40-L144 (105 LOC)internal/installer/defaults.go
func runSystem(p *tea.Program, opts Options) error {
log := func(text string) {
p.Send(tui.LogLine{Text: text})
}
state, err := LoadState()
if err != nil {
return fmt.Errorf("load state: %w", err)
}
// Apply macOS defaults
log("==> Applying macOS defaults")
for _, d := range MacOSDefaults {
if opts.DryRun {
log(fmt.Sprintf(" Would set: %s", d.Label))
continue
}
// Read current value and type first for undo
stateKey := fmt.Sprintf("%s:%s", d.Domain, d.Key)
if _, exists := state.OriginalDefaults[stateKey]; !exists {
current, err := readDefault(d.Domain, d.Key)
if err == nil {
typ, typErr := readDefaultType(d.Domain, d.Key)
if typErr == nil {
state.OriginalDefaults[stateKey] = typ + ":" + current
} else {
state.OriginalDefaults[stateKey] = d.Type + ":" + current
}
}
}
// Write new value
if err := writeDefault(d.Domain, d.Key, d.Type, d.Value); err != nil {
return fmt.Errorf("defaults write %s %s: %w", d.Domain,readDefault function · go · L146-L152 (7 LOC)internal/installer/defaults.go
func readDefault(domain, key string) (string, error) {
result, err := shell.Run("defaults", "read", domain, key)
if err != nil {
return "", err
}
return strings.TrimSpace(result.Stdout), nil
}readDefaultType function · go · L154-L171 (18 LOC)internal/installer/defaults.go
func readDefaultType(domain, key string) (string, error) {
result, err := shell.Run("defaults", "read-type", domain, key)
if err != nil {
return "", err
}
// Output is like "Type is boolean", "Type is integer", "Type is float", "Type is string"
out := strings.TrimSpace(result.Stdout)
switch {
case strings.Contains(out, "boolean"):
return "-bool", nil
case strings.Contains(out, "integer"):
return "-int", nil
case strings.Contains(out, "float"):
return "-float", nil
default:
return "-string", nil
}
}writeDefault function · go · L173-L176 (4 LOC)internal/installer/defaults.go
func writeDefault(domain, key, typ, value string) error {
_, err := shell.Run("defaults", "write", domain, key, typ, value)
return err
}Repobility · code-quality intelligence platform · https://repobility.com
isProcessRunning function · go · L178-L181 (4 LOC)internal/installer/defaults.go
func isProcessRunning(name string) bool {
result, err := shell.Run("pgrep", "-x", name)
return err == nil && strings.TrimSpace(result.Stdout) != ""
}isAerospaceRunning function · go · L183-L185 (3 LOC)internal/installer/defaults.go
func isAerospaceRunning() bool {
return isProcessRunning("AeroSpace")
}appendUnique function · go · L188-L195 (8 LOC)internal/installer/defaults.go
func appendUnique(slice []string, item string) []string {
for _, s := range slice {
if s == item {
return slice
}
}
return append(slice, item)
}PhaseNames function · go · L20-L28 (9 LOC)internal/installer/installer.go
func PhaseNames() []string {
return []string{
"Preflight",
"Backup",
"Packages",
"Configs",
"System",
}
}Run function · go · L31-L61 (31 LOC)internal/installer/installer.go
func Run(p *tea.Program, opts Options) {
phases := []struct {
name string
fn func(p *tea.Program, opts Options) error
}{
{"Preflight", runPreflight},
{"Backup", runBackup},
{"Packages", runPackages},
{"Configs", runConfigs},
{"System", runSystem},
}
for i, phase := range phases {
p.Send(tui.PhaseStarted{Name: phase.name})
err := phase.fn(p, opts)
if err != nil {
p.Send(tui.PhaseFailed{Name: phase.name, Error: err})
p.Send(tui.InstallFinished{Err: fmt.Errorf("phase %q failed: %w", phase.name, err)})
return
}
p.Send(tui.PhaseCompleted{Name: phase.name})
pct := ((i + 1) * 100) / len(phases)
p.Send(tui.ProgressUpdate{Percent: pct})
}
p.Send(tui.InstallFinished{})
}runPreflight function · go · L11-L29 (19 LOC)internal/installer/preflight_phase.go
func runPreflight(p *tea.Program, opts Options) error {
checks := preflight.RunAll()
for _, c := range checks {
if c.Passed {
p.Send(tui.LogLine{Text: fmt.Sprintf("==> %s: %s", c.Name, c.Detail)})
} else if c.Warning {
p.Send(tui.LogLine{Text: fmt.Sprintf("==> %s: ⚠ %s", c.Name, c.Detail)})
} else {
p.Send(tui.LogLine{Text: fmt.Sprintf("==> %s: ✗ %s", c.Name, c.Detail)})
}
}
if !preflight.AllPassed(checks) {
return fmt.Errorf("preflight checks failed — run 'omachy doctor' for details")
}
return nil
}statePath function · go · L32-L38 (7 LOC)internal/installer/state.go
func statePath() string {
if statePathOverride != "" {
return statePathOverride
}
home, _ := os.UserHomeDir()
return filepath.Join(home, stateDir, stateFile)
}LoadState function · go · L41-L69 (29 LOC)internal/installer/state.go
func LoadState() (*State, error) {
path := statePath()
data, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return &State{
DeployedConfigs: make(map[string]string),
OriginalDefaults: make(map[string]string),
}, nil
}
return nil, err
}
var s State
if err := json.Unmarshal(data, &s); err != nil {
// Corrupted state file — treat as empty rather than failing
return &State{
DeployedConfigs: make(map[string]string),
OriginalDefaults: make(map[string]string),
}, nil
}
if s.DeployedConfigs == nil {
s.DeployedConfigs = make(map[string]string)
}
if s.OriginalDefaults == nil {
s.OriginalDefaults = make(map[string]string)
}
return &s, nil
}Same scanner, your repo: https://repobility.com — Repobility
SaveState function · go · L72-L102 (31 LOC)internal/installer/state.go
func SaveState(s *State) error {
path := statePath()
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0755); err != nil {
return err
}
data, err := json.MarshalIndent(s, "", " ")
if err != nil {
return err
}
// Write to temp file then rename for atomic update
tmp, err := os.CreateTemp(dir, "state-*.json")
if err != nil {
return err
}
tmpPath := tmp.Name()
if _, err := tmp.Write(data); err != nil {
tmp.Close()
os.Remove(tmpPath)
return err
}
if err := tmp.Close(); err != nil {
os.Remove(tmpPath)
return err
}
return os.Rename(tmpPath, path)
}Taps function · go · L22-L32 (11 LOC)internal/manifest/manifest.go
func Taps() []string {
seen := map[string]bool{}
var taps []string
for _, pkg := range Packages() {
if pkg.Tap != "" && !seen[pkg.Tap] {
seen[pkg.Tap] = true
taps = append(taps, pkg.Tap)
}
}
return taps
}Packages function · go · L35-L58 (24 LOC)internal/manifest/manifest.go
func Packages() []Package {
return []Package{
{Name: "nikitabobko/tap/aerospace", Tap: "nikitabobko/tap", Cask: true},
{Name: "sketchybar", Tap: "FelixKratz/formulae"},
{Name: "borders", Tap: "FelixKratz/formulae"},
{Name: "ghostty", Cask: true},
{Name: "neovim"},
{Name: "tree-sitter"},
{Name: "tmux"},
{Name: "font-hack-nerd-font", Cask: true},
{Name: "font-jetbrains-mono", Cask: true},
{Name: "starship"},
{Name: "fzf"},
{Name: "lazygit"},
{Name: "lazydocker"},
{Name: "atuin"},
{Name: "zsh-syntax-highlighting"},
{Name: "zsh-autosuggestions"},
{Name: "neofetch"},
{Name: "node", SkipIfBinary: "node"},
{Name: "python", SkipIfBinary: "python3"},
{Name: "go", SkipIfBinary: "go"},
}
}Services function · go · L61-L69 (9 LOC)internal/manifest/manifest.go
func Services() []Package {
var svcs []Package
for _, pkg := range Packages() {
if pkg.Service {
svcs = append(svcs, pkg)
}
}
return svcs
}Configs function · go · L72-L82 (11 LOC)internal/manifest/manifest.go
func Configs() []ConfigMapping {
return []ConfigMapping{
{Source: "aerospace/aerospace.toml", Dest: "~/.config/aerospace/aerospace.toml", Mode: 0644},
{Source: "sketchybar", Dest: "~/.config/sketchybar", IsDir: true, Mode: 0755},
{Source: "borders/bordersrc", Dest: "~/.config/borders/bordersrc", Mode: 0755},
{Source: "ghostty/config", Dest: "~/Library/Application Support/com.mitchellh.ghostty/config", Mode: 0644},
{Source: "tmux/tmux.conf", Dest: "~/.tmux.conf", Mode: 0644, NeverOverwrite: true},
{Source: "starship.toml", Dest: "~/.config/starship.toml", Mode: 0644},
{Source: "omachy/dev-session.sh", Dest: "~/.config/omachy/dev-session.sh", Mode: 0755},
}
}RunAll function · go · L26-L35 (10 LOC)internal/preflight/preflight.go
func RunAll() []Check {
return []Check{
checkArch(),
checkMacOSVersion(),
checkHomebrew(),
checkXcodeCLI(),
checkSeparateSpaces(),
checkAeroSpaceVersion(),
}
}AllPassed function · go · L38-L45 (8 LOC)internal/preflight/preflight.go
func AllPassed(checks []Check) bool {
for _, c := range checks {
if !c.Passed && !c.Warning {
return false
}
}
return true
}checkArch function · go · L47-L52 (6 LOC)internal/preflight/preflight.go
func checkArch() Check {
if runtime.GOARCH == "arm64" {
return Check{Name: "Architecture", Passed: true, Detail: "Apple Silicon (arm64)"}
}
return Check{Name: "Architecture", Passed: true, Detail: fmt.Sprintf("%s (supported)", runtime.GOARCH)}
}Repobility analyzer · published findings · https://repobility.com
checkMacOSVersion function · go · L54-L77 (24 LOC)internal/preflight/preflight.go
func checkMacOSVersion() Check {
result, err := shell.Run("sw_vers", "-productVersion")
if err != nil {
return Check{Name: "macOS version", Passed: false, Detail: "Could not determine macOS version"}
}
version := strings.TrimSpace(result.Stdout)
parts := strings.Split(version, ".")
if len(parts) < 1 {
return Check{Name: "macOS version", Passed: false, Detail: "Could not parse macOS version"}
}
major, err := strconv.Atoi(parts[0])
if err != nil {
return Check{Name: "macOS version", Passed: false, Detail: fmt.Sprintf("Could not parse version: %s", version)}
}
if major < 13 {
return Check{Name: "macOS version", Passed: false, Detail: fmt.Sprintf("%s (requires >= 13.0 Ventura)", version)}
}
name := macOSName(major)
return Check{Name: "macOS version", Passed: true, Detail: fmt.Sprintf("%s (%s)", version, name)}
}macOSName function · go · L79-L90 (12 LOC)internal/preflight/preflight.go
func macOSName(major int) string {
names := map[int]string{
13: "Ventura",
14: "Sonoma",
15: "Sequoia",
16: "Tahoe",
}
if name, ok := names[major]; ok {
return name
}
return "macOS"
}checkHomebrew function · go · L92-L233 (142 LOC)internal/preflight/preflight.go
func checkHomebrew() Check {
path, found := shell.Which("brew")
if !found {
return Check{
Name: "Homebrew",
Passed: false,
Detail: "Not found. Install from https://brew.sh",
}
}
return Check{Name: "Homebrew", Passed: true, Detail: path}
}
func checkXcodeCLI() Check {
cmd := exec.Command("xcode-select", "-p")
output, err := cmd.Output()
if err != nil {
return Check{
Name: "Xcode CLI tools",
Passed: false,
Detail: "Not installed. Run: xcode-select --install",
}
}
return Check{Name: "Xcode CLI tools", Passed: true, Detail: strings.TrimSpace(string(output)) + " (ensure up to date via Software Update)"}
}
func checkAeroSpaceVersion() Check {
_, found := shell.Which("aerospace")
if !found {
// Not installed yet — that's fine, Homebrew will install it.
return Check{Name: "AeroSpace version", Passed: true, Detail: "Not yet installed (will be installed)"}
}
result, err := shell.Run("aerospace", "--version")
if err != nil {
return Check{
Napage 1 / 2next ›