pasto
Version, currently 0.12.521 versions
- 0.12.5latestMay 4, 2026
- 0.12.4not indexedMay 4, 2026
- 0.12.3not indexedMay 4, 2026
- 0.12.2not indexedMay 4, 2026
- 0.12.1not indexedMay 4, 2026
- 0.12.0not indexedMay 4, 2026
- 0.11.1not indexedMay 4, 2026
- 0.11.0not indexedMay 4, 2026
- 0.10.0not indexedMay 4, 2026
- 0.9.1not indexedMay 4, 2026
- 0.9.0not indexedMay 4, 2026
- 0.8.0not indexedMay 4, 2026
- 0.7.1not indexedMay 4, 2026
- 0.7.0not indexedMay 4, 2026
- 0.6.0not indexedMay 4, 2026
- 0.5.0not indexedMay 4, 2026
- 0.4.0not indexedMay 4, 2026
- 0.3.0not indexedMay 4, 2026
- 0.2.0not indexedMay 4, 2026
- 0.1.1not indexedMay 4, 2026
- 0.1.0not indexedMay 4, 2026
github.com/ralsina/pasto
Crystal-based pastebin application with live syntax highlighting preview and extensive theme support
28 stars
0 dependents
License: MIT
Installation
# Add this to your shard.yml
dependencies:
pasto:
github: ralsina/pasto
version: ~> 0.12.5Then run:
shards installshard.yml
- Crystal
1.13.0- License
- MIT
- Author
- ralsina <ralsina@kde.org>
- Targets
pastofrom src/pasto.crpasto-clifrom src/pasto_cli.crpasto-sshfrom src/pasto_ssh.crpasto-backupfrom src/pasto_backup.crpasto-cryptofrom src/pasto_crypto.cr
- Executables
pastopasto-sshpasto-backuppasto-cryptopasto-cli
Dependencies
Runtime Dependencies
- mcp*github: ralsina/mcp
- hansa*github: ralsina/hansa
- kemal*github: kemalcr/kemal
- sepia*github: ralsina/sepia
- shirk*github: ralsina/shirk
- tartrazine*github: ralsina/tartrazine
- kemal-cache*github: kemalcr/kemal-cache
- rate_limiter*github: ralsina/rate_limiter
- docopt-config*github: ralsina/docopt-config
- kemal-session*github: kemalcr/kemal-session
- baked_file_handler*github: ralsina/baked_file_handler
README
# Pasto
A Crystal-based pastebin application with live syntax highlighting, SSH access, user accounts, and extensive theme support.


