@qvac/skills 0.0.0 → 0.1.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.
Files changed (84) hide show
  1. package/LICENSE.md +198 -0
  2. package/README.md +49 -0
  3. package/index.d.ts +4 -0
  4. package/index.js +9 -0
  5. package/package.json +87 -1
  6. package/skills/apple-notes/SKILL.md +92 -0
  7. package/skills/apple-notes/append-note.applescript +9 -0
  8. package/skills/apple-notes/cli.schema.json +32 -0
  9. package/skills/apple-notes/create-note.applescript +15 -0
  10. package/skills/apple-notes/delete-note.applescript +10 -0
  11. package/skills/apple-notes/edit-note.applescript +10 -0
  12. package/skills/apple-notes/read-note.applescript +28 -0
  13. package/skills/apple-notes/references/read.md +65 -0
  14. package/skills/apple-notes/references/write.md +105 -0
  15. package/skills/apple-notes/search-notes.applescript +21 -0
  16. package/skills/apple-reminders/SKILL.md +129 -0
  17. package/skills/apple-reminders/cli.schema.json +201 -0
  18. package/skills/apple-reminders/references/edit.md +69 -0
  19. package/skills/apple-reminders/references/view.md +58 -0
  20. package/skills/asana/SKILL.md +59 -0
  21. package/skills/diagrams/SKILL.md +107 -0
  22. package/skills/diagrams/references/class.md +29 -0
  23. package/skills/diagrams/references/er.md +27 -0
  24. package/skills/diagrams/references/flowchart.md +33 -0
  25. package/skills/diagrams/references/gantt.md +38 -0
  26. package/skills/diagrams/references/mindmap.md +35 -0
  27. package/skills/diagrams/references/pie.md +27 -0
  28. package/skills/diagrams/references/sequence.md +32 -0
  29. package/skills/diagrams/references/state.md +30 -0
  30. package/skills/diagrams/references/timeline.md +28 -0
  31. package/skills/excel/SKILL.md +120 -0
  32. package/skills/excel/references/create.md +374 -0
  33. package/skills/excel/references/edit.md +353 -0
  34. package/skills/excel/references/read.md +99 -0
  35. package/skills/github/SKILL.md +42 -0
  36. package/skills/gmail/SKILL.md +142 -0
  37. package/skills/gmail/operations.json +71 -0
  38. package/skills/google-calendar/SKILL.md +139 -0
  39. package/skills/google-calendar/operations.json +62 -0
  40. package/skills/google-docs/SKILL.md +74 -0
  41. package/skills/google-docs/operations.json +61 -0
  42. package/skills/google-docs/references/create.md +97 -0
  43. package/skills/google-docs/references/edit.md +146 -0
  44. package/skills/google-docs/references/read.md +49 -0
  45. package/skills/google-drive/SKILL.md +118 -0
  46. package/skills/google-drive/operations.json +40 -0
  47. package/skills/google-sheets/SKILL.md +71 -0
  48. package/skills/google-sheets/operations.json +85 -0
  49. package/skills/google-sheets/references/create.md +54 -0
  50. package/skills/google-sheets/references/edit.md +124 -0
  51. package/skills/google-sheets/references/read.md +74 -0
  52. package/skills/image-generation/SKILL.md +48 -0
  53. package/skills/music-generation/SKILL.md +76 -0
  54. package/skills/notion/SKILL.md +61 -0
  55. package/skills/notion/operations.json +53 -0
  56. package/skills/notion/references/comments.md +65 -0
  57. package/skills/notion/references/databases.md +68 -0
  58. package/skills/notion/references/pages.md +119 -0
  59. package/skills/notion/references/tasks.md +28 -0
  60. package/skills/obsidian/SKILL.md +122 -0
  61. package/skills/obsidian/cli.schema.json +392 -0
  62. package/skills/obsidian/references/read.md +79 -0
  63. package/skills/obsidian/references/write.md +67 -0
  64. package/skills/pdf/SKILL.md +110 -0
  65. package/skills/pdf/references/create.md +169 -0
  66. package/skills/pdf/references/transform.md +270 -0
  67. package/skills/pdf/scripts/decrypt.py +26 -0
  68. package/skills/pdf/scripts/encrypt.py +25 -0
  69. package/skills/pdf/scripts/extract_text.py +25 -0
  70. package/skills/pdf/scripts/merge.py +21 -0
  71. package/skills/pdf/scripts/rotate.py +27 -0
  72. package/skills/presentations/SKILL.md +118 -0
  73. package/skills/presentations/references/create.md +399 -0
  74. package/skills/presentations/references/edit.md +314 -0
  75. package/skills/presentations/references/read.md +127 -0
  76. package/skills/spotify/SKILL.md +86 -0
  77. package/skills/weather/SKILL.md +33 -0
  78. package/skills/word/SKILL.md +141 -0
  79. package/skills/word/references/create.md +368 -0
  80. package/skills/word/references/edit.md +704 -0
  81. package/skills/word/references/read.md +141 -0
  82. package/skills/word/references/replace.md +86 -0
  83. package/skills/word/scripts/list_paragraphs.py +19 -0
  84. package/skills/word/scripts/replace_paragraphs.py +58 -0
