Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning, Rick Cook
Python is a simple, easy-to-understand, and minimalistic language, and yet very powerful.It is one of the easiest programming languages to learn because it has a clean and readable syntax that makes it easy for beginners to read and use. Besides, Python is free and open-source.
Python is an interpreted, high-level, and general-purpose programming language with batteries included. It is used for web development, AI, machine learning, operating systems, mobile application development, and video games.
Ubuntu, Debian: sudo apt-get install python3 python3-pip python3-venv. Arch: sudo pacman -S python python-pip
Install Visual Studio Code and some extensions. Arch:
# Arch
git clone https://aur.archlinux.org/visual-studio-code-bin.git
cd visual-studio-code-bin
makepkg -si
cd ..
rm -rf visual-studio-code-bin
yay -S consolas-font
# macOS
brew install --cask visual-studio-code
brew install --cask font-jetbrains-mono # optional, used in the settings below
# Install the extensions
code --install-extension ms-python.python # Python, installs Pylance + Python Debugger too
code --install-extension charliermarsh.ruff # linter + formatter + import sorter, replaces Pylint/autopep8/isort
code --install-extension streetsidesoftware.code-spell-checker
code --install-extension streetsidesoftware.code-spell-checker-spanish
code --install-extension pkief.material-icon-theme
code --install-extension oderwat.indent-rainbow
Open a project folder: mkdir -p ~/macOS/myPython && cd ~/myPython && code .
New File.
Create a virtual environment (python3 -m venv venv) and activate it (source ./venv/bin/activate). Upgraded pip (python -m pip install --upgrade pip). deactivate (when you want to leave it).
Visual Studio Code is a multiplatform source-code editor made by Microsoft. Its functionality can be extended using extensions.
mkdir -p ~/macOS/myPython && cd ~/myPython) and open VS Code in it (code .). Alternatively, launch VS Code and go to File, Open Folder…
Debug. Press F5 and choose Python File, or use Run, Start Debugging. Step with F10 (over), F11 (into) and Shift+F11 (out).

VS Code keeps debugging configuration in .vscode/launch.json (Run, Open Configurations). The debugger type is now debugpy (the old “type”: “python” still appears in older guides). To pass arguments to your program, use args:
{
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"args": ["myarg1", "myarg2"], // or "${command:pickArgs}" to be asked every run
"console": "integratedTerminal"
}
]
}
Activate a virtual environment: source myProject/bin/activate. To deactivate it: deactivate
Install packages in the active environment (the integrated terminal activates it for you): python -m pip install yourPackage. You can also use the Python sidebar: Environment Managers, right-click the environment, Manage Packages.
“No pip installer available in the selected environment”: the venv was created without pip. Fix it with python -m ensurepip –upgrade, or delete .venv and recreate it. Don’t set include-system-site-packages = true, because that makes the environment see (and depend on) your global packages.
~/Library/Application Support/Code/User/settings.json. If you keep dotfiles with GNU Stow, mirror that path inside the package (code/Library/Application Support/Code/User/settings.json).
# 1. Create the folders inside the code package:
mkdir -p "code/Library/Application Support/Code/User"
# 2.A Move your existing VS Code settings into the package, if you have them:
mv "$HOME/Library/Application Support/Code/User/settings.json" \
"code/Library/Application Support/Code/User/settings.json"
# 2.B If the file doesn’t exist yet, create it:
touch "code/Library/Application Support/Code/User/settings.json"
# 3. Have Stow link the package into your home directory:
stow --target="$HOME" code
# 4. Check that the link was created:
ls -l "$HOME/Library/Application Support/Code/User/settings.json"
{
// —————— Workbench ——————
"workbench.colorTheme": "Dark Modern", // any installed theme name
"workbench.iconTheme": "material-icon-theme",
"workbench.settings.editor": "json", // open settings.json instead of the Settings UI
"workbench.settings.openDefaultSettings": true, // show read-only defaults next to your overrides
"workbench.editor.enablePreview": false, // every opened file gets a permanent tab
"workbench.activityBar.visible": true,
"window.zoomLevel": 1,
// —————— Editor ——————
"editor.fontSize": 16,
"editor.fontFamily": "JetBrains Mono, Menlo, Monaco, monospace", // Consolas is not on macOS
"editor.fontLigatures": true, // draw -> != == as single glyphs (visual only)
"editor.tabSize": 4,
"editor.insertSpaces": true, // PEP 8: 4 spaces, never tabs, formatters expect it
"editor.formatOnSave": true,
"editor.formatOnPaste": true,
"editor.accessibilitySupport": "off",
"editor.codeActionsOnSave": {
"source.fixAll": "explicit", // only on a manual save (Cmd+S)
"source.organizeImports": "explicit"
},
// —————— Files ——————
"files.trimTrailingWhitespace": true,
"files.trimFinalNewlines": true,
"files.insertFinalNewline": true, // POSIX/PEP 8 style: exactly one final newline
"files.autoSave": "afterDelay", // AUTO-SAVE
"files.autoSaveDelay": 1000,
"explorer.confirmDragAndDrop": false,
"explorer.confirmDelete": false, // Deleted files go to the Trash, still recoverable
// —————— Terminal ——————
"terminal.integrated.fontSize": 16,
"terminal.integrated.fontFamily": "JetBrains Mono, Menlo, monospace",
"terminal.integrated.scrollback": 20000, // 1,000,000 lines eats RAM
"terminal.integrated.cursorStyle": "line",
"terminal.integrated.defaultProfile.osx": "zsh",
// —————— Python ——————
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python", // fallback, a .venv is also auto-detected
"python.envFile": "${workspaceFolder}/.env",
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff", // or "ms-python.autopep8" / "ms-python.black-formatter"
"editor.codeActionsOnSave": {
"source.fixAll.ruff": "explicit",
"source.organizeImports.ruff": "explicit"
}
},
// —————— Markdown (snippets need quick suggestions on) ——————
"[markdown]": {
"editor.quickSuggestions": { "other": "on", "comments": "off", "strings": "on" }
},
// —————— Code Runner (optional extension) ——————
"code-runner.clearPreviousOutput": true,
"code-runner.runInTerminal": true,
"code-runner.showExecutionMessage": false,
"code-runner.saveFileBeforeRun": true,
"code-runner.executorMap": {
"python": "$pythonPath -u $fullFileName" // uses the interpreter selected in VS Code
},
// —————— Spell checker ——————
"cSpell.enabled": true,
"cSpell.language": "en,es",
"cSpell.diagnosticLevel": "Warning" // Error | Warning | Information | Hint
}
# First, one-time setup in the terminal:
brew install git gh
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git config --global init.defaultBranch
.venv/
__pycache__/
*.pyc
.env
credentials.py
*.pkl
*.pickle
Backup/
.DS_Store
git add .): Changes, Stage All Changes.git commit): : type a message and click ✓, Commit.gh auth login, choose HTTPS, and answer Y to “Authenticate Git with your GitHub credentials?”. It stores the credentials in the macOS Keychain.Cmd+Shift+P, Snippets: Configure Snippets, then New Global Snippets file… or pick a language such as markdown.
{
"Insert Raw HTML": {
"prefix": "raw",
"body": [
"{{< raw >}}",
"${1: markdown_content}",
"{{< /raw >}}"
],
"description": "Insert Raw HTML"
},
"Insert Code": {
"prefix": "code",
"body": [
"``` ${1|html,python,md,bash,javascript,json|} ",
"${2: markdown_content}",
"```"
],
"description": "Insert Code"
},
"Markdown link": {
"prefix": "link",
"body": [
"[${1: link_text}](${2: link_url})"
],
"description": "Markdown link"
}
}
prefix defines the trigger word that display the snippet. body is one or more lines of content, and description is an optional description of the snippet.
Some snippets have placeholders, e.g. ${1:markdown_content}. Press Tab to jump to the next one. Placeholders can offer choices, e.g. ${1|html,python,md,bash,javascript,json|}: when the placeholder is selected, VS Code shows a pick list.
You can use Snippet generator to create snippets for Visual Studio Code, Sublime Text, and Atom.
cd ~\macOS (macOS is where I save all my configuration files)
mkdir -p "code/Library/Application Support/Code/User/snippets" where mkdir -p creates every missing folder in one go. Besides, the quotes are required because Application Support contains a space.
Create (or move) your current settings into the package: code "$HOME/dotfiles/macOS/code/Library/Application Support/Code/User/snippets/markdown.json"
VS Code stores language snippets as SNIPPET_LANGUAGE.json in User/snippets/. mv "$HOME/Library/Application Support/Code/User/snippets/markdown.json" "$HOME/macOS/code/Library/Application Support/Code/User/snippets/markdown.json"
Dry run, then link. Always preview first. -n means “simulate”, -v means “verbose”.
cd ~/macOS
stow -nv --no-folding -t ~ code
LINK: Library/Application Support/Code/User/settings.json => ../../../../macOS/code/Library/Application Support/Code/User/settings.json
LINK: Library/Application Support/Code/User/snippets/markdown.json => ../../../../../macOS/code/Library/Application Support/Code/User/snippets/markdown.json
WARNING: in simulation mode so not modifying filesystem.
# No errors means it is safe. Now do it for real:
stow -v --no-folding -t ~ code
# where...
# --no-folding: by default, if a whole folder doesn't exist yet, Stow links the entire folder.
# For Code/User, which also contains caches and workspace data, that would push VS Code's junk into your repo.
# With --no-folding, Stow creates real folders and links only your files.
# -t ~: the target is your home folder.
# Check
ls -l "$HOME/Library/Application Support/Code/User/"
[...]
lrwxr-xr-x@ 1 nmaximo7 staff 74 Oct 11 14:02 settings.json -> ../../../../macOS/code/Library/Application Support/Code/User/settings.json
ls -l /Users/nmaximo7/Library/Application\ Support/Code/User/snippets/markdown.json
lrwxr-xr-x@ 1 nmaximo7 staff 86 Oct 11 14:02 /Users/nmaximo7/Library/Application Support/Code/User/snippets/markdown.json -> ../../../../../macOS/code/Library/Application Support/Code/User/snippets/markdown.json
The extension list. Export what is installed right now:
cd ~/dotfiles/macOS/code
code --list-extensions | sort > vs-code-extensions.txt
# code --list-extensions prints one extension ID per line (publisher.name).
# sort keeps the file stable so git diffs stay small.
cat vs-code-extensions.txt
# Problem: this file now sits inside the code package, and Stow would symlink it into ~.
# Tell Stow to ignore it with a .stow-local-ignore file at the package root (each line is a regular expression):
cat > .stow-local-ignore <<'EOF'
^/vs-code-extensions\.txt$
^/\.stow-local-ignore$
EOF
# Re-run from ~/dotfiles/macOS (-R = restow):
stow -v --no-folding -t ~ -R code
# and check that ls -l ~/vs-code-extensions.txt says "No such file".
# How you restore it on another Mac:
xargs -L1 code --install-extension < ~/dotfiles/macOS/code/vs-code-extensions.txt
git add . && git commit -am “my Code configuration” && git push
Open a workspace, create a folder name .vscode if it does not exist.
Create a file named tasks.json inside the .vscode folder.
Define a custom task that will automatically run a terminal command when the workspace is opened, e.g., start the Hugo server (hugo server)
{
"version": "2.0.0",
"tasks": [
{
// Task 1: Clean the public directory before building
// This ensures you start with a fresh build every time
"label": "Clean Public Directory",
"type": "shell",
"command": "rm",
"args": [
"-rf", // Recursive force delete
"public/" // Hugo's output directory
],
"group": {
"kind": "build",
"isDefault": false
},
"problemMatcher": [],
"presentation": {
"reveal": "silent", // Don't show output for this simple task
"panel": "shared"
}
},
{
// Task 2: Start Hugo development server
// Runs after cleaning the public directory
"label": "Start Hugo Server",
"dependsOrder": "sequence", // Run dependencies in order
"dependsOn": "Clean Public Directory", // First clean, then start
"type": "shell",
"command": "hugo",
"args": [
"server",
"--disableFastRender", // Full rebuild on changes (more reliable)
"--bind=0.0.0.0", // Allow access from other devices on network
"--baseURL=dirIP:1313", // It is used to generatre absolute URL for tre site resouces, e.g., images, sitemaps, etc.
"--poll=700ms",
"--noBuildLock" // Don't create .hugo_build.lock file.
],
"group": {
"kind": "build",
"isDefault": true // This is the default build task (Ctrl+Shift+B)
},
"presentation": {
"reveal": "always", // Always show the terminal
"panel": "dedicated", // Use dedicated panel (better than "new")
"showReuseMessage": false, // Don't show reuse message
"clear": true, // Clear terminal before running
"echo": true, // Show the command being run
"focus": false // Don't steal focus from editor
},
"problemMatcher": [],
"runOptions": {
"runOn": "folderOpen" // Auto-start when folder opens
},
"isBackground": true // Mark as background task (keeps running)
},
{
// Task 3: Build production site (no server)
"label": "Build Production Site",
"dependsOrder": "sequence",
"dependsOn": "Clean Public Directory",
"type": "shell",
"command": "hugo",
"args": [
"--minify", // Minify HTML/CSS/JS
"--cleanDestinationDir" // Clean destination before building
],
"group": "build",
"presentation": {
"reveal": "always",
"panel": "shared",
"clear": true
},
"problemMatcher": []
},
{
// Task 4: Stop Hugo Server
// Useful to stop the auto-started server
"label": "Stop Hugo Server",
"type": "shell",
"command": "pkill",
"args": [
"-f",
"hugo server"
],
"group": "none",
"presentation": {
"reveal": "silent",
"panel": "shared"
},
"problemMatcher": []
}
]
}
Save the configuration file and open the workspace.
Add to your keybindings.json (Ctrl+Shift+P, type Open Keyboard Shortcuts):
[
{
"key": "ctrl+shift+h",
"command": "workbench.action.tasks.runTask",
"args": "Start Hugo Server"
},
{
"key": "ctrl+shift+k",
"command": "workbench.action.tasks.runTask",
"args": "Stop Hugo Server"
}
]
VS Code Remote - SSH allows you to open folders on any remote machine, virtual machine, or container with a running SSH server and use the full VS Code feature set — including IntelliSense, debugging, and extensions — as if you were working locally.
While password-based authentication is supported, key-based authentication is strongly recommended for enhanced security and convenience: ssh-keygen -t rsa -b 4096 -C "your_email@example.com" / ssh-keygen -t ed25519 -C "your_email@example.com" (generate key), ssh-copy-id username@hostname (copy public key to remote server).
In Windows, ssh -i {path to private key file}\id_rsa {name}@{machine}, e.g., ssh -i C:\Users\Owner/.ssh/id_rsa {name}@{machine}.
nmaximo7@192.168.1.46. ssh nmaximo7@192.168.1.46 (the full ssh command you would use to connect to the host from the command line). \home\nmaximo7\.ssh\config or ssh -i ~/.ssh/config yourname@dirIPAddress
Host myserver # Alias used in VS Code (friendly name)
HostName dirIPAddress # IP address or domain, e.g., 192.168.1.46
User yourname # SSH username, e.g., nmaximo7
IdentityFile ~/.ssh/id_rsa # It should point to your private key, not the config file itself.
Edit vscode.nix (~/dotfiles/vscode.nix) as follows:
programs.vscode = {
userSettings = {
[...]
"remote.SSH.useLocalServer" = false;
# Normally the Visual Studio Code Remote-SSH extension launches a small local helper server.
# VS Code will connect directly via SSH, without intermediate local node process.
"remote.SSH.defaultExtensions" = [];
# Normally VS Code automatically installs some extensions on the remote host.
# No extensions are auto-installed.
"remote.SSH.remotePlatform" = {
"myserver" = "linux";
};
# Host alias: myserver, platform: linux (it skips auto-detecting the OS).
"remote.SSH.configFile" = "/home/nmaximo7/.ssh/config";
# Use my Home-Manager generated SSH config instead of default.
# Since I have defined programs.ssh.matchBlocks Home-Manager will generate this file automatically.
"remote.SSH.serverInstallPath" = {
"myserver" = "/mnt/data/justtothepoint";
};
# Normally VS Code installs its remote server ~/.vscode-server.
# We override it to /mnt/data/justtothepoint
{ config, pkgs, ... }:
let
username = "nmaximo7";
dotfiles = "/home/${username}/dotfiles";
in
{
# Enable Home Manager
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.backupFileExtension = "backup";
home-manager.users.nmaximo7 = { pkgs, ... }:
{
home.stateVersion = "25.05";
[...]
programs.ssh = {
enable = true;
enableDefaultConfig = false;
matchBlocks = {
"*" = {
serverAliveInterval = 60;
serverAliveCountMax = 3;
};
myserver = {
hostname = "192.168.1.46";
user = "nmaximo7";
identityFile = "~/.ssh/id_rsa";
};
};
};
[...]
# This generates an SSH config equivalent to:
Host myserver
HostName 192.168.1.46
User nmaximo7
IdentityFile ~/.ssh/id_rsa