Skip to content

Commit 1ed3c0f

Browse files
matthewwilsonclaude
andcommitted
Cross-platform compatibility: macOS + Windows support
- Replace sqlite3 exercise with curl in Lesson 14 (curl ships on both platforms) - Rewrite validate-14.sh to check api-response.json using Node.js instead of sqlite3 - Add Windows key bindings (Win+Shift+S, Ctrl+Click) to Lesson 15 - Fix Unix-centric language in Lesson 13 ("Unix tools" → "command-line tools") - Update graduation bonus challenge #5 to reference curl/GitHub MCP instead of sqlite3 - Update README with cross-platform install instructions and Git Bash prerequisite Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent eb0c253 commit 1ed3c0f

6 files changed

Lines changed: 40 additions & 31 deletions

File tree

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,20 @@ An interactive, hands-on tutorial for learning Claude Code — built entirely in
44

55
## Prerequisites
66

7-
- [Claude Code](https://claude.anthropic.com/claude-code) installed (`npm install -g @anthropic-ai/claude-code`)
8-
- Node.js 18 or later
97
- An Anthropic account (authenticated with Claude Code)
8+
- **Windows only:** [Git for Windows](https://git-scm.com/download/win) (provides Git Bash, which Claude Code requires)
9+
10+
## Install Claude Code
11+
12+
**macOS / Linux:**
13+
```bash
14+
curl -fsSL https://claude.ai/install.sh | bash
15+
```
16+
17+
**Windows (PowerShell):**
18+
```powershell
19+
irm https://claude.ai/install.ps1 | iex
20+
```
1021

1122
## Getting Started
1223

tutorial/lessons/13-headless-mode.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Claude processes the prompt, prints the result, and exits. No interactive UI, no
1818

1919
### Piping input
2020

21-
Combine Claude with standard Unix tools:
21+
Combine Claude with standard command-line tools:
2222

2323
```bash
2424
cat error.log | claude -p "explain this error and suggest a fix" > summary.txt

tutorial/lessons/14-cli-tools-and-mcp.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,19 @@ Here's a decision framework:
8181

8282
Let's see Claude use a CLI tool for data work. Ask Claude:
8383

84-
> "Create a SQLite database at `exercises/sample-app/tasks.db` with a `tasks` table matching our Task interface (id, title, priority, completed, createdAt). Insert at least three sample tasks with different priorities. Then query the database to show what's in it."
84+
> "Use curl to fetch todos from `https://jsonplaceholder.typicode.com/todos?_limit=5`, save the response to `exercises/sample-app/api-response.json`, then analyze the data — how many are completed vs incomplete?"
8585
86-
This demonstrates Claude using `sqlite3` — a non-code-editing CLI tool — to create and populate a real database. Watch how Claude translates the Task interface into SQL and handles the data types.
86+
This demonstrates Claude using `curl` — a non-code-editing CLI tool — to fetch real API data and work with it. Watch how Claude runs the command, saves the output, and reasons about the JSON response.
8787

8888
## Hints
8989

90-
- Ask Claude to show you the exact `sqlite3` commands it plans to run before executing them, so you can understand how it maps the Task interface to SQL.
91-
- If `sqlite3` isn't found, have Claude help you install it or adjust your PATH, then retry the exercise.
92-
- After Claude creates the database, have it run a `SELECT * FROM tasks;` query to verify that your sample rows were inserted correctly.
90+
- If you want to see what Claude is doing step by step, ask it to explain each command before running it.
91+
- `curl` is pre-installed on both macOS and Windows 10+, so this should work on any modern system.
92+
- After Claude saves the file, have it read back the JSON and summarize what it contains.
9393

9494
## Completion Criteria
9595

96-
- A SQLite database file exists at `exercises/sample-app/tasks.db`.
97-
- The database contains a `tasks` table matching the Task interface.
98-
- The `tasks` table contains at least three rows of data.
96+
- A JSON file exists at `exercises/sample-app/api-response.json`.
97+
- The file contains valid JSON with at least one entry.
9998

10099
When you're done, type `/next` to continue.

tutorial/lessons/15-working-with-images.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ You can include multiple images in a single conversation. For example:
3232
3333
### Image references
3434

35-
When Claude mentions an image in its response, you can `Cmd+Click` (Mac) or `Ctrl+Click` (Linux) the reference to open it.
35+
When Claude mentions an image in its response, you can `Ctrl+Click` (Windows/Linux) or `Cmd+Click` (Mac) the reference to open it.
3636

3737
## Exercise
3838

3939
**Try providing an image to Claude.**
4040

4141
Option A — If you have a screenshot handy:
42-
- Take a screenshot of anything (`Cmd+Shift+4` on Mac) and paste it with `Ctrl+V` / `Cmd+V`
42+
- Take a screenshot (`Cmd+Shift+4` on Mac, `Win+Shift+S` on Windows) and paste it with `Ctrl+V` / `Cmd+V`
4343
- Ask Claude to describe what it sees
4444

4545
Option B — Reference a file path:
@@ -50,7 +50,7 @@ Option C — Just read:
5050

5151
## Hints
5252

53-
1. The easiest approach: take a screenshot of this terminal right now (`Cmd+Shift+4` on Mac), then paste it into Claude and ask "what do you see?"
53+
1. The easiest approach: take a screenshot of this terminal right now (`Cmd+Shift+4` on Mac, `Win+Shift+S` on Windows), then paste it into Claude and ask "what do you see?"
5454
2. Claude can read most common image formats: PNG, JPG, GIF, WebP
5555
3. This is about knowing the capability exists — you'll use it naturally when you encounter a visual debugging situation
5656

tutorial/lessons/16-graduation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Pick a small feature — for example, "sort tasks by priority". Ask me to implem
4646

4747
### 5. MCP Integration
4848

49-
In Lesson 14 you used `sqlite3` via the CLI to create a database. Now try configuring the [SQLite MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/sqlite) in `.claude/settings.json` and using it to query the same database. Compare the experience — how does structured tool access differ from raw CLI? When would you prefer one over the other?
49+
In Lesson 14 you used `curl` via the CLI to fetch API data. Now try configuring the [GitHub MCP server](https://github.com/modelcontextprotocol/servers/tree/main/src/github) in `.claude/settings.json` and using it to list issues or PRs on a repo. Then do the same thing with the `gh` CLI. Compare the experience — how does structured MCP tool access differ from raw CLI? When would you prefer one over the other?
5050

5151
## Common Frustrations (and What to Do)
5252

tutorial/validators/validate-14.sh

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,33 @@
11
#!/usr/bin/env bash
22
# Validator for Lesson 14: CLI Tools & MCP Servers
3-
# Checks that tasks.db exists with a tasks table and at least one row.
3+
# Checks that api-response.json exists with valid JSON content.
44

55
set -euo pipefail
66

77
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
88
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
9-
DB_FILE="$REPO_ROOT/exercises/sample-app/tasks.db"
9+
JSON_FILE="$REPO_ROOT/exercises/sample-app/api-response.json"
1010

11-
# Check 1: tasks.db must exist
12-
if [ ! -f "$DB_FILE" ]; then
13-
echo "[LESSON 14] INCOMPLETE: exercises/sample-app/tasks.db does not exist"
11+
# Check 1: api-response.json must exist
12+
if [ ! -f "$JSON_FILE" ]; then
13+
echo "[LESSON 14] INCOMPLETE: exercises/sample-app/api-response.json does not exist"
1414
exit 1
1515
fi
16-
echo "[LESSON 14] tasks.db found"
16+
echo "[LESSON 14] api-response.json found"
1717

18-
# Check 2: Must contain a tasks table
19-
if sqlite3 "$DB_FILE" ".tables" 2>/dev/null | grep -q "tasks"; then
20-
echo "[LESSON 14] tasks table found"
21-
else
22-
echo "[LESSON 14] INCOMPLETE: tasks.db does not contain a 'tasks' table"
18+
# Check 2: Must contain valid JSON (use Node.js — guaranteed available)
19+
if ! node -e "JSON.parse(require('fs').readFileSync('$JSON_FILE', 'utf8'))" 2>/dev/null; then
20+
echo "[LESSON 14] INCOMPLETE: api-response.json does not contain valid JSON"
2321
exit 1
2422
fi
23+
echo "[LESSON 14] valid JSON"
2524

26-
# Check 3: Must have at least one row
27-
ROW_COUNT=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM tasks;" 2>/dev/null || echo "0")
28-
if [ "$ROW_COUNT" -ge 3 ]; then
29-
echo "[LESSON 14] tasks table has $ROW_COUNT row(s)"
25+
# Check 3: Must have at least one entry (array with length > 0)
26+
ENTRY_COUNT=$(node -e "const d = JSON.parse(require('fs').readFileSync('$JSON_FILE', 'utf8')); console.log(Array.isArray(d) ? d.length : 1)" 2>/dev/null || echo "0")
27+
if [ "$ENTRY_COUNT" -ge 1 ]; then
28+
echo "[LESSON 14] JSON contains $ENTRY_COUNT entry/entries"
3029
else
31-
echo "[LESSON 14] INCOMPLETE: tasks table has $ROW_COUNT row(s) — insert at least three sample tasks"
30+
echo "[LESSON 14] INCOMPLETE: api-response.json appears to be empty"
3231
exit 1
3332
fi
3433

0 commit comments

Comments
 (0)