Skip to content

workbench§

Everything I open to get work done. fish in Ghostty, uv, bun and fnm for the languages, Zed to write code, and a handful of apps. Almost all of it installs with one curl or one paru line, and I keep forgetting which one, so they’re all written down here.

fastfetch in Ghostty, showing CachyOS on the ROG Zephyrus G14 with niri, fish, both AMD GPUs and 38 GiB of memory

fastfetch on this machine.

The machine§

An ASUS ROG Zephyrus G14 from 2022, the GA402RJ.

CPU AMD Ryzen 9 6900HS, 8 cores, 16 threads, up to 4.9 GHz
GPU Radeon RX 6700S, plus the Radeon 680M inside the CPU
Memory 38.4 GiB, as the system sees it
Disk 1 TB, btrfs
Screen 14”, 2560×1600 at 120 Hz, scaled 1.5×
Second screen a 24” Samsung (LF24T35), 1920×1080 at 60 Hz

CachyOS set up the drivers for both GPUs on its own, there’s more on that in desktop.

The shell§

The shell is fish, version 4.9. It suggests commands from history as you type and knows the flags of most programs, with no setup.

What CachyOS already sets up§

CachyOS ships its own fish config, the cachyos-fish-config package, and my config.fish loads it on the first line. It brings:

  • a notification when a long command finishes. Anything that takes more than 10 seconds pops a notification when it’s done, through the done plugin.
  • ls with icons. ls, la, ll and lt are all eza, folders first.
  • man pages in color, piped through bat.
  • !! and !$ like in bash. sudo !! reruns the last command with sudo.
  • a pile of aliases, like update (picks the fastest mirrors, then updates), cleanup (removes orphan packages) and jctl (errors from this boot’s log).
  • fastfetch every time a terminal opens. I turned this one off.

What I added§

This is my whole config.fish:

~/.config/fish/config.fish
source /usr/share/cachyos-fish-config/cachyos-config.fish

# overwrite greeting to disable fastfetch
function fish_greeting # (1)!
end

# bun
set --export BUN_INSTALL "$HOME/.bun" # (2)!
set --export PATH $BUN_INSTALL/bin $PATH

# aws
set --export AWS_PROFILE ranqia-prod # (3)!
set --export AWS_REGION us-east-1

# Added by jcode installer
if not contains "/home/adeildo/.local/bin" $PATH
    set -gx PATH "/home/adeildo/.local/bin" $PATH
end

# Pi
fish_add_path "/home/adeildo/.local/share/fnm/node-versions/v24.19.0/installation/bin" # (4)!
  1. The CachyOS config defines fish_greeting to run fastfetch. Defining it again, empty, wins because it comes later. Terminals open straight to the prompt now.
  2. The bun installer wrote these two lines.
  3. The AWS profile and region I use for work, so the aws CLI and Terraform pick them up without flags.
  4. Pi’s installer wrote this one. It installs Pi with the npm from Node 24.19.0 and puts that folder on the PATH, so if I ever switch the default Node version, this line needs to change too.

Everything else fish loads comes from conf.d/. That’s where installers leave their files: fnm’s lives there, and so does the fish wrapper for claude-code-profiles.

The prompt§

The prompt is Tide. I install it with fisher, which is in the Arch repos, and then run the setup wizard:

sudo pacman -S fisher
fisher install ilancosman/tide@v6
tide configure

The wizard shows real previews and you pick with the keyboard. Mine ended up on one line, with no frame:

  • left side, the Arch icon, the folder I’m in and the git branch, with counts for staged, changed and untracked files.
  • right side, things that only show up when they matter. The exit code of a command that failed, how long a slow command took, the Python virtualenv, the Node version inside a Node project, and the AWS profile.

Languages§

Each language gets its own manager, installed from its own script and not from pacman. They live in my home folder and don’t get in the way of the system packages.

uv manages Python versions, virtualenvs and packages, all in one tool.

curl -LsSf https://astral.sh/uv/install.sh | sh

It lands in ~/.local/bin, which is already on the PATH. When I need a new package in a project, it’s always uv add, never a hand edit to pyproject.toml, so the lockfile stays in sync.

bun runs JavaScript and TypeScript, installs packages and runs scripts, and it’s fast at all of it.

curl -fsSL https://bun.sh/install | bash

It installs into ~/.bun, adds two lines to config.fish (the ones marked above) and drops its completions in ~/.config/fish/completions/. The global packages I install with bun add -g are mostly agent tools, they get their own page in agents.

This is the one I always forget the name of. It’s fnm, Fast Node Manager. It does the same job as nvm, reads the same .nvmrc and .node-version files, but it’s a single Rust binary and it works in fish without any adapter.

curl -fsSL https://fnm.vercel.app/install | bash

