From watzon-claude-code
Use this skill when working with the Crystal programming language. Crystal is a statically-typed, compiled language with Ruby-like syntax. It features type inference, null safety, macros, and compiles to efficient native code. Use for understanding Crystal's standard library, syntax, semantics, concurrency model, and FFI bindings.
npx claudepluginhub joshuarweaver/cascade-code-languages-misc-2 --plugin watzon-claude-codeThis skill uses the workspace's default tool permissions.
Use this skill when working with the Crystal programming language. a statically-typed, compiled language with Ruby-like syntax that combines Ruby's coding efficiency with C's runtime performance.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Use this skill when working with the Crystal programming language. a statically-typed, compiled language with Ruby-like syntax that combines Ruby's coding efficiency with C's runtime performance.
This skill should be triggered when:
Int32 | String)String?) must be checked before useArray(T), Hash(K, V))Hello World
# hello.cr
puts "Hello, World!"
Variables and Types
name = "Crystal" # : String
count = 42 # : Int32
pi = 3.14 # : Float64
enabled = true # : Bool
nothing = nil # : Nil
# Type annotations work too
x : Int32 = 10
String Interpolation
name = "World"
puts "Hello, #{name}!" # => Hello, World!
Defining Methods
def greet(name : String) : String
"Hello, #{name}!"
end
def add(x : Int32, y : Int32) : Int32
x + y
end
Default Arguments
def greet(name : String, enthusiastic : Bool = false)
message = "Hello, #{name}"
enthusiastic ? "#{message}!" : message
end
Blocks and Procs
# Using a block
[1, 2, 3].map { |x| x * 2 } # => [2, 4, 6]
# Short syntax
[1, 2, 3].map(&.to_s) # => ["1", "2", "3"]
# Storing a block
double = ->(x : Int32) { x * 2 }
double.call(5) # => 10
If/Else
if count > 0
puts "Positive"
elsif count < 0
puts "Negative"
else
puts "Zero"
end
# Ternary
result = count > 0 ? "positive" : "non-positive"
Case/When
case value
when 1, 2, 3
puts "Small"
when 4..10
puts "Medium"
else
puts "Large"
end
Unless
puts "Access denied" unless user.logged_in?
Class Definition
class Person
property name : String
property age : Int32
def initialize(@name : String, @age : Int32)
end
def greet : String
"Hi, I'm #{@name}, #{@age} years old"
end
end
person = Person.new("Alice", 30)
person.greet # => "Hi, I'm Alice, 30 years old"
Inheritance
class Employee < Person
def initialize(@name : String, @age : Int32, @title : String)
super(@name, @age)
end
end
Structs for Value Types
struct Point
property x : Float64
property y : Float64
def initialize(@x : Float64, @y : Float64)
end
end
Arrays
# Literal
numbers = [1, 2, 3, 4, 5]
# Operations
numbers << 6 # append
numbers.first # => 1
numbers.last # => 5
numbers.size # => 5
numbers.includes?(3) # => true
numbers.map { |x| x * 2 } # => [2, 4, 6, 8, 10]
Hashes
# Literal
scores = {"Alice" => 100, "Bob" => 95}
# Access
scores["Alice"] # => 100
scores["Charlie"]? # => nil (safe access)
scores.fetch("Dave", 0) # => 0 (default)
Ranges
1..10 # inclusive range
1...10 # exclusive range
('a'..'z').to_a.first(3) # => ['a', 'b', 'c']
Union Types
def process(value : Int32 | String)
# Methods must exist for ALL types in the union
value.to_s
end
Nilable Types
def find_user(id : Int32) : User?
# Returns User or nil
users.find { |u| u.id == id }
end
user = find_user(1)
if user
puts user.name # user is guaranteed non-nil here
end
# Safe navigation
name = user&.name || "Unknown"
Type Narrowing
value = rand > 0.5 ? 42 : "hello"
if value.is_a?(Int32)
value.abs # Compiler knows value is Int32 here
else
value.size # Compiler knows value is String here
end
Begin/Rescue/Ensure
begin
File.read("nonexistent.txt")
rescue ex : FileNotFoundError
puts "File not found: #{ex.message}"
rescue ex : Exception
puts "Error: #{ex.message}"
ensure
puts "Cleanup code runs here"
end
Custom Exceptions
class MyError < Exception
end
raise MyError.new("Something went wrong")
Spawning Fibers
spawn do
puts "Running in background"
sleep 1
puts "Done"
end
puts "Main continues"
Fiber.yield # Let other fibers run
Channels
channel = Channel(Int32).new
spawn do
channel.send(42)
end
result = channel.receive # Blocks until value is available
puts result # => 42
Async Operations
def fetch_data : String
"data"
end
# Non-blocking with spawn
spawn { puts fetch_data }
Fiber.yield
Compile-time Execution
# Run shell command at compile time
{% `echo "compiled at build time"` %}
# Check compile-time flags
{% if flag?(:x86_64) %}
puts "Running on 64-bit architecture"
{% end %}
Macro Methods
macro define_method(name, content)
def {{name}}
{{content}}
end
end
define_method(:greet, puts "Hello from macro!")
Reading Files at Compile Time
# Embed file contents at compile time
VERSION = {{ read_file("VERSION.txt").strip }}
Reading Files
# Read entire file
content = File.read("file.txt")
# Read line by line
File.each_line("file.txt") do |line|
puts line
end
# Check file exists
if File.exists?("file.txt")
puts "File exists"
end
Writing Files
# Write string to file
File.write("output.txt", "Hello, File!")
# Append to file
File.open("log.txt", "a") do |file|
file.puts "Log entry"
end
Parsing JSON
require "json"
data = JSON.parse(%({"name": "Alice", "age": 30}))
data["name"].as_s # => "Alice"
data["age"].as_i # => 30
Generating JSON
require "json"
hash = {"name" => "Bob", "age" => 25}
JSON.build do |json|
json.object do
json.field "name", hash["name"]
json.field "age", hash["age"]
end
end
JSON Mapping
require "json"
class User
include JSON::Serializable
property name : String
property age : Int32
end
user = User.from_json(%({"name": "Charlie", "age": 35}))
user.to_json # => %({"name":"Charlie","age":35})
Simple GET Request
require "http"
response = HTTP.get("https://api.example.com/data")
puts response.status_code # => 200
puts response.body
POST with JSON Body
require "http"
response = HTTP.post("https://api.example.com/users",
headers: {"Content-Type" => "application/json"},
body: %({"name": "Dave"}).to_json
)
HTTP Client with Persistent Connection
require "http"
client = HTTP::Client.new("https://api.example.com")
response = client.get("/endpoint")
client.close
Parsing XML
require "xml"
xml = <<-XML
<person id="1">
<firstname>Jane</firstname>
<lastname>Doe</lastname>
</person>
XML
document = XML.parse(xml)
person = document.first_element_child
if person
puts person["id"] # => "1"
puts person.content # => "Jane"
end
Building XML
require "xml"
string = XML.build(indent: " ") do |xml|
xml.element("person", id: 1) do
xml.element("firstname") { xml.text "Jane" }
xml.element("lastname") { xml.text "Doe" }
end
end
Declaring External Library
lib LibC
fun strlen(s : UInt8*) : SizeT
end
# Call C function
LibC.strlen(pointer)
C Linking
@[Link("pcre")]
lib LibPCRE
fun pcre_compile(pattern : UInt8*) : Pointer(Void)
end
Pointer Operations
x = 1
ptr = pointerof(x)
ptr.value = 2
puts x # => 2
# Allocated memory
ptr = Pointer.malloc(2, 42)
ptr[0] # => 42
ptr[1] # => 42
require "bit_array"
ba = BitArray.new(12) # => "BitArray[000000000000]"
ba[2] # => false
0.upto(5) { |i| ba[i * 2] = true }
ba # => "BitArray[101010101010]"
ba[2] # => true
# Union simplification
Union(Int32 | String) # => (Int32 | String)
Union(Int32) # => Int32
Union(Int32, Int32, Int32) # => Int32
require "weak_ref"
ref = WeakRef.new("oof".reverse)
p ref # => #<WeakRef(String):...>
GC.collect
p ref # => #<WeakRef(String):... @target=Pointer.null>
p ref.value # => nil
This skill includes comprehensive documentation in references/:
getting_started.md)standard_library.md)syntax_and_semantics.md){% %} for compile-time code# : TypeName commentsTo refresh this skill with updated documentation: