feat: add export mode with showcase redaction to explain command#230
feat: add export mode with showcase redaction to explain command#230sunnypatneedi wants to merge 9 commits intoentireio:mainfrom
Conversation
Adds structured export functionality to the explain command for creating
portfolio-ready showcases of AI sessions with privacy-safe redaction.
Key additions:
- Export flags: --export, --showcase, --format (json/markdown), -o/--output
- Showcase redaction: pattern-based + structural + blocklist redaction
- Settings integration: showcase config in strategy_options
- Formatters: JSON and Markdown output formats
- Integration tests: full export workflow coverage
The showcase redaction applies aggressive privacy filters including:
- Pattern-based: URLs, IPs, DB strings, emails, JWTs, PEM keys, ARNs
- Structural: project-relative paths, project name normalization
- Blocklist: user-defined terms (company names, codenames)
- Entropy-based: existing secret detection
Configuration example in .entire/settings.json:
{
"strategy_options": {
"showcase": {
"redact_paths": true,
"redact_usernames": true,
"redact_project_info": true,
"allowed_paths": ["src/", "lib/"],
"custom_blocklist": ["company-name"]
}
}
}
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
55bd345 to
0ac238d
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 7 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| } | ||
| if (exportFormat != "" || outputFile != "") && !exportFlag { | ||
| return errors.New("--format and --output require --export flag") | ||
| } |
There was a problem hiding this comment.
Default format value breaks non-export explain command
High Severity
The --format flag has a default value of "json" (line 199), so exportFormat is never empty. The validation exportFormat != "" on line 170 is therefore always true, causing every non-export explain invocation (e.g., entire explain -c <id>) to fail with "--format and --output require --export flag". The check needs to use cmd.Flags().Changed("format") or set the default to "" instead.
Additional Locations (1)
| }) | ||
|
|
||
| return result | ||
| } |
There was a problem hiding this comment.
AllowedDomains broken by unconditional email redaction in redactPatterns
High Severity
redactPatterns unconditionally replaces all emails with [EMAIL] (line 172) before redactUsernames gets a chance to check AllowedDomains. By the time redactUsernames runs (line 52), no email patterns remain in the text to match, so the allowed-domains preservation logic never fires. The AllowedDomains configuration option is effectively non-functional.
Additional Locations (1)
| }) | ||
|
|
||
| return result | ||
| } |
There was a problem hiding this comment.
Path redaction drops leading slash from replacement
Medium Severity
homePathPattern matches the full prefix including the leading / (e.g., /Users/john), but redactFilePaths replaces the match with just [PATH] (no leading /). This means /Users/john/project/file.go becomes [PATH]/project/file.go instead of the intended /[PATH]/project/file.go. All test expectations for path redaction assume the leading slash is preserved, so they would fail.
| regexp.MustCompile(`git@[^:]+:[^/]+/[^\s.]+\.git`), | ||
| regexp.MustCompile(`https://[^/]+/[^/]+/[^\s.]+\.git`), | ||
| regexp.MustCompile(`https://[^/]+/[^/]+/[^\s/]+`), // GitHub/GitLab URLs without .git | ||
| } |
There was a problem hiding this comment.
Overly broad HTTPS URL pattern redacts non-git URLs
Medium Severity
The third git remote regex https://[^/]+/[^/]+/[^\s/]+ matches any HTTPS URL with two or more path segments, not just git remotes. This would incorrectly replace URLs like https://docs.example.com/guide/setup or https://api.stripe.com/v1/charges with [GIT_REMOTE]. The pattern also compiles new regexps on every call to redactProjectInfo.
|
|
||
| // Match word boundaries | ||
| return `\b` + result + `\b` | ||
| } |
There was a problem hiding this comment.
Glob wildcard * converts to greedy .* matching
High Severity
globToRegex converts the glob wildcard * to .* (greedy, matches any character including spaces). Combined with \b word-boundary anchoring, the pattern internal-* becomes \binternal-.*\b, which greedily matches from the first internal- all the way to the last word boundary in the string. For input "internal-api.company.com and internal-web.company.com", instead of producing two separate [REDACTED] replacements, the entire string is consumed as a single match. The * glob should map to something like [^\s]* (non-whitespace) to stay within token boundaries.
redact/showcase.go
Outdated
| emailPattern = regexp.MustCompile(`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`) | ||
|
|
||
| // AWS account IDs (12 digits in AWS context) | ||
| awsAccountPattern = regexp.MustCompile(`(?i)(aws|account|arn)[\s:][^\s]*?([0-9]{12})\b`) |
There was a problem hiding this comment.
AWS account pattern fails with space before digits
Medium Severity
The awsAccountPattern regex (aws|account|arn)[\s:][^\s]*?([0-9]{12}) uses [^\s]*? (non-whitespace chars, non-greedy) to bridge between the context word and the 12-digit ID. When the input is "AWS account: 123456789012", the space after the colon is whitespace, so [^\s]*? cannot advance past it and the 12-digit group is never reached. The pattern fails to match the common format where a space follows the colon, leaving the account ID unredacted.
| for i, path := range content.Metadata.FilesTouched { | ||
| filesTouched[i] = redact.Showcase(path, *showcaseConfig) | ||
| } | ||
| } |
There was a problem hiding this comment.
Summary fields bypass showcase redaction entirely
High Severity
In runExportCheckpoint, showcase redaction is applied to transcriptBytes, prompts, contextMd, and filesTouched, but the original content object is passed unmodified to the formatters. Both formatExportJSON and formatExportMarkdown then read content.Metadata.Summary fields (Intent, Outcome, Learnings, Friction, OpenItems) directly, completely bypassing redaction. AI-generated summaries can contain sensitive data like internal IPs, company names, or emails, which would appear unredacted in the showcase export.
Additional Locations (1)
…dback) Fixed all 7 issues reported by Cursor Bugbot: High Severity (4 issues): 1. Default format value breaks non-export explain command - Changed validation to use cmd.Flags().Changed() instead of checking empty string 2. AllowedDomains broken by unconditional email redaction - Moved email redaction from redactPatterns() to redactUsernames() 3. Glob wildcard greedy matching - Changed * expansion from .* to [\w-]* to stay within token boundaries 4. Summary fields bypass showcase redaction - Added redaction for all Summary struct fields (Intent, Outcome, Learnings, Friction, OpenItems) Medium Severity (3 issues): 5. Path redaction drops leading slash - Changed replacement from [PATH] to /[PATH] to preserve leading slash 6. Overly broad HTTPS URL pattern - Made GCP pattern more specific to require known resource types 7. AWS account pattern fails with space - Added separator capture group to preserve colons/spaces in replacement Also: - Fixed test failures caused by invalid checkpoint IDs (12-hex-char format) - Updated glob test to document Go regex limitation (no lookahead support) - Reordered redaction layers: paths → patterns → git remotes → emails → blocklist - Made AWS ARN pattern support optional account IDs (S3 ARNs) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Adds a new `entire insights` command that provides analytics and metrics across all sessions and checkpoints. Features: - Session statistics: count, duration, token usage aggregates - Top contributors by checkpoint count - Most active files across all sessions - Checkpoint distribution by strategy - Time-based analytics (sessions per day/week) - Filtering by date range, strategy, and file path - Multiple output formats: table, JSON, CSV - Caching for improved performance Usage: entire insights # Show all insights entire insights --sessions # Session statistics only entire insights --files # File activity only entire insights --format json # JSON output entire insights --since "7 days ago" # Filter by date entire insights --strategy manual-commit # Filter by strategy Implementation: - insights.go: Main command and CLI interface - insights_analytics.go: Core analytics calculations - insights_cache.go: Caching layer for performance - insights_filters.go: Filtering logic - insights_formatters.go: Output formatting (table/JSON/CSV) - insights_test.go: Unit tests - integration_test/insights_test.go: Integration tests Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Added json tags to all structs for proper marshaling - Fixed redefinition of built-in 'max' function (renamed to maxCount) - Converted if-else chain to switch statement in barChar - Added nolint comments for intentional patterns: * unparam: error returns kept for consistency * maintidx: high complexity acceptable for HTML formatting * gosec G602: safe array access with bounded loop * nilerr: intentional error ignoring in fallback logic - Fixed constant usage throughout insights.go (replaced string literals) - Fixed boolean expression in insights_test.go for better readability - Updated Long description and examples to match actual flag values - Removed duplicate unknownStrategyName constant declaration All lint checks now pass with 0 issues. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Renamed --formatJSON flag to --json for consistency with integration tests
- Updated error message to match flag name change
- Fixed integration test expectations:
* Changed expected JSON field names from PascalCase to snake_case
(to match the json tags: total_sessions, total_checkpoints, etc.)
* Updated mutually exclusive error check to accept Cobra's default
error message format
All integration tests now pass.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Renamed unused parameters to _ in formatExportJSON and formatExportMarkdown - Wrapped json.MarshalIndent error for proper error handling - Removed unnecessary string() conversions (Context is already string) - Added nolint comment for unparam in formatExportMarkdown All new lint issues resolved (0 new issues compared to main). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements two major enhancements to the explain command's export functionality: 1. Multi-session export with --all flag: - Export all checkpoints at once with `--all` - Filter by session using `--session` with `--all` - JSON array output format for multiple checkpoints - Markdown sections format for multiple checkpoints 2. Selective content export flags: - --no-prompts: Exclude prompts from export - --no-context: Exclude context.md from export - --no-transcript: Exclude transcript from export - --include-tool-calls: Extract and include tool calls separately - --include-file-diffs: Placeholder for future file diff inclusion Key changes: - Added exportOptions struct to control export content - Implemented extractToolCalls() to parse JSONL transcripts - Updated all formatters to respect content preferences - Added validation for conflicting flags - All unit tests pass Example usage: entire explain --export --all --session 2026-01-13 --showcase -o output.json entire explain -c abc123 --export --no-prompts --include-tool-calls -o output.json Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Entire-Checkpoint: 48304b2e0d3c
7a91302 to
e5b1078
Compare
🚀 Updated PR with Additional FeaturesI've added two major enhancements to this PR on top of the existing export/showcase functionality: ✅ 1. Multi-Session Export (
|