The script installs into ~/.local/share/fnm and, when your shell is fish, writes ~/.config/fish/conf.d/fnm.fish. Then:

fnm install 24
fnm default 24

My default is Node 24.19.0.

Make it switch versions by itself

The installer sets fnm up without --use-on-cd, so walking into a project with a .nvmrc doesn’t change the Node version. I only noticed while writing this page. Adding the flag to the line in conf.d/fnm.fish fixes it:

~/.config/fish/conf.d/fnm.fish
fnm env --use-on-cd --shell fish | source

Now cd into a project picks the version from its .nvmrc or .node-version, and says so when that version isn’t installed yet.

Editor§

I write code and open files in Zed.

curl -f https://zed.dev/install.sh | sh

That puts the app in ~/.local/zed.app and the zed command in ~/.local/bin. It updates itself. zed . opens the current folder.

The settings file is the one thing I copy to every new machine. Here’s what each part does, grouped:

settings.json
"languages": {
  "Python": {
    "tab_size": 4,
    "format_on_save": "on",
    "language_servers": ["ty", "ruff"] // (1)!
  },
  "TypeScript": {
    "tab_size": 2,
    "format_on_save": "on",
    "inlay_hints": { "enabled": false } // (2)!
  },
  "TSX": { "inlay_hints": { "enabled": false } }
}
  1. By default Zed runs basedpyright and ruff on Python, and keeps ty turned off. This list replaces the default completely. ty checks the types, ruff lints and formats, and basedpyright never starts. Both come from Astral, the same people behind uv.
  2. The inline type hints are on everywhere else, but not in TypeScript.

Saving a Python file runs ruff’s formatter and sorts the imports. That second part is Zed’s default for Python, I didn’t have to add it.

Setting What it does
theme: DankShell Dark Transparent the theme DMS writes with the wallpaper colors, so Zed changes along with everything else
icon_theme: Material Icon Theme the file icons from VS Code’s Material theme
buffer_font_family: JetBrainsMono Nerd Font Mono JetBrains Mono, with the Nerd Font icons
buffer_font_weight: 350 a bit thinner than the regular 400
buffer_font_features: calt, liga ligatures, so => and != render as one symbol
ui_font_size: 17 menus and panels one point bigger than the default
colorize_brackets rainbow brackets, each nesting level gets a color
indent_guides.coloring: indent_aware the indent lines are colored by depth too
show_whitespaces: trailing dots only for spaces left at the end of a line
unnecessary_code_fade: 0.4 unused imports and variables fade a bit more
gutter.folds: false no fold arrows next to the line numbers
gutter.min_line_number_digits: 0 the gutter is only as wide as the line numbers need
gutter.git_gutter_width: 5 px the git change bars have a fixed width
soft_wrap: editor_width long lines wrap at the edge of the window
show_wrap_guides: false no vertical ruler at 80 columns
Setting What it does
project_panel.dock: left the file tree on the left, like VS Code
git_panel, outline_panel, collaboration_panel: left every panel on the left too
terminal.dock: right the terminal opens on the right, next to the code
bottom_dock_layout: left_aligned the bottom dock starts at the left edge of the window
project_panel.hide_root no root folder row at the top of the tree
project_panel.indent_size: 13 a tighter tree, 13 px per level
project_panel.entry_spacing: standard less space between the files in the tree
active_pane_modifiers.inactive_opacity: 0.7 splits I’m not typing in are dimmed
title_bar.button_layout: “” no minimize, maximize and close buttons, niri doesn’t need them
title_bar.show_branch_status_icon the branch icon in the title bar shows the git status
status_bar.show_active_file the name of the open file at the bottom
tab_bar.show_nav_history_buttons: false no back and forward arrows in the tab bar
search.button, debugger.button: false two fewer buttons in the status bar
tabs.file_icons, tabs.git_status tabs get the file icon and turn yellow or green when the file changed
tabs.show_diagnostics: errors tabs mark files that have errors
file_finder.modal_max_width: medium a wider file finder, so long paths fit
Setting What it does
base_keymap: VSCode VS Code shortcuts, the ones my hands already know
autosave: on_focus_change a file saves when I switch to another tab or panel
use_smartcase_search search ignores case, until I type a capital letter
scroll_sensitivity: 2 scrolls twice as far per wheel step
autoscroll_on_clicks clicking near the edge of the editor scrolls it
hide_mouse: never the mouse stays visible while I type
inlay_hints.enabled inline type and parameter hints, off by default
diagnostics.inline.enabled errors show at the end of the line, not only on hover
git.inline_blame.padding: 1 the blame text sits right after the code
default_open_behavior, cli_default_open_behavior: new_window each project opens in its own window, and with niri that means its own column
session.trust_all_worktrees skips the “do you trust this folder?” question. Project settings and language servers start on their own, so only turn it on if you only open code you trust
Setting What it does
disable_ai turns off every AI feature in Zed. The agent panel, the inline assistant and edit predictions are all gone
edit_predictions.provider: none no autocomplete suggestions from a model
telemetry.diagnostics, telemetry.metrics: false no crash reports and no usage data sent to Zed

