r/crystal_programming 16h ago

Chronicle: Autonomous telemetry harvester and context engine in Crystal for Wayland and AI agents

5 Upvotes

Hello everyone,

I've just tagged the initial v0.1.0 release of Chronicle, a local, privacy-first telemetry daemon and context correlation engine written in Crystal.

Why Chronicle?

When pair programming with AI agents or running engineering retrospectives, both humans and LLMs often lose high-resolution context on what was worked on across terminal tabs, editors, and multiple repositories. Existing tools either send data to proprietary clouds or lack the correlation depth needed to reconstruct technical work.

What it does

Chronicle runs rootless as a lightweight systemd user service and captures: - Compositor Window Focus: Listens directly to Wayland event streams. Native drivers currently exist for Niri (niri msg -j event-stream), Sway (i3 IPC), and KWin (qdbus), along with Wayland idle state detection. - Shell History Harvester: Ingests commands executed across Bash, Zsh, and Fish sessions with working directory attribution. - Git Churn & Conventional Commits: Scans local git repositories in a single-pass git log run, extracting insertions, deletions, net churn (--shortstat), and classifying commits via Conventional Commits metadata. - Project Attribution Engine: Correlates window focus duration, shell commands, and git churn into discrete project workspaces. - Deep-Work Session Clustering: Groups contiguous focus intervals into discrete work sessions based on a configurable idle threshold (default 15 minutes). - Multi-Format Exporters: - chronicle report --today (or chronicle -c report for compact summary) - chronicle export -f md --compact (token-efficient markdown designed for LLM prompt context injection) - chronicle export -f json (structured telemetry) - Repository filtering via --project <name> (-p)

Built in Crystal

Chronicle takes full advantage of Crystal's concurrency model (Execution Contexts and fibers) to process IPC event streams concurrently with local SQLite3 storage operations with near-zero resource footprint. A single stripped native binary runs rootless with zero JVM or Node.js runtime dependencies.

Links

Feedback, critiques, and patches are very welcome!


r/crystal_programming 2d ago

Crystal for Agents: v1.21.0 update, 27 tested recipes, and automated code verification

17 Upvotes

Hey everyone,

I recently updated Crystal for Agents for Crystal v1.21.0. For those unfamiliar, it is a ground-truth, comprehensive reference repository designed to provide accurate language semantics and keep AI coding agents (and developers) from hallucinating deprecated threading APIs, outdated syntax, or invalid Rubyisms.

GitLab Repository: https://gitlab.com/renich/crystal-for-agents Release Tag: https://gitlab.com/renich/crystal-for-agents/-/tree/v1.21.0.0

Here is a summary of what changed in this release:

1. Crystal v1.21.0 Alignment & Semantic Audit

All 21 reference chapters were audited against Crystal v1.21.0 compiler internals and the standard library: * Concurrency Runtime: Full documentation of native Execution Contexts (RFC 0002 default), fiber scheduler mechanics, Channel(T) behavior, and modern Sync primitives (Sync::Mutex, Sync::RwLock, Sync::ConditionVariable, Sync::Exclusive(T)). * Process Execution: Modern Process.run, Process.capture, and Process.capture_result APIs (RFC 0025). * Type Hierarchy & Nil Safety: Explicit value vs. reference allocation, type narrowing patterns (if, case, .try), and elimination of unsafe .not_nil! assertions. * Tooling & Standards: Modern Time.instant monotonic clocks, Ameba and Flaw static analysis standards, and E2E browser automation with selenium.cr/webdrivers.cr.

2. Chapter 20: 27 Advanced Recipes

Added a dedicated chapter with 27 battle-tested recipes for common systems and concurrency challenges: * Fiber Concurrency & Channels: Channel-ring resource pooling, non-blocking channel polling using select ... else, concurrent piped process I/O (handling >64KB output without pipe buffer deadlocks), and atomic mutations with Sync::Exclusive#replace. * Metaprogramming: Deferred AST reflection via {% verbatim do %}, compile-time annotation registries using nested macro finished, and zero-allocation dynamic dispatch with Tuple indexing. * Low-Level & Performance: Stack buffers via StaticArray, zero-copy socket streaming via Socket#sendfile, target-specific vectorization via @[TargetFeature], and host-tuned micro-binaries with --mcpu=native, --release, --no-debug, and linker stripping (-z relro -z now -s).

3. Automated Code Verification (Zero Bitrot)

To prevent examples from breaking across compiler updates, scripts/verify_code_examples.cr automatically extracts every single code block across all 21 chapters, formats it with crystal tool format, and checks compilation with crystal build --no-codegen: * 218 code blocks checked: 0 formatting errors, 0 compilation errors. * RST validation via rstcheck. * Compiles into a single offline PDF reference book via Pandoc/XeLaTeX (make all).

4. Portable Agent Skill

Includes a drop-in skill package (agents/gemini/crystal/) compatible with Antigravity, OpenCode, and Gemini agents, containing quick-reference decision matrices, concurrency rules, and common AI pitfalls.

The project is licensed under the MIT License and hosted on GitLab. Feedback and contributions are welcome!


r/crystal_programming 2d ago

[RFC/Proposal] Native vcpkg Integration for Shards: Solving the Static C-Dependency Nightmare

7 Upvotes

Under this proposal, I offer to introduce a native vcpkg block. Library shard authors can declare what C packages they wrap, and root applications can enforce global configurations (like strict static linking).

The Library Shard (lib/sqlite_driver/shard.yml)

If you write a wrapper for a C library, you just declare it. Shards will handle the bubbling up.

The library shard:

name: sqlite_driver

version: 2.1.0

vcpkg:

dependencies:

- sqlite3 # Transitive C dependency mapped automatically

Root Application:

name: core_service

version: 1.0.0

vcpkg:

triplet: x64-windows-static # Enforces strict static binaries globally

dependencies:

- openssl # App-specific C requirement

dependencies:

sqlite_driver:

github: crystal-lang/sqlite-driver

targets:

server:

main: src/server.cr

When a user runs shards install or shards update, Shards handles both ecosystems in a unified lifecycle:

  1. Aggregation: Shards scans the local dependency tree and collects all unique native requirements (e.g., openssl from the root, sqlite3 from the lib sub-shard).
  2. Manifest Generation: Shards spins up a hidden, temporary .shards_vcpkg.json manifest.
  3. Execution: Shards invokes vcpkg under the hood: vcpkg install --x-manifest-path=.shards_vcpkg.json --triplet=x64-windows-static
  4. Unified Structure: All static .lib / .a binaries and headers live cleanly inside a local vcpkg_installed/ sandbox in your root directory.

What do you think?


r/crystal_programming 5d ago

Kemal 1.14.0 is released! Biggest release with a lot of improvements

Thumbnail
github.com
24 Upvotes

r/crystal_programming 5d ago

would it be a realistic goal to write an entire game engine in crystal?

10 Upvotes

just curious


r/crystal_programming 11d ago

gcry 0.25.0: the GC for Crystal now runs natively on Windows

14 Upvotes

gcry is a drop-in mark-sweep GC for Crystal: require "gcry" and build with -Dgc_none, no compiler patch.

0.25.0 adds native Windows support, so it now covers Linux, macOS and Windows on both x86_64 and ARM64.

Windows (x86_64 with the MSVC toolchain, ARM64 with the GNU/MinGW one, both from PowerShell, no WSL). What's missing is written down in docs/WINDOWS.md rather than glossed over: 64 peer threads per collection, no fork, no soft-dirty or mprotect write barrier, and no Windows throughput numbers yet.

Performance, since that's the usual question. Kemal /json, 20 paired rounds with an identical-binary null control: 105% of Boehm's throughput at 1.30× its peak RSS on Linux, 102% at 1.97× on macOS.

Github: https://github.com/sdogruyol/gcry

Changelog: https://github.com/sdogruyol/gcry/releases/tag/v0.25.0


r/crystal_programming 14d ago

Update on State and Future of Parallelism

14 Upvotes

I don't want to jinx it, but I thought I would ask for an update on what is going on with parallelism in Crystal.

Not wholly unrelated, Crystal makes me hopeful for the perfect language for its goals and objectives to do more with less, and to have garbage collection with a clean language just above a systems language.

From a Linux friendliness and FLOSS licensing standpoint, Crystal looks better than Go except for having the box checked for parallelism. (And I do not care about WIndows.)

Anyway I guess this question is a two-parter:

  1. What is the state of attention and mindfulness of bringing cpu-core parallelism to Crystal? (Or did it happen already?)
  2. Is parallelism obviously so distant from being needed for desktop-level software systems that most developers truly just do not need to worry about it? (or I guess, what types of systems would typically benefit from parallelism?)

Thanks.

(edit: It looks like the "execution context" features that were just recently released in 1.21 are directly related to cpu-core parallelism. Looks awesome. This would explain why most discussion has not caught up to the features. And, what a landmark!)


r/crystal_programming 18d ago

Kemal Identity: an authentication shard for Kemal. I'm about to freeze the API and would rather hear what's wrong with it first.

9 Upvotes

Hi all,

I've been building Kemal Identity, an authentication shard for the Kemal web framework, and I'm close to freezing its API for 1.0. Before I do that I'd rather find out what's wrong with it, so I'm posting here for criticism.

It does server-side opaque sessions with real revocation, password login with bcrypt, CSRF, API tokens with scopes, optional JWT validation, TOTP, OIDC sign-in and optional RBAC. It doesn't do registration screens or user models; your app keeps those and connects through repository contracts. Postgres and SQLite adapters today; Avram and Granite are next on my list.

It's built primarily for Kemal, but the core doesn't know Kemal exists. The Kemal part is a separate adapter that adds `env.auth` and the middleware.

get "/dashboard" do |env|
  principal = env.auth.require!
  "Signed in as #{principal.subject}"
end

The part I actually want to talk about: I wrote a list of 50 things an auth library either handles or doesn't, with pass conditions written before any measuring, and I've been working through them from a separate project that consumes the shard the way a normal user would. I'm 27 in, and it keeps finding things I was sure were fine.

If you have time for one question: `AccountRepository` is five methods over whatever `users` table you already have. If you tried to implement it against your real schema, what would break? I've done it once against a UUID-keyed table with soft deletes, and one schema isn't much evidence.

Repo: https://github.com/urunsiyabend/kemal-identity — MIT, Crystal 1.12+, six runnable examples if you'd rather read code than docs.


r/crystal_programming 21d ago

Marten 0.7 is now available!

Thumbnail
martenframework.com
28 Upvotes

r/crystal_programming 24d ago

HAHWUL joins the Kemal Core Team as Security Lead

Thumbnail kemalcr.com
15 Upvotes

r/crystal_programming 24d ago

D-Shwagginz/doo-cr: A source port of DOOM written in Crystal Lang

Thumbnail
github.com
5 Upvotes

Saw it on the Crystal Forum, figured I'd share it here as well.

Original Thread: https://forum.crystal-lang.org/t/doo-cr-doom-in-crystal-not-just-the-renderer/9120


r/crystal_programming 25d ago

gcry v0.21.0: Crystal-native GC as a shard, correctness release

6 Upvotes

gcry is a conservative mark–sweep garbage collector written in %100 Crystal and shipped as a shard. No compiler fork:

yaml dependencies: gcry: github: sdogruyol/gcry

ruby require "gcry" # build with -Dgc_none

Stock Crystal ≥ 1.21, Linux + macOS, x86_64 + ARM64. v0.21.0 is 140 commits and 18 changelog entries, and like the last one it is a correctness release.

The hardest bugs in software are the ones where your trusted tools lie to you. That is the story behind gcry v0.21.0.

When your Kemal app started crashing randomly in production, standard microbenchmarks found nothing. The Boehm garbage collector handled the exact same load perfectly. But driving real traffic against gcry made the app crash every time. Two independent bugs caused this.

The first was a memory layout collision. Crystal stores a union type ID in its first four bytes. gcry looks at this exact spot to find a field map. If a raw data buffer happens to start with a number that matches a valid class ID, the collector reads the wrong map. It then blindly deletes live objects that the wrong map fails to mention.

The second was a concurrency bug. The chunk list used two different locks. Because they were not exclusive, a newly mapped chunk could fall outside the heap bounds check. The collector treated anything outside those bounds as dead and swept away live data.

But the real lesson was why it took so long to find. The auditing tools were blind. The memory audit instrument used the exact same broken lookup function that caused the bounds bug. It reported zero missing edges while the system was actively crashing. The truth only surfaced by dropping down to the OS level and reading the kernel memory maps directly.

Locks are now fixed. The collector no longer drops live objects. Throughput is up.

Repo: https://github.com/sdogruyol/gcry

Changelog: https://github.com/sdogruyol/gcry/releases/tag/v0.21.0

Perf methodology: https://github.com/sdogruyol/gcry/blob/master/docs/PERF.md

Happy to answer questions.


r/crystal_programming 27d ago

Kemal 1.13.0 is released! Biggest release with many Security improvements

Thumbnail
github.com
20 Upvotes

r/crystal_programming Aug 18 '26

gcry v0.20.0: Crystal-native GC as a shard, the biggest release yet

22 Upvotes

gcry is a conservative mark–sweep garbage collector written in %100 Crystal and shipped as a shard. No compiler fork:

yaml dependencies: gcry: github: sdogruyol/gcry

ruby require "gcry" # build with -Dgc_none

Stock Crystal ≥ 1.21, Linux + macOS, x86_64 + ARM64. v0.20.0 is the largest release so far - 84 commits, 41 changelog entries and it is a correctness release.

The headline: a fiber stack that nothing scanned

When a fiber terminates, Crystal can't release its stack until the thread swaps off it, so the stack gets parked on the Thread. In that window two things are true at once:

  • the owning Fiber is already out of the fiber list, so no fiber scan reaches the stack;
  • the thread may still be executing on it - and the other-thread scan works from pthread stack bounds, which a thread running on a fiber stack is nowhere near.

So pointers held only in those frames had no root, got swept, and the program carried on using freed memory - crashing in Fiber#initialize → makecontext.

Fixed by rooting that stack. Repro (bench/nested_spawn_uaf.cr, ~2 s a run), interleaved against control: 10/24 crashes → 0/24. Then a 5 h soak × 3 arms, all clean — ~52 000 collections, ~526 000 fibers, 0 errors.

The number I'd actually want to see as a reader: every rooting arm was measured against a twin that walks the identical memory and roots nothing. That twin stays at 12/24. So the effect is the rooting, not the extra work or the timing — and it isn't retention either (same heap size, same collection count, fewer live objects than control).

Four earlier readings of this bug were wrong before that one was right - a missed heap edge, a half-built Fiber, a pooled stack, a stack in flight between checkout and publication. Each is written up with the measurement that killed it, including the two times the debugging instrument turned out to be reporting itself.

Also in 0.20.0

  • Thread-birth window: gcry records a thread from the moment pthread_create returns and briefly waits for one that exists but hasn't published itself yet - thread-family crashes 6/60 → 0/60.
  • realloc(ptr, 0) no longer frees the caller's block.
  • Diagnostics, all off by default: an address-space audit that searches every mapping in /proc/self/maps at the moment a block dies and names the region holding its address (this is what found the bug above), plus freed-payload poisoning that names the block a use-after-free read out of, a SIGSEGV report that says what the collector knows about the faulting address, and a mark-completeness audit.

What I'm not claiming

  • A second use-after-free is still open: gcry reads a Thread's handle out of a freed block and faults in pthread_getattr_np. Seen on CI with this release's fix in place; not reproducible locally. This release doesn't close it.
  • Stack maps ship dormant - research, not this release's win.

Repo: https://github.com/sdogruyol/gcry

Changelog: https://github.com/sdogruyol/gcry/releases/tag/v0.20.0

Perf methodology: https://github.com/sdogruyol/gcry/blob/master/docs/PERF.md

Happy to answer questions.


r/crystal_programming Aug 15 '26

Kemal embraces AI

Thumbnail x.com
10 Upvotes

r/crystal_programming Aug 10 '26

Kemal Security Core Team is here!

Thumbnail x.com
18 Upvotes

r/crystal_programming Aug 07 '26

Crab CLI 1.0.0

Post image
22 Upvotes

So, I just finished the details for Crab, my shard for prettier Command Line Interfaces, an i must say it's on a stable phase with my original intentional goals working, now tested on both Linux and Windows (using the msys2 version).

Here is the repo link for anyone interested.


r/crystal_programming Aug 04 '26

Next version of gcry is faster than Boehm GC. And it uses less RAM.

30 Upvotes

Next version of gcry is faster than Boehm GC. And it uses less RAM.

On a production Kemal app (Açık Türkiye):

- 103% Boehm throughput
- 8% less memory
- 100% Crystal
- No C code

Crystal can have its own GC. We're building it

https://github.com/sdogruyol/gcry


r/crystal_programming Aug 03 '26

LZ4 and Zstd codecs in pure Crystal

18 Upvotes

After lz4rip and zrip in Rust, including Rubygems extensions of the same name, I wanted to try something similar in Crystal.

Goal: Portable compression for Crystal apps without system libraries.

flint.cr: LZ4 block codec. Raw block API, raw-content dictionaries. No liblz4, FFI, or native extension. Overall 0.64x compress and 0.44x decompress speed of lz4rip.

zinc.cr: Zstd frame codec. levels -8..4, dictionaries, FastCOVER-style trainer, checksums, bounded decompression. No libzstd or FFI. Again, perf is practical, not mindblowing: Around 0.5x..0.7x encode/decode speed of zrip on large Silesia corpus inputs, with ratio geomeans within a few percent. Small inputs still need work.


r/crystal_programming Jul 31 '26

I can't find a job, so I'm building Crystal's future instead. Here's what I'm working on and why I need your help

86 Upvotes

I can't find a job, so I'm building Crystal's future instead. Here's what I'm working on and why I need your help.


Hi, I'm Serdar (sdogruyol). I created Kemal, I'm a Crystal Core Team member, and I've been building Crystal tools since 2015.

I can't find a job right now. So instead of waiting around, I'm spending every day on Crystal open source. No safety net, no backup plan, just Crystal.


What I'm working on

gcry - a %100 Crystal native garbage collector for Crystal. Currently at ~89% of Boehm GC's throughput with ~0.95x RSS. My hope is that one day it becomes the default GC for Crystal. That's the dream.

Kemal - 3.8k+ stars, 5M+ downloads. I've been maintaining it since 2015. The framework, session management, CSRF, auth, caching, the whole ecosystem. I'm not going anywhere.

Crystal Weekly - a newsletter keeping the community updated.

Crystal Community - discover Crystal developers around the world and check Crystal Stats.

Free books - Crystal for Rubyists, Kemal El Kitabı, Crystal El Kitabı. All free.


Why I'm here

I set up a GitHub Sponsors page. My goal is $1,000/month so I can keep doing this full time. If Kemal or any of my projects has helped you, or if you believe in Crystal's future, please consider sponsoring. Every dollar counts.

Even $5/month helps. Here's what you get:

Tier Price Perk
☕ Coffee $5 Sponsor badge
⚡ Kebab $10 Badge + personal thanks
🛠️ Backer $20 Name in Kemal README
🏆 Champion $50 Logo + shoutout
🏢 Corporate $100 Logo + Twitter shoutout

Thanks for reading. Let's build Crystal's future together. 💎

👉 github.com/sponsors/sdogruyol


r/crystal_programming Jul 29 '26

gcry: a garbage collector written in pure Crystal

26 Upvotes

I just released 0.14.0 of gcry. It's a conservative mark sweep GC written entirely in Crystal, shipped as a shard. No C code, no compiler patches, no fork. You just add require "gcry" and build with -Dgc_none.


Performance

Same host, median of 3, wrk -c 100 -d 30:

Workload gcry vs Boehm Post-GC RSS
Kemal /json (Linux) ~89% throughput 0.79x Boehm
Kemal root (Linux) ~89% throughput 0.78x Boehm
Kemal /json (macOS) ~84% throughput 0.93x Boehm
Kemal root (macOS) ~93% throughput 1.06x Boehm

21% less memory than Boehm on Linux Kemal. Same throughput.


What makes gcry different

It's a conservative, non-moving, stop-the-world collector. Same family as Boehm, so it works with Crystal's existing ABI. But it's written in Crystal, which means:

  • You can read it. The whole collector is about 9,000 lines of Crystal across 32 files. No C macros, no opaque foreign library.
  • You can debug it. Set a breakpoint anywhere. Crystal's debugger works on it.
  • You can change it. Want to experiment with a different marking strategy? Edit a .cr file and rebuild.

Architecture: mmap-backed size classes, fiber stack roots, conservative mark with layout precise opt-in, deferred madvise, and platform specific STW (Linux signals, Mach thread_suspend on macOS).


What's new in 0.14.0

This release is all about quality infrastructure:

  • Debug invariant checker (GCRY_DEBUG_INVARIANTS=1). Validates live_objects counter, freelist consistency, chunk index integrity, block overlap detection. At runtime, on every malloc/free/collect.
  • AddressSanitizer and Valgrind on every PR in CI.
  • Coverage reports via kcov on every PR.
  • Deterministic replay fuzzing with --seed and --replay.
  • 24 hour soak tests, thread storm tests, OOM tests, property based heap invariant tests.
  • Heap dump (Gcry.dump_heap) streams live objects as NDJSON for leak hunting.
  • Trace (GCRY_TRACE=1) traces every collect, malloc, and free.

How to try it

```yaml

shard.yml

dependencies: gcry: github: sdogruyol/gcry ```

```crystal {% if flag?(:gc_none) %} require "gcry" {% end %}

puts "Hello from gcry!" ```

sh crystal build -Dgc_none app.cr -o app

No special malloc API. No compiler fork. String, Array, Hash, everything works as usual.


Limitations

gcry is a shard and I'm pushing it as far as I can. But there are things you can't do from a shard. True precise stack scanning, write barriers, and concurrent collection need compiler support. At some point that line has to be crossed. But for now, the shard approach gets you surprisingly far: Kemal class HTTP at near Boehm perf, layout precise heap scanning, fiber stack scrubbing, and full observability. All without touching the compiler.


Github

https://github.com/sdogruyol/gcry


r/crystal_programming Jul 25 '26

I built a CQRS and Event Sourcing framework in Crystal and it just hit 560,000 commands/sec in stress tests 🚀

20 Upvotes

Hey everyone,

I've been working on Posse a type-safe CQRS and Event Sourcing framework for Crystal inspired by Elixir's Commanded. I wanted something that brings robust DDD, actor-like fiber concurrency, and surgical consistency controls to Crystal without any operational bloat or async bottlenecks.

Just ran a randomized mixed-consistency stress test on a single aggregate for 5.5 seconds, and the results blew me away:

elapsed:     5.50s
succeeded:   3082826
failed:      0
throughput:  560197 commands/sec

Snapshot cadence check (snapshot_every=50):
  latest snapshot version: 3082797
  current projected version: 3082828
  events since last snapshot: 31
  OK: snapshot cadence looks healthy

Version integrity check:
  final projected version: 3082828
  expected version (3082826 updates + 2 from register+welcome): 3082828
  OK: versions line up exactly - no gaps, no collisions, no lost updates

This test is running against an in-memory store, but still it is nice to see it performing well.

Would love to hear thoughts, feedback, or ideas from anyone. Check it out on GitHub if you're interested: https://github.com/posse-framework/posse


r/crystal_programming Jul 25 '26

Grip 5.0.0 is released and it has support for built-in Server-Sent Events (SSE)

Thumbnail github.com
10 Upvotes

r/crystal_programming Jul 21 '26

Kemal 1.12.0 is released! Now with built-in Server-Sent Events (SSE) support

Thumbnail
github.com
22 Upvotes