Conversation
Add -T/--tree-only flag to output just the file structure without file contents. This is useful for sharing project layout with LLMs without overwhelming context with full file contents. - Add CLI flag with short (-T) and long (--tree-only) forms - Add T keybinding to toggle tree-only mode in interactive TUI - Update markdown and text templates to conditionally render files - Update documentation with new option and example usage
- Add TestSetTreeOnlyMode to verify setter method - Add TestPrepareTemplateDataTreeOnly to verify empty files with structure - Add tree-only tests for markdown, text, and XML format renderers
Add FilePaths field to TemplateData to provide file paths independently of file contents. This allows XML format to build the directory structure correctly in tree-only mode when Files array is empty. - Add FilePaths to TemplateData struct - Populate FilePaths in PrepareTemplateData (always, not just tree-only) - Update XML format to use FilePaths for directory structure - Update tests to include and verify FilePaths field
📝 WalkthroughWalkthroughA new tree-only mode feature has been added that allows users to output only file structure without file contents. The feature is implemented via CLI flag (-T/--tree-only), keyboard toggle (T), and propagated through the generator and UI to conditionally skip file content collection and render only directory trees. Changes
Sequence DiagramsequenceDiagram
participant User
participant CLI
participant Config
participant Generator
participant Template
participant Output
User->>CLI: Invoke with -T flag (or press T key)
CLI->>Config: Set TreeOnly = true
Config->>Generator: SetTreeOnlyMode(true)
Generator->>Generator: Prepare TemplateData:<br/>Collect FilePaths<br/>Skip collectFiles()
Generator->>Template: Pass TemplateData with FilePaths<br/>Files remains empty
Template->>Template: Conditional rendering:<br/>{{if .Files}} skipped<br/>Directory tree from FilePaths rendered
Template->>Output: Render structure only<br/>(no file contents)
Output->>User: Display tree structure
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
internal/generator/generator.go (1)
205-208: Non-deterministic order ofFilePathsdue to map iteration.Iterating over
expandedSelection(a map) produces non-deterministic ordering. While this may not cause functional issues, it can lead to inconsistent output between runs, which could be problematic for diffing or reproducibility.🔎 Suggested fix to ensure deterministic ordering
filePaths := make([]string, 0, len(expandedSelection)) for path := range expandedSelection { filePaths = append(filePaths, path) } + sort.Strings(filePaths)You'll need to add
"sort"to the imports.cmd/grab/main.go (1)
221-221: Consider extracting parameters into a struct.The
runNonInteractivefunction now has 10 parameters, which can be difficult to maintain and prone to argument ordering mistakes. Consider grouping these into a configuration struct similar tomodel.Config.🔎 Example refactor
type nonInteractiveConfig struct { rootPath string filterMgr *filesystem.FilterManager outputPath string useTempFile bool formatName string skipRedaction bool resolveDeps bool maxDepth int maxFileSize int64 treeOnly bool } func runNonInteractive(cfg nonInteractiveConfig) { // ... }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
README.mdcmd/grab/main.gointernal/generator/format.gointernal/generator/formats/formats_test.gointernal/generator/formats/markdown.gointernal/generator/formats/text.gointernal/generator/formats/xml.gointernal/generator/generator.gointernal/generator/generator_test.gointernal/model/init_update.gointernal/model/model.gointernal/model/view.gointernal/ui/help.go
🧰 Additional context used
🧬 Code graph analysis (3)
internal/model/view.go (1)
internal/ui/styles.go (1)
GetStyleInfo(92-98)
internal/generator/formats/formats_test.go (4)
internal/generator/format.go (2)
TemplateData(14-18)FileData(6-11)internal/generator/formats/markdown.go (1)
MarkdownFormat(13-13)internal/generator/formats/text.go (1)
TxtFormat(14-14)internal/generator/formats/xml.go (1)
XMLFormat(15-15)
internal/generator/generator_test.go (4)
internal/generator/generator.go (1)
NewGenerator(34-54)internal/cache/manager.go (1)
ResetGlobalCache(29-31)internal/filesystem/gitignore.go (1)
NewGitIgnoreManager(25-51)internal/filesystem/filter.go (1)
NewFilterManager(12-16)
🔇 Additional comments (33)
internal/generator/formats/xml.go (1)
64-66: LGTM! Clean separation of structure and content.The switch from iterating over
data.Filestodata.FilePathsfor tree construction is correct. This enables the XML filesystem structure to be built in both standard mode (when Files contains content) and tree-only mode (when Files is empty but FilePaths is populated). The file content list at lines 79-85 correctly continues to usedata.Files.internal/generator/formats/markdown.go (1)
47-55: LGTM! Conditional rendering correctly implemented.The addition of
{{if .Files}}properly guards the "Project Files" section so it only renders when files are present. The double{{end}}{{end}}correctly closes both the{{range .Files}}loop and the{{if .Files}}conditional. This ensures tree-only mode outputs only the structure section.internal/generator/format.go (1)
17-17: LGTM! Clean extension of template data.The addition of the
FilePathsfield enables templates to access the list of file paths for structure-only rendering. This additive change maintains backward compatibility while supporting the new tree-only mode.internal/model/view.go (1)
356-359: LGTM! Consistent footer indicator pattern.The tree-only status indicator follows the established pattern used by the dependency and redaction indicators. The styling with
ui.GetStyleInfo()is consistent with other informational footer elements.README.md (4)
30-30: LGTM! Clear feature documentation.The tree-only mode feature is well-documented with a clear description of its purpose and use case.
112-112: LGTM! Complete flag documentation.The CLI flag documentation clearly explains the purpose and benefit of the tree-only mode.
182-186: LGTM! Practical usage example.The example demonstrates the correct combination of flags (
-T -n) for non-interactive tree-only output.
222-222: LGTM! Keyboard control documented.The keyboard shortcut is clearly documented with an accurate description of its behavior.
internal/ui/help.go (2)
24-24: LGTM! Help text consistent with implementation.The keyboard shortcut description accurately reflects the toggle behavior and is consistent with other mode toggles.
70-70: LGTM! Usage documentation complete.The CLI flag usage text is clear and aligns with the README documentation.
internal/generator/formats/text.go (1)
60-70: LGTM! Consistent conditional rendering across formats.The text format implements the same conditional rendering pattern as Markdown. The
{{if .Files}}guard ensures the "PROJECT FILES" section only appears when files are present, and the double{{end}}{{end}}correctly closes both the range and if blocks.internal/model/init_update.go (1)
474-482: LGTM! Clean toggle implementation.The "T" key handler follows the established pattern used by other mode toggles (dependency resolution at lines 434-442 and secret redaction at lines 464-473). The implementation correctly:
- Toggles the state
- Synchronizes with the generator via
SetTreeOnlyMode- Provides clear user feedback
- Refreshes the viewport
internal/generator/generator.go (4)
29-29: LGTM!The
TreeOnlyfield is appropriately added as an exported boolean, consistent with other mode flags likeRedactSecrets.
79-82: LGTM!The
SetTreeOnlyModemethod follows the same pattern asSetRedactionMode, providing a clean API for toggling tree-only output.
225-227: LGTM!The conditional skip of
collectFileswhenTreeOnlyis enabled correctly implements the tree-only behavior while still building the structure tree. This preserves the secret scanning loop below (which will simply iterate over an empty slice).
244-248: LGTM!
FilePathsis correctly included in the returnedTemplateData, enabling formats (particularly XML) to build directory structures even when file contents are not collected.internal/generator/generator_test.go (3)
154-158: LGTM!Good addition to verify that
FilePathsis populated alongsideFilesin the normal (non-tree-only) mode.
222-238: LGTM!Thorough test coverage for
SetTreeOnlyModeverifying the default value and toggle behavior in both directions.
240-294: LGTM!Comprehensive test for tree-only mode that validates:
- Structure is generated (non-empty)
- Files slice is empty (no content collected)
- FilePaths is still populated for XML format support
The inline comment on line 290 clarifies the design intent.
internal/model/model.go (4)
73-73: LGTM!The unexported
treeOnlyfield appropriately encapsulates the tree-only state within the Model.
91-91: LGTM!The exported
TreeOnlyfield inConfigallows external configuration of the tree-only mode.
198-198: LGTM!Correctly propagates the
TreeOnlyconfiguration to the generator during model initialization.
231-231: LGTM!The model's internal
treeOnlystate is properly initialized from the config, enabling UI features like the footer indicator.internal/generator/formats/formats_test.go (5)
156-158: LGTM!Good update to include
FilePathsin the standard test data, ensuring existing tests remain valid with the new field.
160-166: LGTM!Well-structured helper function that creates tree-only test data with:
- Non-empty
Structurefor the tree display- Empty
Filesslice (no content)- Populated
FilePathsfor XML directory building
168-189: LGTM!Good test coverage for Markdown tree-only mode, verifying the structure header is present while the files section is absent.
191-212: LGTM!Appropriate test for text format tree-only mode, mirroring the Markdown test structure.
214-246: LGTM!Thorough XML tree-only test that validates:
- XML header and project tags are present
- Directory structure is built from
FilePaths(e.g.,<directory name="src">)- File entries appear in the filesystem section
- No
<file path=content elements are renderedcmd/grab/main.go (5)
53-53: LGTM!Variable declaration for the new tree-only flag.
96-98: LGTM!Clear flag definitions with both long (
--tree-only) and short (-T) forms, consistent with CLI conventions.
194-194: LGTM!The
treeOnlyflag is correctly passed to the non-interactive execution path.
208-208: LGTM!The
TreeOnlyconfiguration is properly set for the interactive (TUI) mode.
309-309: LGTM!Correctly enables tree-only mode on the generator in the non-interactive path.
Overview
Adds a new tree-only mode (
-T/--tree-onlyflag) that outputs only the file structure without file contents. This is useful for sharing project layouts with LLMs when you want to provide context about code organization without consuming tokens on file contents.Motivation
When working with LLMs, there are scenarios where you want to share your project structure to help the model understand the codebase organization, without needing the actual file contents. This saves significant tokens and provides a quick way to communicate project layout.
Resolves #22
Changes
CLI & Configuration
-T/--tree-onlyflags tocmd/grab/main.gomodel.ConfigwithTreeOnlyfieldrunNonInteractive()to support tree-only modeGenerator
TreeOnlyfield toGeneratorstructSetTreeOnlyMode()methodFilePathsfield toTemplateDatafor XML format supportPrepareTemplateData()to skip file content collection in tree-only modeOutput Formats
{{if .Files}}conditional to hide "Project Files" section{{if .Files}}conditional to hide "PROJECT FILES" sectionFilePathsfor building directory structure (works in both modes)TUI
Tkey binding to toggle tree-only modeDocumentation
grab -T -nTkeyBreaking Changes
None
Testing
TestSetTreeOnlyMode- verifies mode togglingTestPrepareTemplateDataTreeOnly- verifies generator produces structure without file contentsTestMarkdownFormatTreeOnly- verifies markdown output excludes file sectionTestTxtFormatTreeOnly- verifies text output excludes file sectionTestXMLFormatTreeOnly- verifies XML output has filesystem structure but no file contents./grab -T -nproduces structure-only outputSummary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.