@apilift/cli 1.4.22 → 1.4.23
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/dist/apilift.js +20 -10
- package/dist/plugin/.claude-plugin/plugin.json +2 -2
- package/dist/plugin/.codex-plugin/plugin.json +14 -6
- package/dist/plugin/assets/apilift-icon.png +0 -0
- package/dist/plugin/skills/discover/SKILL.md +26 -0
- package/dist/plugin/skills/discover/agents/openai.yaml +4 -0
- package/dist/plugin/skills/discover/references/browser-capture.md +13 -0
- package/dist/plugin/skills/discover/references/documented-api.md +9 -0
- package/dist/plugin/skills/discover/references/operation-contract.md +15 -0
- package/dist/plugin/skills/discover/references/recovery.md +7 -0
- package/dist/plugin/skills/use/SKILL.md +18 -0
- package/dist/plugin/skills/use/agents/openai.yaml +4 -0
- package/package.json +2 -2
package/dist/apilift.js
CHANGED
|
@@ -34363,6 +34363,12 @@ import { cpSync, existsSync as existsSync4, mkdirSync as mkdirSync8, readFileSyn
|
|
|
34363
34363
|
import { homedir as homedir2 } from "node:os";
|
|
34364
34364
|
import { dirname as dirname6, join as join12, resolve as resolve2 } from "node:path";
|
|
34365
34365
|
import { fileURLToPath } from "node:url";
|
|
34366
|
+
function missingSkill(root) {
|
|
34367
|
+
return skillNames.find((name) => !existsSync4(join12(root, "skills", name, "SKILL.md")));
|
|
34368
|
+
}
|
|
34369
|
+
function completeCopy(source, target) {
|
|
34370
|
+
return files(source).every((path2) => existsSync4(join12(target, path2)));
|
|
34371
|
+
}
|
|
34366
34372
|
function files(root, relative = "") {
|
|
34367
34373
|
return readdirSync(join12(root, relative), { withFileTypes: true }).flatMap((entry2) => {
|
|
34368
34374
|
const path2 = join12(relative, entry2.name);
|
|
@@ -34405,7 +34411,7 @@ function active(agent2, expected) {
|
|
|
34405
34411
|
if (typeof plugin.enabled !== "boolean" || typeof plugin.version !== "string") return { ready: false, known: false, detail: `${agent2} plugin status could not be checked: Apilift status is incomplete` };
|
|
34406
34412
|
if (!plugin.enabled) return { ready: false, known: true, detail: "Apilift is disabled in this agent" };
|
|
34407
34413
|
if (plugin.version !== expected) return { ready: false, known: true, detail: "The active Apilift plugin does not match the packaged version" };
|
|
34408
|
-
return { ready: true, known: true, detail: "
|
|
34414
|
+
return { ready: true, known: true, detail: "Apilift setup, use and discovery skills are active" };
|
|
34409
34415
|
} catch (error62) {
|
|
34410
34416
|
const code = typeof error62 === "object" && error62 && "code" in error62 ? error62.code : void 0;
|
|
34411
34417
|
const reason = code === "ETIMEDOUT" ? "plugin list timed out after 10 seconds" : code === "ENOENT" ? `${agent2} executable was not found` : "plugin list failed";
|
|
@@ -34415,7 +34421,8 @@ function active(agent2, expected) {
|
|
|
34415
34421
|
function inspectAgentPlugin(agent2, env, sourceOverride) {
|
|
34416
34422
|
if (env.APILIFT_DEV_PLUGIN_ROOT) return { ready: false, version: "development", detail: "Development plugin activation has not been verified" };
|
|
34417
34423
|
const source = resolve2(sourceOverride || join12(dirname6(fileURLToPath(import.meta.url)), "plugin"));
|
|
34418
|
-
|
|
34424
|
+
const missing = missingSkill(source);
|
|
34425
|
+
if (missing) return { ready: false, version: "unknown", detail: `CLI package is missing its ${missing} skill` };
|
|
34419
34426
|
const version2 = readJson(join12(source, `.${agent2}-plugin`, "plugin.json"))?.version;
|
|
34420
34427
|
if (typeof version2 !== "string" || !/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(version2)) throw new Error("Plugin package version is invalid");
|
|
34421
34428
|
const bundleDigest = digest(source);
|
|
@@ -34423,23 +34430,25 @@ function inspectAgentPlugin(agent2, env, sourceOverride) {
|
|
|
34423
34430
|
const home = resolve2(env.APILIFT_AGENT_HOME || homedir2());
|
|
34424
34431
|
const plugin = agent2 === "codex" ? join12(home, "plugins", "apilift") : join12(home, ".agents", "plugins", "plugins", "apilift");
|
|
34425
34432
|
const marker = readJson(join12(plugin, markerName));
|
|
34426
|
-
const staged = marker?.package === "apilift" && marker.bundleDigest === bundleDigest && marker.version === version2 &&
|
|
34427
|
-
if (!staged) return { ready: false, version: expected, detail: "
|
|
34428
|
-
if (env.APILIFT_AGENT_HOME || env.APILIFT_AGENT_NO_ACTIVATE === "1") return { ready: false, version: expected, detail: "
|
|
34433
|
+
const staged = marker?.package === "apilift" && marker.bundleDigest === bundleDigest && marker.version === version2 && completeCopy(source, plugin);
|
|
34434
|
+
if (!staged) return { ready: false, version: expected, detail: "Apilift plugin files are missing or stale" };
|
|
34435
|
+
if (env.APILIFT_AGENT_HOME || env.APILIFT_AGENT_NO_ACTIVATE === "1") return { ready: false, version: expected, detail: "Apilift skills are staged; activation is unverified" };
|
|
34429
34436
|
const activation = active(agent2, expected);
|
|
34430
34437
|
return { ready: activation.ready, version: expected, detail: activation.detail, checkFailed: !activation.known };
|
|
34431
34438
|
}
|
|
34432
34439
|
function ensureAgentPlugin(agent2, env, sourceOverride) {
|
|
34433
34440
|
if (env.APILIFT_DEV_PLUGIN_ROOT) {
|
|
34434
34441
|
const source2 = resolve2(env.APILIFT_DEV_PLUGIN_ROOT);
|
|
34435
|
-
|
|
34442
|
+
const missing2 = missingSkill(source2);
|
|
34443
|
+
if (missing2) throw new Error(`Development plugin ${missing2} skill is missing`);
|
|
34436
34444
|
const bundleDigest2 = digest(source2);
|
|
34437
34445
|
const root = resolve2(env.APILIFT_HOME || join12(homedir2(), ".local", "share", "apilift"));
|
|
34438
34446
|
writeJson(join12(root, "agent-plugins", `${agent2}.json`), { root: source2, digest: bundleDigest2 });
|
|
34439
34447
|
return { ready: false, version: `dev+${bundleDigest2.slice(0, 12)}`, detail: "Development plugin source recorded; activation was not verified" };
|
|
34440
34448
|
}
|
|
34441
34449
|
const source = resolve2(sourceOverride || join12(dirname6(fileURLToPath(import.meta.url)), "plugin"));
|
|
34442
|
-
|
|
34450
|
+
const missing = missingSkill(source);
|
|
34451
|
+
if (missing) throw new Error(`CLI package is missing its ${missing} skill`);
|
|
34443
34452
|
const version2 = readJson(join12(source, `.${agent2}-plugin`, "plugin.json"))?.version;
|
|
34444
34453
|
if (typeof version2 !== "string" || !/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(version2)) throw new Error("Plugin package version is invalid");
|
|
34445
34454
|
const bundleDigest = digest(source);
|
|
@@ -34449,7 +34458,7 @@ function ensureAgentPlugin(agent2, env, sourceOverride) {
|
|
|
34449
34458
|
const marker = readJson(join12(plugin, markerName));
|
|
34450
34459
|
if (existsSync4(plugin) && marker?.package !== "apilift") throw new Error(`Refusing to replace unmanaged plugin ${plugin}`);
|
|
34451
34460
|
const expected = agent2 === "codex" ? `${version2}+codex.${bundleDigest.slice(0, 12)}` : version2;
|
|
34452
|
-
const current = marker?.bundleDigest === bundleDigest && marker.version === version2 &&
|
|
34461
|
+
const current = marker?.bundleDigest === bundleDigest && marker.version === version2 && completeCopy(source, plugin);
|
|
34453
34462
|
if (!current) {
|
|
34454
34463
|
const staging = `${plugin}.stage-${process.pid}`;
|
|
34455
34464
|
rmSync4(staging, { recursive: true, force: true });
|
|
@@ -34476,7 +34485,7 @@ function ensureAgentPlugin(agent2, env, sourceOverride) {
|
|
|
34476
34485
|
if (document.name !== "personal" || !Array.isArray(document.plugins)) throw new Error("Unsupported personal plugin marketplace");
|
|
34477
34486
|
document.plugins = [...document.plugins.filter((item) => typeof item === "object" && item !== null && item.name !== "apilift"), { name: "apilift", source: { source: "local", path: "./plugins/apilift" }, policy: { installation: "AVAILABLE", authentication: "ON_INSTALL" }, category: "Developer Tools" }];
|
|
34478
34487
|
writeJson(marketplacePath, document);
|
|
34479
|
-
writeJson(join12(marketplace, ".claude-plugin", "marketplace.json"), { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", name: "personal", description: "Personal agent plugins", owner: { name: "Local" }, plugins: [{ name: "apilift", description: "Apilift
|
|
34488
|
+
writeJson(join12(marketplace, ".claude-plugin", "marketplace.json"), { "$schema": "https://anthropic.com/claude-code/marketplace.schema.json", name: "personal", description: "Personal agent plugins", owner: { name: "Local" }, plugins: [{ name: "apilift", description: "Use logged-in apps and discover missing actions with Apilift", source: "./plugins/apilift", category: "development" }] });
|
|
34480
34489
|
if (env.APILIFT_AGENT_HOME || env.APILIFT_AGENT_NO_ACTIVATE === "1") return { ready: false, version: expected, detail: `Plugin staged at ${plugin}; activation is disabled` };
|
|
34481
34490
|
const initial = active(agent2, expected);
|
|
34482
34491
|
if (!initial.known) return { ready: false, version: expected, detail: initial.detail, checkFailed: true };
|
|
@@ -34500,11 +34509,12 @@ function ensureAgentPlugin(agent2, env, sourceOverride) {
|
|
|
34500
34509
|
const activation = active(agent2, expected);
|
|
34501
34510
|
return { ready: activation.ready, version: expected, detail: activation.detail, checkFailed: !activation.known };
|
|
34502
34511
|
}
|
|
34503
|
-
var markerName;
|
|
34512
|
+
var markerName, skillNames;
|
|
34504
34513
|
var init_plugin = __esm({
|
|
34505
34514
|
"src/plugin.ts"() {
|
|
34506
34515
|
"use strict";
|
|
34507
34516
|
markerName = ".apilift-managed.json";
|
|
34517
|
+
skillNames = ["setup", "use", "discover"];
|
|
34508
34518
|
}
|
|
34509
34519
|
});
|
|
34510
34520
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apilift",
|
|
3
|
-
"version": "1.4.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.4.23",
|
|
4
|
+
"description": "Use logged-in apps and discover missing actions with Apilift.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Apilift"
|
|
7
7
|
},
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"skills": "./skills/",
|
|
10
10
|
"interface": {
|
|
11
11
|
"displayName": "Apilift",
|
|
12
|
-
"shortDescription": "
|
|
13
|
-
"longDescription": "
|
|
12
|
+
"shortDescription": "Agent access to your apps",
|
|
13
|
+
"longDescription": "Give your agent reusable access to logged-in apps. Apilift finds existing actions or builds and verifies missing ones from documented APIs and browser activity. Use it to read, create, and update app data. Requires the Apilift CLI; browser actions also require Chrome, the Apilift extension, and a signed-in account.",
|
|
14
14
|
"developerName": "Apilift",
|
|
15
15
|
"category": "Developer Tools",
|
|
16
16
|
"capabilities": [
|
|
@@ -18,7 +18,15 @@
|
|
|
18
18
|
],
|
|
19
19
|
"websiteURL": "https://apilift.dev",
|
|
20
20
|
"defaultPrompt": [
|
|
21
|
-
"
|
|
22
|
-
|
|
21
|
+
"Set up Apilift for this agent.",
|
|
22
|
+
"Use Apilift to complete a task in one of my logged-in apps.",
|
|
23
|
+
"Add missing actions for an app with Apilift."
|
|
24
|
+
],
|
|
25
|
+
"brandColor": "#000000",
|
|
26
|
+
"brandColorDark": "#D8FF73",
|
|
27
|
+
"composerIcon": "./assets/apilift-icon.png",
|
|
28
|
+
"logo": "./assets/apilift-icon.png",
|
|
29
|
+
"privacyPolicyURL": "https://apilift.dev/privacy",
|
|
30
|
+
"termsOfServiceURL": "https://apilift.dev/terms"
|
|
23
31
|
}
|
|
24
32
|
}
|
|
Binary file
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: discover
|
|
3
|
+
description: Create or extend a persistent Apilift interface from current documented APIs or, when unavailable, observed logged-in UI behavior. Publish only the independent resources needed for the requested outcome.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Discover or extend an app
|
|
7
|
+
|
|
8
|
+
Turn the requested outcome into the smallest set of reliable actions. Remain one discovery owner for the app's semantic decisions, browser operation, verification, cleanup, and publication. Do not use source code, old capture files, another worker's drafts, browser storage, or secret values as an answer key. Follow the CLI's current response and the returned editable files for command details; this skill supplies decisions that must be made before those commands.
|
|
9
|
+
|
|
10
|
+
## Select scope and route
|
|
11
|
+
|
|
12
|
+
Find existing coverage with `apilift apps search <query>` and focused `actions search` or `actions show`. Begin a new app with `apilift apps new <slug>` or extend the selected existing app with `apilift apps update <app>`. Use a stable root `--session <worker-label>` on every command if the runtime has no stable identity. Report the authoritative app and visibility before accessing its UI. One session owns at most one selected draft; leave another worker's draft alone.
|
|
13
|
+
|
|
14
|
+
For every requested action, assess current first-party operation and access documentation before browser preflight. `apilift discover api assess <entity.verb>` creates a focused editable finding; save a researched conclusion with `discover api save`. API documentation, authorization, and credential acquisition are separate questions. A missing local key or authentication failure does not prove the API route is absent. Use [documented-api.md](references/documented-api.md) for this decision. Use [browser-capture.md](references/browser-capture.md) only when the requested operation still needs observed UI behavior.
|
|
15
|
+
|
|
16
|
+
## Author one resource at a time
|
|
17
|
+
|
|
18
|
+
Use `apilift discover draft <kind> [name]` for `app`, `entity`, `transport`, `browser-page`, or `action`. Its response gives a private JSONC path; edit that file. The file contains the published `definition` and local `dependencies`, `verification`, and `capture` settings. App origin is its primary UI location, not every request destination. Publish missing entity and connection resources before an action that depends on them; a browser connection also needs a published browser page. Keep credential values and recurring local context values out of every definition. Read [operation-contract.md](references/operation-contract.md) before defining an action.
|
|
19
|
+
|
|
20
|
+
Check the selected file with `apilift discover check`; it sends no app request and reports independent field errors. An executable connection or action needs an explicit `apilift discover run` with representative values in `verification.inputs`; a connection also selects `verification.probeOrigin`. Inspect saved output against official documentation or observed app state and set `verification.review` to `accepted` only when its meaning is correct. A schema match or HTTP success alone is insufficient. For a mutation, assess its separate readback proof and never repeat the write merely to improve evidence. Metadata resources need no app execution. `apilift discover publish` publishes the exact selected version after its gates and sends no app request.
|
|
21
|
+
|
|
22
|
+
## Recover and finish
|
|
23
|
+
|
|
24
|
+
Use `apilift discover status` to recover the selected draft, result path, recording phase, or pending publication. A lost publication response is reconciled with the exact retained `discover publish` request before editing, deferring, or discarding. `discover rebase` is for a version conflict after reviewing the current resource. `discover defer` retains owned work, `discover discard` abandons only its unpublished draft, and `discover close` leaves the app when owned in-flight work has settled. A stopped recording must be confirmed or canceled before changing drafts or tabs. Follow [recovery.md](references/recovery.md) before treating a failed route as a terminal blocker.
|
|
25
|
+
|
|
26
|
+
Completion means the requested actions are published and the original authorized outcome is handled, or a specific human-only or external prerequisite is identified. Inspect published consumer help from a fresh session and obtain required values through its published source actions; the author's local verification inputs are not consumer coverage. Do not send an extra mutation merely to demonstrate publication. Report actual verification, authorized test state, one optional cleanup attempt if relevant, and remaining gaps.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Observe a logged-in UI
|
|
2
|
+
|
|
3
|
+
Use UI observation only after a focused current API and access assessment. Publish the browser page, then run `apilift browser check <app>` and follow its setup diagnostics before capture; the first connection need not exist for this check. Chrome with the Apilift extension must be controllable in the intended signed-in profile; an incompatible connection does not authorize another browser or account. Use `apilift browser tabs <app>` and the returned selection path if several tabs match, leaving a tab owned by another agent untouched. Follow the repository browser lease when developing inside the repository.
|
|
4
|
+
|
|
5
|
+
Publish a `browser-page` definition with `pageOrigin` and `startUrl` for the selected UI page. Publish a separate browser `transport` with `mode: "browser"`, fixed `allowedOrigins`, read-only `probes` and `dependencies.browserPage` naming that published page. A safe documented page read can be a probe when no JSON route has been observed; use an empty response contract and review the bounded non-JSON format/status result. That result confirms only reachability; inspect the signed-in UI and confirm the page's meaning before accepting the probe. A safe observed read can also inform the probe. Run and semantically review each configured origin before publishing the connection. Preserve working direct connections; each action selects its own published connection.
|
|
6
|
+
|
|
7
|
+
Before recording, select an action draft and describe the domain entity, verb, effect, successful result, input meanings and verification plan. Put caller-chosen representative values in `verification.inputs`, declare their schema in the definition, and select the tab in the file's `capture` settings. Arm with `apilift discover capture start` before entering the first caller value when a UI editor autosaves. Perform one authorized scenario in the selected tab and immediately run `apilift discover capture stop` after its causal request. If stop acknowledgement is lost, retry stop without replaying the app operation or changing tabs; if the scenario cannot proceed, use `discover capture cancel`.
|
|
8
|
+
|
|
9
|
+
Stop returns a bounded ranked candidate list. Use `discover capture list` for further candidate metadata and `discover capture show <candidate-id>` for selected evidence. Choose the causal exchange with `discover capture select <candidate-id>`; selection updates the owned draft from the retained observation. Preserve observed structure, review every binding and response field, and replace private samples with caller inputs, generated values, public literals or reachable source actions. An observed identifier is not automatically a caller choice. Do not export raw capture data to the repository.
|
|
10
|
+
|
|
11
|
+
Only when the selected request contains an unexplained authentication header, run `discover capture auth <candidate-id>` while evidence is current; no field or storage scope is required for its bounded default search of retained non-browser-owned headers against localStorage and sessionStorage. `discover capture show <candidate-id> --part request` displays header names and eligible field pointers without values. Narrow the search through the draft's `capture.authField` or `capture.authScope` only when the observed evidence supports it. Map a supported value-free locator to the browser connection's `definition.inject[].from` and its destination header to `definition.inject[].to`, then validate a safe connection probe; `definition.credentials` is only for separately saved human-provided secrets. Browser-managed cookies are sent by browser replay and do not require a storage locator. Do not turn secret values, browser-owned headers, or account data into action inputs or constants. Evidence expiry calls for a safe read or explicit primer, never another mutation.
|
|
12
|
+
|
|
13
|
+
Do not change tabs, browser surfaces, or draft ownership until stop or cancel confirms the recording boundary. A capture or controller failure is a local problem; apply [recovery.md](recovery.md) before declaring an app capability absent.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Assess a documented API
|
|
2
|
+
|
|
3
|
+
Search current first-party documentation for the selected operation and its authorization path. Record both in the file returned by `apilift discover api assess <entity.verb>`, then run `apilift discover api save`. A prose operation guide can be enough to author a selected action; an OpenAPI document is useful evidence but is not an import command. Documentation silence, a missing local credential, and an auth error are different findings. Follow explicit current documentation the user supplies even if an earlier assessment was negative.
|
|
4
|
+
|
|
5
|
+
A direct connection is an independent `transport` draft. Give it a meaningful description, `mode: "direct"`, fixed `baseUrl`, explicit `allowedOrigins`, value-free `credentials` requirements and harmless read `probes` for its destinations. Research and write concrete HTTPS acquisition steps before testing an operation that needs a key. The app's `origin` is its primary UI location; it is not a substitute for a connection destination. A transport with several origins needs one successful, semantically reviewed `discover run` per origin by editing `verification.probeOrigin` between runs. For a read using POST or another non-GET method, declare its semantic read effect rather than deriving effect from method.
|
|
6
|
+
|
|
7
|
+
If verification reports a missing or changed credential, follow the returned `credentials add` setup link. The person enters the value through the secure form, and the agent then selects the intended saved entry for this session with the exact CLI continuation. Do not ask for a key in chat or store it in a draft, command, environment variable, or capture. Acquisition instructions are required even if a key is already saved; they let the next user provision access. Re-run the same selected transport verification after human setup and inspect its meaning before accepting review.
|
|
8
|
+
|
|
9
|
+
A scoped harmless probe can take explicit local `verification.inputs`. Publish a reachable read action that supplies an app-owned identifier for later consumers; never embed an observed account identifier in a published probe or make the origin dynamic. Do not add a published context-variable resource. Begin browser fallback only after the requested documented operation, authorization, and provisioning route have been assessed. A local environment failure is not proof that the app lacks an API capability.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Define and prove an action
|
|
2
|
+
|
|
3
|
+
Name a precise domain `entity.verb` for the requested outcome. Before transport capture, define its entity, semantic effect, caller decisions, useful returned result, and independent proof of a mutation. Do not expand one read into general CRUD coverage. Check whether returned objects are the requested entities or containers requiring traversal and pagination. HTTP success and a matching title do not establish complete coverage.
|
|
4
|
+
|
|
5
|
+
An action's published `definition` describes its effect, JSON Schema `inputs`, request, response and, for a mutation, readback proof. `dependencies.transport` selects one published connection and is translated to the action's selected transport at publication. Request fields include method, URL, optional headers, query and JSON body. Use typed `{"$input":"name"}` and encoded `{input.name}` bindings for caller values. Public protocol literals are allowed; captured account identifiers, credential values and local defaults are not. Use generated bindings for fresh request identifiers, never a caller flag invented from a captured identifier.
|
|
6
|
+
|
|
7
|
+
Each visible input and response field needs a semantic description; caller inputs also need synthetic examples. A value owned by the app needs a published source action with a compatible selected result path. Producers never run implicitly: the consumer runs the documented source and supplies its selected value. Do not use a prose-only dependency, a published context-variable resource, or the author's local verification value as a source. Per-app scalar `context` defaults are a consumer convenience with exact input-name matching, not an action contract or account model. Ambiguous generic names are passed explicitly.
|
|
8
|
+
|
|
9
|
+
Select the useful response subtree with `response.path` when needed and validate it with `response.schema`; projected fields use paths relative to the selected subtree or array member. Preserve meaningful variants and nullable fields observed in real results. If verification reports a mismatch, inspect the selected value and correct its type or projection rather than weakening the contract to pass. Keep identity and relationship fields needed for further discovery.
|
|
10
|
+
|
|
11
|
+
A mutation needs a separate read-only proof request and meaningful comparisons to the intended state. A proof failure leaves the write possibly applied; inspect state through an authorized read and never repeat a possibly sent write just to get stronger proof. For a delete, an explicit absence proof may establish success. A readback or probe using POST may declare semantic `effect: "read"`; method alone is not the effect.
|
|
12
|
+
|
|
13
|
+
Put representative local values in `verification.inputs`, run `apilift discover check`, then explicitly `apilift discover run`. Judge the saved output against documentation or observed UI state. Set `verification.review` to `accepted` only after that judgment and `rejected` with notes otherwise; `discover publish` does not execute the app operation again. After publication, inspect `actions show` as a fresh consumer, obtain every required value through published source actions and finish the originally authorized outcome. Do not send a second mutation merely to test publication.
|
|
14
|
+
|
|
15
|
+
A genuinely terminal, command-scoped unavailable boundary may be documented only with evidence. Authentication, account tier, local transport, missing permission and ambiguous UI are retryable or user-specific blockers, not proof of app-wide absence. Keep existing working actions intact and defer unresolved work.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Recover from a failed route
|
|
2
|
+
|
|
3
|
+
1. Protect owned state first. If a recording is active, confirm `discover capture stop` or `discover capture cancel`; if a publication response was lost, inspect `discover status` and reconcile the retained `discover publish` request. Keep useful drafts and evidence.
|
|
4
|
+
2. Read the complete bounded diagnostic and exact continuation. Use `apilift doctor`, selected CLI help or the editable file only for the uncertainty at hand. Retry after a relevant state change or an explicitly safe recovery instruction; never infer success from a shell wrapper without the process exit status.
|
|
5
|
+
3. Reassess the requested outcome. A local command, browser or credential failure is evidence about that route, not proof that the app lacks the capability. Continue through another authorized documented route or independent action when it can advance the outcome without weakening proof or policy.
|
|
6
|
+
4. Ask the person only for login, MFA, CAPTCHA, WebAuthn, credential provisioning in the secure UI, new permission or a material scope choice they alone can supply. Do not ask them to paste a secret into chat or a command.
|
|
7
|
+
5. If no authorized route remains, report the precise missing outcome, retained owned state, materially different routes checked and exact prerequisite. Use `discover defer` to retain retryable work and `discover close` only after selected in-flight work is settled.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: use
|
|
3
|
+
description: Use Apilift to read, create, update, rename, or export data in logged-in apps when no first-party CLI, SDK, MCP server, or documented API covers the task. Check existing actions before browser work and discover missing coverage.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Use an indexed app
|
|
7
|
+
|
|
8
|
+
Use Apilift when a more direct installed capability does not cover the requested outcome. For a task in a logged-in app, check Apilift coverage before opening or operating its browser UI. Treat the CLI's current output as the navigation and execution contract. Do not read discovery drafts, captures, registry internals, browser storage, or implementation code to learn how to call a published action.
|
|
9
|
+
|
|
10
|
+
Start with `apilift` if the next command is unknown. Search by app name or domain with `apilift apps search <query>`, then select the intended app with `apilift apps use <app>`. Search unknown task vocabulary with `apilift actions search <app> <query>`; use the displayed `actions list` or `actions show` command for focused documentation. Read the selected action's effects, inputs, result, limits, and source instructions before `apilift run <app> <entity.verb> [input flags]`. A selected app is a use-session choice, not proof that any action was verified or authorized. Cached documentation is last-known; execution still requires current online authorization.
|
|
11
|
+
|
|
12
|
+
Use explicit flags for ambiguous values. `apilift context set <name> <scalar> --app <app>` saves an exact-name scalar default in this agent's app session; `context show`, `unset`, and `clear` inspect or remove it. An explicit action flag wins over a default. Do not save complex objects, opaque values copied from examples, or inferred account identifiers. Obtain an app-owned value through the published source action and its documented selection path. If the source is missing, that is missing coverage. Clear defaults when the access scope changes; credential selection also invalidates them.
|
|
13
|
+
|
|
14
|
+
For a direct connection requiring a saved credential, use the exact `credentials list`, `use`, or `add` continuation printed for that app and connection. Selection belongs to this agent session and does not switch browser login. Only the person uses the secure credential form; never ask for a secret in chat, shell arguments, environment variables, files, or a generic dashboard field. `credentials unbound` and `attach` are explicit recovery paths after a registry reset, never an invitation to match a secret by app name or origin. For browser actions, use the selected signed-in Chrome tab and the CLI's `browser check` or `browser tabs` guidance. An unusable Chrome connection is a local blocker, not evidence that the app lacks an action.
|
|
15
|
+
|
|
16
|
+
Respect policy, entitlement, effect, cost, and unavailable boundaries before dispatch. A refusal does not authorize direct HTTP or a new interface around it. Do not automatically retry a mutation that may have reached the app, including one whose result or readback proof was lost. Follow the retained invocation's recovery instruction and inspect state through a documented read. Check returned objects against the requested domain meaning, traverse pagination and containers where needed, and do not claim completion from a title or status code alone. Read only the selected result fields needed for the decision; oversized output is saved to the path printed by the CLI.
|
|
17
|
+
|
|
18
|
+
If the app, action, required input source, or result field is absent, tell the discovery owner the user outcome, the precise missing consumer capability, semantic input sources, required result, official documentation supplied by the user, and which published actions must remain intact. One owner should extend the app with the `discover` skill, then the consumer should read the newly published action help and complete the original task. Ask about test-state effects only when they are outside existing authorization. `apilift apps release <app>` ends this use session and clears its local selections and defaults when the work is done.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apilift/cli",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.23",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=24.16.0 <27"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "71f3e4ff037702755b511a14ec98c2ed9fb4e045",
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|
|
42
42
|
"url": "git+https://github.com/egor-sergeev/apilift.git",
|