agentleFS
DatabricksKnown publisherdatabricks/sjsonnet/CLAUDE.md

sjsonnet

CLAUDE.md319 starsChanged 5 months agoApache-2.0View on GitHub

Uses the Mill version declared in build.mill. Cross-built against the latest patch releases on the configured Scala 2.12.x (JVM only), 2.13.x, and 3.3.x LTS lines; exact versions are declared by scalaVersions and jvmScalaVersions in build.mill. Assembly JARs are written under out/sjsonnet/jvm/<scala-version>/assembly.dest/out.jar. Run one with java -Xss100m -jar out.jar. We follow the Databricks Scala style guide. Scala sources are formatted with scalafmt (config in .scalafmt.conf). The SjsonnetCrossModule and bench modules mix in ScalafmtModule. CI checks formatting on PRs, so run reformat…

  • In this repositoryOne other file it gives its agents.

The file

We split this CLAUDE.md into the rules it gives an agent

4 rules. About 0 are common, 1 is distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Every bug fix should include a regression test:

    line 68
  2. Very specific:

    Create new_test_suite/<descriptive_name>.jsonnet with a minimal reproducer.

    line 70
  3. Very specific:

    Create new_test_suite/<descriptive_name>.jsonnet.golden with expected output.

    line 71
  4. Very specific:

    Run ./mill 'sjsonnet.jvm[_]'.test to verify.

    line 74

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

sjsonnet Development Guide

Build & Test

Uses the Mill version declared in build.mill. Cross-built against the latest patch releases on the configured Scala 2.12.x (JVM only), 2.13.x, and 3.3.x LTS lines; exact versions are declared by scalaVersions and jvmScalaVersions in build.mill.

# Compile all JVM Scala versions
./mill 'sjsonnet.jvm[_]'.compile

# Run all JVM tests
./mill 'sjsonnet.jvm[_]'.test

# Run all tests across all platforms
./mill __.test

# Build assembly JARs
./mill 'sjsonnet.jvm[_]'.assembly

# GraalVM native image
./mill sjsonnet.graal.nativeImage

Assembly JARs are written under out/sjsonnet/jvm/<scala-version>/assembly.dest/out.jar. Run one with java -Xss100m -jar out.jar.

Formatting

We follow the Databricks Scala style guide.

Scala sources are formatted with scalafmt (config in .scalafmt.conf). The SjsonnetCrossModule and bench modules mix in ScalafmtModule.

# Format all sources
./mill __.reformat

# Check formatting without changing files
./mill __.checkFormat

CI checks formatting on PRs, so run reformat before committing.

Test Structure

  • Framework: uTest
  • Test suites (sjsonnet/test/resources/):
    • test_suite/ — From C++ Jsonnet (upstream). ~183 .jsonnet files with .golden expected output.
    • go_test_suite/ — From go-jsonnet.
    • new_test_suite/ — sjsonnet-specific tests (deep nesting, regex, etc.).
  • Test sources:
    • test/src/ — Shared tests (parser, evaluator, renderer, stdlib).
    • test/src-jvm/ — JVM-only (MainTests, file I/O, XxHash64).
    • test/src-jvm-native/ — JVM + Native (FileTests, ConfigTests, gzip, md5, sha).
    • test/src-js/ — Scala.js (FileTests).

Golden file tests

Each .jsonnet test file has a .golden file containing expected output. Files named error.* expect non-zero exit and their .golden holds the expected stderr (including stack traces).

Refresh golden outputs:

./sjsonnet/test/resources/refresh_golden_outputs.sh

The .sync_ignore files in test_suite/ and go_test_suite/ list tests to skip when syncing from upstream (e.g. differing YAML parser behavior).

Writing tests for bug fixes

Every bug fix should include a regression test:

  1. Create new_test_suite/<descriptive_name>.jsonnet with a minimal reproducer.
  2. Create new_test_suite/<descriptive_name>.jsonnet.golden with expected output.
    • Success tests: JSON output followed by a newline, using std.assertEqual chains ending in true.
    • Error tests (filename starts with error.): expected stderr including stack traces.
  3. Run ./mill 'sjsonnet.jvm[_]'.test to verify.

Debug Stats

The --debug-stats flag prints runtime counters and timing to stderr after evaluation:

sjsonnet --debug-stats myfile.jsonnet

Output includes thunk creation counts, function/builtin call counts, comprehension iterations, import/parse counts, and phase timing (eval, materialize). Counters are formatted with stable labels for machine parsing. The DebugStats class (sjsonnet/src/sjsonnet/DebugStats.scala) is wired through Interpreter -> Evaluator, with parse counting handled by CountingParseCache.

Benchmarks

JMH benchmarks live in bench/. Benchmark suites in bench/resources/: bug_suite/, cpp_suite/, go_suite/, sjsonnet_suite/.

# Run all regression tests
./mill bench.runRegressions

# Run specific regressions
./mill bench.runRegressions bench/resources/bug_suite/assertions.jsonnet

# List all benchmark regression files
./mill bench.listRegressions

# Refresh benchmark golden outputs
./bench/resources/refresh_golden_outputs.sh

For ad-hoc benchmarking, hyperfine is available on the PATH.

Architecture

