# 🐦 ssky - Simple Bluesky Client

A lightweight, command-line Bluesky client that makes it easy to interact with the Bluesky social network from your terminal.

## ✨ Features

- 🔑 Simple authentication and session management
- 📝 Post, reply, quote, and repost content
- 🔍 Search posts and users
- 👥 Follow/unfollow users
- 📊 View timelines and profiles
- 🖼️ Support for images and link cards
- 📦 Linux shell friendly output formats

## 🚀 Quick Start

### Installation

```bash
pip install ssky
```

### Login

```bash
ssky login your-handle.bsky.social:your-password
```

Or set credentials via environment variable:
```bash
export SSKY_USER=your-handle.bsky.social:your-password
```

### Configuration

By default, ssky stores session data in `~/.ssky`. You can customize this location using the `SSKY_CONFIG_PATH` environment variable:

```bash
# Use a custom session file location
export SSKY_CONFIG_PATH=/path/to/custom/session
ssky login your-handle.bsky.social:your-password

# Useful for testing or managing multiple accounts
export SSKY_CONFIG_PATH=~/.ssky-test
```

**Note:** The `SSKY_CONFIG_PATH` must be set before running ssky commands, as it's evaluated when the session module is first loaded.

## 📖 Basic Usage

### Posting

```bash
# Simple post
ssky post "Hello, Bluesky!"

# Post with images
ssky post "Check out these photos!" --image photo1.jpg --image photo2.jpg

# Reply to a post
ssky post "Great post!" --reply-to at://did:plc:.../app.bsky.feed.post/...

# Quote a post
ssky post "Interesting!" --quote at://did:plc:.../app.bsky.feed.post/...
```

### Reading

```bash
# View your timeline
ssky get

# View your timeline with full threads
ssky get --thread

# Get specific post with its thread
ssky get at://did:plc:.../app.bsky.feed.post/... --thread

# Get user's posts as threads with custom depth
ssky get user.bsky.social --thread --thread-depth 5 --thread-parent-height 2

# View someone's profile
ssky profile user.bsky.social

# Search posts
ssky search "keyword"

# Search users
ssky user "username"
```

### Social Actions

```bash
# Follow a user
ssky follow user.bsky.social

# Repost a post
ssky repost at://did:plc:.../app.bsky.feed.post/...

# Delete a post
ssky delete at://did:plc:.../app.bsky.feed.post/...
```

## 🔧 Advanced Usage

### Thread Retrieval

Retrieve posts along with their complete conversation threads:

```bash
# Get timeline with full threads (each post expanded to its thread)
ssky get --thread

# Get specific post's thread
ssky get at://did:plc:.../app.bsky.feed.post/... --thread

# Get user's posts as threads
ssky get user.bsky.social --thread

# Control thread depth (default: 10 replies deep)
ssky get --thread --thread-depth 5

# Include parent posts (default: 0 parents)
ssky get --thread --thread-parent-height 2

# Save threads to files
ssky get --thread --output ./threads
```

**Thread Output Formatting:**
- **Short/ID format** (`-S`, `-I`): Reply lines prefixed with `"| "`
- **Long/Text format** (`-L`, `-T`): Posts within thread separated by `"|"`, independent threads by `"----------------"`
- **JSON/simple-json**: Cannot be used with `--thread` (returns error)

### Output Formats

```bash
# Get only post IDs
ssky get --id

# Get only text content
ssky get --text

# Get full JSON output
ssky get --json

# Get simplified JSON with facets metadata (ideal for programmatic access)
ssky get --simple-json

# Save posts to files
ssky get --output ./posts
```

#### Facets Metadata in Simple-JSON

The `--simple-json` format includes structured facets metadata for rich text features:

- **links**: URLs with byte positions and text
- **mentions**: User mentions with handles, DIDs, and byte positions
- **tags**: Hashtags with byte positions and text