The file still has an agent section with models and a Claude Code server, from before I turned AI off. With disable_ai on, none of it runs. My AI work happens in the terminal, see agents.

The whole settings.json

download it and drop it in ~/.config/zed/settings.json.

// Zed settings
//
// For information on how to configure Zed, see the Zed
// documentation: https://zed.dev/docs/configuring-zed
//
// To see all of Zed's default settings without changing your
// custom settings, run `zed: open default settings` from the
// command palette (cmd-shift-p / ctrl-shift-p)
{
  "preview_tabs": {
    "enable_preview_from_file_finder": false,
    "enabled": true
  },
  "tab_bar": {
    "show_pinned_tabs_in_separate_row": false,
    "show_tab_bar_buttons": true,
    "show_nav_history_buttons": false,
    "show": true
  },
  "debugger": {
    "button": false
  },
  "search": {
    "button": false
  },
  "status_bar": {
    "show_active_file": true,
    "line_endings_button": false,
    "active_language_button": true
  },
  "relative_line_numbers": "disabled",
  "colorize_brackets": true,
  "lsp_document_colors": "inlay",
  "auto_signature_help": false,
  "scroll_beyond_last_line": "one_page",
  "markdown_preview_font_family": "Noto Sans",
  "buffer_font_weight": 350.0,
  "default_open_behavior": "new_window",
  "proxy": "",
  "diff_view_style": "split",
  "agent_servers": {
    "claude-acp": {
      "default_config_options": {
        "mode": "auto",
        "effort": "medium"
      },
      "type": "registry"
    }
  },
  "disable_ai": true,
  "base_keymap": "VSCode",
  "cli_default_open_behavior": "new_window",
  "outline_panel": {
    "dock": "left",
  },
  "collaboration_panel": {
    "dock": "left",
  },
  "terminal": {
    "button": true,
    "font_family": "JetBrainsMono Nerd Font Mono",
    "default_height": 350.0,
    "font_size": 13.0,
    "dock": "right"
  },
  "agent": {
    "tool_permissions": {
      "tools": {
        "write_file": {
          "default": "allow",
        },
      },
    },
    "inline_assistant_model": {
      "provider": "copilot_chat",
      "model": "gpt-5.2-codex",
      "enable_thinking": false,
    },
    "default_profile": "write",
    "dock": "right",
    "default_height": 400,
    "default_model": {
      "enable_thinking": true,
      "provider": "copilot_chat",
      "model": "claude-haiku-4.5",
    },
  },
  "tabs": {
    "file_icons": true,
    "git_status": true,
    "show_diagnostics": "errors",
  },
  "git_panel": {
    "collapse_untracked_diff": true,
    "dock": "left",
    "tree_view": false,
  },
  "file_finder": {
    "modal_max_width": "medium",
  },
  "project_panel": {
    "git_status_indicator": false,
    "diagnostic_badges": false,
    "folder_indicator": "icon",
    "entry_spacing": "standard",
    "dock": "left",
    "hide_root": true,
    "auto_fold_dirs": true,
    "indent_size": 13.0,
    "git_status": true,
    "show_diagnostics": "all",
  },
  "title_bar": {
    "button_layout": "",
    "show_menus": false,
    "show_user_picture": true,
    "show_user_menu": true,
    "show_onboarding_banner": true,
    "show_branch_status_icon": true,
  },
  "seed_search_query_from_cursor": "always",
  "centered_layout": {
    "right_padding": 0.1,
    "left_padding": null,
  },
  "active_pane_modifiers": {
    "inactive_opacity": 0.7,
  },
  "telemetry": {
    "diagnostics": false,
    "metrics": false,
  },
  "git": {
    "path_style": "file_name_first",
    "hunk_style": "staged_hollow",
    "branch_picker": {
      "show_author_name": true
    },
    "blame": {
      "show_avatar": true
    },
    "git_gutter": "tracked_files",
    "diff_base": "head",
    "inline_blame": {
      "min_column": 0,
      "location": "inline",
      "show_commit_summary": false,
      "padding": 1,
    },
  },
  "inlay_hints": {
    "enabled": true,
    "show_type_hints": true,
    "show_parameter_hints": true,
    "show_other_hints": true,
  },
  "edit_predictions": {
    "mode": "subtle",
    "provider": "none",
  },
  "diagnostics": {
    "button": true,
    "inline": {
      "padding": 1,
      "enabled": true,
    },
  },
  "show_whitespaces": "trailing",
  "allow_rewrap": "in_comments",
  "toolbar": {
    "code_actions": false,
  },
  "gutter": {
    "min_line_number_digits": 0,
    "folds": false,
    "breakpoints": true,
    "runnables": true,
    "git_gutter_width": {
      "custom": 5.0
    },
    "line_numbers": true,
  },
  "indent_guides": {
    "background_coloring": "disabled",
    "coloring": "indent_aware",
  },
  "scrollbar": {
    "show": "auto",
    "git_diff": true,
    "diagnostics": "all",
    "selected_symbol": true,
  },
  "use_smartcase_search": true,
  "autoscroll_on_clicks": true,
  "scroll_sensitivity": 2.0,
  "autosave": "on_focus_change",
  "cursor_shape": "bar",
  "buffer_line_height": "comfortable",
  "buffer_font_family": "JetBrainsMono Nerd Font Mono",
  "buffer_font_features": { "calt": true, "liga": true },
  "preferred_line_length": 80,
  "show_wrap_guides": false,
  "unnecessary_code_fade": 0.4,
  "hide_mouse": "never",
  "soft_wrap": "editor_width",
  "icon_theme": {
    "mode": "system",
    "light": "Material Icon Theme",
    "dark": "Material Icon Theme",
  },
  "session": {
    "trust_all_worktrees": true,
  },
  "bottom_dock_layout": "left_aligned", // espaço que terminal ocupa.
  "ui_font_size": 17.0,
  "buffer_font_size": 15.0,
  "theme": {
    "mode": "system",
    "light": "DankShell Light",
    "dark": "DankShell Dark Transparent",
  },
  "languages": {
    "Python": {
      "tab_size": 4,
      "format_on_save": "on",
      "colorize_brackets": true,

      "language_servers": [
        // Enable ty and ruff,
        // Other built-in servers (basedpyright, pyright, pylsp)
        // are disabled by being omitted from this list.
        "ty",
        "ruff",
      ],
    },
    "TypeScript": {
      "tab_size": 2,
      "format_on_save": "on",
      "colorize_brackets": true,
      "inlay_hints": { "enabled": false },
    },
    "TSX": { "inlay_hints": { "enabled": false } },
  },
  "lsp": {},
}

