diff --git a/crates/engine/src/cmd/path.rs b/crates/engine/src/cmd/path.rs
--- a/crates/engine/src/cmd/path.rs
+++ b/crates/engine/src/cmd/path.rs
@@ -798,13 +798,21 @@ fn insert_anchor(s: &mut Session, p: &Value) -> Result<Value> {
     let si = usize_opt(p, "subpath", "path.insertAnchor")?.unwrap_or(0);
     let seg = p.get("segment").and_then(Value::as_u64).map(index).ok_or_else(|| bad("path.insertAnchor", "missing segment"))?;
     let t = number_or(p, "t", 0.5, "path.insertAnchor")?.clamp(0.0, 1.0);
-    let idx = s.edit("Add Anchor Point", |d, _| {
+    let idx = s.edit("Add Anchor Point", |d, sel| {
         let path = path_mut(d, id)?;
         let sp = path.subpaths.get_mut(si).ok_or_else(|| EngineError::Other("no such subpath".into()))?;
         if seg >= sp.segment_count() {
             return Err(EngineError::Other("no such segment".into()));
         }
-        Ok(sp.insert_anchor(seg, t))
+        let idx = sp.insert_anchor(seg, t);
+        // A path that wasn't selected becomes the selection, its new anchor direct-selected, so
+        // the point added shows and can be edited at once (#4237).
+        if !sel.contains(id) {
+            sel.clear();
+            sel.add(id);
+            sel.anchors.entry(id).or_default().insert((si, idx));
+        }
+        Ok(idx)
     })?;
     Ok(json!({ "anchor": idx }))
 }
diff --git a/crates/engine/src/tests/draw2.rs b/crates/engine/src/tests/draw2.rs
--- a/crates/engine/src/tests/draw2.rs
+++ b/crates/engine/src/tests/draw2.rs
@@ -1737,6 +1737,30 @@ fn remove_anchor_points_keeps_the_paths_closed() {
     assert_eq!(spec.menu, &["Object", "Path"][..]);
 }
 
+#[test]
+fn add_anchor_point_selects_the_path_it_was_added_to() {
+    // #4237: an anchor added to a path that wasn't selected selects that path, the new anchor
+    // direct-selected, so it shows at once; undo puts the old selection back. A path already
+    // selected (the Pen's Auto Add) keeps its selection.
+    let mut s = session();
+    let other = rect(&mut s, 300.0, 0.0, 50.0, 50.0);
+    let line = |s: &mut Session| {
+        NodeId(s.execute("path.create", &json!({"anchors": [{"x": 0, "y": 0}, {"x": 100, "y": 0}]})).unwrap()["id"].as_u64().unwrap())
+    };
+    let id = line(&mut s);
+    s.execute("select.set", &json!({"ids": [other.0]})).unwrap();
+    s.execute("path.insertAnchor", &json!({"id": id.0, "segment": 0, "t": 0.5})).unwrap();
+    assert_eq!(s.doc().unwrap().selection.objects, [id]);
+    assert_eq!(selected_anchors(&s, id), [(0, 1)]);
+    s.execute("edit.undo", &json!({})).unwrap();
+    assert_eq!(s.doc().unwrap().selection.objects, [other]);
+    let kept = line(&mut s);
+    s.execute("select.set", &json!({"ids": [kept.0]})).unwrap();
+    s.execute("path.insertAnchor", &json!({"id": kept.0, "segment": 0, "t": 0.5})).unwrap();
+    assert_eq!(s.doc().unwrap().selection.objects, [kept]);
+    assert!(selected_anchors(&s, kept).is_empty(), "a path selected as a whole stays so");
+}
+
 fn selected_anchors(s: &Session, id: NodeId) -> Vec<(usize, usize)> {
     s.doc().unwrap().selection.anchors.get(&id).map(|set| set.iter().copied().collect()).unwrap_or_default()
 }
