Skip to content

Commit 8cbea91

Browse files
authored
Merge pull request #19 from alexey1312/feature/toon
Add TOON format support with configurable output options
2 parents a348b4f + 9f47d8b commit 8cbea91

File tree

6 files changed

+700
-23
lines changed

6 files changed

+700
-23
lines changed

CLAUDE.md

Lines changed: 114 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ swift build 2>&1 | xcsift
3939
swift test 2>&1 | xcsift
4040

4141
# Print detailed warnings list (by default only warning count is shown in summary)
42-
swift build 2>&1 | xcsift --print-warnings
43-
xcodebuild build 2>&1 | xcsift --print-warnings
42+
swift build 2>&1 | xcsift --warnings
43+
xcodebuild build 2>&1 | xcsift --warnings
4444

4545
# Quiet mode - suppress output when build succeeds with no warnings or errors
4646
swift build 2>&1 | xcsift --quiet
@@ -75,6 +75,57 @@ xcodebuild test 2>&1 | xcsift --coverage --coverage-path path/to/file.xcresult
7575
# xcodebuild (.xcresult → JSON via xcrun xccov):
7676
# - ~/Library/Developer/Xcode/DerivedData/**/*.xcresult (searches automatically)
7777
# - Current directory/**/*.xcresult
78+
79+
# TOON format (30-60% fewer tokens for LLMs)
80+
# Token-Oriented Object Notation - optimized for LLM consumption
81+
82+
# Basic TOON output
83+
xcodebuild build 2>&1 | xcsift --format toon
84+
xcodebuild build 2>&1 | xcsift -f toon
85+
86+
# TOON with warnings
87+
swift build 2>&1 | xcsift -f toon --warnings
88+
xcodebuild build 2>&1 | xcsift -f toon -w
89+
90+
# TOON with coverage
91+
swift test --enable-code-coverage 2>&1 | xcsift -f toon --coverage
92+
xcodebuild test -enableCodeCoverage YES 2>&1 | xcsift -f toon -c
93+
94+
# Combine all flags
95+
xcodebuild test 2>&1 | xcsift -f toon -w -c --coverage-details
96+
97+
# TOON format features:
98+
# - 30-60% token reduction compared to JSON
99+
# - Tabular format for uniform arrays (errors, warnings, tests)
100+
# - Human-readable indentation-based structure
101+
# - Ideal for LLM consumption and API cost reduction
102+
# - Works with all existing flags (--quiet, --coverage, --warnings)
103+
104+
# TOON Configuration - customize delimiter and length markers
105+
106+
# Delimiter options (default: comma):
107+
# - comma: CSV-style format (default, most compact)
108+
# - tab: TSV-style format (better for Excel/spreadsheet import)
109+
# - pipe: Alternative separator (good for data with many commas)
110+
111+
# Tab delimiter - useful for Excel/spreadsheet import
112+
xcodebuild build 2>&1 | xcsift -f toon --toon-delimiter tab
113+
swift build 2>&1 | xcsift --format toon --toon-delimiter tab
114+
115+
# Pipe delimiter - alternative when data contains many commas
116+
xcodebuild test 2>&1 | xcsift -f toon --toon-delimiter pipe
117+
118+
# Length marker options (default: none):
119+
# - none: [3]{file,line,message}: (default, most compact)
120+
# - hash: [#3]{file,line,message}: (Ruby/Perl-style length prefix)
121+
122+
# Hash length marker - adds # prefix to array counts
123+
xcodebuild build 2>&1 | xcsift -f toon --toon-length-marker hash
124+
swift build 2>&1 | xcsift --format toon --toon-length-marker hash
125+
126+
# Combine configuration options
127+
xcodebuild test 2>&1 | xcsift -f toon --toon-delimiter tab --toon-length-marker hash -w -c
128+
swift test 2>&1 | xcsift -f toon --toon-delimiter pipe --toon-length-marker hash --coverage-details
78129
```
79130

80131
## Architecture
@@ -85,7 +136,7 @@ The codebase follows a simple two-component architecture:
85136

86137
1. **main.swift** - Entry point using Swift ArgumentParser
87138
- Reads from stdin and coordinates parsing/output
88-
- Outputs JSON format only
139+
- Outputs JSON or TOON format (controlled by `--format` / `-f` flag)
89140

90141
2. **OutputParser.swift** - Core parsing logic
91142
- `OutputParser` class with regex-based line parsing
@@ -98,7 +149,7 @@ The codebase follows a simple two-component architecture:
98149
1. Stdin input → `readStandardInput()`
99150
2. Raw text → `OutputParser.parse()` → line-by-line regex matching
100151
3. Parsed data → `BuildResult` struct
101-
4. Output formatting (JSON/compact) → stdout
152+
4. Output formatting (JSON or TOON) → stdout
102153

103154
### Key Features
104155
- **Error/Warning Parsing**: Multiple regex patterns handle various Xcode error formats
@@ -136,6 +187,12 @@ Tests are in `Tests/OutputParserTests.swift` using XCTest framework. Test cases
136187
- Target extraction from xcodebuild output
137188
- Coverage target filtering
138189
- Summary-only vs details mode for coverage output
190+
- **TOON format encoding** (8 tests):
191+
- Basic TOON encoding
192+
- TOON with errors, warnings, and failed tests
193+
- TOON with code coverage
194+
- Token efficiency verification (30-60% reduction)
195+
- Summary-only vs details mode in TOON format
139196

140197
Run individual tests:
141198
```bash
@@ -145,17 +202,20 @@ swift test --filter OutputParserTests.testParseError
145202
## Dependencies
146203