Extensions§

Zed already understands the big languages by itself. Extensions fill in the rest, and I install them from the extensions page (Ctrl+Shift+X).

Extension What it adds
Material Icon Theme the file icons
oxc Oxlint and Oxfmt, a linter and a formatter for JavaScript and TypeScript, written in Rust
Comment highlights TODO, FIXME, NOTE and friends inside comments
Git Firefly colors for .gitignore, .gitattributes, git config and the interactive rebase file
Dockerfile Dockerfile and Docker Compose
Terraform Terraform and HCL
Prisma Prisma schemas
SQL SQL highlighting
TOML TOML, for pyproject.toml and friends
Make Makefiles
HTML HTML
Emmet Emmet abbreviations, ul>li*3 then Tab
QML QML, the language DMS and its plugins are written in

Apps§

  • Google Chrome Google Chrome


    The regular, stable Chrome. It’s in the AUR as google-chrome.

  • Ghostty Ghostty


    The terminal, opened with Super+Enter. It came with the DMS installer, and its theme is dankcolors, which DMS generates from the wallpaper. Font is JetBrains Mono Nerd Font at 12.

  • Nautilus


    GNOME’s file manager. Plain, and it looks great with the DMS colors. It’s also what opens when an app asks me to pick a file, see desktop.

  • Discord Discord


    Straight from the Arch repos.

  • Spotify Spotify


    From the AUR. What’s playing is also what paints the system, with Music Theme.

  • Steam Steam


    From the Arch repos. cachyos-gaming-meta adds CachyOS’s own Proton and Wine next to it.

All of them in one go:

paru -S google-chrome spotify discord nautilus steam

paru comes with CachyOS. It works like pacman, but it also builds packages from the AUR, which is where Chrome and Spotify live.

Command-line tools§

The rest of what I installed by hand, straight from paru:

Package What for
github-cli gh, for pull requests from the terminal. It’s also git’s login for GitHub
docker docker-compose docker-buildx containers. My user is in the docker group, so no sudo
aws-cli-v2 terraform sops jq work infrastructure. sops keeps secrets encrypted inside the repo
tailscale the Tailscale VPN
amdgpu_top what each GPU is doing, per process
dua-cli finds what’s eating the disk, dua i for the interactive view
ttf-jetbrains-mono-nerd the font in the terminal and in Zed
paru -S github-cli docker docker-compose docker-buildx aws-cli-v2 terraform sops jq tailscale amdgpu_top dua-cli ttf-jetbrains-mono-nerd

The AI tools, starting with Pi, get their own page: agents.