Skip to content

feat: add stdin support for CLI using temp-file approach#68

Open
mvance wants to merge 13 commits intosteipete:mainfrom
mvance:feature/stdin-temp-file-support
Open

feat: add stdin support for CLI using temp-file approach#68
mvance wants to merge 13 commits intosteipete:mainfrom
mvance:feature/stdin-temp-file-support

Conversation

@mvance
Copy link
Contributor

@mvance mvance commented Feb 7, 2026

Summary

This PR adds stdin support to the summarize CLI, allowing users to pipe content directly into the tool using - as the input argument. This is particularly useful for summarizing clipboard content and integrating with shell workflows.

Changes

Core Implementation

  • Extended InputTarget type to include { kind: 'stdin' } in src/content/asset.ts
  • Added stdin resolution in resolveInputTarget() to recognize - (including surrounding whitespace) as stdin input
  • Implemented stdin processing in runCli() using temp-file approach:
    • Reads stdin content into a temporary file with secure permissions (0o600)
    • Processes via existing handleFileInput logic to minimize code duplication
    • 50MB size limit to prevent memory issues
    • Automatic cleanup in finally block
    • Uses injected stdin from RunEnv (falls back to process.stdin)
  • Updated help text to document stdin support in argument descriptions and examples

Error Handling

  • Clear error for empty stdin: "Stdin is empty"
  • Clear error for oversized input: "Stdin content exceeds maximum size of 50.0MB"
  • Clear error for --extract with stdin: "--extract is not supported for piped stdin input"
  • Updated error for --markdown-mode restrictions with better messaging

Documentation

  • Updated README.md with stdin section including examples and 50MB size limit note
  • Added stdin examples to both rich and concise help text
  • Focused examples on practical use case: pbpaste | summarize -

Testing

  • Added comprehensive stdin resolution tests in tests/input.resolve-input-target.test.ts
  • Created new tests/cli.stdin.test.ts with 6 tests covering:
    • Empty stdin handling (completely empty and whitespace-only)
    • --extract flag rejection with stdin
    • --markdown-mode llm allowance for stdin
    • --markdown-mode readability rejection for stdin
    • Basic stdin processing without errors
  • All tests pass (39 total across related test suites)

Usage Examples

# Summarize clipboard content
pbpaste | summarize -

# Pipe command output
echo "Meeting notes..." | summarize -

# With options
pbpaste | summarize - --length short

Technical Details

  • Temp file approach: Reuses existing handleFileInput logic, minimizing changes and maintaining consistency
  • Size limit: 50MB maximum to prevent OOM issues
  • Security: Temp files created with 0o600 permissions
  • Cleanup: Automatic removal in finally block prevents temp file accumulation
  • Unix convention: Uses standard - to represent stdin
  • Compatibility: No breaking changes; existing file and URL inputs work unchanged

Performance

  • Streaming size check prevents loading oversized content into memory
  • Efficient Buffer handling with minimal copying
  • Random filename suffix prevents collisions

Future Enhancements

This PR lays groundwork for future transcript markdown formatting support via --markdown-mode llm for stdin/file inputs.

Verification

  • ✅ All existing tests pass (no regressions)
  • ✅ New tests added and passing
  • ✅ Build compiles successfully
  • ✅ Linting passes (0 errors)
  • ✅ Manual testing confirms proper behavior

CI Status Note

The extension-e2e test failures shown in CI are pre-existing flaky tests that are also failing on the main branch. These failures are unrelated to the stdin support changes in this PR. The extension E2E tests involve Chrome browser automation that is sensitive to timing and environment conditions.

All relevant unit tests pass successfully:

  • test (22): ✅ Pass
  • test (24): ✅ Pass
  • GitGuardian Security Checks: ✅ Pass

Related

This implements stdin support using the temp-file approach, which keeps the implementation simple while enabling powerful shell integration workflows.

mvance added 13 commits February 6, 2026 14:25
- Extend InputTarget type to include { kind: 'stdin' }
- Add resolveInputTarget handling for '-' input
- Implement stdin processing in runCli with temp file cleanup
- Update help text to document stdin support
- Add comprehensive tests for stdin functionality
- Follow existing error handling patterns
- Reuse handleFileInput logic for minimal changes
- Fix import duplication: use fs.readFile consistently
- Optimize Buffer handling in streamToString function
- Fix edge case: check for existing file named '-' before treating as stdin
- Add test file cleanup with afterAll hook
- Add streaming size limit check to prevent OOM (50MB max)
- Update README with stdin documentation and examples
- Add stdin examples to CLI help text
- Improve error messages for stdin size limits
- Fix help text: change --length bullet to valid --length short preset
- Add stdin to RunEnv type for dependency injection
- Use injected stdin from RunEnv instead of hardcoded process.stdin
- Handle false return from handleFileInput with explicit error
- Add random suffix to temp file name for uniqueness
- Fix fragile test assertion to properly verify stdin processing
- Add stdin-specific error message when using --extract with piped input
- Update test to expect new error message
- Optimize streamToString to avoid redundant Buffer copying when chunk is already a Buffer
- Remove cat file.txt | summarize - example from help.ts and README.md
  (passing filename directly is more practical)
- Remove curl -s https://example.com | summarize - example
  (summarize can fetch URLs directly)
- Remove cat file.txt | summarize - from concise help
- Remove LESSONS_LEARNED.md (not intended for upstream)
- Keep pbpaste | summarize - as primary stdin example
  (this is the most useful real-world use case)
- Update restriction to allow --markdown-mode llm for stdin and file inputs
- Reject other markdown modes (readability, auto, off) with clear error message
- Add tests for --markdown-mode llm allowance and other mode restrictions
- Error message indicates --markdown-mode llm transcript formatting is coming soon
- Follows CodeRabbit recommendation to support --markdown-mode llm use case
The third guard was contradicting the intended logic:
- First guard: Allow URL/file/stdin
- Second guard: Only allow llm mode for file/stdin
- Third guard (BUG): Rejected file inputs even with llm mode

Removed the redundant third guard since the first guard already restricts
to URL/file/stdin, making the third guard unreachable and buggy.

CodeRabbit issue: #3 (comment)
- Update README.md to remove 'file contents' from notes (removed examples)
- Fix awkward usage string in concise help: <url-or-file-or--> -> <input>
- Clarify --markdown-mode error message for file/stdin inputs
- Update test expectation for new error message
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant