This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
PunQLite is a Pharo Smalltalk binding for UnQLite, a fast, lightweight embedded NoSQL database with key-value storage and Jx9 scripting engine support. The project provides a Dictionary-like interface for storing and retrieving data with minimal overhead.
PunQLite-Core # FFI bindings, low-level library interface
├─ UnQLiteFFI # FFI wrapper for C library
├─ UnQLiteLibrary # Library loading and platform detection
└─ UnQLiteConstants # C constants mapping
PunQLite-DB-Codec # Pluggable codec system for value serialization
├─ PqCodec # Abstract codec base class
├─ PqUtf8Codec # UTF-8 string encoding (default)
├─ PqJsonCodec # JSON serialization via STONJSON
└─ PqFuelCodec # Fuel binary serialization (preserves class types)
PunQLite-DB # High-level database API (depends on Core, DB-Codec)
├─ PqDatabase # Main database interface (Dictionary-like API)
├─ PqCursor # Cursor-based iteration
├─ PqCollection # Collection interface
└─ PqValueAppender # Efficient value appending
PunQLite-Jx9 # Jx9 scripting engine integration
├─ PqJx9Executer # Script execution
├─ PqJx9Context # Execution context
├─ PqJx9Value # Value marshalling between Smalltalk and Jx9
└─ Extensions # Adds Jx9 conversion methods to core classes
PunQLite-Tests # Test suite (depends on all above)
PunQLite-Tools # Spec2 GUI browser (depends on PunQLite-DB)
FFI Layer: Uses Pharo's UnifiedFFI to interface with the native UnQLite C library. All FFI calls go through UnQLiteFFI class with type mappings for pointers (db_ptr, cursor_ptr, vm_ptr, value_ptr, context_ptr).
Handle Management: PqObject is the base class managing native handles and provides lifecycle methods (close, release). Subclasses (PqDatabase, PqCursor, PqJx9Executer) must properly release their native resources.
Dictionary Protocol: PqDatabase implements standard Dictionary methods (at:, at:put:, at:ifAbsent:, at:ifPresent:, keys, do:) making it intuitive for Smalltalk developers.
Cursor-Based Iteration: For efficient database scanning, use PqCursor which provides seek:untilEndDo: and standard iteration protocols.
Jx9 Integration: Bidirectional conversion between Smalltalk objects and Jx9 values via extension methods (e.g., String>>asJx9Value:, Integer>>asJx9Value:). The PqJx9Executer manages script compilation and execution lifecycle.
Codec System: Pluggable encoding/decoding for transparent object serialization. PqCodec defines the encode:/decode: protocol with three implementations:
PqUtf8Codec(default): UTF-8 string encodingPqJsonCodec: JSON serialization for arrays/dictionariesPqFuelCodec: Fuel binary serialization preserving class types
Configure via PqDatabase>>codec: or globally via PqSettings>>defaultCodecClassName:.
The UnQLite shared library must be placed in the Pharo image directory:
- Linux:
unqlite.so - macOS:
unqlite.dylib - Windows:
unqlite.dll
Pre-built binaries are available from the releases page:
UnQLite is very easy to compile - it consists of only two files (unqlite.c and unqlite.h).
Compilation commands:
# Linux
gcc -c unqlite.c
gcc -shared -o unqlite.so unqlite.o
# macOS
gcc -c unqlite.c
gcc -dynamiclib -o unqlite.dylib unqlite.o
# Windows (MinGW)
gcc -c unqlite.c
gcc -shared -static-libgcc -o unqlite.dll unqlite.oNote: For 32-bit systems, add the -m32 option to both gcc commands.
Download UnQLite source from: https://github.com/symisc/unqlite
The BaselineOfPunQLite>>preLoad method checks for library presence and displays compilation instructions in the Transcript if missing. This ensures compatibility with CI/CD environments where error dialogs would be problematic.
This is a Pharo Smalltalk project. Use the available Smalltalk MCP tools for all Smalltalk operations:
Essential Commands:
mcp__smalltalk-interop__get_class_source- Read full class definitionsmcp__smalltalk-interop__get_method_source- Read specific method implementationsmcp__smalltalk-interop__search_implementors- Find all implementors of a methodmcp__smalltalk-interop__search_references- Find references to methods/symbolsmcp__smalltalk-interop__eval- Execute Smalltalk code in the running imagemcp__smalltalk-interop__run_package_test- Run all tests in a packagemcp__smalltalk-interop__run_class_test- Run tests for a specific test classmcp__smalltalk-validator__validate_tonel_smalltalk_from_file- Validate Tonel syntax
Testing Workflow:
# Run all PunQLite tests
mcp__smalltalk-interop__run_package_test('PunQLite-Tests')
# Run specific test class
mcp__smalltalk-interop__run_class_test('PqDatabaseTest')
mcp__smalltalk-interop__run_class_test('PqJx9Test')
mcp__smalltalk-interop__run_class_test('PqCollectionTest')Development Pattern:
- Use
search_classes_liketo find relevant classes - Use
get_class_sourceto understand class structure - Use
get_method_sourceto read specific implementations - Validate changes with
validate_tonel_smalltalk_from_file - Run tests with
run_class_testorrun_package_test
# Load via Metacello
Metacello new
repository: 'github://mumez/PunQLite/repository'
baseline: 'PunQLite';
load.
# Or from Pharo CatalogTest packages are in repository/PunQLite-Tests/:
PqDatabaseTest- Core database operations and codec integrationPqJx9Test- Jx9 scripting integrationPqCollectionTest- Collection protocolPqCodecTest- UTF-8 codec testsPqJsonCodecTest- JSON codec testsPqFuelCodecTest- Fuel codec tests
All tests use in-memory databases (PqDatabase openOnMemory) to avoid file system dependencies.
PunQLite supports both auto-commit and explicit transaction modes:
- Auto-commit (default): Each operation is automatically committed
- Manual transactions: Call
database disableAutoCommitthen usedatabase transact: [ ... ]
Cursor operations and manual transactions provide better performance for bulk operations.
-
Resource Leaks: Always call
closeorreleaseonPqDatabase,PqCursor, andPqJx9Executerinstances. Useensure:blocks in production code. -
Jx9 Type Marshalling: Jx9 variables must be extracted with proper type conversion (
asInt,asString,asBoolean). CheckPqJx9Valuefor supported types. -
Cursor Validity: Cursors become invalid after database operations. Create fresh cursors for each iteration.
-
FFI Platform Differences: The FFI layer has platform-specific differences in 32-bit vs 64-bit integer handling. The recent commit addresses C integer size issues (see commit 30f854b).
- Main branch:
master(for PRs) - Development branch:
develop(current active branch) - Source format: Tonel format under
repository/(migrated from Cypress/Monticello)
The project uses GitHub Actions with SmalltalkCI for continuous integration:
- Workflow configuration:
.github/workflows/main.yml - Tests run on multiple Pharo versions
- Automatically compiles UnQLite library for testing
- Validates all packages on push and pull requests
- PunQLite-DB-Codec package for pluggable value serialization
PqUtf8Codec(default),PqJsonCodec,PqFuelCodecimplementationsPqDatabasecodec support:storeAt:valueEncoded:,fetchAt:intoDecoded:PqCursorcodec support:currentValueIntoDecoded:- Global codec configuration via
PqSettings>>defaultCodecClassName:
- PqDatabaseBrowser migrated from Spec1 to Spec2
- Fixed style violations and API compatibility issues
- Modern UI with improved menu handling
- Removed obsolete PunQLite-Help package (Spec1-based help browser)
- Removed obsolete ConfigurationOfPunQLite package (replaced by BaselineOf)
- Migrated to Tonel format for better git integration
- Fixed variadic function handling in Jx9 VM configuration
- Improved 32-bit vs 64-bit integer handling
- Better platform detection and library loading
- Enhanced memory management with ExternalAddress
- Added comprehensive class comments for key classes
- Improved README with library installation instructions
- Added this CLAUDE.md for AI-assisted development