## Features
### Core Features
- 🚀 **Fast & Lightweight**: Built with Crystal for excellent performance
- 🎨 **Live Preview**: Real-time syntax highlighting as you type
- 🌈 **Extensive Theming**: 321+ syntax highlighting themes from Tartrazine
- 🎭 **Smart Language Detection**: Auto-detects language with Hansa classification
- 📱 **Responsive Design**: Works beautifully on desktop and mobile
- 🔒 **Built-in Security**: Rate limiting and size validation
### SSH Access
- 🔑 **SSH Paste Creation**: Create pastes directly via SSH (`cat file | ssh pasto.example.com`)
- 👤 **SSH Key Authentication**: Your SSH key becomes your identity
- 🔗 **Automatic Account Linking**: SSH keys automatically linked to user accounts
### User Accounts & Profiles
- 📋 **User Profiles**: View and manage all your pastes in one place
- ✏️ **Editable Display Names**: Personalize your profile
- 🎨 **Theme Preferences**: UI and syntax theme preferences saved per user
- 🔐 **Session Management**: Secure web sessions with cookie-based auth
### Paste Management
- 📝 **Paste Titles**: Add optional titles or auto-generate from content
- 📜 **Version History**: Full edit history with Sepia versioning
- 🕐 **View Past Versions**: Browse and compare previous versions
- ✏️ **Edit Your Pastes**: Modify pastes you own
- 🗑️ **Delete Pastes**: Remove pastes from your profile
### Modern UI
- 🎯 **Clean Interface**: Modern design with Pico CSS and Lucide icons
- 📐 **Collapsible Sidebar**: Theme controls in a space-saving sidebar
- ⌨️ **CodeJar Editor**: Lightweight code editor with syntax highlighting
- 🔄 **Live Preview Pane**: See rendered output as you type
### AI Assistant Integration (MCP)
- 🤖 **Model Context Protocol**: Native MCP support for AI assistant integration
- 🔧 **Zero Installation**: AI assistants can access pastes without local setup
- 🛡️ **Secure Access**: Uses existing API keys and authentication
- 📝 **Full CRUD**: Create, retrieve, list, update, and delete pastes via MCP
- 🎯 **Tool Discovery**: AI assistants automatically discover available paste operations
## Quick Start
### Docker (Recommended)
The easiest way to run Pasto is with Docker Compose:
```bash
# Clone the repository
git clone https://github.com/ralsina/pasto.git
cd pasto
# Start Pasto (web + SSH server)
docker compose up -d
# View logs
docker compose logs -f
# Stop Pasto
docker compose down
```
The services will be available at:
- **Web interface**: <http://localhost:3000>
- **SSH access**: `ssh -p 2222 localhost`
- **CLI tool**: `pasto-cli --server=localhost login` (see [CLI.md](CLI.md))
#### Docker Configuration
The `docker-compose.yml` file includes:
- **pasto** service: Web interface on port 3000
- **pasto-ssh** service: SSH server on port 2222
- **Persistent volumes** for data, sessions, cache, and SSH keys
To customize, edit the environment variables in `docker-compose.yml`:
```yaml
environment:
PASTO_PORT: 3000
PASTO_MAX_PASTE_SIZE: 1048576 # 1MB
PASTO_THEME: monokai
PASTO_RATE_LIMIT: 10
PASTO_SESSION_SECRET: "your-secret-here" # Change in production!
```
#### Volumes
| Volume | Path | Description |
|--------|------|-------------|
| `pasto-data` | `/app/data` | Pastes, users, SSH keys (back this up!) |
| `pasto-sessions` | `/app/sessions` | Web sessions |
| `pasto-cache` | `/app/public/cache` | Rendered HTML cache |
| `pasto-ssh-keys` | `/app/ssh-keys` | SSH host keys |
#### Backup
```bash
# Backup all data
docker compose exec pasto tar -czf - /app/data > pasto-backup.tar.gz
# Or copy volumes
docker run --rm -v pasto-data:/data -v $(pwd):/backup alpine \
tar -czf /backup/pasto-data-backup.tar.gz /data
```
### Manual Installation
```bash
# Clone the repository
git clone https://github.com/ralsina/pasto.git
cd pasto
# Install dependencies
shards install
# Build the application
shards build --release
# Run the server
./bin/pasto
```
### SSH Usage
Create a paste via SSH:
```bash
# Simplest form - just pipe content
cat myfile.py | ssh -p 2222 pasto.example.com
# Or use echo
echo "Hello, World!" | ssh -p 2222 pasto.example.com
# Redirect from file
ssh -p 2222 pasto.example.com < myfile.py
# Explicit paste command (also works)
cat myfile.py | ssh -p 2222 pasto.example.com paste
```
The server returns the URL of your new paste.
Other SSH commands:
```bash
# Login to link SSH key with web account
ssh -p 2222 pasto.example.com login
# Show help
ssh -p 2222 pasto.example.com help
```
### CLI Usage
The `pasto-cli` tool provides a convenient command-line interface for Pasto:
```bash
# Login to a Pasto server (SSH authentication)
pasto-cli --server=pasto.example.com --ssh-port=2222 login
# Create a paste
echo 'print("Hello, World!")' | pasto-cli paste --language=python
# List your pastes
pasto-cli list
# Get a paste
pasto-cli get <paste-id>
# Delete a paste
pasto-cli delete <paste-id>
```
The CLI supports:
- **SSH-based authentication** using your SSH keys
- **Automatic host derivation** - specify `--server` or `--ssh-host`, the other is auto-detected
- **Terminal hyperlinks** - clickable paste IDs in supported terminals
- **Human-readable timestamps** - relative time display
- **Full CRUD operations** - create, read, update, delete pastes
- **Credential storage** - saves API keys securely in `~/.config/pasto/credentials.yml`
For detailed CLI documentation, see [CLI.md](CLI.md).
### Zero-Knowledge Encryption
Pasto supports **zero-knowledge encryption** where you encrypt content locally before sending it to the server. The server never sees your password or can decrypt your content.
#### Using pasto-crypto CLI Tool
The `pasto-crypto` tool enables you to encrypt content locally using AES-256-GCM encryption with PBKDF2 key derivation.
**Encrypt content locally:**
```bash
# Encrypt with a random password (recommended for maximum security)
./bin/pasto-crypto encrypt --random-pass --output encrypted.txt input.txt
# Output: Environment variables needed for decryption
# PASTO_PASSWORD=wxyeniX58PDup7O!VR2UGyQejOib%pk!
# PASTO_SALT=SEp4IYOd36ICRA4szDdy2w==
# PASTO_IV=wCKCNS9IW3r/48Md
# PASTO_ITERATIONS=100000
```
**Create encrypted paste via SSH:**
```bash
# Save the environment variables from encryption
export PASTO_PASSWORD="wxyeniX58PDup7O!VR2UGyQejOib%pk!"
export PASTO_SALT="SEp4IYOd36ICRA4szDdy2w=="
export PASTO_IV="wCKCNS9IW3r/48Md"
# Create paste with zero-knowledge encryption
cat encrypted.txt | ssh -p 2222 pasto.example.com paste \
--iv "$PASTO_IV" \
--salt "$PASTO_SALT" \
--iterations 100000
```
**Decrypt in the browser:**
1. Open the paste URL in your browser
2. Enter the **password** (not the key!) when prompted
3. The content is decrypted client-side using Web Crypto API
**What makes it zero-knowledge?**
- **Password stays with you**: The server only stores the salt and IV, never the password
- **PBKDF2 key derivation**: Your password is securely stretched with 100,000 iterations
- **AES-256-GCM encryption**: Military-grade encryption
- **Client-side decryption**: Content is decrypted in your browser, not on the server
- **Server can't read**: Even if the server is compromised, your encrypted pastes remain secure
**Full example workflow:**
```bash
# 1. Create a file with sensitive content
cat > secret.txt <<EOF
API_KEY=sk_live_1234567890abcdef
DATABASE_URL=postgres://user:pass@localhost/db
EOF
# 2. Encrypt it locally with a random password
./bin/pasto-crypto encrypt --random-pass --output secret.enc secret.txt
# 3. Save the credentials (keep these safe!)
export PASTO_PASSWORD="iJOK#rPpD!GfRwBA5kQZT@0RA5YV7GCG"
export PASTO_SALT="utJ7JzIALDE9Ak1WzCGOnQ=="
export PASTO_IV="AwnXIR7s2313cdBr"
# 4. Create the paste via SSH
cat secret.enc | ssh -p 2222 pasto.example.com paste \
--iv "$PASTO_IV" \
--salt "$PASTO_SALT" \
--title "Production Credentials"
# Output: http://pasto.example.com/abc123-def456
# 🔐 Zero-trust encrypted paste created
# 5. Share the URL + PASSWORD with your teammate
# Teammate opens URL, enters password, and sees decrypted content
# The server administrators cannot see the content even if they wanted to!
```
**Decrypting locally (optional):**
```bash
# Decrypt the encrypted file back to plaintext
./bin/pasto-crypto decrypt \
--password "$PASTO_PASSWORD" \
--salt "$PASTO_SALT" \
--iv "$PASTO_IV" \
--output decrypted.txt \
encrypted.txt
```
**Security best practices:**
- Use `--random-pass` for generating strong passwords
- Save the password securely (password manager, not in plain text files)
- Share the password through a different channel than the paste URL
- The server stores `encryption_iv` and `encryption_salt` but cannot decrypt without your password
### Web Usage
1. Navigate to `http://localhost:3000`
2. Type or paste your code in the editor
3. Watch the live preview update
4. Click **+** to create the paste
## Configuration
Pasto supports three configuration methods (in order of priority):
1. **Command line arguments**
2. **Environment variables** (prefixed with `PASTO_`)
3. **Configuration file** (`pasto.yml`)
### Command Line Options
```bash
./bin/pasto \
--port 3000 \
--bind 0.0.0.0 \
--max-paste-size 102400 \
--theme default-dark \
--ssh-enabled true \
--ssh-port 2222 \
--storage-dir ./data \
--cache-dir ./public/cache
```
### Environment Variables
```bash
export PASTO_PORT=3000
export PASTO_MAX_PASTE_SIZE=102400
export PASTO_THEME=monokai
export PASTO_SSH_ENABLED=true
export PASTO_SSH_PORT=2222
export PASTO_RATE_LIMIT=10
```
### Configuration File (`pasto.yml`)
```yaml
port: 3000
bind: "0.0.0.0"
max_paste_size: 102400 # 100KB
theme: default-dark
ssh_enabled: true
ssh_port: 2222
storage_dir: ./data
cache_dir: ./public/cache
rate_limit: 10
rate_window: 60
```
## API Endpoints
### Create Paste (Web)
```bash
curl -X POST http://localhost:3000 \
-d "content=print('Hello!')&language=python&title=My%20Paste"
```
### View Paste
```bash
# View paste
curl http://localhost:3000/{paste-id}
# View with language override
curl http://localhost:3000/{paste-id}?lang=python
# View with file extension
curl http://localhost:3000/{paste-id}.py
```
### View Paste History
```bash
# View all versions (owner only)
curl http://localhost:3000/{paste-id}/history
# View specific version
curl http://localhost:3000/{paste-id}/version/1
```
### Live Highlighting API
```bash
curl -X POST http://localhost:3000/highlight \
-d "content=def hello(): pass&language=python&theme=monokai"
```
## AI Assistant Integration (MCP)
Pasto supports the **Model Context Protocol (MCP)**, enabling AI assistants like Claude to directly interact with your pastes. This allows AI assistants to create, retrieve, and manage pastes without any local setup.
### Getting Started
1. **Generate an API Key**: Visit `/profile` on your Pasto instance and click "Generate API Key"
2. **Copy the API Key**: It will start with `pasto_ak_`
3. **Configure Your AI Assistant**: Use the MCP client configuration below
### MCP Tools Available
Pasto provides these MCP tools for AI assistants:
#### create_paste
Create a new paste with content and optional metadata.
**Parameters:**
- `content` (required): The paste content
- `title` (optional): Paste title
- `language` (optional): Programming language for syntax highlighting
- `filename` (optional): Filename for language detection
- `private` (optional): Make paste private (default: false)
- `encrypted` (optional): Encrypt paste content (default: false)
- `burn_after_reading` (optional): Delete after first view (default: false)
- `expires_in` (optional): Expiration time - "1h", "1d", "1w", "1m", "never"
**Example:**
```
Please create a paste with this Python code: print("Hello, World!")
Make it private and set it to expire in 1 week.
```
#### get_paste
Retrieve paste content and metadata by ID.
**Parameters:**
- `id` (required): The paste ID to retrieve
**Example:**
```
Please retrieve the paste with ID abc123 and show me its details.
```
#### list_pastes
List user's pastes with pagination and filtering.
**Parameters:**
- `page` (optional): Page number (default: 1)
- `limit` (optional): Items per page, max 100 (default: 20)
- `private_only` (optional): Filter to private pastes only
- `public_only` (optional): Filter to public pastes only
- `encrypted_only` (optional): Filter to encrypted pastes only
- `language` (optional): Filter by programming language
**Example:**
```
Show me my private Python pastes, 10 at a time.
```
#### update_paste
Update an existing paste's content or metadata (creates new version).
**Parameters:**
- `id` (required): The paste ID to update
- `content` (required): New content for the paste
- `title` (optional): New title
- `language` (optional): New programming language
- `filename` (optional): New filename
- `private` (optional): Make paste private
- `burn_after_reading` (optional): Set burn-after-reading flag
- `expires_in` (optional): Update expiration time
**Example:**
```
Update paste xyz789 with this new JavaScript code and make it public.
```
#### delete_paste
Permanently delete a paste.
**Parameters:**
- `id` (required): The paste ID to delete
- `confirm` (required): Set to true to confirm deletion
**Example:**
```
Please permanently delete paste xyz789 and confirm you want to do this.
```
### Claude Desktop Configuration
Add this to your Claude Desktop configuration:
```json
{
"mcpServers": {
"pasto": {
"transport": "http",
"url": "https://your-pasto-instance.com/mcp",
"headers": {
"Authorization": "Bearer pasto_ak_xxxxxxxxxxxx"
}
}
}
}
```
### Usage Examples
#### Creating a Paste
```
User: Create a paste with this Rust code:
fn main() {
println!("Hello, Pasto!");
}
Claude: I'll create a paste with that Rust code for you.
✅ Paste created successfully!
🔗 URL: https://your-pasto-instance.com/abc123
📝 ID: abc123
🏷️ Title: Untitled
🔐 Private: false
🔒 Encrypted: false
```
#### Listing Your Pastes
```
User: Show me my recent pastes
Claude: 📄 **Your Pastes (Page 1 of 1)**
📊 Total: 5 pastes | Showing: 20 per page
🌐 **My Rust Script** (abc123)
🔤 rust
📅 2024-12-22T10:30:00Z
⏰ Never expires
🔐**Secret Algorithm** (def456)
🔒 python
📅 2024-12-21T15:45:00Z
⏰ Expires: 2024-12-28T15:45:00Z
```
### Security
- **Authentication Required**: All MCP requests require valid API keys
- **Permission Control**: Users can only access their own pastes
- **Rate Limiting**: MCP endpoints respect existing rate limits
- **HTTPS Recommended**: Use HTTPS in production environments
### Troubleshooting
**Authentication Errors**: Ensure your API key starts with `pasto_ak_` and is valid.
**Permission Denied**: Make sure you're trying to access your own pastes.
**Not Found**: Verify the paste ID exists and hasn't expired.
## Supported Languages
Pasto supports 35+ programming languages including:
- **Popular**: Python, JavaScript, TypeScript, Java, C, C++, C#, Go, Rust
- **Web**: HTML, CSS, SCSS, Sass, JSON, XML, YAML, Markdown
- **Systems**: Bash, Shell, PowerShell, Dockerfile
- **Data**: SQL, MySQL, PostgreSQL, CSV
- **And more**: PHP, Ruby, Perl, Kotlin, Scala, ActionScript...
*Only languages with working Tartrazine lexers are available.*
## Theme Support
### UI Themes (Pico CSS)
- 15 color schemes: Slate, Zinc, Gray, Neutral, Stone, Red, Orange, Amber, Yellow, Lime, Green, Emerald, Cyan, Sky, Indigo, Violet, Fuchsia, Pink
- Light/Dark/Auto modes with system preference detection
### Syntax Themes (Tartrazine)
- 321+ themes including popular ones like Dracula, Monokai, Nord, Solarized, One Dark, GitHub, VS Code themes, and many more
## Project Structure
```
pasto/
├── src/
│ ├── pasto.cr # Entry point, configuration
│ ├── server.cr # Kemal routes and middleware
│ ├── paste.cr # Paste model, highlighting, themes
│ ├── pasto_ssh.cr # SSH server entry point
│ └── views/
│ ├── layout.ecr # Main layout with sidebar
│ ├── index.ecr # Create paste page
│ ├── show.ecr # View paste page
│ ├── edit.ecr # Edit paste page
│ ├── history.ecr # Version history page
│ └── profile_content.ecr # User profile
├── data/ # Sepia storage directory
├── public/cache/ # Cached rendered pastes
├── sessions/ # Session storage
└── pasto.yml # Configuration file
```
## Development
```bash
# Install dependencies
shards install
# Build
shards build
# Build release
shards build --release
# Run tests
crystal spec
# Format code
crystal tool format src/
# Lint
./bin/ameba src/
```
## Security Features
- **Rate Limiting**: Configurable per-IP rate limits
- **Size Validation**: Maximum paste size enforcement
- **HTML Escaping**: All content properly sanitized
- **Session Security**: Secure cookie-based sessions
- **SSH Key Auth**: Public key authentication for SSH access
## Dependencies
- **[Kemal](https://kemalcr.com/)**: Web framework
- **[Tartrazine](https://github.com/ralsina/tartrazine)**: Syntax highlighting (321+ themes)
- **[Hansa](https://github.com/ralsina/hansa)**: Language classification
- **[Sepia](https://github.com/ralsina/sepia)**: Object persistence with versioning
- **[Shirk](https://github.com/ralsina/shirk)**: SSH server
- **[Pico CSS](https://picocss.com/)**: Minimal CSS framework
- **[Lucide](https://lucide.dev/)**: Icon library
- **[CodeJar](https://medv.io/codejar/)**: Code editor
## License
MIT License - see [LICENSE](LICENSE) for details.
## Author
Created by [Roberto Alsina](https://github.com/ralsina)
---
**Pasto** - Modern pastebin with SSH access and live preview.
## Public Instance
A public Pasto instance is available at [https://pasto1.ralsina.me](https://pasto1.ralsina.me).
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
0.12.5- Tagged
- May 4, 2026
- Commit
6d601017afe6- Crystal
1.13.0- Indexed
- yes
Dependents
No indexed shard depends on this one yet.
Repository
github.com/ralsina/pasto
Metadata
- Created
- Aug 12, 2026
- Updated
- Aug 12, 2026
- Synced
- Aug 12, 2026
- Versions
- 21