147204
- **Swift ArgumentParser**: CLI argument handling (Package.swift dependency)
205+
- **TOONEncoder**: Token-Oriented Object Notation encoder for efficient LLM output (Package.swift dependency)
148206
- **Foundation**: Core Swift framework for regex, JSON encoding, string processing
149207
- **XCTest**: Testing framework (test target only)
150208

151209
## Output Formats
152210

153-
The tool outputs structured data optimized for coding agents:
211+
The tool outputs structured data optimized for coding agents in two formats:
212+
213+
### JSON Format (default)
154214

155215
- **JSON**: Structured format with `status`, `summary`, `errors`, `warnings` (optional), `failed_tests`, `coverage` (optional)
156216
- **Summary always includes warning count**: `{"summary": {"warnings": N, ...}}`
157217
- **Summary includes coverage percentage** (when `--coverage` flag is used): `{"summary": {"coverage_percent": X.X, ...}}`
158-
- **Detailed warnings list** (with `--print-warnings` flag): `{"warnings": [{"file": "...", "line": N, "message": "..."}]}`
218+
- **Detailed warnings list** (with `--warnings` flag): `{"warnings": [{"file": "...", "line": N, "message": "..."}]}`
159219
- **Default behavior** (without flag): Only shows warning count in summary, omits detailed warnings array to reduce token usage
160220
- **Quiet mode** (with `--quiet` or `-q` flag): Produces no output when build succeeds with zero warnings and zero errors
161221
- **Coverage data** (with `--coverage` flag):
@@ -188,3 +248,51 @@ The tool outputs structured data optimized for coding agents:
188248
- Supports both SPM (`swift test --enable-code-coverage`) and xcodebuild (`-enableCodeCoverage YES`) formats
189249
- Automatically detects format and parses accordingly
190250
- Warns to stderr if target was detected but no matching coverage data found
251+
252+
### TOON Format (with `--format toon` / `-f toon` flag)
253+
254+
**TOON (Token-Oriented Object Notation)** is a compact serialization format optimized for LLM consumption, providing **30-60% token reduction** compared to JSON.
255+
256+
**Key Features:**
257+
- Tabular format for uniform arrays (errors, warnings, tests, coverage files)
258+
- Indentation-based structure (similar to YAML)
259+
- Human-readable while optimized for machine parsing
260+
- Works with all existing flags (`--quiet`, `--coverage`, `--warnings`)
261+
- Ideal for reducing LLM API costs
262+
263+
**Example TOON Output:**
264+
265+
```toon
266+
status: failed
267+
summary:
268+
errors: 1
269+
warnings: 3
270+
failed_tests: 0
271+
passed_tests: null
272+
build_time: null
273+
coverage_percent: null
274+
errors[1]{file,line,message}:
275+
main.swift,15,"use of undeclared identifier \"unknown\""
276+
warnings[3]{file,line,message}:
277+
Parser.swift,20,"immutable value \"result\" was never used"
278+
Parser.swift,25,"variable \"foo\" was never mutated"
279+
Model.swift,30,"initialization of immutable value \"bar\" was never used"
280+
```
281+
282+
**Token Efficiency Comparison:**
283+
284+
For the same build output with 1 error and 3 warnings:
285+
- **JSON**: 652 bytes
286+
- **TOON**: 447 bytes
287+
- **Savings**: 31.4% (205 bytes)
288+
289+
**When to Use TOON:**
290+
- Passing build output to LLM APIs (reduces costs)
291+
- Processing large build outputs with many errors/warnings
292+
- Automated CI/CD pipelines with LLM analysis
293+
- Token-constrained environments
294+
295+
**When to Use JSON:**
296+
- Integrating with existing JSON-based tooling
297+
- Maximum compatibility with JSON parsers
298+
- Pretty-printed output for human debugging

