VS Code in Home: local installation and font customization without sudo
Published on 17 April 2026
Why install VS Code in`/opt`or via`apt`when you can put it in your home and turn your IDE into a playground without ever typing`sudo`? Here is the story of a local installation followed by a fierce struggle to enlarge the fonts of the menu and the file explorer.
- toc
-
[]
overview of the course
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
actor Développeur as dev
actor "opencode\n+ LLM" as agent
package "Home User (~)" #LightGreen {
package "~/apps/" {
component "VS Code\n(tarball)" as vscode #SkyBlue
component "vscode-update.sh" as script #LightYellow
}
package "~/.config/Code/" {
component "settings.json" as settings #Lavender
}
package "~/.vscode-custom-css/" {
component "custom.css\n(zoom: 1.25)" as customcss #Lavender
}
}
cloud "code.visualstudio.com" as download
dev --> vscode : Télécharge & installe
dev --> script : Lance mise à jour
script --> download : wget dernière version
script --> vscode : Remplace + re-patch CSS
agent --> settings : Écrit config
agent --> customcss : Écrit zoom CSS
agent --> vscode : Patch workbench CSS
note right of vscode
Installation dans le home
= contrôle total sans sudo
end note
@enduml
The Why: VS Code in the Home
The problem with the system installation
VS Code installed via`apt`, dnf`or in/opt`lock the application files behind root privileges. Any modification of the native CSS, of`product.json`or the installation folder requires`sudo`.
But, when one usesopencode(CLI tool for driving an LLM on its code), the agent needs to be able to:
-
Write in the configuration files`~/.config/Code/User/settings.json`) — that’s already in the home
-
Edit the IDE assets (workbench CSS,
product.json) for advanced customizations — that’s blocked without sudo
The solution: a local installation
We download the official tarball archive and extract it directly into`~/apps/`(nothing)
mkdir -p ~/apps
cd ~/apps
wget "https://code.visualstudio.com/sha/download?build=stable&os=linux-x64" -O vscode.tar.gz
tar -xzf vscode.tar.gz
rm vscode.tar.gz
The binary is then located in`~/apps/VSCode-linux-x64/bin/code`. None`sudo`is not necessary to read, edit, or replace any file under`~/apps/VSCode-linux-x64/`.
Concrete advantages
@startuml
skinparam backgroundColor #FEFEFE
rectangle "System Installation\n(/opt, apt, dnf)" #LightCoral {
card "VS Code owned by root" {
[CSS du workbench : sudo requis]
[product.json : sudo requis]
[Dossier d'install : non modifiable]
}
}
rectangle "Home installation\n(~/apps)" #LightGreen {
card "VS Code user property" {
[CSS du workbench : libre]
[product.json : libre]
[Dossier d'install : libre]
[Script update maison]
}
}
"System Installation\n(/opt, apt, dnf)" -right-> "Home installation\n(~/apps)" : **Non, merci**\nJe prends le home
note bottom of "Home installation\n(~/apps)"
L'agent opencode+LLM peut
modifier les fichiers de l'IDE
sans aucune élévation de privilèges
end note
@enduml
| Advantage | detail |
|---|---|
No sudo |
All IDE files belong to the user |
Direct CSS modification |
One can patch`workbench.desktop.main.css`without privilege escalation |
Home update script |
A simple shell script automatically downloads, replaces, and repatches |
Isolation |
The system installation is not polluted; rollback = delete the folder |
Customize the main menu font
The observation
The default font of the main menu (File, Edit, View…) and dropdowns is too small. VS Code offers no setting to modify it.
The technique: direct CSS patch
We add CSS at the end of the file`workbench.desktop.main.css`</think>
@startuml skinparam backgroundColor #FEFEFE autonumber actor Développeur as dev participant "workbench.desktop\n.main.css" as css participant "product.json" as product participant "VS Code" as vscode == Patch CSS == dev -> css : Ajouter règles font-size\n(.menubar-menu-title, etc.) dev -> vscode : Redémarrer VS Code vscode -> vscode : Charge le CSS patché vscode --> dev : Menus et dropdowns en 23px/22px ✓ == Suppression warning == vscode --> dev : ⚠️ "Your installation is corrupt" dev -> product : Supprimer clé "checksums"\n(python3 -c ...) dev -> vscode : Redémarrer VS Code vscode --> dev : Plus de warning ✓ note over css, product Deux fichiers dans ~/apps/ = modifiables sans sudo end note @enduml
CSS_FILE="$HOME/apps/VSCode-linux-x64/resources/app/out/vs/workbench/workbench.desktop.main.css"
cat >> "$CSS_FILE" << 'EOF'
.menubar-menu-title{font-size:23px!important}
.menubar>.menubar-menu-button{font-size:23px!important}
.monaco-menu-option{font-size:22px!important;line-height:34px!important}
.monaco-menu .action-label:not(.codicon){font-size:22px!important}
.menubar-menu-items-holder .monaco-menu .action-item .action-label{font-size:22px!important}
EOF
Remove the integrity warning
VS Code detects changes to its files and displays a banner \"Your installation is corrupt\". To avoid it, one removes the checksums of`product.json`:
import json
product_json = "$HOME/apps/VSCode-linux-x64/resources/app/product.json"
with open(product_json, 'r') as f:
data = json.load(f)
data.pop('checksums', None)
with open(product_json, 'w') as f:
json.dump(data, f, indent=2)
After restart, no more warnings and the menus are finally readable.
Customize the Explorer pane font — the battle
Attempt 1: a parameter that does not exist
We first try the native parameter`workbench.tree.fontSize`in`settings.json`:
{
"workbench.tree.fontSize": 20
}
Result :no effect. This setting does not exist in VS Code. Proof that unrecognized settings are silently ignored.
Attempt 2: the Custom CSS and JS Loader extension
We install the extension`be5invis.vscode-custom-css`</think>
~/apps/VSCode-linux-x64/bin/code --install-extension be5invis.vscode-custom-css
We create a CSS file in`~/.vscode-custom-css/custom.css`with selectors targeting the explorer elements :
.monaco-tree-rows .monaco-tree-row,
.sidebar .monaco-list-row,
.explorer-viewlet .monaco-list-row,
.monaco-list-row .monaco-icon-label {
font-size: 22px !important;
line-height: 36px !important;
}
And we reference this file in the settings :
{
"vscode_custom_css.imports": [
"file:///home/user/.vscode-custom-css/custom.css"
]
}
Result:the changes do not apply.
The trap: you need to enable the extension each time
The extension documentation is vague on this crucial point: after each custom CSS modification, it is necessary toimperativelyexecute the command from the palette:
-
Ctrl+Shift+P→ typeEnable Custom CSS and JS -
VS Code asks for a restart → accept
Without this step, the CSS is never injected into the IDE.
Attempt 3: the lines overlap
Even with`font-size: 22px` et line-height: 36px, the letters with stems (g, p, f, b) overflow onto the neighboring lines. We try to add`height` et min-height[no output]
.monaco-list-row {
height: 36px !important;
min-height: 36px !important;
}
Result :no change. VS Code calculates line heights in JavaScript and overrides CSS values.
The solution : zoom on the parent container
@startuml
skinparam backgroundColor #FEFEFE
rectangle "Attempt 1\nNonexistent parameter" #LightCoral {
card "workbench.tree.fontSize" as t1 {
[VS Code ignore le paramètre]
}
}
rectangle "Attempt 2\nCustom CSS + font-size" #LightYellow {
card ".monaco-list-row { font-size: 22px }" as t2 {
[Texte plus grand\nmais lignes superposées]
}
}
rectangle "Attempt 3\nfont-size + line-height + height" #LightYellow {
card "height: 36px !important" as t3 {
[VS Code override\npar JavaScript]
[Aucun effet]
}
}
rectangle "Solution\nzoom on parent container" #LightGreen {
card ".monaco-list-rows { zoom: 1.25 }" as t4 {
[Texte + espacement\nproportionnels]
[Layout JS respecté]
[✓ Résultat conforme]
}
}
t1 -down-> t2 : Pas de paramètre ?\nOn essaie le CSS
t2 -down-> t3 : Lignes superposées ?\nOn force la hauteur
t3 -down-> t4 : Override JS ?\nOn utilise zoom
@enduml
Rather than fighting against the JavaScript layout, we use the property.`zoom`on the lines container:
.explorer-viewlet .monaco-list-rows,
.sidebar .monaco-list-rows {
zoom: 1.25;
}
`zoom`uniformly enlarges the container’s rendering — text and spacing — without breaking the layout computed by VS Code’s JavaScript engine. The factor 1.25 roughly corresponds to going from 13px to 16px.
Result :file names are finally readable, lines are correctly spaced.
Summary of selectors and what works
| Approach | CSS | Result |
|---|---|---|
|
|
Larger text but overlapping lines |
|
|
No effect (override JS) |
|
|
Successful — text + spacing proportionals |
The automatic update script
@startuml
skinparam backgroundColor #FEFEFE
autonumber
actor "Developer\nor cron" as dev
participant "vscode-update.sh" as script
participant "vscode tarball\n(code.visualstudio.com)" as remote
participant "~/apps/\nVSCode-linux-x64/" as local
participant "~/apps/\nvscode-backup/" as backup
participant "workbench\n.desktop.main.css" as css
participant "product.json" as product
dev -> script : ./vscode-update.sh
script -> local : Lire version courante
script -> remote : wget dernière version
script -> script : Comparer versions
alt Version identique
script --> dev : "Already up to date!"
else Nouvelle version
script -> backup : Sauvegarder installation courante\n(horodatée)
script -> local : rm -rf ancienne installation
script -> local : mv nouvelle installation
script -> css : Ajouter patch CSS\n(menubar 23px, dropdown 22px)
script -> product : Supprimer checksums\n(python3)
script --> dev : "Update complete\n1.xx.yy → 1.zz.ww"
end note
@enduml
The problem
When VS Code updates, it replaces the installation folder andclear all CSS patches. It is necessary to reapply the changes manually each time.
The script `vscode-update.sh
We create`~/apps/vscode-update.sh`:
#!/bin/bash
set -e
VSCODE_DIR="$HOME/apps/VSCode-linux-x64"
BACKUP_DIR="$HOME/apps/vscode-backup"
TEMP_DIR="/tmp/vscode-update"
MENUBAR_FONT_SIZE="23px"
DROPDOWN_FONT_SIZE="22px"
echo "=== VS Code Local Updater ==="
CURRENT_VERSION=$("$VSCODE_DIR/bin/code" --version 2>/dev/null | head -1)
echo "Current version: $CURRENT_VERSION"
echo "Downloading latest VS Code..."
mkdir -p "$TEMP_DIR"
wget -q "https://code.visualstudio.com/sha/download?build=stable&os=linux-x64" \
-O "$TEMP_DIR/vscode.tar.gz"
echo "Extracting..."
mkdir -p "$TEMP_DIR/extracted"
tar -xzf "$TEMP_DIR/vscode.tar.gz" -C "$TEMP_DIR/extracted"
NEW_VERSION=$("$TEMP_DIR/extracted/VSCode-linux-x64/bin/code" \
--version 2>/dev/null | head -1)
echo "New version: $NEW_VERSION"
if [ "$CURRENT_VERSION" = "$NEW_VERSION" ]; then
echo "Already up to date!"
rm -rf "$TEMP_DIR"
exit 0
fi
echo "Backing up current installation..."
mkdir -p "$BACKUP_DIR"
cp -r "$VSCODE_DIR" "$BACKUP_DIR/VSCode-linux-x64-$(date +%Y%m%d-%H%M%S)"
echo "Updating..."
rm -rf "$VSCODE_DIR"
mv "$TEMP_DIR/extracted/VSCode-linux-x64" "$VSCODE_DIR"
rm -rf "$TEMP_DIR"
CSS_FILE="$VSCODE_DIR/resources/app/out/vs/workbench/workbench.desktop.main.css"
echo "Re-applying custom CSS patch \
(menubar=${MENUBAR_FONT_SIZE}, dropdown=${DROPDOWN_FONT_SIZE})..."
cat >> "$CSS_FILE" << CSSEOF
.menubar-menu-title{font-size:${MENUBAR_FONT_SIZE}!important}\
.menubar>.menubar-menu-button{font-size:${MENUBAR_FONT_SIZE}!important}\
.monaco-menu-option{font-size:${DROPDOWN_FONT_SIZE}!important;\
line-height:34px!important}\
.monaco-menu .action-label:not(.codicon)\
{font-size:${DROPDOWN_FONT_SIZE}!important}\
.menubar-menu-items-holder .monaco-menu .action-item .action-label\
{font-size:${DROPDOWN_FONT_SIZE}!important}
CSSEOF
PRODUCT_JSON="$VSCODE_DIR/resources/app/product.json"
if [ -f "$PRODUCT_JSON" ]; then
echo "Removing checksums to prevent integrity warning..."
python3 -c "
import json
with open('$PRODUCT_JSON','r') as f: data=json.load(f)
data.pop('checksums', None)
with open('$PRODUCT_JSON','w') as f: json.dump(data,f,indent=2)
print('Done.')
"
fi
echo "=== Update complete: $CURRENT_VERSION -> $NEW_VERSION ==="
The script :
-
Download the latest stable version
-
Check if the version differs from the current
-
Save the current installation (timestamped) in`~/apps/vscode-backup/`
-
Replace the installation folder
-
Reapplythe CSS patch of the main menu
-
Remove the checksums de `product.json`to avoid the integrity warning
| Customizations of the Explorer pane via the Custom CSS extension and the file`~/.vscode-custom-css/custom.css`They survive updates because they live outside the installation folder. |
Involved files—overview
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
rectangle "VS Code installation\n(~/apps/VSCode-linux-x64/)" #LightCoral {
component "workbench.desktop\n.main.css" as css #LightCoral
component "product.json" as product #LightCoral
component "binary\nbin/code" as binary #LightCoral
}
rectangle "User configuration\n(~/.config/Code/)" #LightGreen {
component "settings.json" as settings #LightGreen
component "extensions/" as extensions #LightGreen
}
rectangle "Persistent customization\n(~/.vscode-custom-css/)" #SkyBlue {
component "custom.css\n(zoom: 1.25)" as customcss #SkyBlue
}
rectangle "Automation\n(~/apps/)" #LightYellow {
component "vscode-update.sh" as script #LightYellow
component "vscode-backup/" as backup #LightYellow
}
script ..> css : Re-patch après MAJ
script ..> product : Supprime checksums\naprès MAJ
settings --> customcss : Référence via\nvscode_custom_css.imports
extensions ..> css : Custom CSS Loader\ninjecte custom.css
note bottom of css
**Ne survit pas** aux mises à jour
Re-patché par le script
end note
note bottom of customcss
**Survit** aux mises à jour
Vit hors du dossier d'installation
end note
note bottom of settings
**Survit** aux mises à jour
Vit dans ~/.config/
end note
@enduml
| Path | Role | Does it survive updates? |
|---|---|---|
|
Installation of the IDE |
No (replaced) |
|
Workbench CSS (menu, dropdowns) |
No (re-patched by the script) |
|
Integrity checksums |
No (re-cleaned by the script) |
|
Automatic update script |
Yes |
|
User settings (fontSize, custom CSS) |
yes |
|
Custom CSS for Explorer (zoom) |
Yes |
Lessons learned
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultFontName sans-serif
skinparam ArrowColor #444444
rectangle "**Local installation**\n in the home" as install #LightGreen {
card "No sudo\n to modify CSS/config" as i1
card "opencode+LLM can\n modify everything" as i2
card "Rollback = restore\n the timestamped backup" as i3
}
rectangle "**CSS Customization**\n zoom vs font-size" as css #LightYellow {
card "zoom > font-size\n for components list" as c1
card "Layout JS override\n height/line-height" as c2
card "Custom CSS extension\n requires manual activation\n (Ctrl+Shift+P)" as c3
}
rectangle "**Automation**\n update script" as auto #LightCoral {
card "Re-patch CSS after\n each update" as a1
card "Delete checksums\n product.json" as a2
card "Timestamped backup\n before replacement" as a3
}
install -right-> css : ensuite
css -right-> auto : enfin
note top of install
Contrôle total sans élévation
de privilèges
end note
note top of auto
Sans script, chaque MAJ
efface les patches CSS
end note
@enduml
Install in the home frees everything
A local installation in`~/apps`gives full control over VS Code:
-
No`sudo`to modify the CSS or the configuration
-
The opencode+LLM agent can write to the config files and assets of the IDE.
-
Rollback trivial: Restore the timestamped backup
zoom` > font-size for list components
VS Code controls line height via JavaScript. Modify`font-size`without being able to touch the height allocated by the layout engine gives texts that overflow. The property`zoom`on the parent container scales everything proportionally and works around this problem.
Custom CSS extension requires explicit activation
It is not a "set and forget" setting. Every change to the custom CSS file requires re-running "Enable Custom CSS and JS" from the command palette (Ctrl+Shift+P)
An update script is indispensable
Without a script, every VS Code update deletes the workbench CSS patches. The script`vscode-update.sh`automates the download, the replacement, the re-patch, and the cleaning of the checksums
Quick references
-
VS Code download: https://code.visualstudio.com/Download
-
Custom CSS and JSLoader Extension :`be5invis.vscode-custom-css`
-
Issue VS Code requesting a native setting for the Explorer font:https://github.com/microsoft/vscode/issues/149[github.com/microsoft/vscode#149]