shirk
Version, currently 0.2.13 versions
- 0.3.0latestDec 26, 2025
- 0.2.1not indexedDec 26, 2025
- 0.2.0not indexedDec 26, 2025
github.com/ralsina/shirk
No description declared in shard.yml.
Nothing has been indexed for 0.2.1 yet. The tag is recorded, its shard.yml has not been read, so the manifest and dependency list below are empty because they are unknown rather than because they are absent.
Installation
# Add this to your shard.yml
dependencies:
shirk:
github: ralsina/shirk
version: ~> 0.2.1Then run:
shards installshard.yml
No shard.yml has been indexed for 0.2.1. You can read it on the repository.
Dependencies
Unknown: the shard.yml for this version has not been read yet.
README
This README is the one indexed from the repository at its latest ref, not from the tag for this version.
Shirk
A Crystal library for building SSH servers and clients using libssh. Provides both low-level FFI bindings and high-level callback-based APIs.
High-Level Client API
The Shirk::Client class provides a clean interface for SSH client connections:
require "shirk"
client = Shirk::Client.new("localhost", 2222, user: "admin")
# Password authentication
client.auth_password("secret")
# Or public key authentication
client.auth_publickey("~/.ssh/id_rsa")
# Execute commands
result = client.exec("whoami")
puts result.stdout # "admin"
puts result.exit_code # 0
client.disconnect
Authentication Methods
Multiple authentication methods are supported:
# Password authentication
client.auth_password("secret")
# Public key with file
client.auth_publickey("/path/to/key")
# Public key with base64 data
client.auth_publickey_base64("-----BEGIN RSA PRIVATE KEY-----...")
# SSH agent
client.auth_agent
# Check available methods
puts client.auth_methods # ["password", "publickey"]
ExecResult
Command execution returns an ExecResult with:
result.stdout- standard outputresult.stderr- standard errorresult.exit_code- process exit statusresult.success?- true if exit code is 0
Features
- Multiple authentication methods - Password, public key (file/base64), SSH agent
- Command execution with proper stdout/stderr capture
- Connection management with proper error handling
- Host key verification with configurable strictness
- Comprehensive configuration - Host, port, user, timeout, verbosity
Examples
Simple Client
crystal build examples/client_example.cr -o client
./client pubkey localhost 22 admin ~/.ssh/id_rsa
Simple Server
⚠️ Important Limitations
This library is designed for non-interactive SSH command execution, such as:
- Remote API endpoints
- Automated deployment commands
- CI/CD integrations
- Git-over-SSH servers
It is NOT suitable for:
- Interactive shells (bash, zsh, etc.)
- Full terminal emulation (PTY)
- Real-time streaming input/output
- Commands that require user interaction (vim, nano, less, etc.)
Stdin Handling
The high-level API (Shirk::Server) collects all stdin before calling your handler. This means:
- ✅
echo "data" | ssh host commandworks - all piped data is available inctx.stdin - ✅
ssh host commandwithout stdin works - handler is called after a short timeout with emptyctx.stdin - ❌ Interactive input doesn't work - there's no way to read/write incrementally
If you need more control over stdin handling, use the low-level API (see examples/ssh_server.cr) which provides raw callbacks for data as it arrives.
Requirements
- Crystal 1.0+
- libssh (install via your package manager)
Installation
Add to your shard.yml:
dependencies:
shirk:
github: ralsina/shirk
High-Level API
The Shirk::Server class provides a clean callback-based interface:
require "shirk"
server = Shirk::Server.new(
host: "0.0.0.0",
port: 2222,
host_key: "ssh_host_rsa_key"
# KEX algorithms default to include post-quantum support:
# ml-kem-768-sha256-x25519-sha256@libssh.org:sntrup761x25519-sha512@openssh.com:...
)
# Public key authentication - receives SHA256 fingerprint
server.on_auth_pubkey do |user, fingerprint|
puts "Key auth: #{user} with #{fingerprint}"
true # accept all keys
end
# Password authentication
server.on_auth_password do |user, password|
user == "admin" && password == "secret"
end
# Handle exec requests
server.on_exec do |ctx|
puts "Command: #{ctx.command}"
ctx.write("Hello, #{ctx.user}!\n")
ctx.write_stderr("No errors\n")
0 # exit code
end
server.run
High-Level Client API
The Shirk::Client class provides a clean interface for SSH client connections:
require "shirk"
client = Shirk::Client.new("localhost", 2222, user: "admin")
# Password authentication
client.auth_password("secret")
# Or public key authentication
client.auth_publickey("~/.ssh/id_rsa")
# Execute commands
result = client.exec("whoami")
puts result.stdout # "admin"
puts result.exit_code # 0
client.disconnect
Authentication Methods
Multiple authentication methods are supported:
# Password authentication
client.auth_password("secret")
# Public key with file
client.auth_publickey("/path/to/key")
# Public key with base64 data
client.auth_publickey_base64("-----BEGIN RSA PRIVATE KEY-----...")
# SSH agent
client.auth_agent
# Check available methods
puts client.auth_methods # ["password", "publickey"]
ExecResult
Command execution returns an ExecResult with:
result.stdout- standard outputresult.stderr- standard errorresult.exit_code- process exit statusresult.success?- true if exit code is 0
ExecContext
The on_exec callback receives an ExecContext with:
ctx.command- the command stringctx.user- authenticated usernamectx.stdin- all stdin data from client (collected before handler runs)ctx.write(data)- write to stdoutctx.write_stderr(data)- write to stderr- Return value is the exit code
Features
- Post-quantum cryptography - supports ML-KEM-768x25519 and SNTRUP761x25519 key exchange algorithms by default
- Fork model - each connection runs in a child process for isolation
- Password auth via
on_auth_passwordcallback - Public key auth via
on_auth_pubkeycallback (receives SHA256 fingerprint) - Exec handling with proper stdout/stderr/exit status
- Shell support via
on_shellcallback (optional)
Low-Level API
For more control, use the FFI bindings directly. See examples/ssh_server.cr for a complete example that closely follows the libssh C API.
Examples
Simple Server
crystal build examples/simple_server.cr -o simple_server
./simple_server
Test with:
ssh -p 2222 admin@localhost # password: secret
# or with Python
python3 -c "import paramiko; c=paramiko.SSHClient(); c.set_missing_host_key_policy(paramiko.AutoAddPolicy()); c.connect('localhost',2222,username='admin',password='secret'); print(c.exec_command('whoami')[1].read())"
Simple Client
# Password authentication
crystal run examples/client_example.cr -- password localhost 2222 admin secret
# Public key authentication
crystal run examples/client_example.cr -- pubkey localhost 2222 admin ~/.ssh/id_rsa
# SSH agent authentication
crystal run examples/client_example.cr -- agent localhost 2222 admin
Generate Host Key
ssh-keygen -t rsa -b 2048 -f ssh_host_rsa_key -N ""
Development
shards install
crystal spec
crystal build examples/simple_server.cr
Contributing
- Fork it (https://github.com/ralsina/shirk/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
Contributors
- Roberto Alsina - creator and maintainer
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
0.2.1- Tagged
- Dec 26, 2025
- Commit
38de21ba56f9- Indexed
- not yet
Dependents
Repository
github.com/ralsina/shirk
Metadata
- Created
- Aug 12, 2026
- Updated
- Sep 26, 2026
- Synced
- Sep 26, 2026
- Versions
- 3