Computing Foundations › The Command Line › Day 13
Hands-on lab — Day 13: Package Managers: Homebrew, apt, and winget
- ← Back to the Day 13 lesson
- Open the hands-on files on GitHub — clone or download them from the public labs repository
- Local path in your clone:
labs/sections/computing-foundations/day-013-package-managers-homebrew-apt-and-winget/
Commands
Setup
cd labs/sections/computing-foundations/day-013-package-managers-homebrew-apt-and-winget Run
bash examples/detect_pkg_manager.sh
bash starter/detect_pkg_manager.sh Test
bash tests/run_tests.sh File tree
examples/command-cheatsheet.md examples/detect_pkg_manager.sh expected-output/FIELDS.md expected-output/sample-macos.txt metadata.yml README.md requirements/README.md security.md starter/detect_pkg_manager.sh starter/package-manager-worksheet.md tests/run_tests.sh troubleshooting.md
Lab README
Day 013 lab — Know Your Package Manager
Lesson
- Lesson title: Package Managers: Homebrew, apt, and winget
- Day number: 13 of 365
- Lesson article: https://ai-roadmap-365.github.io/day-013-package-managers-homebrew-apt-and-winget
- Lab files: everything you need is in this directory — follow “How to run” below.
- Browse the course locally: from the repository root, this lab also appears in the course website at
/labs/day-013-package-managers-homebrew-apt-and-wingetwhen the site is running.
Purpose
Day 13's lesson explains what package managers are and why they matter. This lab makes it concrete and safe: you inspect your own machine to discover which package managers it already has, run read-only queries against them, and record how you would install software — without installing anything. It is a look-before-you-leap tour of the software that manages all your other software.
Learning objectives
- Detect which package managers are present on your machine with
command -v. - Run safe, read-only queries against a manager (version, list, repository info).
- Identify your operating system's default system package manager.
- Read a cross-manager command cheat sheet and map a task across brew/apt/winget.
- Explain why a manager install is safer and more repeatable than a manual one.
Prerequisites
- The Day 13 lesson (read it first — it explains every concept this lab inspects).
- A terminal: Terminal.app (macOS), any terminal (Linux), or PowerShell/WSL (Windows).
- Comfort running basic commands (Days 8–12). No prior package-manager experience needed.
Supported operating systems
- macOS — fully supported (tested on macOS with Apple Silicon). Detects
brew, andpip/npmwhen present. - Linux — fully supported. Detects
apt/apt-getand runsapt-cache policyread-only. - Windows — run the winget commands from the cheat sheet in PowerShell, or run the scripts unmodified inside WSL.
Hardware requirements
Any computer made in roughly the last 15 years. The lab only reads information about installed software; it needs no minimum RAM, disk, or GPU.
Required software
bash(3.2 or newer — preinstalled on macOS and Linux).- Standard OS utilities only:
command,uname,date,sed,grep,head. - Whatever package managers you already have — the lab installs none.
Free and open-source options
Everything here is free. Homebrew and apt are fully open-source, as are the packages in their main repositories; winget is free and first-party on Windows. The lab itself uses only bash and standard utilities. No account, API key, or purchase is required.
Installation
None. Copy this directory (or clone the repository) and you are ready:
cd labs/sections/computing-foundations/day-013-package-managers-homebrew-apt-and-winget
File structure
day-013-package-managers-homebrew-apt-and-winget/
├── README.md ← you are here
├── metadata.yml ← machine-readable lab metadata
├── starter/
│ ├── detect_pkg_manager.sh ← YOUR working file (4 exercises)
│ └── package-manager-worksheet.md ← worksheet for the practice assignment
├── examples/
│ ├── detect_pkg_manager.sh ← completed reference detector
│ └── command-cheatsheet.md ← brew / apt / winget task-by-task table
├── tests/
│ └── run_tests.sh ← automated checks (read-only, exits 0/1)
├── expected-output/
│ ├── sample-macos.txt ← real captured run (macOS, Apple Silicon)
│ └── FIELDS.md ← required fields on every platform
├── requirements/
│ └── README.md ← dependency statement (none beyond the OS)
├── troubleshooting.md
└── security.md
How to run
From this directory:
## 1. See the finished result first
bash examples/detect_pkg_manager.sh
## 2. Your task: complete the four exercises in the starter, then run it
bash starter/detect_pkg_manager.sh
## 3. Check your work
bash tests/run_tests.sh
What the commands do
bash examples/detect_pkg_manager.sh— runs the reference detector: it checks forbrew,apt,apt-get,winget,pip,pip3, andnpmwithcommand -v, and for each one found prints its location and one read-only query (brew --versionandbrew list;apt-cache policy;winget --version;pip/pip3 --version;npm --version). It installs nothing.bash starter/detect_pkg_manager.sh— the same skeleton with four read-only queries left as numbered exercises; each comment names the exact command to add.bash tests/run_tests.sh— runs both scripts and checks they exit 0, print the report header/footer, and report either a found manager or a clear "none detected" message; it also statically scans both scripts to confirm they contain nosudoand no install/remove/upgrade commands.
Expected output
See expected-output/sample-macos.txt — a
real captured run:
=== Package Manager Report ===
Generated on: 2026-07-12
Operating system kernel: Darwin
FOUND: brew -> /opt/homebrew/bin/brew
read-only query: brew --version
Homebrew 6.0.9
read-only query: brew list | head
abseil
ada-url
aom
apr
apr-util
FOUND: pip -> /opt/homebrew/opt/python@3.14/libexec/bin/pip
read-only query: pip --version
pip 25.2 from /opt/homebrew/lib/python3.14/site-packages/pip (python 3.14)
FOUND: npm -> /opt/homebrew/bin/npm
read-only query: npm --version
11.17.0
----------------------------------------
Detected 3 package manager(s) above (read-only).
Nothing was installed, removed, or upgraded.
=== End of report ===
Your values will differ — that is the point. On Debian/Ubuntu the report finds
apt/apt-get and shows apt-cache policy output instead;
expected-output/FIELDS.md lists exactly which
fields must appear on every platform.
Validation steps
- Run
bash examples/detect_pkg_manager.sh— it must exit without errors and print the header and footer. - Confirm it either lists at least one
FOUND:manager or states clearly that none were detected. - Complete the four exercises in
starter/detect_pkg_manager.shand run it — the placeholder(exercise N: ...)lines should be replaced by real read-only query output. - Confirm you installed and removed nothing.
- Run the tests (next section) — all checks must pass.
Tests
bash tests/run_tests.sh
Expected final line: 14 checks, 0 failure(s). The command exits 0 on success
and non-zero on any failure, so it can run in CI. The suite includes a static
safety scan that fails if either script contains sudo or an
install/remove/upgrade command — this lab is strictly read-only.
Cleanup
Nothing to clean up: the scripts only read information and write nothing outside
their own console output. To reset your work, restore the starter from git:
git checkout -- starter/detect_pkg_manager.sh.
Troubleshooting
See troubleshooting.md for the full list (no managers found, brew/pip absent, Windows/WSL notes, safety-scan failures).
Security notes
See security.md. Short version: the scripts make no network
calls, need no elevated privileges, and install nothing — but real installs
elsewhere do change your system and sometimes need sudo, so run those
deliberately and only from trusted repositories.
Extension exercises
- Show the dependency tree of a package you have:
brew deps --tree wget(macOS) orapt-cache depends wget(Linux). Count how many packages one small tool rests on. - Add a
pip3 list(Python) ornpm ls -g --depth=0(global Node packages) read-only query to the detector and note how a language manager's inventory differs from a system manager's. - Using the cheat sheet, write out (do not run) the full sequence you would use on your OS to search for, install, list, and then remove a package — the complete life cycle.
Navigation
- Previous day: Day 12 — Shell Scripting: Variables, Loops, and Conditionals (
labs/sections/computing-foundations/day-012-shell-scripting-variables-loops-and-conditionals/). - Next day: Day 14 — Automating Tasks with Shell Scripts and cron (
labs/sections/computing-foundations/day-014-automating-tasks-with-shell-scripts-and/, to be written).
Expected output
FIELDS.md
# Expected report fields (all platforms)
A correct run of `detect_pkg_manager.sh` prints, in order:
1. `=== Package Manager Report ===`
2. `Generated on: YYYY-MM-DD`
3. `Operating system kernel: <Darwin | Linux | ...>`
4. Zero or more `FOUND: <manager> -> <path>` blocks, each followed by one or
more indented `read-only query:` lines and their output.
5. A summary line: either `Detected <n> package manager(s) above ...` or
`No package managers detected on this machine.`
6. `=== End of report ===`
The script always exits `0`.
## What differs by platform
- **macOS:** typically finds `brew` (if installed) and, when Python/Node are
present, `pip`/`pip3` and `npm`. Never finds `apt`, `apt-get`, or `winget`.
`sample-macos.txt` in this directory is a real captured run (macOS, Apple
Silicon, 2026-07-12): it found `brew`, `pip`, and `npm`.
- **Debian/Ubuntu Linux:** finds `apt` and `apt-get`; the read-only query is
`apt-cache policy`, which lists the configured repositories without changing
anything. May also find `pip3`/`npm`. Never finds `brew` (unless separately
installed) or `winget`.
- **Windows (PowerShell/WSL):** in native PowerShell you would check
`winget --version` and `winget list`. Under WSL the script runs as on Linux.
No matter the platform, the script installs, removes, and upgrades **nothing**.
A run that finds no managers at all is a valid outcome and still exits `0`.
sample-macos.txt
=== Package Manager Report ===
Generated on: 2026-07-12
Operating system kernel: Darwin
FOUND: brew -> /opt/homebrew/bin/brew
read-only query: brew --version
Homebrew 6.0.9
read-only query: brew list | head
abseil
ada-url
aom
apr
apr-util
FOUND: pip -> /opt/homebrew/opt/python@3.14/libexec/bin/pip
read-only query: pip --version
pip 25.2 from /opt/homebrew/lib/python3.14/site-packages/pip (python 3.14)
FOUND: npm -> /opt/homebrew/bin/npm
read-only query: npm --version
11.17.0
----------------------------------------
Detected 3 package manager(s) above (read-only).
Nothing was installed, removed, or upgraded.
=== End of report ===
Source files
examples/command-cheatsheet.md (2072 bytes)
# Package Manager Command Cheat Sheet
The same task, three managers. Learn the model once and read across the row.
Commands that change the system are marked; this lab runs only the read-only
ones (search, list, version, info).
| Task | Homebrew (macOS) | apt (Debian/Ubuntu) | winget (Windows) |
| --- | --- | --- | --- |
| Show the manager's version | `brew --version` | `apt --version` | `winget --version` |
| Refresh the repository index | `brew update` | `sudo apt update` | (automatic) |
| Search for a package | `brew search wget` | `apt search wget` | `winget search wget` |
| Show info about a package | `brew info wget` | `apt show wget` | `winget show wget` |
| **Install** a package | `brew install wget` | `sudo apt install wget` | `winget install wget` |
| List installed packages | `brew list` | `apt list --installed` | `winget list` |
| **Upgrade** everything | `brew upgrade` | `sudo apt upgrade` | `winget upgrade --all` |
| **Remove** a package | `brew uninstall wget` | `sudo apt remove wget` | `winget uninstall wget` |
| Show a package's dependencies | `brew deps --tree wget` | `apt-cache depends wget` | (see `winget show`) |
## Notes
- **sudo:** apt installs system-wide, so its *changing* commands (install,
upgrade, remove) need administrator rights via `sudo`. Homebrew installs into
your user space and normally does not. On Windows, winget may prompt for
elevation for some installers.
- **update vs upgrade (apt):** `apt update` refreshes the local copy of the
repository index; `apt upgrade` actually moves installed packages to newer
versions. They are different commands — do not confuse them.
- **Read-only vs changing:** version, search, info, list, and dependency
queries change nothing and are safe to explore with. Install, upgrade, and
remove change your system — run them deliberately.
- **Language managers:** `pip install <name>` (Python) and `npm install <name>`
(Node.js) follow the same model one layer down, for code libraries rather
than whole applications. You will meet them in a later lesson.
examples/detect_pkg_manager.sh (2279 bytes)
#!/usr/bin/env bash
# Day 013 lab — completed reference implementation.
#
# Detects which package managers are available on THIS machine and runs one
# safe, READ-ONLY query against each one it finds. It never installs, removes,
# or upgrades anything, never uses sudo, and needs no network connection.
#
# Detected: brew, apt, apt-get, winget, pip, pip3, npm.
set -u
echo "=== Package Manager Report ==="
echo "Generated on: $(date '+%Y-%m-%d')"
echo "Operating system kernel: $(uname -s)"
echo
found=0
# have <name> -> prints the resolved path if the command exists, else nothing.
have() {
command -v "$1" 2>/dev/null
}
# header <name> -> if <name> exists, print the FOUND line and return 0.
header() {
local path
path="$(have "$1")"
if [ -n "${path}" ]; then
found=$((found + 1))
echo "FOUND: $1 -> ${path}"
return 0
fi
return 1
}
# query <description> <command...> -> label and run a read-only query, indented.
query() {
local desc="$1"
shift
echo " read-only query: ${desc}"
"$@" 2>&1 | sed 's/^/ /' | head -n 6
}
# --- System package managers -------------------------------------------
if header brew; then
query "brew --version" brew --version
query "brew list | head" bash -c 'brew list 2>/dev/null | head -n 5'
echo
fi
if header apt; then
query "apt-cache policy (configured repositories)" apt-cache policy
echo
elif header apt-get; then
query "apt-cache policy (configured repositories)" apt-cache policy
echo
fi
if header winget; then
query "winget --version" winget --version
echo
fi
# --- Language package managers -----------------------------------------
if header pip; then
query "pip --version" pip --version
echo
elif header pip3; then
query "pip3 --version" pip3 --version
echo
fi
if header npm; then
query "npm --version" npm --version
echo
fi
echo "----------------------------------------"
if [ "${found}" -eq 0 ]; then
echo "No package managers detected on this machine."
echo "That is a valid result: on macOS you may not have Homebrew yet; on"
echo "minimal Linux, apt should be present. Nothing was installed."
else
echo "Detected ${found} package manager(s) above (read-only)."
echo "Nothing was installed, removed, or upgraded."
fi
echo "=== End of report ==="
metadata.yml (634 bytes)
lesson_id: D013
day: 13
kind: command-line-inspection
languages: [bash]
setup_commands:
- cd labs/sections/computing-foundations/day-013-package-managers-homebrew-apt-and-winget
run_commands:
- bash examples/detect_pkg_manager.sh
- bash starter/detect_pkg_manager.sh
test_commands:
- bash tests/run_tests.sh
cleanup_commands:
- 'git checkout -- starter/detect_pkg_manager.sh # optional: reset your work'
requires_network: false
requires_api_key: false
estimated_minutes: 30
last_executed: '2026-07-12'
executed_on: 'macOS (Apple Silicon), bash tests/run_tests.sh → 14 checks, 0 failure(s); detector found brew, pip, npm'
requirements/README.md (765 bytes)
# Dependencies — Day 013 lab
**None beyond a POSIX shell.** This lab intentionally has zero installable
dependencies — fitting, since its whole subject is installing software:
- `bash` ≥ 3.2 (preinstalled on macOS and every mainstream Linux distribution)
- Standard OS utilities: `command`, `uname`, `date`, `sed`, `grep`, `head` —
all part of the base system.
The lab only *detects and inspects* the package managers you already have; it
installs nothing and needs no network connection. If a manager the script looks
for (brew, apt, apt-get, winget, pip, pip3, npm) is absent, that is simply
reported and is a valid result — you do not need to install anything to
complete the lab.
There is deliberately no `requirements.txt`/`package.json` here.
starter/detect_pkg_manager.sh (2554 bytes)
#!/usr/bin/env bash
# Day 013 lab — YOUR working file.
#
# This starter already prints the report header and detects package managers
# for you. Your task is the four numbered exercises below: each asks you to add
# ONE safe, READ-ONLY query for a manager. Every command you add must be
# read-only — no install, no remove, no upgrade, no sudo, no network required.
#
# The completed reference version is examples/detect_pkg_manager.sh — try the
# exercises yourself first, then compare.
set -u
echo "=== Package Manager Report ==="
echo "Generated on: $(date '+%Y-%m-%d')"
echo "Operating system kernel: $(uname -s)"
echo
found=0
have() { command -v "$1" 2>/dev/null; }
header() {
local path
path="$(have "$1")"
if [ -n "${path}" ]; then
found=$((found + 1))
echo "FOUND: $1 -> ${path}"
return 0
fi
return 1
}
query() {
local desc="$1"; shift
echo " read-only query: ${desc}"
"$@" 2>&1 | sed 's/^/ /' | head -n 6
}
# --- System package managers -------------------------------------------
if header brew; then
# Exercise 1 (Homebrew): add a read-only query that prints Homebrew's version.
# Use exactly: query "brew --version" brew --version
echo " (exercise 1: add the brew --version query here)"
echo
fi
if header apt || header apt-get; then
# Exercise 2 (apt): add a read-only query that shows the configured repositories
# WITHOUT changing anything. Use exactly:
# query "apt-cache policy" apt-cache policy
echo " (exercise 2: add the apt-cache policy query here)"
echo
fi
if header winget; then
# Exercise 3 (winget): add a read-only query that prints winget's version.
# Use exactly: query "winget --version" winget --version
echo " (exercise 3: add the winget --version query here)"
echo
fi
# --- Language package managers -----------------------------------------
if header pip || header pip3; then
# Exercise 4 (pip): add a read-only query that prints pip's version. Use the
# name that exists on your machine, for example:
# query "pip3 --version" pip3 --version
echo " (exercise 4: add the pip/pip3 --version query here)"
echo
fi
if header npm; then
query "npm --version" npm --version
echo
fi
echo "----------------------------------------"
if [ "${found}" -eq 0 ]; then
echo "No package managers detected on this machine."
echo "That is a valid result: nothing was installed."
else
echo "Detected ${found} package manager(s) above (read-only)."
echo "Nothing was installed, removed, or upgraded."
fi
echo "=== End of report ==="
starter/package-manager-worksheet.md (1638 bytes)
# Package Manager Worksheet — Day 013
Fill this in for **your** machine using the read-only commands from the lab.
Do **not** run any install command — this worksheet only records what you find
and what you *would* type.
## 1. Which package managers does your machine have?
Run `command -v brew apt apt-get winget pip pip3 npm` (or `bash examples/detect_pkg_manager.sh`)
and list every one it found:
- Package manager(s) found: `__________________________`
## 2. Your default system package manager
Based on your operating system, which is the *default* system package manager?
(macOS → Homebrew; Debian/Ubuntu → apt; Windows → winget.)
- My operating system: `__________________________`
- My default system package manager: `__________________________`
## 3. How you would install `wget` (write it — do NOT run it)
Write the exact command you *would* use to install the `wget` package on your
operating system. Do not run it.
- Install command for `wget`: `__________________________`
(macOS: `brew install wget` · Debian/Ubuntu: `sudo apt install wget` · Windows: `winget install wget`)
## 4. One package you already have installed
List one package that is already installed, from `brew list`,
`apt list --installed`, or `winget list`:
- A package I already have: `__________________________`
## 5. Short reflection (4–6 sentences)
In your own words, explain why installing that one package with a package
manager was safer and more repeatable than downloading it by hand. Name
**dependency resolution**, **integrity verification**, and **record-keeping**
explicitly.
```
Your paragraph here:
```
tests/run_tests.sh (2764 bytes)
#!/usr/bin/env bash
# Tests for the Day 013 lab. Run from the lab directory:
# bash tests/run_tests.sh
#
# Verifies that the detector runs, produces a well-formed report that either
# lists at least one manager or states clearly that none were detected, and
# exits 0. It ALSO statically checks that the scripts contain no install,
# remove, upgrade, or sudo commands — this lab is strictly read-only.
set -u
lab_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
failures=0
checks=0
check() {
local label="$1" ok="$2"
checks=$((checks + 1))
if [ "${ok}" = "yes" ]; then
echo " ok: ${label}"
else
echo " FAIL: ${label}"
failures=$((failures + 1))
fi
}
run_report_checks() {
local script="$1" output rc
echo "Testing ${script} ..."
output="$(bash "${script}" 2>&1)"
rc=$?
[ "${rc}" -eq 0 ] && check "script exits 0" "yes" || check "script exits 0" "no"
echo "${output}" | grep -q '^=== Package Manager Report ===$' \
&& check "prints report header" "yes" || check "prints report header" "no"
echo "${output}" | grep -q '^=== End of report ===$' \
&& check "prints report footer" "yes" || check "prints report footer" "no"
echo "${output}" | grep -q '^Operating system kernel: ' \
&& check "prints OS kernel line" "yes" || check "prints OS kernel line" "no"
# Either at least one manager was found, or a clear "none detected" message.
if echo "${output}" | grep -q '^FOUND: ' \
|| echo "${output}" | grep -q 'No package managers detected'; then
check "reports a manager OR a clear 'none detected' message" "yes"
else
check "reports a manager OR a clear 'none detected' message" "no"
fi
}
# Static safety check: no mutating or privileged commands anywhere in the lab
# scripts. This lab must never install, remove, upgrade, or use sudo.
check_read_only() {
local script="$1"
echo "Safety-scanning ${script} ..."
# Strip comment lines, then look for dangerous verbs as commands.
local body
body="$(grep -v '^[[:space:]]*#' "${script}")"
if echo "${body}" | grep -Eq '\b(sudo)\b'; then
check "no sudo in ${script##*/}" "no"
else
check "no sudo in ${script##*/}" "yes"
fi
if echo "${body}" | grep -Eq '(brew|apt|apt-get|winget|pip|pip3|npm)[[:space:]]+(install|remove|uninstall|upgrade|update)\b'; then
check "no install/remove/upgrade in ${script##*/}" "no"
else
check "no install/remove/upgrade in ${script##*/}" "yes"
fi
}
run_report_checks "${lab_dir}/examples/detect_pkg_manager.sh"
run_report_checks "${lab_dir}/starter/detect_pkg_manager.sh"
check_read_only "${lab_dir}/examples/detect_pkg_manager.sh"
check_read_only "${lab_dir}/starter/detect_pkg_manager.sh"
echo
echo "${checks} checks, ${failures} failure(s)."
[ "${failures}" -eq 0 ]
Troubleshooting
Troubleshooting — Day 013 lab
The script prints no FOUND: lines at all
None of the managers it looks for are on your PATH. This is a valid result,
and the script says so and still exits 0. On macOS you may simply not have
Homebrew installed yet; on a minimal Linux system, try command -v apt on its
own to confirm apt is present.
brew: command not found
Homebrew is not installed, or its directory is not on your PATH. This lab
never installs anything, so just record that brew is absent and inspect
whichever manager you do have. (If you later choose to install Homebrew, follow
the official instructions at the Homebrew documentation — outside this lab.)
pip is missing but pip3 is present (or vice versa)
On many systems the Python package manager is named pip3. The detector checks
both and reports whichever exists; treat a hit on either as "pip is available."
apt-cache policy prints a lot of output
That command lists every configured repository and pinning rule. The script
indents it and shows only the first few lines with head — that is expected.
apt-cache is read-only and changes nothing.
Permission denied when running the script
You do not need to make it executable — run it through bash explicitly:
bash starter/detect_pkg_manager.sh. If you prefer ./starter/..., first run
chmod +x starter/detect_pkg_manager.sh.
I am on Windows and bash is not recognized
Use WSL (wsl --install, then open Ubuntu and follow the Linux path), or skip
the script and run the winget commands from the cheat sheet directly in
PowerShell (winget --version, winget list), filling the worksheet manually.
The tests report a safety failure
The test suite statically scans both scripts for sudo and for
install/remove/upgrade commands and fails if it finds any. If you edited the
starter and added a changing command, remove it — every query in this lab must
be read-only.
Security notes
Security notes — Day 013 lab
- What the scripts do: detect which package managers exist
(
command -v ...) and run read-only queries (--version,brew list,apt-cache policy). They make no network connections, install nothing, remove nothing, upgrade nothing, write no files outside their own console output, and never usesudo. The test suite statically enforces this. - Real installs need care — and sometimes sudo. Outside this lab, installing
software does change your system, and on Linux (apt) the changing commands
require administrator rights via
sudo. Treatsudoas a deliberate act: neversudoa command you have not read and understood, and prefer official repositories over third-party ones. - Trust the source. A package manager verifies that a download matches what the repository published, but it cannot vouch for software you point it at from an untrusted repository. Read package names carefully — a name that is a near-miss of a popular tool ("typosquatting") is a known trick — and prefer your operating system's official repository.
- Privacy: installing packages tells the repository's servers which software a machine requested. The set of packages you have installed is mildly revealing; this lab only lists it locally and sends nothing anywhere.
- Reading before running: both scripts are short and commented — read them first. Running unread shell scripts is one of the most common ways developers get compromised; every script in this course is small enough to read before you run it.