@@ -0,0 +1,71 @@
1
+ {
2
+ "operations": [
3
+ {
4
+ "tool": "gmail_send",
5
+ "description": "Send an email through Gmail, or reply in a thread when threadId and inReplyTo are given. Pass the message as plain fields — never build the RFC 2822 message or base64 yourself. Confirm the recipient and body with the user before sending.",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "to": {
10
+ "type": "array",
11
+ "items": { "type": "string" },
12
+ "description": "Recipient email addresses"
13
+ },
14
+ "subject": { "type": "string", "description": "Subject line" },
15
+ "text": { "type": "string", "description": "Plain-text body" },
16
+ "html": { "type": "string", "description": "HTML body, used when text is absent" },
17
+ "cc": { "type": "array", "items": { "type": "string" } },
18
+ "bcc": { "type": "array", "items": { "type": "string" } },
19
+ "replyTo": { "type": "string" },
20
+ "threadId": {
21
+ "type": "string",
22
+ "description": "Thread to reply in, from a previous messages.list or messages.get"
23
+ },
24
+ "inReplyTo": {
25
+ "type": "string",
26
+ "description": "Message-ID header of the message being replied to"
27
+ },
28
+ "references": { "type": "string", "description": "References header of the thread" }
29
+ },
30
+ "required": ["to", "subject"]
31
+ },
32
+ "request": {
33
+ "method": "POST",
34
+ "url": "https://gmail.googleapis.com/gmail/v1/users/me/messages/send",
35
+ "builder": "gmail-send"
36
+ }
37
+ },
38
+ {
39
+ "tool": "gmail_draft",
40
+ "description": "Create a Gmail draft without sending it. Pass the message as plain fields — never build the RFC 2822 message or base64 yourself.",
41
+ "parameters": {
42
+ "type": "object",
43
+ "properties": {
44
+ "to": {
45
+ "type": "array",
46
+ "items": { "type": "string" },
47
+ "description": "Recipient email addresses"
48
+ },
49
+ "subject": { "type": "string", "description": "Subject line" },
50
+ "text": { "type": "string", "description": "Plain-text body" },
51
+ "html": { "type": "string", "description": "HTML body, used when text is absent" },
52
+ "cc": { "type": "array", "items": { "type": "string" } },
53
+ "bcc": { "type": "array", "items": { "type": "string" } },
54
+ "replyTo": { "type": "string" },
55
+ "threadId": { "type": "string", "description": "Thread the draft replies in" },
56
+ "inReplyTo": {
57
+ "type": "string",
58
+ "description": "Message-ID header of the message being replied to"
59
+ },
60
+ "references": { "type": "string", "description": "References header of the thread" }
61
+ },
62
+ "required": ["to", "subject"]
63
+ },
64
+ "request": {
65
+ "method": "POST",
66
+ "url": "https://gmail.googleapis.com/gmail/v1/users/me/drafts",
67
+ "builder": "gmail-draft"
68
+ }
69
+ }
70
+ ]
71
+ }
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: google-calendar
3
+ description: List, create, update, and delete Google Calendar events via the Google Calendar REST API.
4
+ aliases: [calendar, meeting+create, meeting+schedule, meeting+book, meeting+move, meeting+cancel, event+create]
5
+ tools: [http_request, calendar_create_meet_event, calendar_add_meet]
6
+ platform: [darwin, linux, win32]
7
+ credentials: [google_calendar_access_token]
8
+ allow_list: [https://www.googleapis.com/calendar/v3/]
9
+ ---
10
+
11
+ # Google Calendar
12
+
13
+ Use `calendar_create_meet_event` and `calendar_add_meet` for Google Meet links, and `http_request` for everything else (list, plain create/update/delete, free/busy). The Google Calendar credential is attached automatically to every `www.googleapis.com/calendar/v3/` request — **never include an `auth` block**.
14
+
15
+ ## Prerequisites
16
+
17
+ Google Calendar must be connected. Each Google skill is connected separately, with its
18
+ own app and its own approval — connecting one grants nothing to the others. If
19
+ credentials are missing, tell the user to connect Google Calendar from Settings, or to
20
+ set the `google_calendar_access_token` credential.
21
+
22
+ ## Base URL
23
+
24
+ `https://www.googleapis.com/calendar/v3` — default `calendarId` is `primary` unless the user names another calendar.
25
+
26
+ ## Temporal Accuracy (Critical)
27
+
28
+ - Resolve relative dates ("today", "tomorrow", "next week", "in 2 hours") to absolute ISO 8601 timestamps **with timezone offset** before calling the API.
29
+ - Never infer "now" from memory when building `timeMin`, `timeMax`, or event start/end values.
30
+ - If the date or time is ambiguous, ask the user instead of guessing.
31
+
32
+ Example: annotation `[Current local time: 2026-08-12 14:00:00 (UTC-03:00)]`, user asks "in 30 minutes for 1 hour" -> `start.dateTime` = `2026-08-12T14:30:00-03:00`, `end.dateTime` = `2026-08-12T15:30:00-03:00`.
33
+
34
+ ## Common Operations
35
+
36
+ ### List upcoming events
37
+
38
+ Always use `singleEvents=true` and `orderBy=startTime` so recurring events expand and sort correctly.
39
+
40
+ ```json
41
+ {
42
+ "url": "https://www.googleapis.com/calendar/v3/calendars/primary/events",
43
+ "method": "GET",
44
+ "query": {
45
+ "timeMin": "<resolved ISO 8601 with offset>",
46
+ "maxResults": 10,
47
+ "singleEvents": true,
48
+ "orderBy": "startTime"
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### Create an event
54
+
55
+ Ask for missing required fields (summary, start, end) before creating.
56
+
57
+ ```json
58
+ {
59
+ "url": "https://www.googleapis.com/calendar/v3/calendars/primary/events",
60
+ "method": "POST",
61
+ "body": {
62
+ "summary": "Design review",
63
+ "start": { "dateTime": "2026-06-10T14:00:00-03:00" },
64
+ "end": { "dateTime": "2026-06-10T15:00:00-03:00" },
65
+ "attendees": [{ "email": "colleague@example.com" }]
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### Create an event with a Google Meet link
71
+
72
+ Use `calendar_create_meet_event` with `summary`, `start`, `end` (ISO 8601 with offset), and optionally `timeZone`, `description`, `location`, `attendees`, `calendarId`.
73
+
74
+ ```json
75
+ {
76
+ "summary": "Sync call",
77
+ "start": "2026-06-10T14:00:00-03:00",
78
+ "end": "2026-06-10T14:30:00-03:00"
79
+ }
80
+ ```
81
+
82
+ To add a Meet link to an event that already exists, use `calendar_add_meet` with `eventId` (and `calendarId` if not `primary`).
83
+
84
+ ### Update an event
85
+
86
+ `PATCH` with only the fields to change.
87
+
88
+ ```json
89
+ {
90
+ "url": "https://www.googleapis.com/calendar/v3/calendars/primary/events/{eventId}",
91
+ "method": "PATCH",
92
+ "body": { "summary": "Updated title" }
93
+ }
94
+ ```
95
+
96
+ ### Delete an event
97
+
98
+ ```json
99
+ {
100
+ "url": "https://www.googleapis.com/calendar/v3/calendars/primary/events/{eventId}",
101
+ "method": "DELETE"
102
+ }
103
+ ```
104
+
105
+ ### Free/busy query
106
+
107
+ ```json
108
+ {
109
+ "url": "https://www.googleapis.com/calendar/v3/freeBusy",
110
+ "method": "POST",
111
+ "body": {
112
+ "timeMin": "2026-06-10T00:00:00Z",
113
+ "timeMax": "2026-06-11T00:00:00Z",
114
+ "items": [{ "id": "primary" }]
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### List calendars
120
+
121
+ ```json
122
+ {
123
+ "url": "https://www.googleapis.com/calendar/v3/users/me/calendarList",
124
+ "method": "GET"
125
+ }
126
+ ```
127
+
128
+ ## Output Policy
129
+
130
+ - Present events with title, date/time (with timezone), location, and attendees when available.
131
+ - For create/update, report the event `id`, start/end time, and `htmlLink` rendered as a Markdown link — e.g. `[event title](htmlLink)`. Never present the URL bare or wrapped in backticks, or it won't be clickable.
132
+ - Confirm before deleting events; show the event title and time so the user can verify.
133
+
134
+ ## Common Mistakes
135
+
136
+ - Sending natural-language dates instead of absolute ISO 8601 with timezone offset.
137
+ - Listing without `singleEvents=true` — recurring events come back collapsed and unsorted.
138
+ - Calling get/patch/delete without a real `eventId` — list/search first.
139
+ - Including an `auth` block by hand — credentials attach automatically; a mistyped key breaks the request.
@@ -0,0 +1,62 @@
1
+ {
2
+ "operations": [
3
+ {
4
+ "tool": "calendar_create_meet_event",
5
+ "description": "Create a Google Calendar event that has a Google Meet link. Use this whenever the user asks for a meeting with a video call; a plain event without a call stays on http_request.",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "summary": { "type": "string", "description": "Event title" },
10
+ "start": {
11
+ "type": "string",
12
+ "description": "Start time, ISO 8601 with a UTC offset, e.g. 2026-03-04T15:00:00-03:00"
13
+ },
14
+ "end": {
15
+ "type": "string",
16
+ "description": "End time, ISO 8601 with a UTC offset"
17
+ },
18
+ "timeZone": {
19
+ "type": "string",
20
+ "description": "IANA time zone, e.g. America/Sao_Paulo"
21
+ },
22
+ "description": { "type": "string" },
23
+ "location": { "type": "string" },
24
+ "attendees": {
25
+ "type": "array",
26
+ "items": { "type": "string" },
27
+ "description": "Attendee email addresses"
28
+ },
29
+ "calendarId": { "type": "string", "description": "Defaults to primary" }
30
+ },
31
+ "required": ["summary", "start", "end"]
32
+ },
33
+ "request": {
34
+ "method": "POST",
35
+ "url": "https://www.googleapis.com/calendar/v3/calendars/{calendarId}/events",
36
+ "urlDefaults": { "calendarId": "primary" },
37
+ "builder": "calendar-meet-event"
38
+ }
39
+ },
40
+ {
41
+ "tool": "calendar_add_meet",
42
+ "description": "Add a Google Meet link to an existing Google Calendar event.",
43
+ "parameters": {
44
+ "type": "object",
45
+ "properties": {
46
+ "eventId": {
47
+ "type": "string",
48
+ "description": "Event id, from a previous events.list or events.insert"
49
+ },
50
+ "calendarId": { "type": "string", "description": "Defaults to primary" }
51
+ },
52
+ "required": ["eventId"]
53
+ },
54
+ "request": {
55
+ "method": "PATCH",
56
+ "url": "https://www.googleapis.com/calendar/v3/calendars/{calendarId}/events/{eventId}",
57
+ "urlDefaults": { "calendarId": "primary" },
58
+ "builder": "calendar-add-meet"
59
+ }
60
+ }
61
+ ]
62
+ }
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: google-docs
3
+ description: Create, read, and edit Google Docs documents via the Google Docs REST API.
4
+ tools: [http_request, docs_create, docs_append_text]
5
+ platform: [darwin, linux, win32]
6
+ credentials: [google_docs_access_token]
7
+ allow_list: [https://docs.googleapis.com/v1/documents, https://www.googleapis.com/drive/v3/files]
8
+ ---
9
+
10
+ # Google Docs
11
+
12
+ Use `docs_create` to create a document and `docs_append_text` to add text or
13
+ pages to it; use `http_request` for everything else (get, replace, insert at a
14
+ position, delete ranges, Drive search, trash). For each `http_request`, set
15
+ `auth.tokenCredentialKey` to `google_docs_access_token`.
16
+
17
+ Never use `exec`, Python, curl, shell flags such as `-H`/`-d`, or a JSON string
18
+ to make a Google Docs request. Call one tool per operation with one complete
19
+ structured object. In particular, `body` must be an object, not a serialized
20
+ JSON string; the tool JSON-encodes it and sets `Content-Type: application/json`
21
+ automatically.
22
+
23
+ ## Load the Recipe File First
24
+
25
+ This file carries no requests. The working request shapes live in three
26
+ reference files — load the one for the job with the `skill` tool BEFORE calling
27
+ `http_request`, then copy its request and change only the values:
28
+
29
+ Each load is a real `skill` tool call — printing the call as JSON or text in
30
+ your reply loads nothing.
31
+
32
+ - **Reading or finding documents** — "what does document X say", "summarize
33
+ my doc", "find / list my documents": call the `skill` tool with
34
+ `name: "google-docs"` and `file: "references/read.md"`.
35
+ - **Creating a new document** (no existing document involved; one page or
36
+ many): call the `skill` tool with `name: "google-docs"` and
37
+ `file: "references/create.md"` — it covers `docs_create` and filling the
38
+ document with `docs_append_text`.
39
+ - **Changing an existing document** — append or insert text, find and
40
+ replace, delete a passage, move it to the trash: call the `skill` tool with
41
+ `name: "google-docs"` and `file: "references/edit.md"`.
42
+
43
+ Never write a request from memory. The recipes carry the exact request shapes
44
+ (`batchUpdate` request names, index rules, page limits) that fail in
45
+ non-obvious ways when improvised; loading the file is one cheap read-only call.
46
+
47
+ ## Prerequisites
48
+
49
+ Google Docs must be connected. Each Google skill is connected separately, with its
50
+ own app and its own approval — connecting one grants nothing to the others. If
51
+ credentials are missing, tell the user to connect Google Docs from Settings, or to
52
+ set the `google_docs_access_token` credential.
53
+
54
+ If Google returns `403 PERMISSION_DENIED` with reason `SERVICE_DISABLED`, the
55
+ credential is working but the OAuth client's Google Cloud project has not
56
+ enabled the Google Docs API. Do not ask the user to reconnect. Tell the project
57
+ owner to open the response's `activationUrl`, enable the API, and retry after
58
+ propagation.
59
+
60
+ ## Identifiers
61
+
62
+ Documents are identified by `documentId` — the alphanumeric string in the URL
63
+ `docs.google.com/document/d/{documentId}/...`, and the `documentId` field of a
64
+ create response. Listing and searching documents go through the Google Drive
65
+ API (`references/read.md`), never the Docs API.
66
+
67
+ ## Output Policy
68
+
69
+ - For document reads, extract and present the text content clearly — do not
70
+ echo the raw JSON structure.
71
+ - For edits, confirm the change with the user first (what text is being
72
+ inserted, replaced, or deleted) unless they already spelled it out.
73
+ - Report success only when the `batchUpdate` response contains `replies` with
74
+ no errors, and name the document (title or link) in the answer.
@@ -0,0 +1,61 @@
1
+ {
2
+ "operations": [
3
+ {
4
+ "tool": "docs_create",
5
+ "description": "Create an empty Google Doc with a title. Call it exactly once per requested document, then append content with docs_append_text using the returned documentId.",
6
+ "parameters": {
7
+ "type": "object",
8
+ "properties": {
9
+ "title": {
10
+ "type": "string",
11
+ "description": "Document title"
12
+ }
13
+ },
14
+ "required": [
15
+ "title"
16
+ ]
17
+ },
18
+ "request": {
19
+ "method": "POST",
20
+ "url": "https://docs.googleapis.com/v1/documents",
21
+ "builder": "docs-create"
22
+ },
23
+ "response": {
24
+ "pick": [
25
+ "documentId",
26
+ "title"
27
+ ]
28
+ }
29
+ },
30
+ {
31
+ "tool": "docs_append_text",
32
+ "description": "Append text to the end of a Google Doc, optionally followed by a page break. One page (80 words or fewer) per call; set pageBreak on every page except the last. Never compute indexes yourself.",
33
+ "parameters": {
34
+ "type": "object",
35
+ "properties": {
36
+ "documentId": {
37
+ "type": "string",
38
+ "description": "Document id, from docs_create or the docs.google.com/document/d/{id} URL"
39
+ },
40
+ "text": {
41
+ "type": "string",
42
+ "description": "Text to append; end it with a newline"
43
+ },
44
+ "pageBreak": {
45
+ "type": "boolean",
46
+ "description": "Insert a page break after the text"
47
+ }
48
+ },
49
+ "required": [
50
+ "documentId",
51
+ "text"
52
+ ]
53
+ },
54
+ "request": {
55
+ "method": "POST",
56
+ "url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
57
+ "builder": "docs-append-text"
58
+ }
59
+ }
60
+ ]
61
+ }
@@ -0,0 +1,97 @@
1
+ # Creating a Google Doc
2
+
3
+ Two typed tools do the whole job: `docs_create` makes the document,
4
+ `docs_append_text` fills it. Typed tools select their own credential. For each fallback `http_request`,
5
+ set `auth.tokenCredentialKey` to `google_docs_access_token`.
6
+
7
+ ## Create the document
8
+
9
+ Call `docs_create` with the title:
10
+
11
+ ```json
12
+ { "title": "My Document" }
13
+ ```
14
+
15
+ The result contains the `documentId`. Capture it and keep using it.
16
+ Create the document exactly once. Do not follow a successful create with a
17
+ Drive search, a GET, or another create just to rediscover the ID. If the result has no
18
+ `documentId`, stop and report that response problem; never append without the
19
+ ID.
20
+
21
+ ## Add the content
22
+
23
+ Call `docs_append_text` once per page. Put the document title as the first
24
+ line of the first page instead of spending a call on a heading, end the text
25
+ with a newline, and keep each call at 80 words or fewer. The 80-word limit
26
+ applies even when the user asks for only one page. Never expand a one-page
27
+ request into a long list in one call.
28
+
29
+ ```json
30
+ {
31
+ "documentId": "<id from docs_create>",
32
+ "text": "My Document\n\nConcise content.\n",
33
+ "pageBreak": false
34
+ }
35
+ ```
36
+
37
+ ## Multi-page documents
38
+
39
+ One requested page per `docs_append_text` call, in order, each 80 words or
40
+ fewer, with `"pageBreak": true` on every page except the last — five requested
41
+ pages therefore take five append calls. Wait for a successful result before
42
+ appending the next page. Do not place several pages of text in one call: if
43
+ the tool reports the arguments are not valid JSON, the call was too large or
44
+ incomplete, so retry only that page with shorter text.
45
+
46
+ ## Finishing
47
+
48
+ Report success only when every append result came back without an error.
49
+ Answer with the document title and the link
50
+ `https://docs.google.com/document/d/{documentId}/edit`; do not read the
51
+ document back to "confirm".
52
+
53
+ ## Without the typed tools
54
+
55
+ The typed tools wrap these two Docs API requests; use them only if the typed
56
+ tools are missing from this chat:
57
+
58
+ ```json
59
+ {
60
+ "url": "https://docs.googleapis.com/v1/documents",
61
+ "auth": { "tokenCredentialKey": "google_docs_access_token" },
62
+ "method": "POST",
63
+ "body": { "title": "My Document" }
64
+ }
65
+ ```
66
+
67
+ ```json
68
+ {
69
+ "url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
70
+ "auth": { "tokenCredentialKey": "google_docs_access_token" },
71
+ "method": "POST",
72
+ "body": {
73
+ "requests": [
74
+ {
75
+ "insertText": {
76
+ "endOfSegmentLocation": {},
77
+ "text": "Page heading\n\nConcise page content.\n"
78
+ }
79
+ },
80
+ { "insertPageBreak": { "endOfSegmentLocation": {} } }
81
+ ]
82
+ }
83
+ }
84
+ ```
85
+
86
+ Then it is one requested page per `batchUpdate` call, the same 80-word limit,
87
+ and the `insertPageBreak` request omitted on the last page;
88
+ never call `/v1/documents:batchUpdate` without the ID.
89
+
90
+ ## Common Mistakes
91
+
92
+ - Recreating or searching for a document after a successful create instead of
93
+ using the returned `documentId` — this produces duplicates and wastes rounds.
94
+ - Sending a whole multi-page document in one call — one page of at most 80
95
+ words per call, `pageBreak` on every page except the last.
96
+ - Computing indexes yourself — `docs_append_text` and `endOfSegmentLocation`
97
+ never need one.
@@ -0,0 +1,146 @@
1
+ # Editing an Existing Google Doc
2
+
3
+ Every request is one `http_request` call with a structured object. For each request, set `auth.tokenCredentialKey` to `google_docs_access_token`. All content edits go through
4
+ `batchUpdate` — there is no PATCH endpoint for document body changes.
5
+
6
+ Get the `documentId` from the URL the user gave, from an earlier create
7
+ response, or from a Drive search (`references/read.md`).
8
+
9
+ Every `http_request` edit is ONE `POST …:batchUpdate` whose body is `{ "requests": [ … ] }` —
10
+ a bare request object without the `requests` array is rejected with 400. Copy
11
+ the request shapes below exactly: the field names are fixed by Google, and any
12
+ other name (`searchText`, `replacementText`, `find`, `replace`, `newText`) fails
13
+ with `Unknown name`. One edit per user request — an edit never needs a
14
+ preceding insert of text that is already in the document.
15
+
16
+ ## Append text
17
+
18
+ Call `docs_append_text` — it appends at the end of the document with no index
19
+ arithmetic and no preliminary GET. End the text with a newline; keep it at 80
20
+ words or fewer per call.
21
+
22
+ ```json
23
+ {
24
+ "documentId": "<documentId>",
25
+ "text": "\nNew paragraph.\n",
26
+ "pageBreak": false
27
+ }
28
+ ```
29
+
30
+ The raw equivalent, for when the typed tool is missing from this chat, is a
31
+ `batchUpdate` with `"insertText": { "endOfSegmentLocation": {}, "text": "…" }`.
32
+
33
+ ## Insert text at a position
34
+
35
+ Use an explicit `location.index` only when editing at a known position. A new
36
+ blank document's first valid insertion point is index 1; index 2 is outside its
37
+ empty paragraph. Indexes count UTF-16 code units and change with every edit, so
38
+ `GET` the document first when you need one.
39
+
40
+ ```json
41
+ {
42
+ "url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
43
+ "auth": { "tokenCredentialKey": "google_docs_access_token" },
44
+ "method": "POST",
45
+ "body": {
46
+ "requests": [
47
+ {
48
+ "insertText": {
49
+ "location": { "index": 1 },
50
+ "text": "Hello, World!"
51
+ }
52
+ }
53
+ ]
54
+ }
55
+ }
56
+ ```
57
+
58
+ ## Replace all text matching a pattern
59
+
60
+ Use `replaceAllText` to find and replace — exactly these keys:
61
+ `containsText` (with `text` and optional `matchCase`) and `replaceText`.
62
+ `containsText.text` is a regex — escape special characters (`.`, `*`, `+`,
63
+ `?`, `[`, `]`, `(`, `)`, `{`, `}`, `^`, `$`, `|`, `\`). No `GET` is needed
64
+ first, and no `insertText` belongs in the same request.
65
+
66
+ ```json
67
+ {
68
+ "url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
69
+ "auth": { "tokenCredentialKey": "google_docs_access_token" },
70
+ "method": "POST",
71
+ "body": {
72
+ "requests": [
73
+ {
74
+ "replaceAllText": {
75
+ "containsText": { "text": "old text", "matchCase": true },
76
+ "replaceText": "new text"
77
+ }
78
+ }
79
+ ]
80
+ }
81
+ }
82
+ ```
83
+
84
+ The reply's `occurrencesChanged` says how many matches were replaced; `0` means
85
+ the text was not found — tell the user instead of retrying with guesses.
86
+
87
+ ## Delete a range of text
88
+
89
+ Fetch the document first, then specify the start and exclusive end index.
90
+
91
+ ```json
92
+ {
93
+ "url": "https://docs.googleapis.com/v1/documents/{documentId}:batchUpdate",
94
+ "auth": { "tokenCredentialKey": "google_docs_access_token" },
95
+ "method": "POST",
96
+ "body": {
97
+ "requests": [
98
+ {
99
+ "deleteContentRange": {
100
+ "range": { "startIndex": 10, "endIndex": 20 }
101
+ }
102
+ }
103
+ ]
104
+ }
105
+ }
106
+ ```
107
+
108
+ ## Move a document to the trash
109
+
110
+ Trashing goes through the Drive API; the user can restore it from Drive's
111
+ trash. Only do this when the user explicitly asks to delete or remove the
112
+ document.
113
+
114
+ ```json
115
+ {
116
+ "url": "https://www.googleapis.com/drive/v3/files/{documentId}",
117
+ "auth": { "tokenCredentialKey": "google_docs_access_token" },
118
+ "method": "PATCH",
119
+ "body": { "trashed": true }
120
+ }
121
+ ```
122
+
123
+ ## Finishing
124
+
125
+ Report success only when the `batchUpdate` response contains `replies` with no
126
+ errors. Do not read the document back to confirm an edit.
127
+
128
+ ## Common Mistakes
129
+
130
+ - Using PATCH on the document body instead of `batchUpdate` — PATCH only
131
+ updates metadata like title, not content.
132
+ - Treating indexes like array offsets — they count UTF-16 code units, range
133
+ ends are exclusive, and a blank document's first usable body index is 1.
134
+ - Using `insertionIndex` or placing `location.index` directly under
135
+ `insertText` — the supported shape is `insertText.location.index`; for
136
+ appends, prefer `insertText.endOfSegmentLocation`.
137
+ - Attempting a numeric-position edit without fetching the document first — you
138
+ won't know the current indexes.
139
+ - Not escaping regex special characters in `containsText` patterns.
140
+ - Renaming the fields — `searchText`, `replacementText`, `replacement`, `find`
141
+ all return 400 `Unknown name`; only `containsText` + `replaceText` exist.
142
+ - Sending a request object without the `{ "requests": [ … ] }` wrapper.
143
+ - Inserting text that is already in the document before an edit — a replace or
144
+ delete works on the existing content directly.
145
+ - Passing curl/Python text or serialized JSON to `http_request` instead of one
146
+ structured tool-call object.