Summary
Companies are starting to ask for sessions for proof-of-work to evaluate orchestration mastery. This allows to export the session in a safe and secure way that showcases the judgement and skills of the individual building with agents.
Adds structured export functionality to the
explaincommand for creating portfolio-ready showcases of AI sessions with privacy-safe redaction.Key Changes
--export,--showcase,--format(json/markdown),-o/--outputstrategy_optionsUsage
```bash
Export with showcase redaction (privacy-safe)
entire explain -c --export --showcase --format=json -o showcase.json
Export as markdown for README
entire explain -c --export --showcase --format=markdown -o SHOWCASE.md
```
Configuration
```json
{
"strategy_options": {
"showcase": {
"redact_paths": true,
"redact_usernames": true,
"redact_project_info": true,
"allowed_paths": ["src/", "lib/"],
"custom_blocklist": ["company-name"]
}
}
}
```
Security Note
Always review output before publishing - redaction is best-effort and cannot guarantee 100% removal of all sensitive data.
Test Plan
redact/showcase_test.go)settings/settings_test.go)cli/explain_formatters_test.go)integration_test/explain_export_test.go)🤖 Generated with Claude Code
Note
Medium Risk
Touches user-facing CLI output and introduces new redaction logic; incorrect patterns or config parsing could leak sensitive data or over-redact shared content, though the feature is opt-in and well-tested.
Overview
Adds a new
entire explain --exportmode (checkpoint-only) that outputs a structured export injsonormarkdown, optionally writing to a file via-o/--output, and enforces clear flag validation/mutual exclusivity with existing transcript/verbosity/generation modes.Introduces showcase redaction (
--showcase) layered on top of existing entropy-based secret redaction, adding pattern/blocklist/structural redaction (e.g., internal URLs, private IPs, DB strings, emails/JWT/PEM, git remote URLs, user paths) and a new settings-backed config parser understrategy_options.showcase.Adds new formatter helpers plus unit and integration test coverage for export formats, settings parsing, and end-to-end redaction behavior, and documents the feature in
CLAUDE.md.Written by Cursor Bugbot for commit 0ac238d. This will update automatically on new commits. Configure here.