Package.resolved

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ let package = Package(
1515
],
1616
dependencies: [
1717
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.0.0"),
18+
.package(url: "https://github.com/mattt/TOONEncoder.git", from: "0.1.1"),
1819
],
1920
targets: [
2021
.executableTarget(
2122
name: "xcsift",
2223
dependencies: [
23-
.product(name: "ArgumentParser", package: "swift-argument-parser")
24+
.product(name: "ArgumentParser", package: "swift-argument-parser"),
25+
.product(name: "TOONEncoder", package: "TOONEncoder")
2426
]
2527
),
2628
.testTarget(

README.md

Lines changed: 106 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ A Swift command-line tool to parse and format xcodebuild/SPM output for coding a
88

99
## Features
1010

11-
- **Token-efficient JSON output** - Structured format optimized for coding agents
11+
- **Token-efficient output formats** - JSON (default) or TOON format (30-60% fewer tokens)
12+
- **TOON format support** - Token-Oriented Object Notation optimized for LLM consumption
1213
- **Structured error reporting** - Clear categorization of errors, warnings, and test failures
1314
- **File/line number extraction** - Easy navigation to problematic code locations
1415
- **Build status summary** - Quick overview of build results
@@ -81,9 +82,9 @@ Pipe xcodebuild output directly to xcsift:
8182
xcodebuild [flags] 2>&1 | xcsift
8283
```
8384

84-
**Important**: Always use `2>&1` to redirect stderr to stdout. This ensures all compiler errors, warnings, and build output are captured, removing noise and providing clean, structured JSON output.
85+
**Important**: Always use `2>&1` to redirect stderr to stdout. This ensures all compiler errors, warnings, and build output are captured, removing noise and providing clean, structured output.
8586

86-
Currently outputs JSON format only.
87+
Supports both **JSON** (default) and **TOON** formats.
8788

8889
### Examples
8990

@@ -92,7 +93,7 @@ Currently outputs JSON format only.
9293
xcodebuild build 2>&1 | xcsift
9394

9495
# Print detailed warnings list (useful for fixing warnings)
95-
xcodebuild build 2>&1 | xcsift --print-warnings
96+
xcodebuild build 2>&1 | xcsift --warnings
9697
xcodebuild build 2>&1 | xcsift -w
9798

9899
# Quiet mode - suppress output when build succeeds with no warnings or errors
@@ -120,6 +121,22 @@ xcodebuild test 2>&1 | xcsift
120121
# Swift Package Manager support
121122
swift build 2>&1 | xcsift
122123
swift test 2>&1 | xcsift
124+
125+
# TOON format (30-60% fewer tokens for LLMs)
126+
# Token-Oriented Object Notation - optimized for reducing LLM API costs
127+
xcodebuild build 2>&1 | xcsift --format toon
128+
xcodebuild build 2>&1 | xcsift -f toon
129+
130+
# TOON with warnings
131+
swift build 2>&1 | xcsift -f toon --warnings
132+
xcodebuild build 2>&1 | xcsift -f toon -w
133+
134+
# TOON with coverage
135+
swift test --enable-code-coverage 2>&1 | xcsift -f toon --coverage
136+
xcodebuild test -enableCodeCoverage YES 2>&1 | xcsift -f toon -c
137+
138+
# Combine all flags
139+
xcodebuild test 2>&1 | xcsift -f toon -w -c --coverage-details
123140
```
124141

125142
## Output Format
@@ -172,7 +189,7 @@ swift test 2>&1 | xcsift
172189
}
173190
```
174191

175-
**Note on warnings:** By default, only the warning count appears in `summary.warnings`. The detailed `warnings` array (shown above) is only included when using the `--print-warnings` flag. This reduces token usage for coding agents that don't need to process every warning.
192+
**Note on warnings:** By default, only the warning count appears in `summary.warnings`. The detailed `warnings` array (shown above) is only included when using the `--warnings` flag. This reduces token usage for coding agents that don't need to process every warning.
176193

177194
**Note on coverage:** The `coverage` section is only included when using the `--coverage-details` flag:
178195
- **Summary-only mode** (default): Only includes coverage percentage in summary for maximum token efficiency
@@ -187,14 +204,95 @@ swift test 2>&1 | xcsift
187204
- **Target filtering** (xcodebuild only): Automatically extracts tested target from stdout and shows coverage for that target only
188205
- xcsift automatically converts `.profraw` files (SPM) or `.xcresult` bundles (xcodebuild) to JSON format without requiring manual llvm-cov or xccov commands
189206

207+
### TOON Format
208+
209+
With the `--format toon` / `-f toon` flag, xcsift outputs in **TOON (Token-Oriented Object Notation)** format, which provides **30-60% token reduction** compared to JSON. This format is specifically optimized for LLM consumption and can significantly reduce API costs.
210+
211+
```toon
212+
status: failed
213+
summary:
214+
errors: 1
215+
warnings: 3
216+
failed_tests: 0
217+
passed_tests: null
218+
build_time: null
219+
coverage_percent: null
220+
errors[1]{file,line,message}:
221+
main.swift,15,"use of undeclared identifier \"unknown\""
222+
warnings[3]{file,line,message}:
223+
Parser.swift,20,"immutable value \"result\" was never used"
224+
Parser.swift,25,"variable \"foo\" was never mutated"
225+
Model.swift,30,"initialization of immutable value \"bar\" was never used"
226+
```
227+
228+
**TOON Benefits:**
229+
- **30-60% fewer tokens** - Reduces LLM API costs significantly
230+
- **Tabular format** - Uniform arrays (errors, warnings) shown as compact tables
231+
- **Human-readable** - Indentation-based structure similar to YAML
232+
- **Compatible** - Works with all existing flags (`--quiet`, `--coverage`, `--warnings`)
233+
234+
**Example token savings:**
235+
- Same build output (1 error, 3 warnings)
236+
- JSON: 652 bytes
237+
- TOON: 447 bytes
238+
- **Savings: 31.4%** (205 bytes)
239+
240+
### TOON Configuration
241+
242+
TOON format can be customized with delimiter and length marker options for different use cases:
243+
244+
**Delimiter Options** (`--toon-delimiter [comma|tab|pipe]`):
245+
- `comma` (default): CSV-style format, most compact
246+
```bash
247+
xcodebuild build 2>&1 | xcsift -f toon
248+
# Output: errors[1]{file,line,message}:
249+
# main.swift,15,"use of undeclared identifier"
250+
```
251+
252+
- `tab`: TSV-style format, ideal for Excel/spreadsheet import
253+
```bash
254+
xcodebuild build 2>&1 | xcsift -f toon --toon-delimiter tab
255+
# Output uses tabs instead of commas, can be directly imported to Excel
256+
```
257+
258+
- `pipe`: Alternative separator, useful when data contains many commas
259+
```bash
260+
xcodebuild build 2>&1 | xcsift -f toon --toon-delimiter pipe
261+
# Output: errors[1]{file|line|message}:
262+
# main.swift|15|"use of undeclared identifier"
263+
```
264+
265+
**Length Marker Options** (`--toon-length-marker [none|hash]`):
266+
- `none` (default): Standard array notation `[3]{...}`
267+
```bash
268+
xcodebuild build 2>&1 | xcsift -f toon
269+
# Output: errors[1]{file,line,message}:
270+
```
271+
272+
- `hash`: Ruby/Perl-style length prefix `[#3]{...}`
273+
```bash
274+
xcodebuild build 2>&1 | xcsift -f toon --toon-length-marker hash
275+
# Output: errors[#1]{file,line,message}:
276+
```
277+
278+
**Combined Configuration:**
279+
```bash
280+
# TSV format with hash markers for data analysis workflows
281+
xcodebuild test 2>&1 | xcsift -f toon --toon-delimiter tab --toon-length-marker hash -w -c
282+
283+
# Pipe-delimited with hash markers for complex data
284+
swift test 2>&1 | xcsift -f toon --toon-delimiter pipe --toon-length-marker hash --coverage-details
285+
```
286+
190287

191288
## Comparison with xcbeautify/xcpretty
192289

193290
| Feature | xcsift | xcbeautify | xcpretty |
194291
|---------|---------|------------|----------|
195-
| **Target audience** | Coding agents | Humans | Humans |
196-
| **Output format** | JSON | Colorized text | Formatted text |
197-
| **Token efficiency** | High | Medium | Low |
292+
| **Target audience** | Coding agents / LLMs | Humans | Humans |
293+
| **Output format** | JSON + TOON | Colorized text | Formatted text |
294+
| **Token efficiency** | Very High (TOON) | Medium | Low |
295+
| **LLM optimization** | Yes (TOON format) | No | No |
198296
| **Machine readable** | Yes | No | Limited |
199297
| **Error extraction** | Structured | Visual | Visual |
200298
| **Code coverage** | Auto-converts | No | No |

0 commit comments

Comments
 (0)