Metadata-Version: 2.4
Name: ccal
Version: 0.1.11
Summary: CLI tool for adding calendar events
Requires-Python: >=3.12
Requires-Dist: google-api-python-client>=2.0
Requires-Dist: google-auth-oauthlib>=1.0
Requires-Dist: icalendar>=6.0
Requires-Dist: keyring>=25.0
Requires-Dist: litellm>=1.0
Requires-Dist: pydantic>=2.13.1
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.24.1
Provides-Extra: ocr
Requires-Dist: pillow>=11.0; extra == 'ocr'
Requires-Dist: pytesseract>=0.3.13; extra == 'ocr'
Description-Content-Type: text/markdown

# ccal

[中文文档](README-zh_cn.md)

A CLI tool that turns natural language text or images into calendar events. Powered by LLMs.

## Features

- **Text input** — describe an event in plain language, ccal parses it into structured fields
- **Image input** — extract text from screenshots/photos via OCR, then parse
- **Multi-LLM support** — works with OpenAI, Anthropic, Gemini, OpenRouter, Deepseek, Groq, Mistral, and more (via [litellm](https://github.com/BerriAI/litellm))
- **ICS export** — generate standard `.ics` files importable by any calendar app
- **Google Calendar sync** — create events directly on Google Calendar via API
- **Apple Calendar sync** — add events via AppleScript (macOS only, auto-fallback to ICS on other platforms)
- **Secure key storage** — API keys stored in your system keyring, never in plain text
- **Geolocation** — auto-detect timezone and location for accurate event scheduling
- **Stdin support** — pipe text from other commands

## Requirements

- Python 3.12+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
- [Tesseract OCR](https://github.com/tesseract-ocr/tesseract) (for image input)

## Installation

### Official installer

The easiest way to install `ccal` is with the official installer for your platform:

```bash
curl -fsSL https://raw.githubusercontent.com/Q1ngX1/ccal/main/install.sh | sh
```

Windows users can install directly with PowerShell:

```powershell
powershell -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/Q1ngX1/ccal/main/install.ps1 | iex"
```

If you are using Git Bash or MinGW, call the same command through `powershell.exe`.

To pin a version or choose a custom destination, pass arguments after `sh -s --`, for example:

```bash
curl -fsSL https://raw.githubusercontent.com/Q1ngX1/ccal/main/install.sh | sh -s -- --version v0.1.11
curl -fsSL https://raw.githubusercontent.com/Q1ngX1/ccal/main/install.sh | sh -s -- --prefix "$HOME/bin"
```

If you already have Tesseract installed on Windows and want `ccal` to use it, download the script first and pass the Tesseract path:

```powershell
powershell -ExecutionPolicy Bypass -Command "$p = Join-Path $env:TEMP 'install-ccal.ps1'; irm https://raw.githubusercontent.com/Q1ngX1/ccal/main/install.ps1 -OutFile $p; powershell -ExecutionPolicy Bypass -File $p -TesseractHome 'C:\Program Files\Tesseract-OCR'"
```

Once installed, you can pull the latest standalone release with:

```bash
ccal update
```

To remove a standalone install, run:

```bash
ccal uninstall --purge
```

If you installed an older Linux release before `ccal uninstall` existed, remove it manually:

```bash
sudo rm -f /usr/local/bin/ccal
rm -f ~/.local/bin/ccal
rm -rf ~/.config/ccal
```

Use the path that matches where you installed `ccal`. If you used a custom prefix, delete the binary from that directory instead. If you installed through a package manager, remove it with that tool.

### From source

If you want to develop locally or run from source:

```bash
git clone https://github.com/your-username/ccal.git
cd ccal
uv sync
```

### Prebuilt binaries

If you want a ready-to-run command-line executable, download the asset for your platform from the GitHub Releases page. The release binaries are built for Linux, macOS, and Windows, and they include the core CLI without the optional OCR extra.

Typical filenames look like:

- `ccal-vX.Y.Z-linux-x86_64`
- `ccal-vX.Y.Z-windows-x86_64.exe`
- `ccal-vX.Y.Z-macos-x86_64`
- `ccal-vX.Y.Z-macos-arm64`

After downloading:

- Linux and macOS:
  ```bash
  chmod +x ccal
  ./ccal --help
  ```
- Windows:
  ```powershell
  .\ccal.exe --help
  ```

## Standalone Builds

See the build guide in [`docs/building.en.md`](docs/building.en.md) for PyInstaller packaging, including bundled OCR/Tesseract support.

## Quick Start

### 1. Setup

```bash
ccal setup
```

This will walk you through configuring:
- LLM provider and model
- API key (stored securely in system keyring)
- Default output method (ICS file, Google Calendar, or Apple Calendar)
- Google Calendar setup, including client type, auth mode, credentials location, and Calendar ID

### 2. Add an event

From text:

```bash
ccal add "Team meeting tomorrow at 3pm in Conference Room A"
```

From an image:

```bash
ccal add flyer.png
```

From stdin:

```bash
echo "Lunch with Alice Friday noon" | ccal add
```

With options:

```bash
ccal add "Dinner Friday 7pm at Luigi's" -o google       # sync to Google Calendar
ccal add "Weekly standup Mon 9am" -o apple               # add to Apple Calendar (macOS)
ccal add "Weekly standup Mon 9am" -o ics                  # export as .ics file
ccal add "会议明天下午两点" -m anthropic/claude-sonnet-4-20250514  # use a specific model
ccal add screenshot.png -l chi_sim                        # OCR with Chinese language
ccal add "Demo at 2pm" -y                                 # skip confirmation
ccal add "Demo at 2pm" --json                             # output as JSON
```

### 3. Parse only (no save)

```bash
ccal parse "Workshop next Wednesday 10am-12pm, Room 301"
ccal parse "下周一上午10点团队周会" --json
```

### 4. View config

```bash
ccal config
```

## Commands

| Command | Description |
|---------|-------------|
| `ccal add [text\|image]` | Parse input and create a calendar event |
| `ccal parse [text\|image]` | Parse and display event fields without saving |
| `ccal update` | Download and install the latest standalone release |
| `ccal uninstall` | Remove the current standalone binary |
| `ccal setup` | Interactive configuration wizard |
| `ccal config` | Show current configuration and platform info |

### `ccal add` options

| Option | Description |
|--------|-------------|
| `-o`, `--output` | Output method: `ics`, `google`, or `apple` |
| `-p`, `--provider` | LLM provider name |
| `-m`, `--model` | LLM model (e.g. `openai/gpt-4o`) |
| `-y`, `--yes` | Skip confirmation, output directly |
| `-l`, `--language` | OCR language (e.g. `chi_sim`, `eng+chi_sim`) |
| `--json` | Output parsed event as JSON |

## Platform Support

| Feature | macOS | Linux | Windows |
|---------|-------|-------|---------|
| ICS export | ✅ | ✅ | ✅ |
| Google Calendar | ✅ | ✅ | ✅ |
| Apple Calendar | ✅ | ❌ fallback to ICS | ❌ fallback to ICS |

## Configuration

Config is stored at `~/.config/ccal/config.toml`. API keys are stored in your system's native keyring (macOS Keychain / Linux Secret Service / Windows Credential Locker).

For Google Calendar integration, ccal uses two different local files:

- `google_credentials.json`: the OAuth client credentials JSON downloaded from Google Cloud Console. This contains the client id and client secret. Keep this file around after setup.
- `google_token_*.json`: the cached login token created after the first successful authorization. The access token inside can expire and refresh automatically, so you usually do not need to touch it. ccal picks the cache file based on the current credentials path and auth mode.

During `ccal setup`, place the credentials JSON in the configured directory, or point setup directly at the JSON file. The setup tutorial also explains:

- `Desktop app` vs `TVs and Limited Input devices`
- `External` vs `Internal`
- `Testing` status and `Test users`
- how to find a Google Calendar ID
- setup-time validation of the selected Calendar ID

You can also configure Google Calendar during `ccal setup` through the dedicated middle step, even if your default output is not Google.

## Project Structure

```
src/
├── main.py                  # CLI entry point (Typer)
├── config.py                # Configuration & keyring management
├── models/
│   ├── model.py             # CalendarEvent Pydantic model
│   └── llm.py               # LLM parsing via litellm
├── input/
│   ├── ocr.py               # Image text extraction (pytesseract)
│   └── geo.py               # IP-based geolocation for timezone
└── connections/
    ├── google_calendar.py   # Google Calendar API integration
    ├── apple_calendar.py    # Apple Calendar via AppleScript (macOS)
    └── ics.py               # ICS file export
```

## License

MIT
