diff --git a/pygittools/tui/worktree.py b/pygittools/tui/worktree.py
index 61a52c0..fc07176 100644
--- a/pygittools/tui/worktree.py
+++ b/pygittools/tui/worktree.py
@@ -34,9 +34,18 @@ def categorize_status(repo: Repository) -> tuple[list[str], list[str], list[str]
 	return staged, unstaged, untracked
 
 
+def _index_path(path: str) -> str:
+	"""Normalize a path for libgit2 index operations.
+
+	pygit2 reports untracked directories with a trailing slash, but
+	``index.add`` rejects those paths.
+	"""
+	return path.removesuffix("/")
+
+
 def stage_path(repo: Repository, path: str) -> None:
 	index = repo.index
-	index.add(path)
+	index.add(_index_path(path))
 	index.write()
 
 
@@ -45,7 +54,7 @@ def stage_paths(repo: Repository, paths: list[str]) -> None:
 		return
 	index = repo.index
 	for path in paths:
-		index.add(path)
+		index.add(_index_path(path))
 	index.write()
 
 
diff --git a/pygittools/tui/worktree_test.py b/pygittools/tui/worktree_test.py
new file mode 100644
index 0000000..bf827c5
--- /dev/null
+++ b/pygittools/tui/worktree_test.py
@@ -0,0 +1,69 @@
+from __future__ import annotations
+
+import subprocess
+from pathlib import Path
+
+import pytest
+from pygit2 import Repository, init_repository
+from pygit2.enums import FileStatus
+
+from pygittools.tui.worktree import categorize_status, stage_path, stage_paths
+
+
+@pytest.fixture
+def repo(tmp_path: Path) -> Repository:
+	repo_path = tmp_path / "repo"
+	repo_path.mkdir()
+	return init_repository(str(repo_path), bare=False)
+
+
+def _init_nested_repo(path: Path) -> None:
+	path.mkdir()
+	subprocess.run(["git", "init"], cwd=path, check=True, capture_output=True)
+	(path / "hello.txt").write_text("hello\n", encoding="utf-8")
+	subprocess.run(["git", "-C", str(path), "add", "hello.txt"], check=True, capture_output=True)
+	subprocess.run(
+		[
+			"git",
+			"-C",
+			str(path),
+			"-c",
+			"user.email=alice@example.com",
+			"-c",
+			"user.name=alice",
+			"commit",
+			"-m",
+			"init",
+		],
+		check=True,
+		capture_output=True,
+	)
+
+
+def test_stage_path_accepts_untracked_directory_trailing_slash(repo: Repository) -> None:
+	workdir = Path(repo.workdir)
+	_init_nested_repo(workdir / "nested")
+
+	_, _, untracked = categorize_status(repo)
+	assert untracked == ["nested/"]
+
+	stage_path(repo, untracked[0])
+
+	staged, _, remaining = categorize_status(repo)
+	assert staged == ["nested"]
+	assert remaining == []
+
+
+def test_stage_paths_accepts_untracked_directory_trailing_slash(repo: Repository) -> None:
+	workdir = Path(repo.workdir)
+	_init_nested_repo(workdir / "pkg")
+	(workdir / "loose.txt").write_text("x\n", encoding="utf-8")
+
+	_, _, untracked = categorize_status(repo)
+	assert set(untracked) == {"pkg/", "loose.txt"}
+
+	stage_paths(repo, untracked)
+
+	status = repo.status()
+	assert status["pkg"] & FileStatus.INDEX_NEW
+	assert status["loose.txt"] & FileStatus.INDEX_NEW
