Skip to content

Commit 6d2ff99

Browse files
groksrcclaude
andcommitted
fix(cli): plain read-note renders the payload faithfully, no decoration
Drop the synthesized title/permalink header and the (no content) placeholder: plain mode is the content verbatim (note body, or the literal file with --include-frontmatter). Decoration belongs to the Rich path. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: Drew Cain <groksrc@gmail.com>
1 parent cab4bf1 commit 6d2ff99

2 files changed

Lines changed: 18 additions & 31 deletions

File tree

src/basic_memory/cli/commands/tool.py

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -389,28 +389,20 @@ def _plain_search_results(result: dict[str, Any], query: str = "") -> None:
389389
print(f" {snippet}")
390390

391391

392-
def _plain_read_note(result: dict[str, Any], *, include_frontmatter: bool = False) -> None:
393-
"""Render read-note as a plain title/permalink header, optional frontmatter, then body."""
394-
title = result.get("title", "")
395-
permalink = result.get("permalink", "")
392+
def _plain_read_note(result: dict[str, Any]) -> None:
393+
"""Render read-note content faithfully: the note body, or the literal file.
394+
395+
Plain mode adds NO decoration: no header line, no synthesized frontmatter
396+
block, no placeholder for empty notes. Without --include-frontmatter the
397+
API returns the note body; with it, the literal file (frontmatter block
398+
included). Either is printed verbatim, trimmed only of the surrounding
399+
newline artifacts the API keeps from frontmatter stripping, so the output
400+
round-trips (e.g. ``read-note X --plain --include-frontmatter > note.md``).
401+
"""
396402
content = result.get("content", "")
397-
398-
# Trigger: --include-frontmatter makes the API return the literal file
399-
# (frontmatter block included) as content.
400-
# Why: plain mode should show that file verbatim -- the file's own
401-
# frontmatter already carries title/permalink, so a header line and a
402-
# synthesized key/value block would both duplicate it.
403-
# Outcome: with the flag, emit ONLY the file; without it, a title/permalink
404-
# header then the body, trimmed to keep the gap a single blank line.
405-
if not include_frontmatter:
406-
header = f"{title} [{permalink}]" if permalink else title
407-
print(header)
408-
print()
409403
body = content.strip("\n") if content else ""
410404
if body:
411405
print(body)
412-
else:
413-
print("(no content)")
414406

415407

416408
def _plain_build_context(result: dict[str, Any]) -> None:
@@ -679,7 +671,7 @@ def read_note(
679671
if mode == "json" or isinstance(result, str):
680672
_print_json(result)
681673
elif mode == "plain":
682-
_plain_read_note(result, include_frontmatter=include_frontmatter)
674+
_plain_read_note(result)
683675
else:
684676
_display_read_note(result, include_frontmatter=include_frontmatter)
685677
except ValueError as e:

tests/cli/test_cli_tool_rich_output.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -755,19 +755,14 @@ def test_search_notes_plain_empty(mock_mcp):
755755
return_value=READ_NOTE_RESULT,
756756
)
757757
def test_read_note_plain_output(mock_mcp):
758-
"""read-note --plain emits a header line and the raw markdown body."""
758+
"""read-note --plain emits the note body faithfully, with no decoration."""
759759
result = _tty_runner(["tool", "read-note", "test-note", "--plain"])
760760

761761
assert result.exit_code == 0, f"CLI failed: {result.output}"
762-
assert "Test Note [notes/test-note]" in result.output
763-
# Raw markdown body, not Rich-rendered
764-
assert "# Test Note" in result.output
765-
assert "hello world" in result.output
766-
# No frontmatter without the flag
767-
assert "tags:" not in result.output
768-
# Exactly one blank line between header and body: the payload's leading
769-
# newline (frontmatter-strip artifact) must not stack with the renderer's.
770-
assert "Test Note [notes/test-note]\n\n# Test Note" in result.output
762+
# No synthesized header line -- plain mode is the payload, faithfully.
763+
assert "[notes/test-note]" not in result.output
764+
# The body verbatim, trimmed of the API's frontmatter-strip newline artifact.
765+
assert result.output == "# Test Note\n\nhello world\n"
771766

772767

773768
@patch(
@@ -798,11 +793,11 @@ def test_read_note_plain_include_frontmatter(mock_mcp):
798793
return_value={"title": "", "permalink": "", "content": "", "frontmatter": {}},
799794
)
800795
def test_read_note_plain_empty_content(mock_mcp):
801-
"""read-note --plain handles empty content."""
796+
"""read-note --plain prints nothing for an empty note (no placeholder)."""
802797
result = _tty_runner(["tool", "read-note", "empty-note", "--plain"])
803798

804799
assert result.exit_code == 0, f"CLI failed: {result.output}"
805-
assert "(no content)" in result.output
800+
assert result.output == ""
806801

807802

808803
@patch(

0 commit comments

Comments
 (0)