ccal 0.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccal-0.1.4/.github/workflows/publish.yml +31 -0
- ccal-0.1.4/.gitignore +39 -0
- ccal-0.1.4/.python-version +1 -0
- ccal-0.1.4/PKG-INFO +177 -0
- ccal-0.1.4/README-zh_cn.md +159 -0
- ccal-0.1.4/README.md +159 -0
- ccal-0.1.4/docs/commands.md +268 -0
- ccal-0.1.4/pyproject.toml +38 -0
- ccal-0.1.4/src/__init__.py +0 -0
- ccal-0.1.4/src/config.py +115 -0
- ccal-0.1.4/src/connections/__init__.py +0 -0
- ccal-0.1.4/src/connections/apple_calendar.py +92 -0
- ccal-0.1.4/src/connections/google_calendar.py +215 -0
- ccal-0.1.4/src/connections/ics.py +16 -0
- ccal-0.1.4/src/event_workflow.py +431 -0
- ccal-0.1.4/src/google_setup.py +158 -0
- ccal-0.1.4/src/input/__init__.py +0 -0
- ccal-0.1.4/src/input/geo.py +41 -0
- ccal-0.1.4/src/input/ocr.py +42 -0
- ccal-0.1.4/src/main.py +412 -0
- ccal-0.1.4/src/models/__init__.py +0 -0
- ccal-0.1.4/src/models/llm.py +119 -0
- ccal-0.1.4/src/models/model.py +153 -0
- ccal-0.1.4/tests/__init__.py +0 -0
- ccal-0.1.4/tests/conftest.py +45 -0
- ccal-0.1.4/tests/test_apple_calendar.py +164 -0
- ccal-0.1.4/tests/test_config.py +114 -0
- ccal-0.1.4/tests/test_geo.py +73 -0
- ccal-0.1.4/tests/test_google_calendar.py +314 -0
- ccal-0.1.4/tests/test_ics.py +51 -0
- ccal-0.1.4/tests/test_llm.py +233 -0
- ccal-0.1.4/tests/test_main.py +962 -0
- ccal-0.1.4/tests/test_model.py +187 -0
- ccal-0.1.4/tests/test_ocr.py +82 -0
- ccal-0.1.4/uv.lock +2277 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: Publish Python Package
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pypi-publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
|
|
24
|
+
- name: Install uv
|
|
25
|
+
uses: astral-sh/setup-uv@v3
|
|
26
|
+
|
|
27
|
+
- name: Build package
|
|
28
|
+
run: uv build
|
|
29
|
+
|
|
30
|
+
- name: Publish package distributions to PyPI
|
|
31
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
ccal-0.1.4/.gitignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info/
|
|
8
|
+
*.egg
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
|
|
13
|
+
# Testing / Coverage
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.coverage
|
|
16
|
+
.coverage.*
|
|
17
|
+
htmlcov/
|
|
18
|
+
|
|
19
|
+
# IDE
|
|
20
|
+
.vscode/
|
|
21
|
+
.idea/
|
|
22
|
+
*.swp
|
|
23
|
+
*.swo
|
|
24
|
+
*~
|
|
25
|
+
|
|
26
|
+
# OS
|
|
27
|
+
.DS_Store
|
|
28
|
+
Thumbs.db
|
|
29
|
+
|
|
30
|
+
# Generated ICS files
|
|
31
|
+
*.ics
|
|
32
|
+
|
|
33
|
+
# Local Google OAuth files
|
|
34
|
+
google_credentials.json
|
|
35
|
+
google_cresntials.json
|
|
36
|
+
google_token_*.json
|
|
37
|
+
|
|
38
|
+
# local image test folder
|
|
39
|
+
.imgs/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
ccal-0.1.4/PKG-INFO
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ccal
|
|
3
|
+
Version: 0.1.4
|
|
4
|
+
Summary: CLI tool for adding calendar events
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: google-api-python-client>=2.0
|
|
7
|
+
Requires-Dist: google-auth-oauthlib>=1.0
|
|
8
|
+
Requires-Dist: icalendar>=6.0
|
|
9
|
+
Requires-Dist: keyring>=25.0
|
|
10
|
+
Requires-Dist: litellm>=1.0
|
|
11
|
+
Requires-Dist: pydantic>=2.13.1
|
|
12
|
+
Requires-Dist: rich>=13.0
|
|
13
|
+
Requires-Dist: typer>=0.24.1
|
|
14
|
+
Provides-Extra: ocr
|
|
15
|
+
Requires-Dist: pillow>=11.0; extra == 'ocr'
|
|
16
|
+
Requires-Dist: pytesseract>=0.3.13; extra == 'ocr'
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# ccal
|
|
20
|
+
|
|
21
|
+
[中文文档](README-zh_cn.md)
|
|
22
|
+
|
|
23
|
+
A CLI tool that turns natural language text or images into calendar events. Powered by LLMs.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- **Text input** — describe an event in plain language, ccal parses it into structured fields
|
|
28
|
+
- **Image input** — extract text from screenshots/photos via OCR, then parse
|
|
29
|
+
- **Multi-LLM support** — works with OpenAI, Anthropic, Gemini, OpenRouter, Deepseek, Groq, Mistral, and more (via [litellm](https://github.com/BerriAI/litellm))
|
|
30
|
+
- **ICS export** — generate standard `.ics` files importable by any calendar app
|
|
31
|
+
- **Google Calendar sync** — create events directly on Google Calendar via API
|
|
32
|
+
- **Apple Calendar sync** — add events via AppleScript (macOS only, auto-fallback to ICS on other platforms)
|
|
33
|
+
- **Secure key storage** — API keys stored in your system keyring, never in plain text
|
|
34
|
+
- **Geolocation** — auto-detect timezone and location for accurate event scheduling
|
|
35
|
+
- **Stdin support** — pipe text from other commands
|
|
36
|
+
|
|
37
|
+
## Requirements
|
|
38
|
+
|
|
39
|
+
- Python 3.12+
|
|
40
|
+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
|
|
41
|
+
- [Tesseract OCR](https://github.com/tesseract-ocr/tesseract) (for image input)
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/your-username/ccal.git
|
|
47
|
+
cd ccal
|
|
48
|
+
uv sync
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
### 1. Setup
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
ccal setup
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This will walk you through configuring:
|
|
60
|
+
- LLM provider and model
|
|
61
|
+
- API key (stored securely in system keyring)
|
|
62
|
+
- Default output method (ICS file, Google Calendar, or Apple Calendar)
|
|
63
|
+
- Google Calendar setup, including client type, auth mode, credentials location, and Calendar ID
|
|
64
|
+
|
|
65
|
+
### 2. Add an event
|
|
66
|
+
|
|
67
|
+
From text:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
ccal add "Team meeting tomorrow at 3pm in Conference Room A"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
From an image:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
ccal add flyer.png
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
From stdin:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
echo "Lunch with Alice Friday noon" | ccal add
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
With options:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
ccal add "Dinner Friday 7pm at Luigi's" -o google # sync to Google Calendar
|
|
89
|
+
ccal add "Weekly standup Mon 9am" -o apple # add to Apple Calendar (macOS)
|
|
90
|
+
ccal add "Weekly standup Mon 9am" -o ics # export as .ics file
|
|
91
|
+
ccal add "会议明天下午两点" -m anthropic/claude-sonnet-4-20250514 # use a specific model
|
|
92
|
+
ccal add screenshot.png -l chi_sim # OCR with Chinese language
|
|
93
|
+
ccal add "Demo at 2pm" -y # skip confirmation
|
|
94
|
+
ccal add "Demo at 2pm" --json # output as JSON
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. Parse only (no save)
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
ccal parse "Workshop next Wednesday 10am-12pm, Room 301"
|
|
101
|
+
ccal parse "下周一上午10点团队周会" --json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 4. View config
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
ccal config
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Commands
|
|
111
|
+
|
|
112
|
+
| Command | Description |
|
|
113
|
+
|---------|-------------|
|
|
114
|
+
| `ccal add [text\|image]` | Parse input and create a calendar event |
|
|
115
|
+
| `ccal parse [text\|image]` | Parse and display event fields without saving |
|
|
116
|
+
| `ccal setup` | Interactive configuration wizard |
|
|
117
|
+
| `ccal config` | Show current configuration and platform info |
|
|
118
|
+
|
|
119
|
+
### `ccal add` options
|
|
120
|
+
|
|
121
|
+
| Option | Description |
|
|
122
|
+
|--------|-------------|
|
|
123
|
+
| `-o`, `--output` | Output method: `ics`, `google`, or `apple` |
|
|
124
|
+
| `-p`, `--provider` | LLM provider name |
|
|
125
|
+
| `-m`, `--model` | LLM model (e.g. `openai/gpt-4o`) |
|
|
126
|
+
| `-y`, `--yes` | Skip confirmation, output directly |
|
|
127
|
+
| `-l`, `--language` | OCR language (e.g. `chi_sim`, `eng+chi_sim`) |
|
|
128
|
+
| `--json` | Output parsed event as JSON |
|
|
129
|
+
|
|
130
|
+
## Platform Support
|
|
131
|
+
|
|
132
|
+
| Feature | macOS | Linux | Windows |
|
|
133
|
+
|---------|-------|-------|---------|
|
|
134
|
+
| ICS export | ✅ | ✅ | ✅ |
|
|
135
|
+
| Google Calendar | ✅ | ✅ | ✅ |
|
|
136
|
+
| Apple Calendar | ✅ | ❌ fallback to ICS | ❌ fallback to ICS |
|
|
137
|
+
|
|
138
|
+
## Configuration
|
|
139
|
+
|
|
140
|
+
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).
|
|
141
|
+
|
|
142
|
+
For Google Calendar integration, ccal uses two different local files:
|
|
143
|
+
|
|
144
|
+
- `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.
|
|
145
|
+
- `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.
|
|
146
|
+
|
|
147
|
+
During `ccal setup`, place the credentials JSON in the configured directory, or point setup directly at the JSON file. The setup tutorial also explains:
|
|
148
|
+
|
|
149
|
+
- `Desktop app` vs `TVs and Limited Input devices`
|
|
150
|
+
- `External` vs `Internal`
|
|
151
|
+
- `Testing` status and `Test users`
|
|
152
|
+
- how to find a Google Calendar ID
|
|
153
|
+
- setup-time validation of the selected Calendar ID
|
|
154
|
+
|
|
155
|
+
You can also configure Google Calendar during `ccal setup` through the dedicated middle step, even if your default output is not Google.
|
|
156
|
+
|
|
157
|
+
## Project Structure
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
src/
|
|
161
|
+
├── main.py # CLI entry point (Typer)
|
|
162
|
+
├── config.py # Configuration & keyring management
|
|
163
|
+
├── models/
|
|
164
|
+
│ ├── model.py # CalendarEvent Pydantic model
|
|
165
|
+
│ └── llm.py # LLM parsing via litellm
|
|
166
|
+
├── input/
|
|
167
|
+
│ ├── ocr.py # Image text extraction (pytesseract)
|
|
168
|
+
│ └── geo.py # IP-based geolocation for timezone
|
|
169
|
+
└── connections/
|
|
170
|
+
├── google_calendar.py # Google Calendar API integration
|
|
171
|
+
├── apple_calendar.py # Apple Calendar via AppleScript (macOS)
|
|
172
|
+
└── ics.py # ICS file export
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# ccal
|
|
2
|
+
|
|
3
|
+
[English](README.md)
|
|
4
|
+
|
|
5
|
+
一个命令行工具,将自然语言文本或图片转换为日历事件。由 LLM 驱动。
|
|
6
|
+
|
|
7
|
+
## 功能特性
|
|
8
|
+
|
|
9
|
+
- **文本输入** — 用自然语言描述事件,ccal 自动解析为结构化字段
|
|
10
|
+
- **图片输入** — 通过 OCR 从截图/照片中提取文字,再进行解析
|
|
11
|
+
- **多 LLM 支持** — 支持 OpenAI、Anthropic、Gemini、OpenRouter、Deepseek、Groq、Mistral 等(通过 [litellm](https://github.com/BerriAI/litellm))
|
|
12
|
+
- **ICS 导出** — 生成标准 `.ics` 文件,可被任何日历应用导入
|
|
13
|
+
- **Google 日历同步** — 通过 API 直接在 Google Calendar 创建事件
|
|
14
|
+
- **Apple 日历同步** — 通过 AppleScript 添加事件(仅 macOS,其他平台自动降级为 ICS)
|
|
15
|
+
- **安全密钥存储** — API key 存储在系统原生密钥链中,不以明文保存
|
|
16
|
+
- **地理定位** — 自动检测时区和位置,确保事件时间准确
|
|
17
|
+
- **管道输入** — 支持从其他命令管道传入文本
|
|
18
|
+
|
|
19
|
+
## 环境要求
|
|
20
|
+
|
|
21
|
+
- Python 3.12+
|
|
22
|
+
- [uv](https://docs.astral.sh/uv/)(推荐)或 pip
|
|
23
|
+
- [Tesseract OCR](https://github.com/tesseract-ocr/tesseract)(图片输入需要)
|
|
24
|
+
|
|
25
|
+
## 安装
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/your-username/ccal.git
|
|
29
|
+
cd ccal
|
|
30
|
+
uv sync
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 快速开始
|
|
34
|
+
|
|
35
|
+
### 1. 初始配置
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
ccal setup
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
将引导你配置:
|
|
42
|
+
- LLM 提供商和模型
|
|
43
|
+
- API key(安全存储在系统密钥链中)
|
|
44
|
+
- 默认输出方式(ICS 文件、Google 日历或 Apple 日历)
|
|
45
|
+
- Google 日历配置,包括客户端类型、鉴权模式、凭据位置和 Calendar ID
|
|
46
|
+
|
|
47
|
+
### 2. 添加事件
|
|
48
|
+
|
|
49
|
+
文本输入:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
ccal add "明天下午3点在会议室A开团队会议"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
图片输入:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
ccal add flyer.png
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
管道输入:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
echo "周五中午和 Alice 吃饭" | ccal add
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
更多选项:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
ccal add "周五晚上7点在 Luigi's 餐厅聚餐" -o google # 同步到 Google 日历
|
|
71
|
+
ccal add "每周一早上9点站会" -o apple # 添加到 Apple 日历 (macOS)
|
|
72
|
+
ccal add "每周一早上9点站会" -o ics # 导出为 .ics 文件
|
|
73
|
+
ccal add "Meeting tomorrow at 2pm" -m anthropic/claude-sonnet-4-20250514 # 指定模型
|
|
74
|
+
ccal add screenshot.png -l chi_sim # 使用中文 OCR
|
|
75
|
+
ccal add "下午2点演示" -y # 跳过确认
|
|
76
|
+
ccal add "下午2点演示" --json # JSON 格式输出
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 3. 仅解析(不保存)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
ccal parse "下周三上午10点到12点,301会议室,技术研讨会"
|
|
83
|
+
ccal parse "下周一上午10点团队周会" --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 4. 查看配置
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
ccal config
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 命令列表
|
|
93
|
+
|
|
94
|
+
| 命令 | 说明 |
|
|
95
|
+
|------|------|
|
|
96
|
+
| `ccal add [文本\|图片]` | 解析输入并创建日历事件 |
|
|
97
|
+
| `ccal parse [文本\|图片]` | 解析并展示事件字段,不保存 |
|
|
98
|
+
| `ccal setup` | 交互式配置向导 |
|
|
99
|
+
| `ccal config` | 查看当前配置和平台信息 |
|
|
100
|
+
|
|
101
|
+
### `ccal add` 选项
|
|
102
|
+
|
|
103
|
+
| 选项 | 说明 |
|
|
104
|
+
|------|------|
|
|
105
|
+
| `-o`, `--output` | 输出方式:`ics`、`google` 或 `apple` |
|
|
106
|
+
| `-p`, `--provider` | LLM 提供商名称 |
|
|
107
|
+
| `-m`, `--model` | LLM 模型(如 `openai/gpt-4o`) |
|
|
108
|
+
| `-y`, `--yes` | 跳过确认,直接输出 |
|
|
109
|
+
| `-l`, `--language` | OCR 语言(如 `chi_sim`、`eng+chi_sim`) |
|
|
110
|
+
| `--json` | 以 JSON 格式输出解析结果 |
|
|
111
|
+
|
|
112
|
+
## 平台支持
|
|
113
|
+
|
|
114
|
+
| 功能 | macOS | Linux | Windows |
|
|
115
|
+
|------|-------|-------|---------|
|
|
116
|
+
| ICS 导出 | ✅ | ✅ | ✅ |
|
|
117
|
+
| Google 日历 | ✅ | ✅ | ✅ |
|
|
118
|
+
| Apple 日历 | ✅ | ❌ 降级为 ICS | ❌ 降级为 ICS |
|
|
119
|
+
|
|
120
|
+
## 配置说明
|
|
121
|
+
|
|
122
|
+
配置文件存储在 `~/.config/ccal/config.toml`。API key 存储在系统原生密钥链中(macOS Keychain / Linux Secret Service / Windows Credential Locker)。
|
|
123
|
+
|
|
124
|
+
使用 Google 日历功能时,`ccal` 会用到两类本地文件:
|
|
125
|
+
|
|
126
|
+
- `google_credentials.json`:从 Google Cloud Console 下载的 OAuth 客户端凭据 JSON,里面包含 client id 和 client secret。这个文件建议一直保留。
|
|
127
|
+
- `google_token_*.json`:首次授权后生成的登录 token 缓存。里面的 access token 会过期,但通常可以自动刷新,所以平时不用手动处理。ccal 会根据当前凭据路径和 auth mode 选择对应的缓存文件。
|
|
128
|
+
|
|
129
|
+
在 `ccal setup` 里,你可以把凭据 JSON 放到配置的目录中,也可以直接把 JSON 文件路径输入给 setup。教程里还会说明:
|
|
130
|
+
|
|
131
|
+
- `Desktop app` 和 `TVs and Limited Input devices` 怎么选
|
|
132
|
+
- `External` 和 `Internal` 的区别
|
|
133
|
+
- `Testing` 状态和 `Test users`
|
|
134
|
+
- 怎么找到 Google Calendar ID
|
|
135
|
+
- setup 阶段会验证所选 Calendar ID 是否可访问
|
|
136
|
+
|
|
137
|
+
你也可以在 `ccal setup` 的中间步骤里单独配置 Google 日历,即使默认输出方式不是 Google 也可以先把 API 配好。
|
|
138
|
+
|
|
139
|
+
## 项目结构
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
src/
|
|
143
|
+
├── main.py # CLI 入口 (Typer)
|
|
144
|
+
├── config.py # 配置与密钥链管理
|
|
145
|
+
├── models/
|
|
146
|
+
│ ├── model.py # CalendarEvent Pydantic 模型
|
|
147
|
+
│ └── llm.py # 通过 litellm 调用 LLM 解析
|
|
148
|
+
├── input/
|
|
149
|
+
│ ├── ocr.py # 图片文字提取 (pytesseract)
|
|
150
|
+
│ └── geo.py # 基于 IP 的地理定位与时区检测
|
|
151
|
+
└── connections/
|
|
152
|
+
├── google_calendar.py # Google Calendar API 集成
|
|
153
|
+
├── apple_calendar.py # Apple Calendar AppleScript 集成 (macOS)
|
|
154
|
+
└── ics.py # ICS 文件导出
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 许可证
|
|
158
|
+
|
|
159
|
+
MIT
|
ccal-0.1.4/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# ccal
|
|
2
|
+
|
|
3
|
+
[中文文档](README-zh_cn.md)
|
|
4
|
+
|
|
5
|
+
A CLI tool that turns natural language text or images into calendar events. Powered by LLMs.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Text input** — describe an event in plain language, ccal parses it into structured fields
|
|
10
|
+
- **Image input** — extract text from screenshots/photos via OCR, then parse
|
|
11
|
+
- **Multi-LLM support** — works with OpenAI, Anthropic, Gemini, OpenRouter, Deepseek, Groq, Mistral, and more (via [litellm](https://github.com/BerriAI/litellm))
|
|
12
|
+
- **ICS export** — generate standard `.ics` files importable by any calendar app
|
|
13
|
+
- **Google Calendar sync** — create events directly on Google Calendar via API
|
|
14
|
+
- **Apple Calendar sync** — add events via AppleScript (macOS only, auto-fallback to ICS on other platforms)
|
|
15
|
+
- **Secure key storage** — API keys stored in your system keyring, never in plain text
|
|
16
|
+
- **Geolocation** — auto-detect timezone and location for accurate event scheduling
|
|
17
|
+
- **Stdin support** — pipe text from other commands
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
|
|
21
|
+
- Python 3.12+
|
|
22
|
+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip
|
|
23
|
+
- [Tesseract OCR](https://github.com/tesseract-ocr/tesseract) (for image input)
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
git clone https://github.com/your-username/ccal.git
|
|
29
|
+
cd ccal
|
|
30
|
+
uv sync
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### 1. Setup
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
ccal setup
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This will walk you through configuring:
|
|
42
|
+
- LLM provider and model
|
|
43
|
+
- API key (stored securely in system keyring)
|
|
44
|
+
- Default output method (ICS file, Google Calendar, or Apple Calendar)
|
|
45
|
+
- Google Calendar setup, including client type, auth mode, credentials location, and Calendar ID
|
|
46
|
+
|
|
47
|
+
### 2. Add an event
|
|
48
|
+
|
|
49
|
+
From text:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
ccal add "Team meeting tomorrow at 3pm in Conference Room A"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
From an image:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
ccal add flyer.png
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
From stdin:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
echo "Lunch with Alice Friday noon" | ccal add
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
With options:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
ccal add "Dinner Friday 7pm at Luigi's" -o google # sync to Google Calendar
|
|
71
|
+
ccal add "Weekly standup Mon 9am" -o apple # add to Apple Calendar (macOS)
|
|
72
|
+
ccal add "Weekly standup Mon 9am" -o ics # export as .ics file
|
|
73
|
+
ccal add "会议明天下午两点" -m anthropic/claude-sonnet-4-20250514 # use a specific model
|
|
74
|
+
ccal add screenshot.png -l chi_sim # OCR with Chinese language
|
|
75
|
+
ccal add "Demo at 2pm" -y # skip confirmation
|
|
76
|
+
ccal add "Demo at 2pm" --json # output as JSON
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 3. Parse only (no save)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
ccal parse "Workshop next Wednesday 10am-12pm, Room 301"
|
|
83
|
+
ccal parse "下周一上午10点团队周会" --json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 4. View config
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
ccal config
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Commands
|
|
93
|
+
|
|
94
|
+
| Command | Description |
|
|
95
|
+
|---------|-------------|
|
|
96
|
+
| `ccal add [text\|image]` | Parse input and create a calendar event |
|
|
97
|
+
| `ccal parse [text\|image]` | Parse and display event fields without saving |
|
|
98
|
+
| `ccal setup` | Interactive configuration wizard |
|
|
99
|
+
| `ccal config` | Show current configuration and platform info |
|
|
100
|
+
|
|
101
|
+
### `ccal add` options
|
|
102
|
+
|
|
103
|
+
| Option | Description |
|
|
104
|
+
|--------|-------------|
|
|
105
|
+
| `-o`, `--output` | Output method: `ics`, `google`, or `apple` |
|
|
106
|
+
| `-p`, `--provider` | LLM provider name |
|
|
107
|
+
| `-m`, `--model` | LLM model (e.g. `openai/gpt-4o`) |
|
|
108
|
+
| `-y`, `--yes` | Skip confirmation, output directly |
|
|
109
|
+
| `-l`, `--language` | OCR language (e.g. `chi_sim`, `eng+chi_sim`) |
|
|
110
|
+
| `--json` | Output parsed event as JSON |
|
|
111
|
+
|
|
112
|
+
## Platform Support
|
|
113
|
+
|
|
114
|
+
| Feature | macOS | Linux | Windows |
|
|
115
|
+
|---------|-------|-------|---------|
|
|
116
|
+
| ICS export | ✅ | ✅ | ✅ |
|
|
117
|
+
| Google Calendar | ✅ | ✅ | ✅ |
|
|
118
|
+
| Apple Calendar | ✅ | ❌ fallback to ICS | ❌ fallback to ICS |
|
|
119
|
+
|
|
120
|
+
## Configuration
|
|
121
|
+
|
|
122
|
+
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).
|
|
123
|
+
|
|
124
|
+
For Google Calendar integration, ccal uses two different local files:
|
|
125
|
+
|
|
126
|
+
- `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.
|
|
127
|
+
- `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.
|
|
128
|
+
|
|
129
|
+
During `ccal setup`, place the credentials JSON in the configured directory, or point setup directly at the JSON file. The setup tutorial also explains:
|
|
130
|
+
|
|
131
|
+
- `Desktop app` vs `TVs and Limited Input devices`
|
|
132
|
+
- `External` vs `Internal`
|
|
133
|
+
- `Testing` status and `Test users`
|
|
134
|
+
- how to find a Google Calendar ID
|
|
135
|
+
- setup-time validation of the selected Calendar ID
|
|
136
|
+
|
|
137
|
+
You can also configure Google Calendar during `ccal setup` through the dedicated middle step, even if your default output is not Google.
|
|
138
|
+
|
|
139
|
+
## Project Structure
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
src/
|
|
143
|
+
├── main.py # CLI entry point (Typer)
|
|
144
|
+
├── config.py # Configuration & keyring management
|
|
145
|
+
├── models/
|
|
146
|
+
│ ├── model.py # CalendarEvent Pydantic model
|
|
147
|
+
│ └── llm.py # LLM parsing via litellm
|
|
148
|
+
├── input/
|
|
149
|
+
│ ├── ocr.py # Image text extraction (pytesseract)
|
|
150
|
+
│ └── geo.py # IP-based geolocation for timezone
|
|
151
|
+
└── connections/
|
|
152
|
+
├── google_calendar.py # Google Calendar API integration
|
|
153
|
+
├── apple_calendar.py # Apple Calendar via AppleScript (macOS)
|
|
154
|
+
└── ics.py # ICS file export
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT
|