# Os Lens

> Use when the student wants to see what the OS does when Python code runs. Wraps dis, sys.settrace, tracemalloc, strace, and /proc inspection. Invoke with /os-lens.

- Skill: `aman-bhandari/os-lens` (Agent Skill)
- Install (CLI): `npx skillmds@latest add aman-bhandari/os-lens`
- Raw SKILL.md: https://api.skillmd.com/api/skills/aman-bhandari/os-lens/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: aman-bhandari (https://skillmd.com/u/aman-bhandari)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/aman-bhandari/os-lens

---


# OS Lens -- See Inside the Machine

Tools for making the invisible visible. When the student asks "what actually happens when this runs?" -- this skill provides the instruments.

## Trigger

- `/os-lens` command
- Student asks to see bytecode, memory allocation, syscalls, or execution trace
- During systems-trace Layer 2 verification when the student wants proof

## Available Instruments

### 1. Bytecode Disassembly (`dis` module)

Shows what the CPython compiler produces. Every Python statement becomes bytecode instructions that the interpreter loop executes.

**Usage:**
```python
import dis
dis.dis(function_name)
```

**When to use:** Understanding what `for`, `with`, `yield`, `async` actually compile to. Settling debates about "which is faster." Seeing that `a + b` is `BINARY_ADD` but `a += b` is `BINARY_ADD` + `STORE_NAME` (or `STORE_FAST` in a function -- different!).

**Coach creates a scratch file** at `topics/topic-N/scratch/dis_inspect.py` with the function to disassemble. Student runs it, reads the output, explains what each opcode does.

### 2. Execution Tracing (`sys.settrace`)

Shows every function call, line execution, and return -- the actual execution path, not what you think happens.

**Usage:**
```python
import sys

def tracer(frame, event, arg):
    if event in ('call', 'return'):
        print(f"{event:8s} {frame.f_code.co_filename}:{frame.f_lineno} {frame.f_code.co_name}")
    return tracer

sys.settrace(tracer)
# ... run the code ...
sys.settrace(None)
```

**When to use:** Understanding decorator execution order, context manager flow, exception propagation path, generator suspend/resume. Seeing that `import` triggers execution of the module's top-level code.

**Warning:** Massive output on real code. Always use on small, isolated examples. Remove before any performance measurement (settrace adds ~10x overhead).

### 3. Memory Allocation Tracking (`tracemalloc`)

Shows where Python allocates memory and how much.

**Usage:**
```python
import tracemalloc

tracemalloc.start()
# ... run the code ...
snapshot = tracemalloc.take_snapshot()
for stat in snapshot.statistics('lineno')[:10]:
    print(stat)
```

**When to use:** Finding memory leaks, comparing list vs generator vs numpy memory footprint, understanding why RSS grows, identifying which line allocates the most.

**Pair with:** `resource.getrusage(resource.RUSAGE_SELF).ru_maxrss` for peak RSS (OS-level, includes C extensions that tracemalloc cannot see).

### 4. Syscall Tracing (`strace`)

Shows every syscall the Python process makes to the kernel. The ground truth of what the OS does.

**Usage (from shell):**
```bash
strace -f -e trace=open,read,write,mmap,close python3 script.py 2>&1 | head -100
```

**Common filters:**
- `-e trace=network` -- socket, connect, sendto, recvfrom
- `-e trace=memory` -- mmap, munmap, brk, mprotect
- `-e trace=file` -- open, close, read, write, stat
- `-e trace=process` -- fork, clone, execve, wait4
- `-f` -- follow child processes (essential for multiprocessing)

**When to use:** Verifying Layer 2 claims ("does `open()` really call `openat()`?"), diagnosing fd leaks, seeing what happens during `import`, understanding why a program is slow (blocked in `read()` vs busy in CPU).

**Note:** `strace` may not be available in all environments. Check with `which strace`. If unavailable, use `ltrace` for library calls or `/proc` inspection.

### 5. Process Memory Map (`/proc/self/maps`)

Shows the virtual memory layout of the running process.

**Usage:**
```python
with open('/proc/self/maps') as f:
    for line in f:
        print(line, end='')
```

**What you see:** Stack, heap, mmap'd files, shared libraries (.so), [vdso], [vsyscall]. Each line shows address range, permissions (rwxp), offset, device, inode, pathname.

**When to use:** Understanding where Python objects live (heap), where C extension code lives (mmap'd .so files), how large the stack is, what shared libraries are loaded. Seeing that `import numpy` maps ~30MB of .so files.

**Pair with:** `/proc/self/status` for VmRSS (resident), VmSize (virtual), VmPeak, Threads count.

### 6. File Descriptor Inspection (`/proc/self/fd`)

Shows all open file descriptors.

**Usage (from shell):**
```bash
ls -la /proc/$(pgrep -f script.py)/fd
```

**Or from Python:**
```python
import os
for fd in os.listdir('/proc/self/fd'):
    try:
        print(f"fd {fd} -> {os.readlink(f'/proc/self/fd/{fd}')}")
    except OSError:
        pass
```

**When to use:** Diagnosing fd leaks, verifying that `with` statements actually close files, seeing socket connections, understanding what stdin/stdout/stderr (0/1/2) point to.

## Session Flow

When the student invokes `/os-lens`:

1. **Ask what they want to see.** "What code are you curious about? What question are you trying to answer?"
2. **Pick the right instrument.** Don't use all of them -- pick the one that answers the question.
3. **Coach creates the inspection script** in `topics/topic-N/scratch/`. The student runs it.
4. **Student reads and explains the output.** Coach does not interpret for them. "What do you see? What does that tell you?"
5. **Connect to the three layers.** "Now you've seen Layer 2 directly. How does this change your mental model?"

## Rules

- Always create scratch files for inspection -- never instrument exercise code directly.
- Clean up scratch files after inspection (or keep them if the student wants a reference).
- Start with the simplest instrument. `dis` before `strace`. `tracemalloc` before `/proc/maps`.
- The goal is understanding, not exhaustive profiling. One instrument, one question, one answer.
- If the student wants to go deep into a specific instrument, that's exploration mode -- capture the artifact.

