@extuitive/skill 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.
- package/LICENSE +21 -0
- package/README.md +514 -0
- package/bin/cli.mjs +932 -0
- package/package.json +40 -0
- package/skills/extuitive/SKILL.md +63 -0
- package/skills/extuitive/references/connect.md +75 -0
- package/skills/extuitive/references/init.md +83 -0
- package/skills/extuitive/references/select.md +89 -0
- package/skills/extuitive/references/tools.md +252 -0
- package/skills/extuitive/references/upload-status.md +102 -0
- package/skills/extuitive/references/upload.md +160 -0
- package/skills/extuitive/scripts/upload.mjs +340 -0
- package/src/constants.mjs +63 -0
- package/src/doctor.mjs +513 -0
- package/src/exec.mjs +139 -0
- package/src/hosts.mjs +350 -0
- package/src/install.mjs +541 -0
- package/src/mcp-setup.mjs +476 -0
- package/src/zip.mjs +246 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FL100 Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
# extuitive-skill
|
|
2
|
+
|
|
3
|
+
An agent skill for [Extuitive](https://extuitive.com), plus an installer that connects
|
|
4
|
+
Claude Code, Codex, or Claude Desktop to the Extuitive MCP server.
|
|
5
|
+
|
|
6
|
+
An Extuitive workspace is one Facebook ads account. The skill lets an agent pick which account
|
|
7
|
+
to work in, upload creative into it, track how that upload is going, and repair a Meta
|
|
8
|
+
connection that has stopped delivering data.
|
|
9
|
+
|
|
10
|
+
Install it from npm:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx extuitive install
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
That puts the skill where your host looks for it, connects the MCP server, and tells you how
|
|
17
|
+
to sign in. Signing in happens in your browser; the installer never handles your credentials.
|
|
18
|
+
|
|
19
|
+
What "puts" and "connects" mean depends on the host. For Claude Code and Codex it is a
|
|
20
|
+
directory copy and a CLI command. For Claude Desktop, whose skills belong to your account
|
|
21
|
+
rather than to this machine, it is a `.zip` to upload and a connector to add — the command
|
|
22
|
+
builds the first and prints the steps for both.
|
|
23
|
+
|
|
24
|
+
**You do not need an Extuitive account first.** The sign-in page has a **Sign up** button
|
|
25
|
+
next to **Log in**, both using a one-time email code, so you can create the account in the
|
|
26
|
+
same browser step that grants your host access. If you have not connected Meta yet, that page
|
|
27
|
+
then points you at the right setup step and brings you back.
|
|
28
|
+
|
|
29
|
+
## Install with an agent
|
|
30
|
+
|
|
31
|
+
Paste this into Claude Code or Codex and it does the rest:
|
|
32
|
+
|
|
33
|
+
> Install the Extuitive skill: run
|
|
34
|
+
> **`npx extuitive install --host codex --yes`**
|
|
35
|
+
> (use `--host claude` in Claude Code, or `--host all`). Then tell me where the skill was
|
|
36
|
+
> installed, linking its name to the `SKILL.md` path the installer printed, relay the sign-in
|
|
37
|
+
> step exactly as printed without running it, and say when the skill and the Extuitive tools
|
|
38
|
+
> will be available.
|
|
39
|
+
|
|
40
|
+
The installer's output is built for that reader. It ends with one block per host:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Codex — the Codex CLI, the Codex desktop app, and the IDE extension
|
|
44
|
+
───────────────────────────────────────────────────────────────────
|
|
45
|
+
Skill installed ~/.codex/skills/extuitive
|
|
46
|
+
/Users/you/.codex/skills/extuitive/SKILL.md
|
|
47
|
+
MCP server registered codex mcp add extuitive --url https://www.extuitive.com/mcp
|
|
48
|
+
Sign-in needed codex mcp login extuitive
|
|
49
|
+
Opens a browser; only you can complete it.
|
|
50
|
+
|
|
51
|
+
The skill is available on your next turn. Codex connects MCP servers when a session
|
|
52
|
+
starts, so the Extuitive tools appear in a new session once you have signed in.
|
|
53
|
+
Try: "Check my Extuitive connection" · "Upload these images to Extuitive"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Three facts on three lines, each with its own state, so the summary an agent gives back can be
|
|
57
|
+
short and still true:
|
|
58
|
+
|
|
59
|
+
> Installed [Extuitive](/Users/you/.codex/skills/extuitive/SKILL.md) in `~/.codex/skills/extuitive`.
|
|
60
|
+
> The skill will be available on your next turn.
|
|
61
|
+
> Sign in with `codex mcp login extuitive`, then start a new session for the Extuitive tools.
|
|
62
|
+
> Try: "Check my Extuitive connection."
|
|
63
|
+
|
|
64
|
+
If you are the agent doing the install, four rules:
|
|
65
|
+
|
|
66
|
+
- **Link the skill name to the absolute `SKILL.md` path** on the second line of the block.
|
|
67
|
+
The first line is the `~` form for display; the second exists for the link.
|
|
68
|
+
- **Report the `Sign-in` line as printed and never run it.** `codex mcp login` opens a browser
|
|
69
|
+
and waits for a redirect your shell cannot receive; `/mcp` belongs to the person's session.
|
|
70
|
+
When it reads `connected`, say so and skip the instruction.
|
|
71
|
+
- **Say what is available when.** The skill is live now (Codex: next turn; Claude Code:
|
|
72
|
+
immediately; Claude Desktop: once uploaded, in new chats). The Extuitive *tools* are not:
|
|
73
|
+
every host connects MCP servers when a session starts, so they appear in a new session, and
|
|
74
|
+
only after sign-in. Do not say "everything is ready" while the `Sign-in` line says `needed`.
|
|
75
|
+
- **Pass `--host` and `--yes`.** Without a TTY the installer refuses to guess which host, and
|
|
76
|
+
without `--yes` it may wait on a prompt you cannot answer. Add `--json` if you would rather
|
|
77
|
+
read structured output than the block.
|
|
78
|
+
|
|
79
|
+
## What gets installed
|
|
80
|
+
|
|
81
|
+
One skill, `extuitive`, which takes a command:
|
|
82
|
+
|
|
83
|
+
| Command | What it does |
|
|
84
|
+
| --- | --- |
|
|
85
|
+
| `init` | Set up from scratch: connect, sign in, confirm it works |
|
|
86
|
+
| `select` | Choose which ad account the rest of the session works in |
|
|
87
|
+
| `upload` | Upload a folder of images or videos into a workspace |
|
|
88
|
+
| `upload-status` | Report how the current upload is going |
|
|
89
|
+
| `connect` | Connect Meta, or repair a workspace that has stopped updating |
|
|
90
|
+
|
|
91
|
+
**The prefix differs by host, and using the wrong one looks like a broken install.**
|
|
92
|
+
|
|
93
|
+
| Host | Invoke | Browse |
|
|
94
|
+
| --- | --- | --- |
|
|
95
|
+
| Claude Code | `/extuitive init` | `/skills` |
|
|
96
|
+
| Codex | `$extuitive init` | `/skills` |
|
|
97
|
+
| Claude Desktop | no prefix — just ask | Customize > Skills |
|
|
98
|
+
|
|
99
|
+
Codex reserves `/` for its own built-in commands, so `/extuitive` there returns
|
|
100
|
+
`Unrecognized command '/extuitive'` even when the skill is installed correctly. Claude Desktop
|
|
101
|
+
has no invocation syntax at all; it matches your request against the skill's description.
|
|
102
|
+
|
|
103
|
+
Arguments go after the command: `/extuitive upload ./creative` or
|
|
104
|
+
`$extuitive upload-status <batch id>`. Claude Code substitutes them into the skill; Codex
|
|
105
|
+
passes your wording through, which works because the command word is still sitting in the
|
|
106
|
+
prompt the model reads.
|
|
107
|
+
|
|
108
|
+
The CLI hosts take a skill's name from its directory, which is why there is one skill with
|
|
109
|
+
commands rather than five skills — `/extuitive-upload` would need a separate directory each
|
|
110
|
+
time, and the command form reads better and keeps one description in front of the model.
|
|
111
|
+
|
|
112
|
+
You usually will not type any of it. Asking for the underlying thing — "upload these ads to
|
|
113
|
+
Extuitive", "check my Extuitive connection" — reaches the skill on its own. The second one
|
|
114
|
+
routes to `init`, which checks tools, sign-in, and workspaces in order and reports where it
|
|
115
|
+
stopped; it is the right first thing to say after installing.
|
|
116
|
+
|
|
117
|
+
## Install
|
|
118
|
+
|
|
119
|
+
Three hosts, and one of them is two things. Worth reading the table before picking, because
|
|
120
|
+
the Claude Desktop app appears twice and installing for one half of it does not reach the
|
|
121
|
+
other:
|
|
122
|
+
|
|
123
|
+
| `--host` | Covers | Skills live |
|
|
124
|
+
| --- | --- | --- |
|
|
125
|
+
| `claude` | The `claude` CLI, and the **Code tab** of the Claude Desktop app | `~/.claude/skills` |
|
|
126
|
+
| `codex` | The Codex CLI, the Codex desktop app, and the IDE extension | `~/.codex/skills` |
|
|
127
|
+
| `claude-desktop` | The **Chat and Cowork tabs** of the Claude Desktop app | your Anthropic account |
|
|
128
|
+
|
|
129
|
+
With no `--host`, the installer detects what is on the machine and asks. `--host all` takes
|
|
130
|
+
everything it can find. `--host both` still works and still means all of them.
|
|
131
|
+
|
|
132
|
+
### Claude Code
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
npx extuitive install --host claude
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Which does:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# skills → ~/.claude/skills/
|
|
142
|
+
claude mcp add --transport http extuitive https://www.extuitive.com/mcp --scope user
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The skill is usable immediately. The server is not: **start a new Claude Code session** —
|
|
146
|
+
servers are connected at startup, so `extuitive` is not in the session you installed from. In
|
|
147
|
+
that new session run `/mcp`, choose `extuitive`, and approve.
|
|
148
|
+
|
|
149
|
+
`/mcp` is the whole sign-in story on Claude Code. There is a `claude mcp login` on recent
|
|
150
|
+
versions, but it is left out on purpose: this output is usually read by an agent inside a
|
|
151
|
+
Claude Code session, and a shell command is the one thing an agent will run for you — from
|
|
152
|
+
the wrong session, possibly on a version without the subcommand, into a browser redirect its
|
|
153
|
+
shell cannot receive.
|
|
154
|
+
|
|
155
|
+
`--scope user` matters. The default is `local`, which ties the server to whichever directory
|
|
156
|
+
you ran the command in, while your skills are available everywhere. That combination works in
|
|
157
|
+
one project and looks broken in the next.
|
|
158
|
+
|
|
159
|
+
### Codex
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npx extuitive install --host codex
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Which does:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# skills → $CODEX_HOME/skills/ (~/.codex/skills/ unless CODEX_HOME is set)
|
|
169
|
+
codex mcp add extuitive --url https://www.extuitive.com/mcp
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Then `codex mcp login extuitive` to sign in. The skill itself is picked up on your next turn;
|
|
173
|
+
the Extuitive **tools** appear in a new Codex session, because MCP servers are connected when
|
|
174
|
+
a session starts.
|
|
175
|
+
|
|
176
|
+
**This is one install for three programs.** The Codex desktop app, the CLI and the IDE
|
|
177
|
+
extension share `~/.codex/config.toml` for MCP and the same skills directories, so there is
|
|
178
|
+
nothing extra to do for the app. If you prefer clicking, the app has the same two things under
|
|
179
|
+
Settings > MCP servers: **Add server**, choosing Streamable HTTP, and **Authenticate**.
|
|
180
|
+
|
|
181
|
+
**Where the skill goes.** Codex scans two personal skill directories, `$CODEX_HOME/skills`
|
|
182
|
+
and `~/.agents/skills`, and loads from both. Codex's own bundled `$skill-installer` — and so
|
|
183
|
+
every "install this skill from a URL" done by an agent — writes to `$CODEX_HOME/skills`, so
|
|
184
|
+
that is where this installer puts Extuitive too, next to the rest of your skills. Earlier
|
|
185
|
+
versions used `~/.agents/skills`; `install` and `update` move a copy found there to the new
|
|
186
|
+
location (keeping a backup if it was edited), and `doctor` names it if one is still around.
|
|
187
|
+
`--dir` overrides all of this, and `--scope project` uses `./.agents/skills`, which is what
|
|
188
|
+
Codex reads for repository skills.
|
|
189
|
+
|
|
190
|
+
Codex no longer needs `[features] skills = true`; skills are on by default. `--write-config`,
|
|
191
|
+
which used to permit adding that line, is accepted and ignored.
|
|
192
|
+
|
|
193
|
+
**Codex app without the CLI on PATH.** The installer runs `codex --version` before trusting
|
|
194
|
+
what `which` found — an npm-installed `codex` whose vendored binary is missing fails with
|
|
195
|
+
`spawn … ENOENT` and would otherwise register nothing — and falls back to the binary inside
|
|
196
|
+
the Codex or ChatGPT desktop app on macOS. Point it somewhere else with `CODEX_CLI_PATH`.
|
|
197
|
+
|
|
198
|
+
### Claude Desktop
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
npx extuitive install --host claude-desktop
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Nothing is registered and nothing is copied into the app, because neither is possible here.
|
|
205
|
+
What the command does is build the archive the app asks for:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
# bundle → ~/.extuitive-skill/bundles/extuitive.zip
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Then, in the app:
|
|
212
|
+
|
|
213
|
+
1. **Settings > Capabilities** — turn on code execution and file creation. The Skills section
|
|
214
|
+
does not appear until you do.
|
|
215
|
+
2. **Customize > Skills** — `+`, then Create skill, then Upload a skill, and choose the
|
|
216
|
+
`extuitive.zip` the command printed.
|
|
217
|
+
3. **Settings > Connectors** — Add custom connector, and paste
|
|
218
|
+
`https://www.extuitive.com/mcp` as the URL.
|
|
219
|
+
4. Approve access in the browser window that opens, then **start a new chat**.
|
|
220
|
+
|
|
221
|
+
Two things are different here and both are the app's design rather than a limitation of this
|
|
222
|
+
installer.
|
|
223
|
+
|
|
224
|
+
**Skills go to your account, not to this machine.** Chat-tab skills run in Anthropic's code
|
|
225
|
+
execution container, and the Customize panel uploads them to your account — which is why they
|
|
226
|
+
then work on claude.ai and on your other devices, and why an uninstall here deletes the
|
|
227
|
+
archive but not the skill. The Code tab is the exception: it reads `~/.claude/skills`, so
|
|
228
|
+
`--host claude` is what serves it.
|
|
229
|
+
|
|
230
|
+
**The connector cannot go in `claude_desktop_config.json`.** That file validates stdio servers
|
|
231
|
+
only, and an entry carrying a `url` is worse than ignored — Claude Desktop rewrites the file
|
|
232
|
+
on next launch with the whole `mcpServers` block removed, taking any servers you added by hand
|
|
233
|
+
with it ([anthropics/claude-code#37286](https://github.com/anthropics/claude-code/issues/37286)).
|
|
234
|
+
There is a way around it, wrapping the endpoint in an `npx mcp-remote` stdio bridge, and this
|
|
235
|
+
installer deliberately does not: it puts a second OAuth implementation and a background Node
|
|
236
|
+
process between the app and a server the app can talk to directly through Connectors.
|
|
237
|
+
|
|
238
|
+
**Uploading from a Chat-tab conversation will not work the way it does in a terminal.** The
|
|
239
|
+
container holds the skill but not your disk, so the skill hands you a browser upload link
|
|
240
|
+
instead. Cowork and the Code tab can reach your files normally.
|
|
241
|
+
|
|
242
|
+
### Options
|
|
243
|
+
|
|
244
|
+
| Flag | Default | Meaning |
|
|
245
|
+
| --- | --- | --- |
|
|
246
|
+
| `--host <name\|all>` | detected | `claude`, `codex`, `claude-desktop`, or `all`. Required without a TTY. |
|
|
247
|
+
| `--scope <user\|project>` | `user` | Every project, or only this one. Ignored by `claude-desktop`, where a skill belongs to an account rather than a directory. |
|
|
248
|
+
| `--dir <path>` | host default | Install skills, or write the bundle, somewhere else entirely. |
|
|
249
|
+
| `--endpoint <url>` | `https://www.extuitive.com/mcp` | Point at a different server. |
|
|
250
|
+
| `--keep-server` | off | Uninstall only: leave the MCP server registered. |
|
|
251
|
+
| `--dry-run` | off | Report what would change, change nothing. |
|
|
252
|
+
| `--yes`, `-y` | off | Take defaults, never prompt. |
|
|
253
|
+
| `--json` | off | Structured output instead of the summary block. |
|
|
254
|
+
|
|
255
|
+
Environment: `CODEX_HOME` moves Codex's config and skills directory together; `CODEX_CLI_PATH`
|
|
256
|
+
and `CLAUDE_CLI_PATH` name the CLI binary when the one on PATH is wrong or missing.
|
|
257
|
+
|
|
258
|
+
No client id, secret, or API key anywhere. The server supports Dynamic Client Registration, so
|
|
259
|
+
both hosts negotiate their own credentials from the URL alone.
|
|
260
|
+
|
|
261
|
+
## How uploading works
|
|
262
|
+
|
|
263
|
+
Worth reading before the tool list, because it explains the shape of everything else.
|
|
264
|
+
|
|
265
|
+
**The MCP tools never carry file bytes.** `create_upload_batch` returns presigned storage URLs
|
|
266
|
+
and whoever holds the files sends the bytes to those URLs directly. No tool accepts a file.
|
|
267
|
+
|
|
268
|
+
That single fact splits the behaviour in two:
|
|
269
|
+
|
|
270
|
+
- **A host that can read your files** — Claude Code, Codex, Cowork — uses the script bundled
|
|
271
|
+
in `skills/extuitive/scripts/upload.mjs` to do the transfer, then reports the outcome
|
|
272
|
+
through the tools.
|
|
273
|
+
- **A host that cannot** uses `create_browser_upload_link` and hands the person a link to
|
|
274
|
+
upload from their browser.
|
|
275
|
+
|
|
276
|
+
The test is reading your files, not running code. A Claude Desktop chat has code execution —
|
|
277
|
+
skills require it — but the container it runs in holds the skill and not your disk, so it
|
|
278
|
+
takes the second path.
|
|
279
|
+
|
|
280
|
+
It also means a finished transfer is not an accepted file. Bytes landing in storage starts a
|
|
281
|
+
check that can still reject the file, so `READY` — not "upload complete" — is the only status
|
|
282
|
+
that means success. The upload and status flows are built around reporting that honestly.
|
|
283
|
+
|
|
284
|
+
The bundled script holds no credential and makes no MCP calls. It receives presigned URLs,
|
|
285
|
+
sends bytes, and reports ETags. Your access token stays in your host's credential store.
|
|
286
|
+
|
|
287
|
+
## Tools
|
|
288
|
+
|
|
289
|
+
Twenty-nine tools in four groups. Full schemas, the error vocabulary, and the status lifecycle
|
|
290
|
+
for the first three groups are in
|
|
291
|
+
[`skills/extuitive/references/tools.md`](skills/extuitive/references/tools.md); the Meta object
|
|
292
|
+
tools carry their own schemas in the server's tool listing.
|
|
293
|
+
|
|
294
|
+
**Workspaces**
|
|
295
|
+
|
|
296
|
+
- `list_workspaces` — every workspace you can reach, with the health of its Meta connection.
|
|
297
|
+
Its `role` and `isOwner` decide who may reconnect Meta and nothing else, and two workspaces
|
|
298
|
+
can point at the same ad account, so neither field tells you where to upload.
|
|
299
|
+
|
|
300
|
+
**Meta connection**
|
|
301
|
+
|
|
302
|
+
- `get_meta_setup_status` — why you have no workspaces, and the link that fixes it.
|
|
303
|
+
- `create_meta_reconnect_link` *(workspaceId)* — repair a workspace's Meta connection. Owner only.
|
|
304
|
+
|
|
305
|
+
**Uploads**
|
|
306
|
+
|
|
307
|
+
- `get_upload_limits` *(workspaceId)* — server-owned ceilings. Never hardcode them.
|
|
308
|
+
- `create_upload_batch` *(workspaceId, files)* — open a batch, get a destination per file.
|
|
309
|
+
- `resign_upload` *(workspaceId, contentId)* — a fresh URL when one expires.
|
|
310
|
+
- `sign_upload_part` *(workspaceId, uploadId, partNumber)* — presign one chunk of a large video.
|
|
311
|
+
- `list_upload_parts` *(workspaceId, uploadId)* — what storage already holds, for resuming.
|
|
312
|
+
- `complete_upload` *(workspaceId, uploadId, parts)* — assemble a multipart upload.
|
|
313
|
+
- `abort_upload` *(workspaceId, uploadId)* — abandon one.
|
|
314
|
+
- `list_upload_batches` *(workspaceId)* — batch history, newest first. The cheap progress check.
|
|
315
|
+
- `get_upload_batch_content` *(workspaceId, batchId)* — per-file rows and status for one batch.
|
|
316
|
+
- `get_upload_content` *(workspaceId, contentId)* — one file.
|
|
317
|
+
- `create_browser_upload_link` *(workspaceId)* — hand the transfer back to the browser.
|
|
318
|
+
|
|
319
|
+
**Meta objects**
|
|
320
|
+
|
|
321
|
+
Build and inspect campaigns in the workspace's connected ad account. Creates are submitted as
|
|
322
|
+
actions and settle asynchronously; `get_meta_action` is the only way to learn whether one worked.
|
|
323
|
+
|
|
324
|
+
- `create_meta_campaign` *(workspaceId, params, summary, rationale, clientToken)* — step one of four.
|
|
325
|
+
- `create_meta_adset` *(workspaceId, params, …)* — step two; needs a `campaign_id`.
|
|
326
|
+
- `create_meta_adcreative` *(workspaceId, params, …)* — step three; needs a `page_id` from
|
|
327
|
+
`list_meta_pages` and media already `PUBLISHED` through the upload tools.
|
|
328
|
+
- `create_meta_ad` *(workspaceId, params, …)* — step four; needs an `adset_id` and a `creative_id`.
|
|
329
|
+
An ad that is not `PAUSED` starts spending as soon as Meta approves it.
|
|
330
|
+
- `get_meta_action` *(workspaceId, actionId)* — poll until `settled`; `EXECUTED` carries the new
|
|
331
|
+
object's `createdId`, `FAILED` carries Meta's own error.
|
|
332
|
+
- `list_meta_actions` *(workspaceId)* — everything created through these tools, newest first.
|
|
333
|
+
- `list_meta_campaigns` / `list_meta_adsets` / `list_meta_ads` *(workspaceId, filters, paging)* —
|
|
334
|
+
read live from Meta, for finding ids of objects that already exist.
|
|
335
|
+
- `get_meta_campaign` / `get_meta_adset` / `get_meta_ad` *(workspaceId, id)* — the full settings
|
|
336
|
+
of one object, including ad set targeting.
|
|
337
|
+
- `list_meta_pages` *(workspaceId)* — pages this workspace can run ads as.
|
|
338
|
+
- `list_meta_pixels` *(workspaceId)* — conversion pixels, with `lastFiredTime` so you can avoid
|
|
339
|
+
a dead one.
|
|
340
|
+
- `list_meta_instagram_accounts` *(workspaceId)* — Instagram accounts the ad account may
|
|
341
|
+
advertise as. Optional; a creative runs on Facebook with a `page_id` alone.
|
|
342
|
+
|
|
343
|
+
## The MCP server
|
|
344
|
+
|
|
345
|
+
- **Endpoint** `https://www.extuitive.com/mcp`
|
|
346
|
+
- **Transport** stateless Streamable HTTP JSON-RPC over `POST`
|
|
347
|
+
- **Auth** OAuth 2.1, authorization code with PKCE `S256`, Dynamic Client Registration, scope `mcp`
|
|
348
|
+
|
|
349
|
+
Workspace membership is verified on every workspace-scoped call rather than once at sign-in,
|
|
350
|
+
so leaving a workspace takes effect immediately. It is checked per call, not per listing, so a
|
|
351
|
+
workspace can appear in `list_workspaces` and still answer `workspace_access_denied` to an
|
|
352
|
+
upload — the skill treats that as a fact to report and route around, not one to explain.
|
|
353
|
+
|
|
354
|
+
This package stores no credential of any kind. Your host holds the OAuth token; the upload
|
|
355
|
+
script only ever sees presigned URLs scoped to a single object, which expire.
|
|
356
|
+
|
|
357
|
+
## Troubleshooting
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
npx extuitive doctor
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
It reports the endpoint, which skills are installed where, and what your host says about the
|
|
364
|
+
server — including the difference between "not registered" and "registered but not signed in",
|
|
365
|
+
which is not visible from the outside. Add `--json` for machine-readable output.
|
|
366
|
+
|
|
367
|
+
Common causes, in the order they usually happen:
|
|
368
|
+
|
|
369
|
+
- **The skill does not appear.** On Codex it appears on the next turn, not the current one;
|
|
370
|
+
in a resumed thread, start a new one. On the CLI hosts, a skill whose frontmatter `name`
|
|
371
|
+
differs from its directory name silently fails to load; `doctor` checks this. A skill can
|
|
372
|
+
also be disabled without being deleted, via `[[skills.config]]` in `~/.codex/config.toml`.
|
|
373
|
+
- **The skill appears twice.** A copy is in both `~/.codex/skills` and `~/.agents/skills`,
|
|
374
|
+
which Codex both scans. `update` moves the old one (backing it up if it differs); `doctor`
|
|
375
|
+
names it.
|
|
376
|
+
- **`codex` is on PATH but nothing was registered.** An npm-installed `codex` whose vendored
|
|
377
|
+
binary is missing dies with `spawn … ENOENT`. The installer falls back to the desktop app's
|
|
378
|
+
binary on macOS; elsewhere, reinstall the CLI or set `CODEX_CLI_PATH`. `doctor` prints which
|
|
379
|
+
binary it is using on the `CLI` line.
|
|
380
|
+
- **The install said it worked and the tools are not there.** Every host connects MCP servers
|
|
381
|
+
when a session starts, so a server registered from inside a running session — or by an
|
|
382
|
+
agent in one — is invisible to it. Start a new session, or a new chat, before concluding
|
|
383
|
+
anything.
|
|
384
|
+
- **Claude Desktop has the skill in one tab and not another.** Chat and Cowork read the copy
|
|
385
|
+
uploaded to your account; the Code tab reads `~/.claude/skills`. They are different
|
|
386
|
+
installs: `--host claude-desktop` and `--host claude` respectively.
|
|
387
|
+
- **Tools are listed but every call is refused.** Sign-in was never completed. Run `/mcp` in
|
|
388
|
+
Claude Code, `codex mcp login extuitive` in a terminal, or click Connect next to `extuitive`
|
|
389
|
+
in Claude Desktop's Settings > Connectors. `doctor` reads Codex's own answer
|
|
390
|
+
(`codex mcp list --json` → `auth_status`), so `Sign-in connected` means a token is actually
|
|
391
|
+
stored.
|
|
392
|
+
- **A `403` part-way through an upload.** Presigned URLs last 30 minutes and a whole batch is
|
|
393
|
+
signed at once, so late files in a big batch can expire mid-transfer. The script reports
|
|
394
|
+
these as `needsResign` and `needsPartResign`; the fix is `resign_upload` or
|
|
395
|
+
`sign_upload_part` and a re-run for just those files.
|
|
396
|
+
- **A batch stuck at `CREATED`.** It was opened by a host that could not send the bytes. Use
|
|
397
|
+
`create_browser_upload_link` instead.
|
|
398
|
+
|
|
399
|
+
## Local development
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
npx extuitive install --endpoint http://localhost:3001/mcp
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Port 3001 is what the lead-magnet app binds with `npm run dev`.
|
|
406
|
+
|
|
407
|
+
Two packages are published from this repository. `@extuitive/skill`, the root, is the skill
|
|
408
|
+
and the installer. `extuitive`, in `packages/extuitive`, is the command: a `bin` that imports
|
|
409
|
+
the installer from `@extuitive/skill` and nothing else, so that what people type is
|
|
410
|
+
`npx extuitive`. Release the root first, then the launcher, since the launcher depends on it.
|
|
411
|
+
To run the checked-out code without publishing, use `node bin/cli.mjs <command>` from the
|
|
412
|
+
repository root.
|
|
413
|
+
|
|
414
|
+
## Update
|
|
415
|
+
|
|
416
|
+
```bash
|
|
417
|
+
npx extuitive update
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
Refreshes an install that is already here. It only touches hosts that already have the skill,
|
|
421
|
+
so running it will not quietly add Codex to a machine set up for Claude Code alone — pass
|
|
422
|
+
`--host` if that is what you want.
|
|
423
|
+
|
|
424
|
+
It rewrites skill files that changed, reports `up to date` for those that did not, and prints
|
|
425
|
+
`Already up to date.` when there was nothing to do. It re-registers the MCP server only if
|
|
426
|
+
your host has lost the registration, and reports sign-in from what your host says rather than
|
|
427
|
+
assuming. A copy at the previous Codex location (`~/.agents/skills`) counts as an install to
|
|
428
|
+
update, and is moved.
|
|
429
|
+
|
|
430
|
+
`install` does the same file work — it has always compared trees and backed up anything that
|
|
431
|
+
differed — so an update is safe to do either way. The difference is what gets printed: install
|
|
432
|
+
adds the sign-up note and the manual steps when a CLI could not be driven; update prints the
|
|
433
|
+
summary block and stops.
|
|
434
|
+
|
|
435
|
+
`npx` fetches the released version from npm, so an update picks up the latest published
|
|
436
|
+
release. To run whatever is on `main` instead, use the repository directly:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
npx github:fl100inc/extuitive-skill update
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Any command in this README works the same way with that prefix.
|
|
443
|
+
|
|
444
|
+
## Uninstall
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
npx extuitive uninstall
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Removes the skill directories — from the current location and from Extuitive's previous Codex
|
|
451
|
+
location, `~/.agents/skills`, if a copy is there — and unregisters the MCP server from your
|
|
452
|
+
host. Pass `--keep-server` to drop the skills but keep the tools registered.
|
|
453
|
+
|
|
454
|
+
On Claude Desktop it deletes the built archive and prints the two removals it cannot do for
|
|
455
|
+
you: the skill, in Customize > Skills, and the connector, in Settings > Connectors. Both live
|
|
456
|
+
on the other side of a browser session.
|
|
457
|
+
|
|
458
|
+
Two things are deliberately left behind.
|
|
459
|
+
|
|
460
|
+
**Your backups**, under `~/.extuitive-skill/backups/`. Each one exists because an install found
|
|
461
|
+
a skill that differed from the one it was about to write, so it may be the only copy of
|
|
462
|
+
something you wrote. The uninstall prints the path; deleting them is your call.
|
|
463
|
+
|
|
464
|
+
**Your sign-in.** The OAuth token lives in your host's own credential store, which is not ours
|
|
465
|
+
to read or clear — on Codex that is the macOS keychain, keyed by server, so a reinstall later
|
|
466
|
+
finds it and reports `Sign-in connected` without asking you again. Revoke access from
|
|
467
|
+
Extuitive if you want it gone.
|
|
468
|
+
|
|
469
|
+
Backups live outside the skills directories on purpose. Both hosts treat every directory in
|
|
470
|
+
their skills root as a skill, and Codex searches it recursively, so a backup kept next to the
|
|
471
|
+
skill it replaced would be loaded as a second, older copy of that skill.
|
|
472
|
+
|
|
473
|
+
## Repository layout
|
|
474
|
+
|
|
475
|
+
```
|
|
476
|
+
bin/cli.mjs install | update | uninstall | doctor
|
|
477
|
+
src/hosts.mjs every per-host difference, as data
|
|
478
|
+
src/ install, MCP setup, doctor, and a ZIP writer
|
|
479
|
+
skills/extuitive/
|
|
480
|
+
SKILL.md routes a command to its reference
|
|
481
|
+
references/ one file per command, plus the full tool reference
|
|
482
|
+
scripts/upload.mjs byte transfer only; no credentials, no MCP calls
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
`SKILL.md` stays short on purpose: it is loaded whenever the skill is considered, while a
|
|
486
|
+
`references/` file is read only once the agent knows which job it is doing. Putting all five
|
|
487
|
+
flows in the front page would spend context on four of them every time.
|
|
488
|
+
|
|
489
|
+
`README.md` lives here at the repo root and nowhere else. Skill directories deliberately do
|
|
490
|
+
not contain one — everything an agent reads belongs in `SKILL.md` or `references/`, and a
|
|
491
|
+
`README.md` inside a skill folder is dead weight in its context window.
|
|
492
|
+
|
|
493
|
+
Host-specific setup commands live only in `src/mcp-setup.mjs`, and every other per-host
|
|
494
|
+
difference — skills directory, previous skills directory, config file, which binary to run —
|
|
495
|
+
is a field in `src/hosts.mjs`. Nothing else branches on a host id. Two of those fields decide
|
|
496
|
+
which code path a host takes rather than which words it prints: `skillDelivery` (`copy` for a
|
|
497
|
+
host that scans a directory, `bundle` for one that takes an upload) and `mcpSetup` (`cli` for
|
|
498
|
+
a host we can drive, `connector-ui` for one where the only supported route is a panel).
|
|
499
|
+
|
|
500
|
+
The skill never names a setup command; it tells the agent to run `doctor` and relay what it
|
|
501
|
+
prints, so a change to a host's CLI is a fix in one file rather than four. The one exception
|
|
502
|
+
is the connector URL, which the skill does name, because a host with no command line cannot
|
|
503
|
+
be told to run `doctor` and a URL has nothing to go stale but its address.
|
|
504
|
+
|
|
505
|
+
`mcp-setup.mjs` also decides the order of the last two steps. Sign-in and new-session are
|
|
506
|
+
printed in whichever order the host can actually do them: Claude Code signs in from inside a
|
|
507
|
+
session, so the new session comes first, while Codex and Claude Desktop sign in outside one
|
|
508
|
+
and open a new session afterwards for the tools. Anything printed here should assume its
|
|
509
|
+
reader is an agent, which will run a shell command it is shown — so a sign-in step that cannot
|
|
510
|
+
survive being run that way does not belong in the output.
|
|
511
|
+
|
|
512
|
+
## Licence
|
|
513
|
+
|
|
514
|
+
MIT
|