Pipeline

Source String → Parser → Expr (AST) → StaticOptimizer → Evaluator → Val → Materializer → ujson.Value → Renderer → Output
  1. Parser (Parser.scala): Fastparse-based, produces Expr AST.
  2. StaticOptimizer (StaticOptimizer.scala): Constant folding, arity specialization, ValidId indexing, static checks.
  3. Evaluator (Evaluator.scala): Walks Expr, produces lazy Val runtime values. Handles imports, function application, tail-call optimization.
  4. Materializer (Materializer.scala): Walks Val, produces ujson.Value. Hybrid recursive/iterative to avoid stack overflow.
  5. Interpreter (Interpreter.scala): Orchestrates the full pipeline; main programmatic entry point.

Key types

  • Expr (Expr.scala): AST nodes — literals, binary ops, function defs/calls, objects, arrays, comprehensions, imports. ExprTags provides byte tags for fast pattern matching.
  • Val (Val.scala): Runtime values — Str, Num, Bool (True/False), Null, Arr, Obj, Func, Builtin. Val.Literal extends both Val and Expr.
  • Eval trait: def value: Val. Implemented by Lazy (deferred, cached) and Val (immediate). Arrays and objects hold Eval, not Val.
  • ValScope (ValScope.scala): Array-based lexical scope with copy-on-write extension.
  • TailCall: Sentinel value for tail-call optimization; resolved via trampoline in TailCall.resolve.

Standard library

Implemented as Scala builtins (not Jsonnet code) in sjsonnet/src/sjsonnet/stdlib/:

  • StdLibModule — builds the std object combining all modules.
  • ArrayModule, StringModule, ObjectModule, MathModule, TypeModule, EncodingModule, ManifestModule, SetModule, NativeRegex.

Platform-specific stdlib extensions:

  • JVM: NativeXz (xz compression), NativeGzip, regex via re2j.
  • Native: NativeGzip, crypto.
  • JS: scala-yaml for YAML parsing.

Source directory layout

Shared and platform-specific sources are split across directories:

DirectoryContents
sjsonnet/src/Shared core (parser, evaluator, materializer, stdlib)
sjsonnet/src-jvm/JVM main class, Platform.scala
sjsonnet/src-jvm-native/Shared JVM + Native (SjsonnetMainBase, Config)
sjsonnet/src-js/Scala.js main class, Platform.scala
sjsonnet/src-native/Scala Native main class, Platform.scala

Modules

  • sjsonnet.jvm — JVM library + CLI (SjsonnetMain)
  • sjsonnet.js — Scala.js (CommonJS)
  • sjsonnet.wasm — WebAssembly (via Scala.js)
  • sjsonnet.native — Scala Native
  • sjsonnet.graal — GraalVM native image
  • sjsonnet.jvm.client / sjsonnet.jvm.server — Client-server mode (background daemon)
  • bench — JMH benchmarks
  • playground — Browser-based Jsonnet playground

Error handling

  • Error — Main exception with message, stack frames (Error.Frame), optional cause.
  • ParseError / StaticError — Parse-time and static analysis failures.
  • Error.fail(msg, pos) throws with position info; Error.withStackFrame(expr) adds frames to exceptions.
  • Public APIs (e.g. Interpreter.interpret) return Either[String, ujson.Value].

Key Design Decisions

  • Lazy evaluation: Arrays and objects hold Eval (not Val). Lazy wraps a thunk, caches the result, and clears the closure after first evaluation.
  • Tail-call optimization: TailCall sentinel + trampoline loop in TailCall.resolve.
  • Hybrid materialization: Recursive up to a depth limit, then switches to an explicit stack to avoid StackOverflowError.
  • Static optimization: StaticOptimizer does constant folding, resolves variable names to scope indices (ValidId), and specializes function application by arity (Apply0–Apply3, ApplyBuiltin0–ApplyBuiltin4).
  • Parse caching: ParseCache / DefaultParseCache caches parsed ASTs to avoid re-parsing imports.
  • Platform abstraction: Path and Importer traits abstract filesystem access across JVM/JS/Native.

Threading Model

  • No internal multithreading requirement: A single Interpreter does not need to evaluate a program using multiple threads.
  • Independent interpreters should not interfere: Applications should be able to run multiple independent Interpreter instances concurrently on platforms that support concurrency, without one interpreter affecting another.
  • Shared mutable state is exceptional: State should belong to an interpreter or evaluation unless it has an explicit concurrency contract and tests.

Dependencies

Key runtime dependencies:

  • fastparse — Parser combinators
  • ujson — JSON AST and rendering
  • pprint — Pretty printing
  • scalatags — HTML generation (for error output)
  • os-lib — Filesystem (JVM/Native)
  • mainargs — CLI argument parsing (JVM/Native)
  • snakeyaml — YAML parsing (JVM)
  • re2j — Regular expressions (JVM)
  • xz / lz4-java — Compression (JVM)

CI

GitHub Actions workflows in .github/workflows/:

  • pr-build.yaml — PR validation: compile + test across JVM/JS/WASM/Native × JDK 17/21/25, format check, GraalVM native tests.
  • release-build.yaml — Release builds (JAR, JS, WASM, playground, native binaries).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.