This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
TOON (Token-Oriented Object Notation) is a PHP 8.1+ library that converts PHP data structures into a compact format optimized for LLM contexts. It reduces token consumption by 30-60% compared to JSON through:
- Removing redundant syntax (braces, brackets, unnecessary quotes)
- Using indentation-based nesting
- Employing tabular format for uniform data rows
- Including explicit array lengths and field declarations
This is a standalone library with no runtime dependencies (only dev dependencies for testing/analysis).
Always prefer just commands over raw composer/vendor commands when available:
# Show all available commands
just
# Quick development cycle (format + test)
just dev
# Prepare for PR (format + analyse + test)
just pr
# Run CI checks (analyse + test, no formatting)
just ci
# Run tests only
just test
# Run tests with coverage
just test-coverage
# Watch mode for testing
just watch-test
# Run benchmarks
just benchmarkTOON PHP is a port of the TOON (Token-Oriented Object Notation) format specification, which achieves 30-60% token reduction vs JSON for LLM contexts. The implementation strictly follows the TOON Specification v1.3+ (see docs/SPEC.md).
- Toon (
src/Toon.php) - Main entry point with single staticencode()method - Normalize (
src/Normalize.php) - Converts PHP values to JSON-compatible structures - Encoders (
src/Encoders.php) - Core encoding logic with format detection - Primitives (
src/Primitives.php) - Encodes primitive values with smart quoting - LineWriter (
src/LineWriter.php) - Manages output lines and indentation - EncodeOptions (
src/EncodeOptions.php) - Configuration with presets - Constants (
src/Constants.php) - Shared syntax tokens - Helpers (
src/helpers.php) - Global helper functions
The encoder automatically selects the optimal format:
- Inline format for arrays of primitives:
[3]: a,b,c - Array-of-arrays format for nested arrays with list items
- Tabular format for uniform object arrays:
[2]{id,name}: 1,Alice - List format (default) for mixed structures with hyphen markers
PHP Array Behavior: PHP converts numeric string keys to integers. The library handles this by quoting numeric keys when encoding.
String Quoting Rules: Strings are quoted only when necessary:
- Reserved words: "true", "false", "null"
- Numeric strings: "42", "3.14"
- Strings with special characters
- Empty strings: ""
Enum Normalization:
BackedEnum: Extracts backing valueUnitEnum: Uses case name as string
- PHP Version: 8.1+ (uses readonly properties, enum support)
- Strict Types: All files must use
declare(strict_types=1); - PHPStan Level: 9 (maximum strictness)
- Code Style: Laravel Pint (run
just fixbefore commits) - Type Safety: Heavy use of
assert()after type checks
- Tests: All tests MUST go in
tests/directory. Never create test PHP files elsewhere in the repo. - Documentation: All documentation MUST go in
docs/folder if needed. Never create report/summary markdown files in the root. - Examples: Example code in documentation and examples/ directory must be valid, executable PHP syntax that matches the actual codebase.
- Spec Files: The official TOON specification lives in
docs/SPEC.md. Always validate implementation changes against the spec.
When adding features:
- Check the spec - Review
docs/SPEC.mdto ensure proposed change conforms to TOON specification - Check spec requirements - Review
docs/spec-requirements.mdfor normative requirements (142 total requirements) - Write tests first in appropriate test file under
tests/ - Implement in relevant src file following spec requirements
- Run
just devto format and test - Update CHANGELOG.md following Keep a Changelog format
- Run
just prbefore submitting
When debugging:
- Check normalization step (
Normalize.php) - Trace through
Encoders.phpformat detection - Check primitive encoding in
Primitives.php - Use
toon_readable()helper for debugging output - Run PHP code directly for quick checks (don't create scattered test files)
When running tests:
# Use just commands (preferred)
just test
just test-coverage
# Run specific test file
vendor/bin/phpunit tests/PrimitivesTest.php
# Run specific test method
vendor/bin/phpunit --filter testEncodesStringsWithoutQuotes- CHANGELOG.md: MUST be updated for all user-facing changes. Follow Keep a Changelog format with sections: Added, Changed, Deprecated, Removed, Fixed, Security.
Version numbers only, with no descriptive text:
- ✅ Correct:
v1.1.0,v1.0.1,v2.0.0 - ❌ Incorrect:
v1.1.0 - New Features,Version 1.0.0: Initial Release
Must be factual and straightforward:
- No emojis - Plain text only
- No marketing language - Avoid "exciting", "amazing", "revolutionary"
- Technical focus - What changed, not how great it is
- Simple headings - Use "Added", "Changed", "Fixed", not "What's New"
Good example:
## Changes in v1.1.0
### Added
- Justfile for task automation
- Token efficiency benchmarks
- PHPDoc documentation
### Changed
- Benchmark output formatting simplified
Documentation must focus on what the package does, not how it was built.
Always avoid:
- Development process details
- Self-referential language ("we verified", "our testing")
- Meta-commentary about development history
- References to comparing against other implementations
- Details about how features were validated
Always include:
- Package features and capabilities
- User-facing functionality
- Clear, direct descriptions of behavior
- Valid, executable PHP code examples
Good (feature-focused):
## Features
- Reduces token consumption by 30-60% compared to JSON
- Supports nested objects and arrays
- Configurable delimiters and formatting optionsBad (process-focused):
## Implementation
This implementation has been verified against the TypeScript version
with extensive testing to ensure correctness.# Preferred: use just command
just benchmark
# Alternative: direct composer
cd benchmarks && composer benchmarkResults are saved to benchmarks/results/token-efficiency.md
When testing quick PHP snippets, run them directly:
# Direct execution (preferred for quick tests)
php -r "require 'vendor/autoload.php'; echo Toon\Toon::encode(['test' => 'data']);"
# Never create temporary test files throughout the repo# Before any commit
just dev
# Before creating PR
just pr
# For CI validation
just ciCRITICAL: This library implements the official TOON Specification v1.3+ (docs/SPEC.md). All code changes MUST conform to the specification.
The specification defines 142 normative requirements across 19 sections:
- 104 MUST/REQUIRED requirements (critical)
- 12 MUST NOT prohibitions (critical)
- 17 SHOULD recommendations (high priority)
- 9 MAY/OPTIONAL features (low priority)
Before making changes:
- Read relevant sections in
docs/SPEC.md - Check
docs/spec-requirements.mdfor specific requirements - Validate your implementation against encoder/decoder conformance checklists (§13 of spec)
Encoder Conformance (Section 13.1): Encoders MUST produce UTF-8 output with LF line endings, use consistent indentation (no tabs), escape exactly 5 characters (\, ", \n, \r, \t), quote delimiter-containing strings, emit accurate array lengths, preserve key order, normalize numbers to non-exponential form, convert -0 to 0, convert NaN/±Infinity to null, and emit no trailing spaces or newlines.
Decoder Conformance (Section 13.2): Decoders MUST parse array headers correctly, split only on active delimiters, unescape valid escapes only, type unquoted primitives correctly, enforce strict-mode rules when enabled, accept optional # length markers, and preserve array/object order.
- Follow the spec - ALL code changes must conform to TOON Specification v1.3+ in
docs/SPEC.md - Use justfile commands - Always prefer
justover raw composer/vendor commands - Keep CHANGELOG.md updated - Document all user-facing changes
- No scattered test files - All tests go in
tests/directory only - No root-level reports - Documentation goes in
docs/folder - Valid PHP in docs - All example code must be syntactically correct and match actual code
- Verify examples - Run
php -lon any example files to ensure syntax validity - Format before commit - Always run
just fixorjust dev - Test after changes - Verify with
just testbefore pushing