flycal-cli 0.6.1 → 0.7.0
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.
- checksums.yaml +4 -4
- data/README.md +42 -24
- data/config/defaults.yml +23 -5
- data/lib/flycal_cli/cli.rb +40 -8
- data/lib/flycal_cli/config.rb +36 -1
- data/lib/flycal_cli/slot_finder.rb +13 -14
- data/lib/flycal_cli/slot_formatter.rb +3 -2
- data/lib/flycal_cli/version.rb +1 -1
- data/locales/en.json +1 -0
- data/locales/it.json +1 -0
- data/mcp/tools.json +15 -14
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a0ee7fffad246d3a457d03eea4af9ace9bb6dfe59a067cc62bf2da08987a72a3
|
|
4
|
+
data.tar.gz: c9a5ae5776356185d80f6e87b368b6027122b27daeeb03378f01b6000486b16a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd15a9fc4be4bb6da73354dc17e600fdbcc19701c9e13668cbf504cdc99bd568a4f10a8d429a39e6ca41d9d4cb77a84501843e2c5820c959f1680a64384d1368
|
|
7
|
+
data.tar.gz: 708402193736049bc5b1ba476d765326ebf5d92d53eef48d12cb81f62b3d93b2a98db6913de535c8b9fdb26922b03f9b487f8e2192f18beb4037ad6c8cc423b3
|
data/README.md
CHANGED
|
@@ -157,10 +157,10 @@ Find free time slots in your calendar. Output is a simple list for copy/paste in
|
|
|
157
157
|
|
|
158
158
|
```bash
|
|
159
159
|
flycal slots
|
|
160
|
+
flycal slots --in "5 days"
|
|
161
|
+
flycal slots --in "12 days" --template dinner
|
|
160
162
|
flycal slots --duration 1h
|
|
161
163
|
flycal slots --from 2026-08-01 --in "2 weeks" --duration 1h
|
|
162
|
-
flycal slots --from 01/08/2026 --in 3days --duration 30min
|
|
163
|
-
flycal slots --in 1week -c Work
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
**Options:**
|
|
@@ -168,24 +168,24 @@ flycal slots --in 1week -c Work
|
|
|
168
168
|
- `--duration` — Slot length. Default: `slots.defaults.default_duration` in config (`45min`). Examples: `1h`, `30 minutes`
|
|
169
169
|
- `--from` / `-f` — Start date/time. Default: `slots.defaults.from` in config (`now`). If a date without time is today, starts from the current time.
|
|
170
170
|
- `--in` / `-i` — Search window from `--from`. Default: `1 week`.
|
|
171
|
+
- `--template` / `-T` — Template from `slots.templates` in config. Default: first template (`work`)
|
|
171
172
|
- `--calendar` / `-c` — Calendar name or ID used as fallback when `exclude_calendars` is not configured
|
|
172
173
|
|
|
173
174
|
**Output:**
|
|
174
175
|
|
|
175
|
-
Always starts with a header and clickable calendar links (OSC 8), then the availability list:
|
|
176
|
-
|
|
177
176
|
```
|
|
178
177
|
found 3 slots
|
|
179
178
|
from wed 29 July 2026 to wed 5 August 2026
|
|
180
179
|
with duration 45min
|
|
181
180
|
for calendars
|
|
181
|
+
template work
|
|
182
182
|
Incode - Antonio
|
|
183
183
|
Personal
|
|
184
184
|
https://calendar.google.com/calendar/r/day/2026/7/29
|
|
185
185
|
|
|
186
186
|
friday 15/7
|
|
187
|
-
10-12
|
|
188
|
-
13-15.30
|
|
187
|
+
10 - 12
|
|
188
|
+
13 - 15.30
|
|
189
189
|
```
|
|
190
190
|
|
|
191
191
|
If `pbcopy` is available (macOS), the slot list without the header is also copied to the clipboard.
|
|
@@ -193,44 +193,62 @@ If `pbcopy` is available (macOS), the slot list without the header is also copie
|
|
|
193
193
|
Slot search windows are configured in `~/.flycal/config.yml`:
|
|
194
194
|
|
|
195
195
|
```yaml
|
|
196
|
+
calendar_default: ~
|
|
197
|
+
locale: en
|
|
196
198
|
slots:
|
|
199
|
+
templates:
|
|
200
|
+
work:
|
|
201
|
+
days:
|
|
202
|
+
- 1
|
|
203
|
+
- 2
|
|
204
|
+
- 3
|
|
205
|
+
- 4
|
|
206
|
+
- 5
|
|
207
|
+
hours:
|
|
208
|
+
- 9:30-13:00
|
|
209
|
+
- 14:00-18:30
|
|
210
|
+
dinner:
|
|
211
|
+
days:
|
|
212
|
+
- 1
|
|
213
|
+
- 2
|
|
214
|
+
- 3
|
|
215
|
+
- 4
|
|
216
|
+
- 5
|
|
217
|
+
- 6
|
|
218
|
+
- 7
|
|
219
|
+
hours:
|
|
220
|
+
- 19-23
|
|
221
|
+
exclude_calendars: []
|
|
197
222
|
defaults:
|
|
198
223
|
from: now
|
|
199
224
|
default_duration: 45min
|
|
200
225
|
free_before: 0m
|
|
201
226
|
free_after: 15m
|
|
202
|
-
exclude_calendars:
|
|
203
|
-
- user@example.com
|
|
204
|
-
- user@gmail.com
|
|
205
|
-
hours:
|
|
206
|
-
- 9:30-13:00
|
|
207
|
-
- 14:00-18:30
|
|
208
|
-
weekdays_only: true
|
|
209
|
-
locale: en
|
|
210
227
|
```
|
|
211
228
|
|
|
212
229
|
Missing keys are filled from `config/defaults.yml` in the gem and saved to your `config.yml` on first read.
|
|
213
230
|
|
|
231
|
+
- `calendar_default: ~` means no default calendar is set (`~` is YAML null)
|
|
232
|
+
- `templates` — named schedules; default used is the first one (`work`)
|
|
233
|
+
- `templates.*.days` — weekdays as numbers: `1` Monday … `7` Sunday
|
|
234
|
+
- `templates.*.hours` — one or more ranges (`H-H`, `HH:MM-HH:MM`, mixed)
|
|
214
235
|
- `defaults.from` — default `--from` for slots (`now` or a date string)
|
|
215
236
|
- `defaults.default_duration` — default slot length when `--duration` is omitted
|
|
216
|
-
- `free_before` — buffer before each slot
|
|
217
|
-
- `free_after` — buffer after each slot; gaps must fit `duration + free_after`,
|
|
218
|
-
- `exclude_calendars`
|
|
219
|
-
- `hours` accepts one or more ranges (`H-H`, `HH:MM-HH:MM`, mixed)
|
|
220
|
-
- `weekdays_only: true` limits slots to Monday-Friday
|
|
221
|
-
- `weekdays_only: false` includes weekends
|
|
237
|
+
- `free_before` — buffer before each slot
|
|
238
|
+
- `free_after` — buffer after each slot; gaps must fit `duration + free_after`, output shows continuous free ranges
|
|
239
|
+
- `exclude_calendars` — calendars whose events block free slots; if empty, `calendar_default` is used
|
|
222
240
|
- `locale` supports `en` and `it` (default is `en`)
|
|
223
241
|
|
|
224
242
|
**Output example:**
|
|
225
243
|
|
|
226
244
|
```
|
|
227
245
|
friday 15/7
|
|
228
|
-
10-12
|
|
229
|
-
13-15.30
|
|
246
|
+
10 - 12
|
|
247
|
+
13 - 15.30
|
|
230
248
|
|
|
231
249
|
monday 21/7
|
|
232
|
-
12-13
|
|
233
|
-
14-15
|
|
250
|
+
12 - 13
|
|
251
|
+
14 - 15
|
|
234
252
|
```
|
|
235
253
|
|
|
236
254
|
## Configuration
|
data/config/defaults.yml
CHANGED
|
@@ -1,12 +1,30 @@
|
|
|
1
|
+
calendar_default: ~
|
|
1
2
|
locale: en
|
|
2
3
|
slots:
|
|
4
|
+
templates:
|
|
5
|
+
work:
|
|
6
|
+
days:
|
|
7
|
+
- 1
|
|
8
|
+
- 2
|
|
9
|
+
- 3
|
|
10
|
+
- 4
|
|
11
|
+
- 5
|
|
12
|
+
hours:
|
|
13
|
+
- 9:30-13:00
|
|
14
|
+
- 14:00-18:30
|
|
15
|
+
dinner:
|
|
16
|
+
days:
|
|
17
|
+
- 1
|
|
18
|
+
- 2
|
|
19
|
+
- 3
|
|
20
|
+
- 4
|
|
21
|
+
- 5
|
|
22
|
+
- 6
|
|
23
|
+
hours:
|
|
24
|
+
- 19-23
|
|
25
|
+
exclude_calendars: []
|
|
3
26
|
defaults:
|
|
4
27
|
from: now
|
|
5
28
|
default_duration: 45min
|
|
6
29
|
free_before: 0m
|
|
7
30
|
free_after: 15m
|
|
8
|
-
exclude_calendars: []
|
|
9
|
-
hours:
|
|
10
|
-
- 9:30-13:00
|
|
11
|
-
- 14:00-18:30
|
|
12
|
-
weekdays_only: true
|
data/lib/flycal_cli/cli.rb
CHANGED
|
@@ -182,11 +182,13 @@ module FlycalCli
|
|
|
182
182
|
--from from config (default: now)
|
|
183
183
|
--in 1 week
|
|
184
184
|
--duration from config (default: 45min)
|
|
185
|
+
--template first template in config (default: work)
|
|
185
186
|
|
|
186
187
|
Examples:
|
|
187
188
|
flycal slots
|
|
188
|
-
flycal slots --
|
|
189
|
-
flycal slots --
|
|
189
|
+
flycal slots --in "5 days"
|
|
190
|
+
flycal slots --in "12 days" --template dinner
|
|
191
|
+
flycal slots --duration 1h --from 2026-08-01
|
|
190
192
|
LONGDESC
|
|
191
193
|
option :duration, type: :string,
|
|
192
194
|
desc: "Slot length (default from config: slots.defaults.default_duration)"
|
|
@@ -194,6 +196,8 @@ module FlycalCli
|
|
|
194
196
|
desc: "Search window from --from (default: 1 week)"
|
|
195
197
|
option :from, type: :string, aliases: "-f",
|
|
196
198
|
desc: "Start date/time (default from config: slots.defaults.from)"
|
|
199
|
+
option :template, type: :string, aliases: "-T",
|
|
200
|
+
desc: "Slot template name from config (default: first template, usually work)"
|
|
197
201
|
option :calendar, type: :string, aliases: "-c", desc: "Calendar name or ID"
|
|
198
202
|
def slots
|
|
199
203
|
apply_locale_override
|
|
@@ -216,13 +220,14 @@ module FlycalCli
|
|
|
216
220
|
from_value = "now" if from_value.empty?
|
|
217
221
|
|
|
218
222
|
begin
|
|
223
|
+
template_name, template = resolve_slots_template(slot_cfg, options[:template])
|
|
219
224
|
slot_duration = DurationParser.to_seconds(duration_value)
|
|
220
225
|
free_before = DurationParser.to_seconds(slot_cfg["free_before"] || "0m")
|
|
221
226
|
free_after = DurationParser.to_seconds(slot_cfg["free_after"] || "0m")
|
|
222
227
|
time_min = parse_slots_from(from_value)
|
|
223
228
|
time_max = DurationParser.add_to_time(in_value, time_min)
|
|
224
|
-
|
|
225
|
-
|
|
229
|
+
hours = parse_workhours(template["hours"])
|
|
230
|
+
days = parse_template_days(template["days"])
|
|
226
231
|
rescue FlycalCli::Error => e
|
|
227
232
|
puts "Error: #{e.message}"
|
|
228
233
|
exit 1
|
|
@@ -266,8 +271,8 @@ module FlycalCli
|
|
|
266
271
|
time_min: time_min,
|
|
267
272
|
time_max: time_max,
|
|
268
273
|
slot_duration_seconds: slot_duration,
|
|
269
|
-
|
|
270
|
-
|
|
274
|
+
hours: hours,
|
|
275
|
+
days: days,
|
|
271
276
|
free_before_seconds: free_before,
|
|
272
277
|
free_after_seconds: free_after
|
|
273
278
|
)
|
|
@@ -279,7 +284,8 @@ module FlycalCli
|
|
|
279
284
|
to: time_max,
|
|
280
285
|
duration: duration_value,
|
|
281
286
|
calendars: calendar_meta,
|
|
282
|
-
count: slot_count
|
|
287
|
+
count: slot_count,
|
|
288
|
+
template: template_name
|
|
283
289
|
)
|
|
284
290
|
puts ""
|
|
285
291
|
output = SlotFormatter.format_output(slots_by_day)
|
|
@@ -472,6 +478,32 @@ module FlycalCli
|
|
|
472
478
|
DateTimeParser.parse(value)
|
|
473
479
|
end
|
|
474
480
|
|
|
481
|
+
def resolve_slots_template(slot_cfg, requested_name)
|
|
482
|
+
templates = slot_cfg["templates"]
|
|
483
|
+
raise FlycalCli::Error, "slots.templates is missing in config.yml." unless templates.is_a?(Hash) && !templates.empty?
|
|
484
|
+
|
|
485
|
+
name = requested_name.to_s.strip
|
|
486
|
+
name = templates.keys.first.to_s if name.empty?
|
|
487
|
+
|
|
488
|
+
template = templates[name]
|
|
489
|
+
unless template.is_a?(Hash)
|
|
490
|
+
available = templates.keys.join(", ")
|
|
491
|
+
raise FlycalCli::Error, "Unknown slots template #{name.inspect}. Available: #{available}"
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
[name, template]
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
def parse_template_days(values)
|
|
498
|
+
days = Array(values).map(&:to_i)
|
|
499
|
+
raise FlycalCli::Error, "slots template days cannot be empty." if days.empty?
|
|
500
|
+
|
|
501
|
+
invalid = days.reject { |d| d.between?(1, 7) }
|
|
502
|
+
raise FlycalCli::Error, "Invalid template days #{invalid.inspect}. Use 1 (Mon) .. 7 (Sun)." unless invalid.empty?
|
|
503
|
+
|
|
504
|
+
days.uniq
|
|
505
|
+
end
|
|
506
|
+
|
|
475
507
|
def copy_slots_to_clipboard(text)
|
|
476
508
|
return unless pbcopy_available?
|
|
477
509
|
|
|
@@ -513,7 +545,7 @@ module FlycalCli
|
|
|
513
545
|
[sh, sm, eh, em]
|
|
514
546
|
end
|
|
515
547
|
|
|
516
|
-
raise FlycalCli::Error, "
|
|
548
|
+
raise FlycalCli::Error, "template hours cannot be empty in config.yml." if ranges.empty?
|
|
517
549
|
|
|
518
550
|
ranges.sort_by { |sh, sm, _eh, _em| (sh * 60) + sm }
|
|
519
551
|
end
|
data/lib/flycal_cli/config.rb
CHANGED
|
@@ -32,7 +32,10 @@ module FlycalCli
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def calendar_default
|
|
35
|
-
load["calendar_default"]
|
|
35
|
+
value = load["calendar_default"]
|
|
36
|
+
return nil if value.nil? || value.to_s.strip.empty? || value.to_s == "~"
|
|
37
|
+
|
|
38
|
+
value.to_s
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
def calendar_default=(calendar_id)
|
|
@@ -98,6 +101,38 @@ module FlycalCli
|
|
|
98
101
|
changed = true
|
|
99
102
|
end
|
|
100
103
|
|
|
104
|
+
if normalized.key?("tempaltes") && !normalized.key?("templates")
|
|
105
|
+
normalized["templates"] = normalized.delete("tempaltes")
|
|
106
|
+
changed = true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
templates = normalized["templates"]
|
|
110
|
+
templates_empty = !templates.is_a?(Hash) || templates.empty?
|
|
111
|
+
|
|
112
|
+
if templates_empty && normalized["hours"]
|
|
113
|
+
days =
|
|
114
|
+
if normalized.key?("weekdays_only") && normalized["weekdays_only"] == false
|
|
115
|
+
[1, 2, 3, 4, 5, 6, 7]
|
|
116
|
+
else
|
|
117
|
+
[1, 2, 3, 4, 5]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
normalized["templates"] = {
|
|
121
|
+
"work" => {
|
|
122
|
+
"days" => days,
|
|
123
|
+
"hours" => deep_dup(normalized["hours"])
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
changed = true
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
%w[hours weekdays_only weekdays-only workhours tempaltes].each do |legacy_key|
|
|
130
|
+
next unless normalized.key?(legacy_key)
|
|
131
|
+
|
|
132
|
+
normalized.delete(legacy_key)
|
|
133
|
+
changed = true
|
|
134
|
+
end
|
|
135
|
+
|
|
101
136
|
return [data, false] unless changed
|
|
102
137
|
|
|
103
138
|
data = data.dup
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module FlycalCli
|
|
4
4
|
class SlotFinder
|
|
5
|
-
|
|
5
|
+
DEFAULT_HOURS = [[9, 0, 18, 0]].freeze
|
|
6
|
+
DEFAULT_DAYS = [1, 2, 3, 4, 5].freeze
|
|
6
7
|
STEP_SECONDS = 900
|
|
7
8
|
|
|
8
9
|
def initialize(
|
|
@@ -10,8 +11,8 @@ module FlycalCli
|
|
|
10
11
|
time_min:,
|
|
11
12
|
time_max:,
|
|
12
13
|
slot_duration_seconds:,
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
hours: DEFAULT_HOURS,
|
|
15
|
+
days: DEFAULT_DAYS,
|
|
15
16
|
free_before_seconds: 0,
|
|
16
17
|
free_after_seconds: 0
|
|
17
18
|
)
|
|
@@ -19,8 +20,8 @@ module FlycalCli
|
|
|
19
20
|
@time_min = time_min
|
|
20
21
|
@time_max = time_max
|
|
21
22
|
@slot_duration_seconds = slot_duration_seconds
|
|
22
|
-
@
|
|
23
|
-
@
|
|
23
|
+
@hours = hours
|
|
24
|
+
@days = Array(days).map(&:to_i)
|
|
24
25
|
@free_before_seconds = free_before_seconds
|
|
25
26
|
@free_after_seconds = free_after_seconds
|
|
26
27
|
end
|
|
@@ -28,7 +29,7 @@ module FlycalCli
|
|
|
28
29
|
def slots_by_day
|
|
29
30
|
result = {}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
each_template_day do |date|
|
|
32
33
|
slots = []
|
|
33
34
|
day_intervals(date).each do |day_start, day_end|
|
|
34
35
|
next if day_end <= day_start
|
|
@@ -47,7 +48,7 @@ module FlycalCli
|
|
|
47
48
|
|
|
48
49
|
private
|
|
49
50
|
|
|
50
|
-
def
|
|
51
|
+
def each_template_day
|
|
51
52
|
date = @time_min.to_date
|
|
52
53
|
end_date = @time_max.to_date
|
|
53
54
|
|
|
@@ -57,18 +58,17 @@ module FlycalCli
|
|
|
57
58
|
end
|
|
58
59
|
end
|
|
59
60
|
|
|
61
|
+
# Template days: 1=Monday ... 7=Sunday
|
|
60
62
|
def include_day?(date)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
workday?(date)
|
|
63
|
+
@days.include?(iso_weekday(date))
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
def
|
|
67
|
-
|
|
66
|
+
def iso_weekday(date)
|
|
67
|
+
date.wday.zero? ? 7 : date.wday
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def day_intervals(date)
|
|
71
|
-
@
|
|
71
|
+
@hours.map do |start_h, start_m, end_h, end_m|
|
|
72
72
|
start_at = Time.local(date.year, date.month, date.day, start_h, start_m, 0)
|
|
73
73
|
end_at = Time.local(date.year, date.month, date.day, end_h, end_m, 0)
|
|
74
74
|
start_at = [@time_min, start_at].max
|
|
@@ -147,7 +147,6 @@ module FlycalCli
|
|
|
147
147
|
return [] if rounded_start >= rounded_end
|
|
148
148
|
return [] if (rounded_end - rounded_start) < @slot_duration_seconds
|
|
149
149
|
|
|
150
|
-
# One continuous free range (not sliding windows of fixed duration)
|
|
151
150
|
[[rounded_start, rounded_end]]
|
|
152
151
|
end
|
|
153
152
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module FlycalCli
|
|
4
4
|
class SlotFormatter
|
|
5
5
|
class << self
|
|
6
|
-
def format_header(from:, to:, duration:, calendars:, count:)
|
|
6
|
+
def format_header(from:, to:, duration:, calendars:, count:, template: nil)
|
|
7
7
|
lines = []
|
|
8
8
|
lines << Locale.t(
|
|
9
9
|
"slots.header",
|
|
@@ -12,6 +12,7 @@ module FlycalCli
|
|
|
12
12
|
to: underline(Locale.format_long_date(to)),
|
|
13
13
|
duration: underline(duration)
|
|
14
14
|
)
|
|
15
|
+
lines << Locale.t("slots.template", name: template) if template && !template.to_s.empty?
|
|
15
16
|
calendars.each do |cal|
|
|
16
17
|
lines << cal[:name].to_s
|
|
17
18
|
end
|
|
@@ -49,7 +50,7 @@ module FlycalCli
|
|
|
49
50
|
end
|
|
50
51
|
|
|
51
52
|
def slot_range(start_at, end_at)
|
|
52
|
-
"#{format_time(start_at)}
|
|
53
|
+
"#{format_time(start_at)} - #{format_time(end_at)}"
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
def format_time(time)
|
data/lib/flycal_cli/version.rb
CHANGED
data/locales/en.json
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"no_available": "No available slots found.",
|
|
33
33
|
"no_calendar": "No calendar found. Run 'flycal config' to set a default.",
|
|
34
34
|
"header": "found %{count} slots\nfrom %{from} to %{to}\nwith duration %{duration}\nfor calendars",
|
|
35
|
+
"template": "template %{name}",
|
|
35
36
|
"copied_to_clipboard": "✓ Slot list copied to clipboard (pbcopy)"
|
|
36
37
|
},
|
|
37
38
|
"errors": {
|
data/locales/it.json
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"no_available": "Nessuno slot disponibile.",
|
|
33
33
|
"no_calendar": "Nessun calendario trovato. Esegui 'flycal config' per impostare il predefinito.",
|
|
34
34
|
"header": "trovati %{count} slot\nda %{from} a %{to}\ncon durata %{duration}\nper i calendari",
|
|
35
|
+
"template": "template %{name}",
|
|
35
36
|
"copied_to_clipboard": "✓ Lista slot copiata negli appunti (pbcopy)"
|
|
36
37
|
},
|
|
37
38
|
"errors": {
|
data/mcp/tools.json
CHANGED
|
@@ -17,18 +17,17 @@
|
|
|
17
17
|
"credentials_path": "~/.flycal/credentials.json",
|
|
18
18
|
"keys": {
|
|
19
19
|
"calendar_default": {
|
|
20
|
-
"type": "string",
|
|
21
|
-
"description": "Default Google Calendar ID used by search and as slots fallback"
|
|
20
|
+
"type": ["string", "null"],
|
|
21
|
+
"description": "Default Google Calendar ID used by search and as slots fallback. YAML null (~) means unset."
|
|
22
22
|
},
|
|
23
23
|
"locale": {
|
|
24
24
|
"type": "string",
|
|
25
25
|
"enum": ["en", "it"],
|
|
26
26
|
"description": "Default CLI locale"
|
|
27
27
|
},
|
|
28
|
-
"slots.
|
|
29
|
-
"type": "
|
|
30
|
-
"
|
|
31
|
-
"description": "Slot search hour ranges, e.g. [\"9:30-13:00\", \"14:00-18:30\"]"
|
|
28
|
+
"slots.templates": {
|
|
29
|
+
"type": "object",
|
|
30
|
+
"description": "Named templates with days (1=Mon..7=Sun) and hours ranges. Default template is the first key (work)."
|
|
32
31
|
},
|
|
33
32
|
"slots.defaults.from": {
|
|
34
33
|
"type": "string",
|
|
@@ -46,10 +45,6 @@
|
|
|
46
45
|
"type": "string",
|
|
47
46
|
"description": "Buffer after each slot; gaps must fit duration + free_after"
|
|
48
47
|
},
|
|
49
|
-
"slots.weekdays_only": {
|
|
50
|
-
"type": "boolean",
|
|
51
|
-
"description": "When true, slots are searched Mon–Fri only"
|
|
52
|
-
},
|
|
53
48
|
"slots.exclude_calendars": {
|
|
54
49
|
"type": "array",
|
|
55
50
|
"items": { "type": "string" },
|
|
@@ -256,7 +251,7 @@
|
|
|
256
251
|
{
|
|
257
252
|
"name": "flycal_slots",
|
|
258
253
|
"title": "Find free time slots",
|
|
259
|
-
"description": "Find free slots
|
|
254
|
+
"description": "Find free slots using a config template (days + hours). Default template is the first one (work). Use --template dinner for evening hours. Subtracts busy events from slots.exclude_calendars. Starts from --from (default: now) for --in (default: 1 week). Duration defaults to 45min. Respects free_before/free_after. Output: header, template name, calendars, Google Calendar day link, continuous free ranges.",
|
|
260
255
|
"interactive": false,
|
|
261
256
|
"requires_auth": true,
|
|
262
257
|
"command": {
|
|
@@ -266,18 +261,20 @@
|
|
|
266
261
|
"duration": ["--duration", "{value}"],
|
|
267
262
|
"from": ["--from", "{value}"],
|
|
268
263
|
"in": ["--in", "{value}"],
|
|
264
|
+
"template": ["--template", "{value}"],
|
|
269
265
|
"calendar": ["--calendar", "{value}"],
|
|
270
266
|
"locale": ["--locale", "{value}"]
|
|
271
267
|
},
|
|
272
268
|
"examples": [
|
|
273
269
|
["flycal", "slots"],
|
|
274
|
-
["flycal", "slots", "--
|
|
275
|
-
["flycal", "slots", "--
|
|
270
|
+
["flycal", "slots", "--in", "5 days"],
|
|
271
|
+
["flycal", "slots", "--in", "12 days", "--template", "dinner"],
|
|
272
|
+
["flycal", "slots", "--duration", "1h"]
|
|
276
273
|
]
|
|
277
274
|
},
|
|
278
275
|
"output": {
|
|
279
276
|
"format": "text/plain",
|
|
280
|
-
"example": "found 3 slots\nfrom wed 29 July 2026 to wed 5 August 2026\nwith duration 45min\nfor calendars\nWork\nhttps://calendar.google.com/calendar/r/day/2026/7/29\n\nfriday 15/7\n10-12\n13-15.30"
|
|
277
|
+
"example": "found 3 slots\nfrom wed 29 July 2026 to wed 5 August 2026\nwith duration 45min\nfor calendars\ntemplate work\nWork\nhttps://calendar.google.com/calendar/r/day/2026/7/29\n\nfriday 15/7\n10 - 12\n13 - 15.30"
|
|
281
278
|
},
|
|
282
279
|
"inputSchema": {
|
|
283
280
|
"type": "object",
|
|
@@ -296,6 +293,10 @@
|
|
|
296
293
|
"type": "string",
|
|
297
294
|
"description": "Search window from --from. Default: 1 week. Examples: 3 days, 1 week, 48 hours (quote if spaces)."
|
|
298
295
|
},
|
|
296
|
+
"template": {
|
|
297
|
+
"type": "string",
|
|
298
|
+
"description": "Template name from slots.templates (default: first template, usually work)."
|
|
299
|
+
},
|
|
299
300
|
"calendar": {
|
|
300
301
|
"type": "string",
|
|
301
302
|
"description": "Fallback calendar name/ID when exclude_calendars is not configured."
|