Computing Foundations › Inside the Machine › Day 1
Hands-on lab — Day 1: How a Computer Works: From Transistors to Programs
- ← Back to the Day 1 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-001-how-a-computer-works-from-transistors/
Commands
Setup
cd labs/sections/computing-foundations/day-001-how-a-computer-works-from-transistors Run
bash examples/inspect_my_computer_completed.sh
bash starter/inspect_my_computer.sh Test
bash tests/run_tests.sh File tree
examples/inspect_my_computer_completed.sh expected-output/FIELDS.md expected-output/sample-macos.txt metadata.yml README.md requirements/README.md security.md starter/inspect_my_computer.sh starter/machine-profile-template.md tests/run_tests.sh troubleshooting.md
Lab README
Day 001 lab — Inspect Your Own Computer
Lesson
- Lesson title: How a Computer Works: From Transistors to Programs
- Day number: 1 of 365
- Lesson article: https://ai-roadmap-365.github.io/day-001-how-a-computer-works-from-transistors
- 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-001-how-a-computer-works-from-transistorswhen the site is running.
Purpose
Day 1's lesson explains the layers between physics and software. This lab makes it concrete: you interrogate your own machine from the terminal and produce a real "machine profile" — the CPU, cores, RAM, disk, and OS you will rely on for the next 364 days.
Learning objectives
- Run commands in a terminal and read their output confidently.
- Measure your machine's CPU model, core count, RAM, free disk, and OS version.
- Convert bytes to GiB and explain the difference between memory (RAM) and storage (disk).
- Complete a small shell script by filling in five well-specified exercises.
- Run an automated test script and interpret its pass/fail output.
Prerequisites
- The Day 1 lesson (read it first — it explains every concept this lab measures).
- A terminal: Terminal.app (macOS), any terminal (Linux), or PowerShell/WSL (Windows).
- No programming experience required; every command is given and explained.
Supported operating systems
- macOS — fully supported (tested on macOS with Apple Silicon).
- Linux — fully supported (any distribution with
lscpu,nproc,/proc/meminfo). - Windows — use the PowerShell alternatives in the lesson's hands-on section (
Get-ComputerInfo), or run the scripts unmodified inside WSL.
Hardware requirements
Any computer made in roughly the last 15 years. The lab only reads system information; it needs no minimum RAM, disk, or GPU.
Required software
bash(3.2 or newer — preinstalled on macOS and Linux).- Standard OS utilities only:
sysctl,sw_vers,df(macOS);lscpu,nproc,df(Linux). All preinstalled.
Free and open-source options
Everything in this lab is free: bash and every command used are open-source or ship with your OS. No account, API key, or purchase is needed — this is true of every lab in the course wherever possible, and any exception is labelled.
Installation
None. Clone the repository (or copy this directory) and you are ready:
cd labs/sections/computing-foundations/day-001-how-a-computer-works-from-transistors
File structure
day-001-how-a-computer-works-from-transistors/
├── README.md ← you are here
├── metadata.yml ← machine-readable lab metadata
├── starter/
│ ├── inspect_my_computer.sh ← YOUR working file (5 exercises)
│ └── machine-profile-template.md ← worksheet for the practice assignment
├── examples/
│ └── inspect_my_computer_completed.sh ← completed reference implementation
├── tests/
│ └── run_tests.sh ← automated checks
├── 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/inspect_my_computer_completed.sh
## 2. Your task: complete the five exercises in the starter, then run it
bash starter/inspect_my_computer.sh
## 3. Check your work
bash tests/run_tests.sh
What the commands do
bash examples/inspect_my_computer_completed.sh— runs the reference script: detects your OS (uname -s), then usessysctl/sw_vers(macOS) orlscpu//proc/meminfo//etc/os-release(Linux) to print your CPU model, core count, RAM (converted from bytes to GiB by dividing by 1073741824), free disk on/(df -h /), and OS version.bash starter/inspect_my_computer.sh— the same skeleton with five values set tounknown; each exercise comment names the exact command to use. Edit the file in any text editor and replace eachunknownassignment with the command in$(...)form.bash tests/run_tests.sh— runs both scripts and checks: exit code 0, header/footer lines, all five profile fields present; and (once your starter has nounknownleft) that every field has a real value and the core count is a positive integer.
Expected output
See expected-output/sample-macos.txt — a real captured run:
=== My Machine Profile ===
Generated on: 2026-07-12
Operating system kernel: Darwin
CPU model: Apple M4 Max
CPU cores: 14
RAM: 36 GiB (38654705664 bytes)
Free disk on /: 436Gi
OS version: macOS 26.5.1
=== End of profile ===
Your values will differ — that is the point. On Linux the kernel line reads Linux and the OS version comes from /etc/os-release (e.g. an Ubuntu or Fedora release name). expected-output/FIELDS.md lists exactly which fields must appear on every platform.
Validation steps
- Run
bash starter/inspect_my_computer.sh— it must exit without errors. - Confirm no line contains
unknown. - Confirm the RAM line shows both GiB and bytes, and the GiB number matches what your OS reports in its own settings UI (About This Mac / System Monitor).
- Run the tests (next section) — all checks must pass.
Tests
bash tests/run_tests.sh
Expected final line: 18 checks, 0 failure(s). (10 strict checks against the reference script, and 8 structural checks against your starter — which become 10 strict checks once you have replaced every unknown). The command exits 0 on success, non-zero on any failure, so it can run in CI.
Cleanup
Nothing to clean up: the scripts only read system information and write nothing outside their own console output. To reset your work, restore the starter file from git: git checkout -- starter/inspect_my_computer.sh.
Troubleshooting
See troubleshooting.md for the full list (command not found, permission messages, byte-conversion confusion, WSL notes).
Security notes
See security.md. Short version: the scripts run no network calls, need no elevated privileges, and expose only local hardware facts — but a machine profile is mildly identifying, so think before pasting it publicly.
Extension exercises
- Add your CPU cache sizes to the profile (macOS:
sysctl hw.l1dcachesize hw.l2cachesize; Linux:lscpu | grep -i cache) and note how much smaller than RAM they are. - Compute how many float32 parameters (4 bytes each) fit in your RAM, and compare that with the parameter counts of AI models you have heard of.
- Extend the script to print GPU information (macOS:
system_profiler SPDisplaysDataType; Linux:lspci | grep -i vgaornvidia-smiif present) and update the tests to check for your new field.
Navigation
- Previous day: none — this is Day 1.
- Next day: Day 2 — The CPU: Fetch, Decode, Execute (
labs/sections/computing-foundations/day-002-the-cpu-fetch-decode-execute/, to be written).
Expected output
FIELDS.md
# Required profile fields (all platforms)
A correct run of `inspect_my_computer.sh` prints, in order:
1. `=== My Machine Profile ===`
2. `Generated on: YYYY-MM-DD`
3. `Operating system kernel: Darwin` (macOS) or `Linux`
4. `CPU model: <non-empty string>`
5. `CPU cores: <positive integer>`
6. `RAM: <n> GiB (<bytes> bytes)`
7. `Free disk on /: <value with unit, e.g. 436Gi or 89G>`
8. `OS version: <non-empty string>` (macOS product version, or PRETTY_NAME from /etc/os-release)
9. `=== End of profile ===`
`sample-macos.txt` in this directory is a real captured run (macOS, Apple
Silicon, 2026-07-12). Linux output has the same shape; only the kernel line
and the OS version wording differ. No field may read `unknown` in a
completed solution.
sample-macos.txt
=== My Machine Profile ===
Generated on: 2026-07-12
Operating system kernel: Darwin
CPU model: Apple M4 Max
CPU cores: 14
RAM: 36 GiB (38654705664 bytes)
Free disk on /: 436Gi
OS version: macOS 26.5.1
=== End of profile ===
Source files
examples/inspect_my_computer_completed.sh (1332 bytes)
#!/usr/bin/env bash
# Day 001 lab — completed reference implementation.
# Prints a machine profile: CPU, cores, RAM, free disk, OS version.
# Supports macOS (Darwin) and Linux; Windows users use the PowerShell
# commands in the README (or run this under WSL).
set -euo pipefail
os="$(uname -s)"
echo "=== My Machine Profile ==="
echo "Generated on: $(date '+%Y-%m-%d')"
echo "Operating system kernel: ${os}"
if [ "${os}" = "Darwin" ]; then
cpu_model="$(sysctl -n machdep.cpu.brand_string)"
cpu_cores="$(sysctl -n hw.ncpu)"
ram_bytes="$(sysctl -n hw.memsize)"
os_version="macOS $(sw_vers -productVersion)"
elif [ "${os}" = "Linux" ]; then
cpu_model="$(lscpu | sed -n 's/^Model name:[[:space:]]*//p' | head -n 1)"
cpu_cores="$(nproc)"
mem_kb="$(sed -n 's/^MemTotal:[[:space:]]*\([0-9]*\) kB/\1/p' /proc/meminfo)"
ram_bytes="$((mem_kb * 1024))"
os_version="$(sed -n 's/^PRETTY_NAME="\(.*\)"/\1/p' /etc/os-release)"
else
echo "Unsupported OS for this script: ${os} (Windows users: see the README's PowerShell section)" >&2
exit 1
fi
disk_free="$(df -h / | awk 'NR==2 {print $4}')"
echo "CPU model: ${cpu_model}"
echo "CPU cores: ${cpu_cores}"
echo "RAM: $((ram_bytes / 1073741824)) GiB (${ram_bytes} bytes)"
echo "Free disk on /: ${disk_free}"
echo "OS version: ${os_version}"
echo "=== End of profile ==="
metadata.yml (610 bytes)
lesson_id: D001
day: 1
kind: command-line-inspection
languages: [bash]
setup_commands:
- cd labs/sections/computing-foundations/day-001-how-a-computer-works-from-transistors
run_commands:
- bash examples/inspect_my_computer_completed.sh
- bash starter/inspect_my_computer.sh
test_commands:
- bash tests/run_tests.sh
cleanup_commands:
- 'git checkout -- starter/inspect_my_computer.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 → 18 checks, 0 failures'
requirements/README.md (587 bytes)
# Dependencies — Day 001 lab
**None beyond a POSIX shell.** This lab intentionally has zero installable
dependencies:
- `bash` ≥ 3.2 (preinstalled on macOS and every mainstream Linux distribution)
- Standard OS utilities: `uname`, `date`, `df`, plus `sysctl`/`sw_vers` on
macOS or `lscpu`/`nproc` and the `/proc/meminfo`, `/etc/os-release` files
on Linux — all part of the base system.
There is deliberately no `requirements.txt`/`package.json` here; the first
lab must run on a factory-fresh machine. Later labs declare their Python or
Node dependencies in this directory.
starter/inspect_my_computer.sh (2005 bytes)
#!/usr/bin/env bash
# Day 001 lab — inspect your own computer from the command line.
#
# This starter script already detects your operating system and prints the
# report skeleton. Your job (README, "Your task" section) is to fill in each
# exercise below with the single command that prints the value, replacing the
# `unknown` assignments. The completed reference version is in
# examples/inspect_my_computer_completed.sh — try it yourself first.
set -euo pipefail
os="$(uname -s)"
echo "=== My Machine Profile ==="
echo "Generated on: $(date '+%Y-%m-%d')"
echo "Operating system kernel: ${os}"
if [ "${os}" = "Darwin" ]; then
# Exercise 1 (macOS): set cpu_model using: sysctl -n machdep.cpu.brand_string
cpu_model="unknown"
# Exercise 2 (macOS): set cpu_cores using: sysctl -n hw.ncpu
cpu_cores="unknown"
# Exercise 3 (macOS): set ram_bytes using: sysctl -n hw.memsize
ram_bytes="unknown"
# Exercise 4 (macOS): set os_version using: sw_vers -productVersion
os_version="unknown"
elif [ "${os}" = "Linux" ]; then
# Exercise 1 (Linux): set cpu_model using: lscpu | grep 'Model name' (clean it with sed or awk)
cpu_model="unknown"
# Exercise 2 (Linux): set cpu_cores using: nproc
cpu_cores="unknown"
# Exercise 3 (Linux): set ram_bytes by reading MemTotal from /proc/meminfo (value is in kB — multiply by 1024)
ram_bytes="unknown"
# Exercise 4 (Linux): set os_version from PRETTY_NAME in /etc/os-release
os_version="unknown"
else
echo "Unsupported OS for this script: ${os} (Windows users: see the README's PowerShell section)" >&2
exit 1
fi
# Exercise 5 (both): set disk_free for / using: df -h / (take the 'Avail' column of the data row)
disk_free="unknown"
echo "CPU model: ${cpu_model}"
echo "CPU cores: ${cpu_cores}"
if [ "${ram_bytes}" != "unknown" ]; then
echo "RAM: $((ram_bytes / 1073741824)) GiB (${ram_bytes} bytes)"
else
echo "RAM: unknown"
fi
echo "Free disk on /: ${disk_free}"
echo "OS version: ${os_version}"
echo "=== End of profile ==="
starter/machine-profile-template.md (1318 bytes)
# My Machine Profile — Day 001 worksheet
Fill in every value from your own machine using the lab script or the
individual commands from the lesson's hands-on section. Keep this file —
Week 1's project (the Annotated Machine Teardown) builds on it.
| Field | Your value | Command you used |
| ------------------------- | ---------- | ---------------- |
| Date measured | | |
| CPU model | | |
| CPU cores | | |
| RAM (GiB) | | |
| RAM (exact bytes) | | |
| Free disk on `/` | | |
| Total disk size | | |
| OS name and version | | |
| Kernel (`uname -s -r`) | | |
## My memory hierarchy, in my machine's real numbers
Write one paragraph: starting from your CPU's registers and ending at your
disk, describe each level of your machine's memory hierarchy, with the sizes
you measured where you have them. (The lesson's memory-hierarchy diagram is
your map; your numbers replace its labels.)
## One thing that surprised me
One or two sentences.
tests/run_tests.sh (2417 bytes)
#!/usr/bin/env bash
# Tests for the Day 001 lab. Run from the lab directory:
# bash tests/run_tests.sh
#
# Verifies that the completed reference script produces a well-formed
# machine profile with real (non-"unknown") values, and — if the learner
# has finished the starter script — checks their version the same way.
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_profile_checks() {
local script="$1" strict="$2" output
echo "Testing ${script} ..."
if ! output="$(bash "${script}" 2>&1)"; then
check "script exits successfully" "no"
echo "${output}" | sed 's/^/ /'
return
fi
check "script exits successfully" "yes"
echo "${output}" | grep -q '^=== My Machine Profile ===$' && check "prints profile header" "yes" || check "prints profile header" "no"
echo "${output}" | grep -q '^=== End of profile ===$' && check "prints profile footer" "yes" || check "prints profile footer" "no"
for field in "CPU model:" "CPU cores:" "RAM:" "Free disk on /:" "OS version:"; do
echo "${output}" | grep -q "^${field}" && check "prints '${field}'" "yes" || check "prints '${field}'" "no"
done
if [ "${strict}" = "strict" ]; then
if echo "${output}" | grep -q "unknown"; then
check "no field is left 'unknown'" "no"
else
check "no field is left 'unknown'" "yes"
fi
cores="$(echo "${output}" | sed -n 's/^CPU cores: //p')"
case "${cores}" in
'' | *[!0-9]*) check "CPU cores is a positive integer" "no" ;;
*) check "CPU cores is a positive integer" "yes" ;;
esac
fi
}
run_profile_checks "${lab_dir}/examples/inspect_my_computer_completed.sh" strict
# The starter ships with 'unknown' values on purpose; once the learner has
# replaced them all, hold their script to the same strict standard.
if grep -q '"unknown"' "${lab_dir}/starter/inspect_my_computer.sh"; then
echo "Note: starter/inspect_my_computer.sh still has unfilled exercises — testing structure only."
run_profile_checks "${lab_dir}/starter/inspect_my_computer.sh" lenient
else
run_profile_checks "${lab_dir}/starter/inspect_my_computer.sh" strict
fi
echo
echo "${checks} checks, ${failures} failure(s)."
[ "${failures}" -eq 0 ]
Troubleshooting
Troubleshooting — Day 001 lab
sysctl: unknown oid or command not found: sw_vers
You are running the macOS commands on Linux (or vice versa). The script chooses the right branch automatically via uname -s; if you are typing commands manually, use the section of the lesson matching your OS.
command not found: lscpu (Linux)
Minimal containers and some distros omit util-linux. Install it (sudo apt install util-linux on Debian/Ubuntu) or read the model name directly: grep 'model name' /proc/cpuinfo | head -n 1.
Permission denied when running the script
You don't need to make it executable — run it through bash explicitly: bash starter/inspect_my_computer.sh. If you prefer ./starter/inspect_my_computer.sh, first run chmod +x starter/inspect_my_computer.sh.
The RAM number looks absurdly large
sysctl -n hw.memsize and /proc/meminfo report bytes and kB respectively. The script converts to GiB by dividing bytes by 1073741824 (1024³). If you see the raw number, you replaced the whole echo line instead of only the ram_bytes="unknown" assignment — restore the file (git checkout -- starter/inspect_my_computer.sh) and edit only the assignments.
My GiB value doesn't match the GB on the box my computer came in
Manufacturers use decimal gigabytes (10⁹ bytes); operating systems usually use binary gibibytes (2³⁰ bytes). 16 GB decimal ≈ 14.9 GiB binary. Both are "right"; the units differ. The Day 4 lesson (binary and data representation) covers this properly.
Tests fail with no field is left 'unknown'
That check is telling you an exercise is still unfinished — search the starter for "unknown" and complete the remaining assignments.
Windows: bash is not recognized
Use WSL (wsl --install, then open Ubuntu and follow the Linux path), or skip the script and run the PowerShell equivalents from the lesson's hands-on section, filling the worksheet manually.
Security notes
Security notes — Day 001 lab
- What the scripts do: read system information (
sysctl,lscpu,df,/proc,/etc/os-release) and print it. They make no network connections, write no files, and change no settings. - Privileges: everything runs as your normal user. Nothing in this lab needs
sudo; if any tutorial ever asks you tosudoa script you haven't read, that is your cue to stop and read it — a habit this course will reinforce. - Privacy: a machine profile (CPU, RAM, OS version) is mildly identifying and reveals patch level. Sharing it in a class forum is normally fine; avoid posting profiles of employer-managed machines, and never share serial numbers or hardware UUIDs (this lab deliberately does not collect them).
- Reading before running: both scripts are short and commented — read them first. Running unread shell scripts from the internet is one of the most common ways developers get compromised; the course's rule is that every lab script is small enough to read and understand before executing.