Example output:
```json
{
  "status": "success",
  "data": [{
    "uri": "at://...",
    "cid": "...",
    "author": {
      "did": "did:plc:...",
      "handle": "user.bsky.social",
      "display_name": "User Name",
      "avatar": "https://..."
    },
    "text": "Check out https://example.com @user.bsky.social #bluesky",
    "created_at": "2024-01-01T00:00:00.000Z",
    "facets": {
      "links": [
        {
          "url": "https://example.com",
          "byte_start": 10,
          "byte_end": 30,
          "text": "https://example.com"
        }
      ],
      "mentions": [
        {
          "handle": "user.bsky.social",
          "did": "did:plc:...",
          "byte_start": 31,
          "byte_end": 49,
          "text": "@user.bsky.social"
        }
      ],
      "tags": [
        {
          "tag": "bluesky",
          "byte_start": 50,
          "byte_end": 58,
          "text": "#bluesky"
        }
      ]
    }
  }]
}
```

### Useful Examples

```bash
# Reply to your last post
ssky post "Update!" --reply-to $(ssky get myself --limit 1 --id)

# Search your own posts
ssky search "keyword" --author myself

# Save your timeline to files
ssky get --output ./timeline
```

## 🤖 IDE Integration

### Cursor Agent MCP Tools

`ssky` provides comprehensive MCP (Model Context Protocol) tools for seamless integration with Cursor Agent, enabling AI-powered Bluesky interactions directly in your development environment.

**Features:**
- 📋 **10 comprehensive tools**: Complete Bluesky functionality
- 🤖 **AI-optimized**: Long format defaults for better AI understanding  
- 🔧 **Full feature support**: Posts with images, quotes, replies, search, social actions
- ⚡ **Real-time integration**: Direct Bluesky interaction from Cursor

**Quick Setup:**
```bash
# For new MCP setup: copy sample configuration (no build required!)
mkdir -p .cursor
cp mcp/mcp.sample.json .cursor/mcp.json

# Set your Bluesky credentials
export SSKY_USER=your-handle.bsky.social:your-password

# Restart Cursor to load the MCP tools
```

✨ **Docker will automatically pull the pre-built image on first use!**

**Advanced Setup:**
- **For existing MCP setup**: Add ssky server to your `.cursor/mcp.json` (see `mcp/mcp.sample.json`)
- **For local development**: Use `cd mcp && ./build.sh && cd ..` to build locally
- **Complete guide**: See [MCP Documentation](mcp/SSKY_MCP_GUIDE.md)

**Available Tools:**
- `ssky_get`, `ssky_search`, `ssky_user`, `ssky_profile` - Content retrieval
- `ssky_post` - Content creation with images/quotes/replies
- `ssky_follow`, `ssky_unfollow`, `ssky_repost`, `ssky_unrepost` - Social actions
- `ssky_delete` - Content management

📖 **[Complete MCP Documentation](mcp/SSKY_MCP_GUIDE.md)**

## 🧪 Development with Dev Container

For development using VS Code Dev Containers:

1. Copy the environment configuration file and set your Bluesky credentials:
   ```bash
   cp .env.local.sample .env.local
   ```
   Edit `.env.local` and add your Bluesky handle and password:
   ```bash
   SSKY_USER=your-handle.bsky.social:your-password
   SSKY_SKIP_REAL_API_TESTS=1
   ```

2. The dev container automatically:
   - Loads environment variables from `.env.local`
   - Installs Claude Code extension
   - Sets up Python 3.12 environment with Docker support

## 🧪 Testing

To run the tests in the `tests/` directory:

1. Copy the environment configuration file and set your Bluesky credentials:
   ```bash
   cp tests/_env tests/.env
   ```
   Edit `tests/.env` and add your Bluesky handle and password.

2. Run tests using pytest:
   ```bash
   # Run all tests
   pytest tests/ -v

   # Run individual feature tests
   pytest tests/test_login.py -v              # Login functionality
   pytest tests/test_post_and_delete.py -v    # Post and delete operations
   pytest tests/test_search.py -v             # Search functionality
   pytest tests/test_follow_unfollow.py -v    # Follow/unfollow operations
   pytest tests/test_get.py -v                # Timeline retrieval
   pytest tests/test_profile.py -v            # Profile display
   pytest tests/test_repost_unrepost.py -v    # Repost/unrepost operations
   pytest tests/test_user.py -v               # User functionality
   ```

## 📝 Requirements

- Python 3.12 or later

## 📜 License

[MIT License](LICENSE)

## 👥 Author

[SimpleSkyClient Project](https://github.com/simpleskyclient)
