@blxzer/cursor-trellis 0.4.2 → 0.4.3
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/CHANGELOG.md +24 -0
- package/README.md +23 -14
- package/README.zh-CN.md +14 -10
- package/bin/smart-search.js +10 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +36 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +42 -153
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts +10 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +38 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/update.d.ts +5 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +137 -40
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/cursor.d.ts +2 -1
- package/dist/configurators/cursor.d.ts.map +1 -1
- package/dist/configurators/cursor.js +4 -2
- package/dist/configurators/cursor.js.map +1 -1
- package/dist/configurators/index.js +4 -4
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/shared.d.ts +8 -0
- package/dist/configurators/shared.d.ts.map +1 -1
- package/dist/configurators/shared.js +27 -1
- package/dist/configurators/shared.js.map +1 -1
- package/dist/configurators/workflow.d.ts +0 -9
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +2 -4
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/constants/paths.d.ts +9 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +13 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/migrations/manifests/0.3.0.json +1 -1
- package/dist/templates/common/bundled-skills/cstl-meta/references/platform-files/skills-and-commands.md +2 -4
- package/dist/templates/common/bundled-skills/cstl-skill-creator/SKILL.md +10 -7
- package/dist/templates/common/bundled-skills/cstl-skill-creator/references/authoring-rules.md +93 -19
- package/dist/templates/common/bundled-skills/cstl-skill-creator/references/general-authoring.md +189 -0
- package/dist/templates/common/bundled-skills/cstl-skill-creator/references/review-checklist.md +10 -5
- package/dist/templates/common/commands/continue.md +5 -4
- package/dist/templates/common/index.d.ts +20 -0
- package/dist/templates/common/index.d.ts.map +1 -1
- package/dist/templates/common/index.js +21 -2
- package/dist/templates/common/index.js.map +1 -1
- package/dist/templates/common/optional-skills/chrome-cdp/SKILL.md +179 -0
- package/dist/templates/common/optional-skills/chrome-cdp/examples/fetch-hook-api-capture.md +149 -0
- package/dist/templates/common/optional-skills/chrome-cdp/scripts/cdp.mjs +903 -0
- package/dist/templates/cursor/agents/cstl-research.md +1 -1
- package/dist/templates/cursor/fixtures/expected-rules.d.ts +1 -1
- package/dist/templates/cursor/fixtures/expected-rules.d.ts.map +1 -1
- package/dist/templates/cursor/fixtures/expected-rules.js +7 -24
- package/dist/templates/cursor/fixtures/expected-rules.js.map +1 -1
- package/dist/templates/cursor/hooks.json +4 -0
- package/dist/templates/cursor/index.d.ts +1 -1
- package/dist/templates/cursor/index.js +1 -1
- package/dist/templates/cursor/rules/cstl-bootstrap.mdc +17 -0
- package/dist/templates/markdown/agents.md +15 -10
- package/dist/templates/markdown/framework/cursor-native-modes-guide.md.txt +12 -9
- package/dist/templates/markdown/framework/cursor-subagent-policy.md.txt +62 -126
- package/dist/templates/markdown/framework/dogfood-only-surfaces.md.txt +4 -6
- package/dist/templates/markdown/framework/execution-strategy.md.txt +2 -0
- package/dist/templates/markdown/framework/index.md.txt +4 -0
- package/dist/templates/markdown/framework/internal-skills-cursor-reachability.md.txt +4 -3
- package/dist/templates/markdown/framework/middleware-protocol.md.txt +83 -0
- package/dist/templates/markdown/framework/parallel-first-execution.md.txt +78 -0
- package/dist/templates/markdown/framework/release-boundary.md.txt +30 -0
- package/dist/templates/markdown/framework/retrieval-daily-guide.md.txt +1 -1
- package/dist/templates/markdown/framework/upgrade.md.txt +15 -0
- package/dist/templates/markdown/index.d.ts +4 -0
- package/dist/templates/markdown/index.d.ts.map +1 -1
- package/dist/templates/markdown/index.js +17 -0
- package/dist/templates/markdown/index.js.map +1 -1
- package/dist/templates/markdown/spec/guides/index.md.txt +0 -6
- package/dist/templates/shared-hooks/event-bridge.py +60 -0
- package/dist/templates/shared-hooks/index.d.ts +1 -1
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +1 -0
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/session-start.py +18 -1
- package/dist/templates/trellis/CONTEXT.md +63 -3
- package/dist/templates/trellis/gitignore.txt +39 -39
- package/dist/templates/trellis/index.d.ts +12 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +73 -15
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/pool/README.md +12 -3
- package/dist/templates/trellis/pool/plan.md +24 -5
- package/dist/templates/trellis/scripts/common/adapter_middleware.py +158 -0
- package/dist/templates/trellis/scripts/common/artifact_locale.py +12 -3
- package/dist/templates/trellis/scripts/common/cursor_retrieval_env.py +5 -2
- package/dist/templates/trellis/scripts/common/full_quality.py +237 -0
- package/dist/templates/trellis/scripts/common/git.py +6 -0
- package/dist/templates/trellis/scripts/common/git_context.py +17 -5
- package/dist/templates/trellis/scripts/common/kernel_command.py +367 -0
- package/dist/templates/trellis/scripts/common/lite_context.py +280 -0
- package/dist/templates/trellis/scripts/common/ondemand_topology.py +225 -0
- package/dist/templates/trellis/scripts/common/parent_orchestration.py +1 -1
- package/dist/templates/trellis/scripts/common/pool_store.py +16 -4
- package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +2 -2
- package/dist/templates/trellis/scripts/common/session_context.py +28 -2
- package/dist/templates/trellis/scripts/common/task_gates.py +73 -12
- package/dist/templates/trellis/scripts/common/task_map.py +42 -9
- package/dist/templates/trellis/scripts/common/task_store.py +286 -56
- package/dist/templates/trellis/scripts/common/test_adapter_middleware.py +56 -0
- package/dist/templates/trellis/scripts/common/test_depends_mode_block.py +9 -0
- package/dist/templates/trellis/scripts/common/test_full_quality.py +197 -0
- package/dist/templates/trellis/scripts/common/test_kernel_command.py +326 -0
- package/dist/templates/trellis/scripts/common/test_lite_path.py +190 -0
- package/dist/templates/trellis/scripts/common/test_ondemand_topology.py +122 -0
- package/dist/templates/trellis/scripts/common/test_pool_store.py +17 -0
- package/dist/templates/trellis/scripts/common/test_task_store_kernel_patch.py +163 -0
- package/dist/templates/trellis/scripts/common/workflow_phase.py +3 -0
- package/dist/templates/trellis/scripts/get_context.py +1 -0
- package/dist/templates/trellis/scripts/pool.py +5 -0
- package/dist/templates/trellis/scripts/task.py +83 -7
- package/dist/templates/trellis/workflow.md +100 -18
- package/dist/utils/cursor-retrieval-env.d.ts +2 -1
- package/dist/utils/cursor-retrieval-env.d.ts.map +1 -1
- package/dist/utils/cursor-retrieval-env.js +3 -2
- package/dist/utils/cursor-retrieval-env.js.map +1 -1
- package/dist/utils/cursor2plus-residue-cleanup.d.ts +38 -0
- package/dist/utils/cursor2plus-residue-cleanup.d.ts.map +1 -0
- package/dist/utils/cursor2plus-residue-cleanup.js +145 -0
- package/dist/utils/cursor2plus-residue-cleanup.js.map +1 -0
- package/dist/utils/manifest-prune.d.ts.map +1 -1
- package/dist/utils/manifest-prune.js +7 -2
- package/dist/utils/manifest-prune.js.map +1 -1
- package/dist/utils/p36-upgrade.d.ts +62 -0
- package/dist/utils/p36-upgrade.d.ts.map +1 -0
- package/dist/utils/p36-upgrade.js +160 -0
- package/dist/utils/p36-upgrade.js.map +1 -0
- package/dist/utils/project-capabilities.d.ts +1 -12
- package/dist/utils/project-capabilities.d.ts.map +1 -1
- package/dist/utils/project-capabilities.js +3 -100
- package/dist/utils/project-capabilities.js.map +1 -1
- package/dist/utils/readiness.d.ts +10 -0
- package/dist/utils/readiness.d.ts.map +1 -1
- package/dist/utils/readiness.js +58 -26
- package/dist/utils/readiness.js.map +1 -1
- package/dist/utils/retrieval-agent-instructions.js +1 -1
- package/dist/utils/retrieval-agent-instructions.js.map +1 -1
- package/dist/utils/template-hash.d.ts.map +1 -1
- package/dist/utils/template-hash.js +11 -1
- package/dist/utils/template-hash.js.map +1 -1
- package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
- package/dist/utils/uninstall-scrubbers.js +52 -14
- package/dist/utils/uninstall-scrubbers.js.map +1 -1
- package/dist/utils/update-rollout-report.d.ts +14 -0
- package/dist/utils/update-rollout-report.d.ts.map +1 -1
- package/dist/utils/update-rollout-report.js +1 -0
- package/dist/utils/update-rollout-report.js.map +1 -1
- package/dist/utils/workflow-ownership.d.ts +1 -1
- package/dist/utils/workflow-ownership.js +4 -4
- package/dist/utils/workflow-ownership.js.map +1 -1
- package/package.json +5 -4
- package/scripts/postinstall.js +6 -7
- package/dist/commands/campaign/canvas-render.d.ts +0 -68
- package/dist/commands/campaign/canvas-render.d.ts.map +0 -1
- package/dist/commands/campaign/canvas-render.js +0 -414
- package/dist/commands/campaign/canvas-render.js.map +0 -1
- package/dist/commands/campaign/compose.d.ts +0 -15
- package/dist/commands/campaign/compose.d.ts.map +0 -1
- package/dist/commands/campaign/compose.js +0 -110
- package/dist/commands/campaign/compose.js.map +0 -1
- package/dist/commands/campaign/index.d.ts +0 -13
- package/dist/commands/campaign/index.d.ts.map +0 -1
- package/dist/commands/campaign/index.js +0 -134
- package/dist/commands/campaign/index.js.map +0 -1
- package/dist/commands/campaign/kind-map.d.ts +0 -6
- package/dist/commands/campaign/kind-map.d.ts.map +0 -1
- package/dist/commands/campaign/kind-map.js +0 -21
- package/dist/commands/campaign/kind-map.js.map +0 -1
- package/dist/commands/campaign/mcp-server.d.ts +0 -6
- package/dist/commands/campaign/mcp-server.d.ts.map +0 -1
- package/dist/commands/campaign/mcp-server.js +0 -167
- package/dist/commands/campaign/mcp-server.js.map +0 -1
- package/dist/commands/campaign/render.d.ts +0 -5
- package/dist/commands/campaign/render.d.ts.map +0 -1
- package/dist/commands/campaign/render.js +0 -103
- package/dist/commands/campaign/render.js.map +0 -1
- package/dist/commands/campaign/trellis-load.d.ts +0 -13
- package/dist/commands/campaign/trellis-load.d.ts.map +0 -1
- package/dist/commands/campaign/trellis-load.js +0 -122
- package/dist/commands/campaign/trellis-load.js.map +0 -1
- package/dist/commands/campaign/types.d.ts +0 -61
- package/dist/commands/campaign/types.d.ts.map +0 -1
- package/dist/commands/campaign/types.js +0 -3
- package/dist/commands/campaign/types.js.map +0 -1
- package/dist/commands/goal/index.d.ts +0 -3
- package/dist/commands/goal/index.d.ts.map +0 -1
- package/dist/commands/goal/index.js +0 -159
- package/dist/commands/goal/index.js.map +0 -1
- package/dist/commands/goal/review.d.ts +0 -6
- package/dist/commands/goal/review.d.ts.map +0 -1
- package/dist/commands/goal/review.js +0 -28
- package/dist/commands/goal/review.js.map +0 -1
- package/dist/commands/rpc/client.d.ts +0 -51
- package/dist/commands/rpc/client.d.ts.map +0 -1
- package/dist/commands/rpc/client.js +0 -147
- package/dist/commands/rpc/client.js.map +0 -1
- package/dist/commands/rpc/index.d.ts +0 -10
- package/dist/commands/rpc/index.d.ts.map +0 -1
- package/dist/commands/rpc/index.js +0 -157
- package/dist/commands/rpc/index.js.map +0 -1
- package/dist/commands/rpc/serve.d.ts +0 -23
- package/dist/commands/rpc/serve.d.ts.map +0 -1
- package/dist/commands/rpc/serve.js +0 -60
- package/dist/commands/rpc/serve.js.map +0 -1
- package/dist/commands/rpc/smoke.d.ts +0 -16
- package/dist/commands/rpc/smoke.d.ts.map +0 -1
- package/dist/commands/rpc/smoke.js +0 -92
- package/dist/commands/rpc/smoke.js.map +0 -1
- package/dist/commands/sdk/index.d.ts +0 -9
- package/dist/commands/sdk/index.d.ts.map +0 -1
- package/dist/commands/sdk/index.js +0 -58
- package/dist/commands/sdk/index.js.map +0 -1
- package/dist/commands/sdk/run.d.ts +0 -42
- package/dist/commands/sdk/run.d.ts.map +0 -1
- package/dist/commands/sdk/run.js +0 -220
- package/dist/commands/sdk/run.js.map +0 -1
- package/dist/commands/sdk/status.d.ts +0 -14
- package/dist/commands/sdk/status.d.ts.map +0 -1
- package/dist/commands/sdk/status.js +0 -69
- package/dist/commands/sdk/status.js.map +0 -1
- package/dist/configurators/cursor2plus-local.d.ts +0 -6
- package/dist/configurators/cursor2plus-local.d.ts.map +0 -1
- package/dist/configurators/cursor2plus-local.js +0 -21
- package/dist/configurators/cursor2plus-local.js.map +0 -1
- package/dist/goal/action-packet.d.ts +0 -89
- package/dist/goal/action-packet.d.ts.map +0 -1
- package/dist/goal/action-packet.js +0 -113
- package/dist/goal/action-packet.js.map +0 -1
- package/dist/goal/audit.d.ts +0 -14
- package/dist/goal/audit.d.ts.map +0 -1
- package/dist/goal/audit.js +0 -12
- package/dist/goal/audit.js.map +0 -1
- package/dist/goal/constants.d.ts +0 -26
- package/dist/goal/constants.d.ts.map +0 -1
- package/dist/goal/constants.js +0 -24
- package/dist/goal/constants.js.map +0 -1
- package/dist/goal/paths.d.ts +0 -8
- package/dist/goal/paths.d.ts.map +0 -1
- package/dist/goal/paths.js +0 -36
- package/dist/goal/paths.js.map +0 -1
- package/dist/goal/preflight.d.ts +0 -21
- package/dist/goal/preflight.d.ts.map +0 -1
- package/dist/goal/preflight.js +0 -97
- package/dist/goal/preflight.js.map +0 -1
- package/dist/goal/review-seam.d.ts +0 -44
- package/dist/goal/review-seam.d.ts.map +0 -1
- package/dist/goal/review-seam.js +0 -153
- package/dist/goal/review-seam.js.map +0 -1
- package/dist/goal/reviewer-rules.d.ts +0 -13
- package/dist/goal/reviewer-rules.d.ts.map +0 -1
- package/dist/goal/reviewer-rules.js +0 -153
- package/dist/goal/reviewer-rules.js.map +0 -1
- package/dist/goal/reviewer.d.ts +0 -9
- package/dist/goal/reviewer.d.ts.map +0 -1
- package/dist/goal/reviewer.js +0 -54
- package/dist/goal/reviewer.js.map +0 -1
- package/dist/goal/runtime.d.ts +0 -32
- package/dist/goal/runtime.d.ts.map +0 -1
- package/dist/goal/runtime.js +0 -242
- package/dist/goal/runtime.js.map +0 -1
- package/dist/goal/sdk-client.d.ts +0 -10
- package/dist/goal/sdk-client.d.ts.map +0 -1
- package/dist/goal/sdk-client.js +0 -34
- package/dist/goal/sdk-client.js.map +0 -1
- package/dist/goal/state.d.ts +0 -40
- package/dist/goal/state.d.ts.map +0 -1
- package/dist/goal/state.js +0 -37
- package/dist/goal/state.js.map +0 -1
- package/dist/goal/task-triggers.d.ts +0 -15
- package/dist/goal/task-triggers.d.ts.map +0 -1
- package/dist/goal/task-triggers.js +0 -23
- package/dist/goal/task-triggers.js.map +0 -1
- package/dist/goal/walls.d.ts +0 -12
- package/dist/goal/walls.d.ts.map +0 -1
- package/dist/goal/walls.js +0 -65
- package/dist/goal/walls.js.map +0 -1
- package/dist/goal/worker-prompt.d.ts +0 -13
- package/dist/goal/worker-prompt.d.ts.map +0 -1
- package/dist/goal/worker-prompt.js +0 -41
- package/dist/goal/worker-prompt.js.map +0 -1
- package/dist/goal/worker.d.ts +0 -42
- package/dist/goal/worker.d.ts.map +0 -1
- package/dist/goal/worker.js +0 -180
- package/dist/goal/worker.js.map +0 -1
- package/dist/templates/common/bundled-skills/cstl-cursor2plus-setup/SKILL.md +0 -63
- package/dist/templates/cursor/commands/cursor2plus-setup.md +0 -82
- package/dist/templates/cursor/rules/cstl-cursor-modes.mdc +0 -32
- package/dist/templates/cursor/rules/cstl-session-rename.mdc +0 -31
- package/dist/templates/cursor/rules/cstl-subagent-dispatch.mdc +0 -34
- package/dist/templates/cursor/rules/cstl-triage.mdc +0 -36
- package/dist/templates/cursor/rules/retrieval-routing.mdc +0 -78
- package/dist/templates/trellis/local/README.md +0 -85
- package/dist/templates/trellis/local/config.local.json.example +0 -6
- package/dist/templates/trellis/local/index.d.ts +0 -8
- package/dist/templates/trellis/local/index.d.ts.map +0 -1
- package/dist/templates/trellis/local/index.js +0 -15
- package/dist/templates/trellis/local/index.js.map +0 -1
- package/dist/templates/trellis/local/patch_wpelc8.py +0 -421
- package/dist/templates/trellis/local/smoke.py +0 -94
- package/dist/templates/trellis/local/subagent-models.json.example +0 -4
- package/dist/templates/trellis/local/trellis-task-models.json.example +0 -10
- package/dist/templates/trellis/local/trellis-task-models.json5.example +0 -45
- package/dist/templates/trellis/local/trellis_task_models_config.py +0 -200
- package/dist/utils/cursor-sdk-gate.d.ts +0 -10
- package/dist/utils/cursor-sdk-gate.d.ts.map +0 -1
- package/dist/utils/cursor-sdk-gate.js +0 -32
- package/dist/utils/cursor-sdk-gate.js.map +0 -1
package/dist/templates/common/bundled-skills/cstl-skill-creator/references/review-checklist.md
CHANGED
|
@@ -5,9 +5,10 @@ Use this checklist before handing off a new or modified skill.
|
|
|
5
5
|
## Frontmatter
|
|
6
6
|
|
|
7
7
|
- [ ] `name` uses lowercase letters, numbers, and hyphens only.
|
|
8
|
-
- [ ] `description` is third-person and trigger
|
|
9
|
-
- [ ] `description` includes both what the skill does and when to use it.
|
|
8
|
+
- [ ] `description` is third-person, specific, and includes trigger terms.
|
|
9
|
+
- [ ] `description` includes both what the skill does (WHAT) and when to use it (WHEN).
|
|
10
10
|
- [ ] The skill name does not collide with a platform built-in helper unless that is intentional.
|
|
11
|
+
- [ ] The skill name is specific (`processing-pdfs`), not vague (`helper`, `utils`, `tools`).
|
|
11
12
|
|
|
12
13
|
## Scope And Boundaries
|
|
13
14
|
|
|
@@ -15,14 +16,18 @@ Use this checklist before handing off a new or modified skill.
|
|
|
15
16
|
- [ ] `When NOT To Use` or equivalent boundary guidance is present when triggers may overlap.
|
|
16
17
|
- [ ] Project-private rules are in `.cstl/spec/` or a project-local skill, not in a public bundled skill.
|
|
17
18
|
- [ ] The skill distinguishes local project customization from upstream Trellis source changes.
|
|
19
|
+
- [ ] Terminology is consistent throughout.
|
|
18
20
|
|
|
19
21
|
## Entry File
|
|
20
22
|
|
|
21
23
|
- [ ] `SKILL.md` is concise and under 500 lines.
|
|
24
|
+
- [ ] `SKILL.md` is written in English unless the target platform or user explicitly requires another language.
|
|
22
25
|
- [ ] `SKILL.md` contains the minimum routing and workflow needed to start.
|
|
23
26
|
- [ ] `## Hard Constraints` appears before `## Workflow` when constraints exist.
|
|
24
|
-
- [ ] Hard constraints are imperative one-liners.
|
|
25
|
-
- [ ] The same rule is not repeated in multiple sections.
|
|
27
|
+
- [ ] Hard constraints are imperative one-liners (`Always X. Never Y.`).
|
|
28
|
+
- [ ] The same rule is not repeated in multiple sections; Hard Constraints is the only rule list.
|
|
29
|
+
- [ ] Workflow has an explicit tool-call sequence and stop conditions.
|
|
30
|
+
- [ ] Tool usage limits are stated when applicable.
|
|
26
31
|
|
|
27
32
|
## References And Assets
|
|
28
33
|
|
|
@@ -36,7 +41,7 @@ Use this checklist before handing off a new or modified skill.
|
|
|
36
41
|
- [ ] Scripts are necessary for determinism, not decorative.
|
|
37
42
|
- [ ] Scripts expose only necessary parameters.
|
|
38
43
|
- [ ] Scripts do not rely on shell variables or state from a previous tool call.
|
|
39
|
-
- [ ] Scripts return structured JSON when they mutate files or provide machine-readable status.
|
|
44
|
+
- [ ] Scripts return structured JSON to stdout when they mutate files or provide machine-readable status.
|
|
40
45
|
- [ ] Syntax checks were run for modified scripts when applicable.
|
|
41
46
|
|
|
42
47
|
## Trellis Template Integration
|
|
@@ -41,21 +41,22 @@ Shows the Phase Index (Plan / Execute / Finish) with routing + skill mapping.
|
|
|
41
41
|
|
|
42
42
|
## Step 4: Decide Where You Are
|
|
43
43
|
|
|
44
|
-
When a task is selected, `get_context.py` shows the selected task
|
|
44
|
+
When a task is selected, `get_context.py` shows the selected task. Route by Kernel / persisted `required_controls.rigor` and `topology.kind`, not by whether `design.md` or `implement.md` exist. `status` is a projection, not the sole truth. This command replaces the user needing to remember the Trellis flow; it does not itself approve implementation.
|
|
45
45
|
|
|
46
46
|
- `status=planning` + no `prd.md` → **1.1** (Read `.cstl/framework/prd-grill-frontier.md` for PRD Grill discipline)
|
|
47
|
-
- `status=planning` + `prd.md`
|
|
48
|
-
- `status=planning` +
|
|
47
|
+
- `status=planning` + `prd.md` + rigor is lite (or missing contract = explicit Lite) → **1.4** review / execution gate
|
|
48
|
+
- `status=planning` + rigor is full + required planning artifacts not complete → stay in planning (`design.md` / `implement.md` only when `required_controls` says so)
|
|
49
49
|
- `status=planning` + required artifacts complete + required jsonl curated or inline mode → execution gate (run `task.py start-execution <task> --check`, report PASS, ask for explicit execution approval, then run `task.py start-execution <task> --approved`)
|
|
50
50
|
- `status=in_progress` + implementation not started → **2.1**
|
|
51
51
|
- `status=in_progress` + implementation done, not yet checked → **2.2**
|
|
52
52
|
- `status=in_progress` + check passed → **3.1**
|
|
53
53
|
- `status=completed` (rare; usually archived immediately) → archive flow
|
|
54
|
+
- `topology.kind=parent-child` → Parent integration path, not ordinary Child closeout. `parent_id` alone does **not** make a Child a Parent.
|
|
54
55
|
|
|
55
56
|
Phase rules (full detail in `.cstl/workflow.md`):
|
|
56
57
|
|
|
57
58
|
1. Run steps **in order** within a phase — `[required]` steps must not be skipped
|
|
58
|
-
2. `[once]` steps are already done if the required output exists. `prd.md` alone can be enough
|
|
59
|
+
2. `[once]` steps are already done if the required output exists. `prd.md` alone can be enough when rigor is Lite; Full follows `required_controls`, not file presence.
|
|
59
60
|
3. You may go back to an earlier phase if discoveries require it
|
|
60
61
|
|
|
61
62
|
## Step 5: Load the Specific Step
|
|
@@ -28,6 +28,17 @@ export interface CommonBundledSkill {
|
|
|
28
28
|
/** Files that must be written under the skill directory */
|
|
29
29
|
files: CommonBundledSkillFile[];
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Optional/experimental skill — same shape as bundled skills, but lives under
|
|
33
|
+
* `optional-skills/` which `getBundledSkillTemplates()` does NOT scan.
|
|
34
|
+
* Installed only via `cstl init --with-optional <name>` (default off).
|
|
35
|
+
*/
|
|
36
|
+
export interface CommonOptionalSkill {
|
|
37
|
+
/** Skill directory name, e.g. "chrome-cdp" */
|
|
38
|
+
name: string;
|
|
39
|
+
/** Files that must be written under the skill directory */
|
|
40
|
+
files: CommonBundledSkillFile[];
|
|
41
|
+
}
|
|
31
42
|
/**
|
|
32
43
|
* Get all command templates (stay as slash commands on all platforms).
|
|
33
44
|
* Results are cached after first call.
|
|
@@ -45,4 +56,13 @@ export declare function getSkillTemplates(): CommonTemplate[];
|
|
|
45
56
|
* lazy-loadable instead of being flattened into one oversized SKILL.md.
|
|
46
57
|
*/
|
|
47
58
|
export declare function getBundledSkillTemplates(): CommonBundledSkill[];
|
|
59
|
+
/**
|
|
60
|
+
* Get all optional/experimental skills (e.g. `optional-skills/chrome-cdp/`).
|
|
61
|
+
*
|
|
62
|
+
* Deliberately separate from {@link getBundledSkillTemplates}: `optional-skills/`
|
|
63
|
+
* is NOT scanned by the bundled pipeline, so default `cstl init` never installs
|
|
64
|
+
* these. They are installed only through `cstl init --with-optional <name>`.
|
|
65
|
+
* Results are cached after first call.
|
|
66
|
+
*/
|
|
67
|
+
export declare function getOptionalSkillTemplates(): CommonOptionalSkill[];
|
|
48
68
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/common/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAuBH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,EAAE,sBAAsB,EAAE,CAAC;CACjC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/common/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAuBH,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,EAAE,sBAAsB,EAAE,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,EAAE,sBAAsB,EAAE,CAAC;CACjC;AAQD;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,EAAE,CAMtD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,EAAE,CAMpD;AA2CD;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,kBAAkB,EAAE,CAM/D;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,IAAI,mBAAmB,EAAE,CAMjE"}
|
|
@@ -32,6 +32,7 @@ function listMarkdownFiles(dir) {
|
|
|
32
32
|
let cachedCommands;
|
|
33
33
|
let cachedSkills;
|
|
34
34
|
let cachedBundledSkills;
|
|
35
|
+
let cachedOptionalSkills;
|
|
35
36
|
/**
|
|
36
37
|
* Get all command templates (stay as slash commands on all platforms).
|
|
37
38
|
* Results are cached after first call.
|
|
@@ -67,8 +68,8 @@ function listDirectories(dir) {
|
|
|
67
68
|
function toPosixRelativePath(root, filePath) {
|
|
68
69
|
return relative(root, filePath).split(sep).join("/");
|
|
69
70
|
}
|
|
70
|
-
function
|
|
71
|
-
const root = join(__dirname,
|
|
71
|
+
function listSkillFiles(rootDir, skillDir) {
|
|
72
|
+
const root = join(__dirname, rootDir, skillDir);
|
|
72
73
|
const files = [];
|
|
73
74
|
function walk(dir) {
|
|
74
75
|
for (const entry of readdirSync(dir)) {
|
|
@@ -88,6 +89,9 @@ function listBundledSkillFiles(skillDir) {
|
|
|
88
89
|
walk(root);
|
|
89
90
|
return files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
90
91
|
}
|
|
92
|
+
function listBundledSkillFiles(skillDir) {
|
|
93
|
+
return listSkillFiles("bundled-skills", skillDir);
|
|
94
|
+
}
|
|
91
95
|
/**
|
|
92
96
|
* Get all multi-file built-in skills.
|
|
93
97
|
*
|
|
@@ -101,4 +105,19 @@ export function getBundledSkillTemplates() {
|
|
|
101
105
|
}));
|
|
102
106
|
return cachedBundledSkills;
|
|
103
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Get all optional/experimental skills (e.g. `optional-skills/chrome-cdp/`).
|
|
110
|
+
*
|
|
111
|
+
* Deliberately separate from {@link getBundledSkillTemplates}: `optional-skills/`
|
|
112
|
+
* is NOT scanned by the bundled pipeline, so default `cstl init` never installs
|
|
113
|
+
* these. They are installed only through `cstl init --with-optional <name>`.
|
|
114
|
+
* Results are cached after first call.
|
|
115
|
+
*/
|
|
116
|
+
export function getOptionalSkillTemplates() {
|
|
117
|
+
cachedOptionalSkills ??= listDirectories("optional-skills").map((name) => ({
|
|
118
|
+
name,
|
|
119
|
+
files: listSkillFiles("optional-skills", name),
|
|
120
|
+
}));
|
|
121
|
+
return cachedOptionalSkills;
|
|
122
|
+
}
|
|
104
123
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/common/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,SAAS,YAAY,CAAC,YAAoB;IACxC,OAAO,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;aACrC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aAChC,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/common/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: chrome-cdp
|
|
3
|
+
description: Interact with local Chrome browser session (only on explicit user approval after being asked to inspect, debug, or interact with a page open in Chrome)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> **experimental** — optional skill, installed on explicit request only (`cstl init --with-optional chrome-cdp`). Not a default Trellis capability.
|
|
7
|
+
>
|
|
8
|
+
> vendored from `blaze-skills/chrome-cdp@4ed61ff`(源 commit);同步机制:改源 → 拷副本 → 更新本标记。不要直接在本副本上分叉内容。
|
|
9
|
+
|
|
10
|
+
# Chrome CDP
|
|
11
|
+
|
|
12
|
+
Lightweight Chrome DevTools Protocol CLI. Connects directly via WebSocket — no Puppeteer, works with 100+ tabs, instant connection.
|
|
13
|
+
|
|
14
|
+
## Required Safety Wording
|
|
15
|
+
|
|
16
|
+
> Use Chrome CDP only after the user explicitly approves interacting with their existing local Chrome browser session for this task. This skill can reveal open tabs, page content, authenticated data, screenshots, profile state, and extension-influenced behavior, and it can mutate real browser state through navigation, clicks, typing, new tabs, or arbitrary CDP commands. Prefer Playwright MCP for reproducible browser automation and UI verification. Ask before `list`; ask again before inspecting content, taking screenshots, evaluating JavaScript, navigating, clicking, typing, opening tabs, or using raw CDP commands. Never use this skill for routine browser tests or when a controlled Playwright/sessionless check is sufficient.
|
|
17
|
+
|
|
18
|
+
## Channel Selection (three-way)
|
|
19
|
+
|
|
20
|
+
| Channel | Status | Use for |
|
|
21
|
+
| --- | --- | --- |
|
|
22
|
+
| Playwright MCP | **default** | Reproducible browser automation, rendered UI evidence, screenshots, UI smoke verification |
|
|
23
|
+
| `cursor-ide-browser` (IDE preview) | IDE 预览 | Page inspection/preview inside the IDE without touching the user's real Chrome profile |
|
|
24
|
+
| `chrome-cdp` (this skill) | real Chrome, attach-only on approval | Inspect/debug/interact with the user's **already-open local Chrome session** (login state, cookies, tabs) — only after explicit user approval |
|
|
25
|
+
|
|
26
|
+
- If a `mcp__chrome-devtools__*` server is present in the environment, ask the user which channel they want: the chrome-devtools MCP server and this CDP CLI are **mutually exclusive** for a given interaction — never run both against the same tab.
|
|
27
|
+
- Never switch to MCP when the user explicitly requires CDP. CDP may have login state that MCP does not.
|
|
28
|
+
|
|
29
|
+
## Prerequisites
|
|
30
|
+
|
|
31
|
+
- Chrome (or Chromium, Brave, Edge, Vivaldi) with remote debugging enabled: open `chrome://inspect/#remote-debugging` and toggle the switch
|
|
32
|
+
- Node.js 22+ (uses built-in WebSocket)
|
|
33
|
+
- If your browser's `DevToolsActivePort` is in a non-standard location, set `CDP_PORT_FILE` to its full path
|
|
34
|
+
|
|
35
|
+
## Hard Constraints
|
|
36
|
+
|
|
37
|
+
- Never use `shot` to read page content. Use it only for visual debugging as a last resort.
|
|
38
|
+
- Always prefer `eval` plus `getBoundingClientRect()` over `shot` to find element coordinates.
|
|
39
|
+
- Always prefer `clickxy` over `click <selector>` unless you have a specific reason to use DOM click.
|
|
40
|
+
- Always check `window.location.href` and `list` after clicking.
|
|
41
|
+
- Always collect volatile page data in one `eval` call when possible.
|
|
42
|
+
- Never switch to MCP when the user explicitly requires CDP. CDP may have login state that MCP does not.
|
|
43
|
+
|
|
44
|
+
## Commands
|
|
45
|
+
|
|
46
|
+
All commands use `scripts/cdp.mjs`. The `<target>` is a **unique** targetId prefix from `list`.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
scripts/cdp.mjs list # list all open tabs (* marks current active tab)
|
|
50
|
+
scripts/cdp.mjs eval <target> <expr> # run JS in page context
|
|
51
|
+
scripts/cdp.mjs clickxy <target> <x> <y> # real mouse click at CSS px coords (preferred)
|
|
52
|
+
scripts/cdp.mjs click <target> <selector> # DOM click by CSS selector (SPA-unreliable)
|
|
53
|
+
scripts/cdp.mjs nav <target> <url> # navigate and wait for load
|
|
54
|
+
scripts/cdp.mjs snap <target> # accessibility tree (token-light alternative to shot)
|
|
55
|
+
scripts/cdp.mjs type <target> <text> # insert text at current focus
|
|
56
|
+
scripts/cdp.mjs html <target> [selector] # full page or element HTML
|
|
57
|
+
scripts/cdp.mjs shot <target> [file] # screenshot (last resort, very token-heavy)
|
|
58
|
+
scripts/cdp.mjs net <target> # network performance entries (resource timing)
|
|
59
|
+
scripts/cdp.mjs loadall <target> <selector> [ms] # [exceptional] repeatedly click a "load more" button until it disappears
|
|
60
|
+
scripts/cdp.mjs evalraw <target> <method> [json] # [exceptional] send a raw CDP command; returns JSON result
|
|
61
|
+
scripts/cdp.mjs open [url] # open new tab
|
|
62
|
+
scripts/cdp.mjs stop [target] # stop daemon(s)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- `net` is safe, read-only (resource timing entries).
|
|
66
|
+
- `loadall` is **exceptional**: it mutates the real page repeatedly; ask for explicit approval before using it.
|
|
67
|
+
- `evalraw` is **exceptional**: it exposes arbitrary CDP methods beyond the curated command list; require exceptional approval before using it.
|
|
68
|
+
|
|
69
|
+
## Active Tab Detection (macOS)
|
|
70
|
+
|
|
71
|
+
`list` automatically marks the currently focused Chrome tab with `*` using AppleScript:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
(* = current active tab in Chrome)
|
|
75
|
+
* B5404DDD MiMo-V2-Pro & Omni & TTS ... https://www.reddit.com/...
|
|
76
|
+
5BE8FE3C Google 新聞 https://news.google.com/...
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- On first run, macOS may show an automation permission dialog — click Allow once.
|
|
80
|
+
- Only works on macOS; silently skipped on other platforms.
|
|
81
|
+
- Reflects the real Chrome foreground tab, updates on every `list` call.
|
|
82
|
+
- **Use this to quickly identify the target without manually matching URLs.**
|
|
83
|
+
|
|
84
|
+
## Windows
|
|
85
|
+
|
|
86
|
+
- Windows uses a **named pipe** per tab (`\\.\pipe\cdp-<targetId>`) instead of a Unix socket; runtime files live under `%LOCALAPPDATA%\cdp\`.
|
|
87
|
+
- Chrome may show an **"Allow debugging?"** popup once per tab daemon — click Allow once. If the daemon fails to start, the error message explicitly asks whether you clicked Allow in Chrome.
|
|
88
|
+
- Remote debugging must be enabled at `chrome://inspect/#remote-debugging` (Windows supported; `DevToolsActivePort` is discovered under `%LOCALAPPDATA%\<browser>\User Data\`).
|
|
89
|
+
|
|
90
|
+
## Coordinates
|
|
91
|
+
|
|
92
|
+
`shot` saves at native resolution: image pixels = CSS pixels × DPR. `clickxy` takes **CSS pixels**.
|
|
93
|
+
Use this conversion only if you already have a screenshot for visual debugging. Do not take a screenshot just to compute click coordinates.
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
CSS px = screenshot px / DPR
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Workflow
|
|
100
|
+
|
|
101
|
+
### Identify the right target quickly
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Run list — the * tab is what the user currently has open in Chrome
|
|
105
|
+
scripts/cdp.mjs list
|
|
106
|
+
# → use the * prefix directly as <target>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Click a JS-driven link (SPA / Google News / React apps)
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# 1. Get element center in CSS px via JS (no screenshot needed)
|
|
113
|
+
eval <target> "var el=document.querySelector('a[href*=\"keyword\"]'); var r=el.getBoundingClientRect(); ((r.left+r.right)/2)+','+((r.top+r.bottom)/2)"
|
|
114
|
+
# → "908,555"
|
|
115
|
+
|
|
116
|
+
# 2. Click using real mouse input
|
|
117
|
+
clickxy <target> 908 555
|
|
118
|
+
|
|
119
|
+
# 3a. Check if current tab navigated
|
|
120
|
+
eval <target> "window.location.href"
|
|
121
|
+
|
|
122
|
+
# 3b. Check if a new tab opened (compare before/after)
|
|
123
|
+
list
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Detect new tab after click
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Before click — note existing targetIds
|
|
130
|
+
list
|
|
131
|
+
# Click ...
|
|
132
|
+
# After click — new entry = new tab
|
|
133
|
+
list
|
|
134
|
+
# Inspect the new tab
|
|
135
|
+
eval <new-target-prefix> "window.location.href"
|
|
136
|
+
eval <new-target-prefix> "document.title"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Inspect page content efficiently
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Preferred: JS query (near-zero tokens)
|
|
143
|
+
eval <target> "document.title"
|
|
144
|
+
eval <target> "Array.from(document.querySelectorAll('a[href*=\"/news/\"]')).map(a=>a.innerText+' | '+a.href).join('\n')"
|
|
145
|
+
|
|
146
|
+
# Alternative: accessibility tree (compact, structured)
|
|
147
|
+
snap <target>
|
|
148
|
+
|
|
149
|
+
# Avoid: screenshot (only when visual layout truly needed)
|
|
150
|
+
shot <target>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Token Cost Guide
|
|
154
|
+
|
|
155
|
+
| Command | Relative cost | Use when |
|
|
156
|
+
|---------|--------------|----------|
|
|
157
|
+
| `eval` | Very low | Reading text, coords, URLs, DOM state |
|
|
158
|
+
| `snap` | Low–Medium | Need page structure overview |
|
|
159
|
+
| `html` | Medium | Need raw HTML of a section |
|
|
160
|
+
| `shot` | Very high | Visual debugging only (last resort) |
|
|
161
|
+
|
|
162
|
+
## Examples
|
|
163
|
+
|
|
164
|
+
| Example | Description |
|
|
165
|
+
|---------|-------------|
|
|
166
|
+
| [`examples/fetch-hook-api-capture.md`](examples/fetch-hook-api-capture.md) | Intercept SPA API responses by injecting a fetch/XHR hook via `eval` — covers inject → trigger → read → paginate workflow |
|
|
167
|
+
|
|
168
|
+
## Runtime Artifacts & Cleanup
|
|
169
|
+
|
|
170
|
+
- Each tab runs a per-tab daemon (holds the CDP session; auto-exits after 20 min idle or when the tab closes).
|
|
171
|
+
- `pages.json` cache + screenshots live in the runtime dir: `%LOCALAPPDATA%\cdp\` (Windows), `$XDG_RUNTIME_DIR/cdp` or `~/.cache/cdp` (Linux), `~/Library/Caches`-adjacent `~/.cache/cdp` (macOS).
|
|
172
|
+
- Stop daemons explicitly when done: `scripts/cdp.mjs stop` (all) or `scripts/cdp.mjs stop <target>` (one).
|
|
173
|
+
- Screenshots saved without an explicit path land in the runtime dir (`screenshot-<target>.png`) — delete them after use; they are local residual artifacts, not evidence for task verification.
|
|
174
|
+
|
|
175
|
+
## When NOT to use this skill
|
|
176
|
+
|
|
177
|
+
- Page content can be fetched statically (use `WebFetch` instead).
|
|
178
|
+
- User has not explicitly asked to interact with Chrome.
|
|
179
|
+
- A controlled Playwright/sessionless check is sufficient.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Fetch Hook — Intercept SPA API Responses
|
|
2
|
+
|
|
3
|
+
The CDP skill does not support `Network` domain event listening (`cdp.mjs` uses a request/response architecture and cannot receive push events like `Network.responseReceived`). Injecting a fetch hook via `eval` is the best alternative for capturing API data from SPA pages.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Page loads data via `fetch` / `XMLHttpRequest` from a backend API (SPA, Next.js, Convex, etc.)
|
|
8
|
+
- You need raw JSON responses rather than reverse-parsing from the DOM
|
|
9
|
+
- You need request parameters for replay or pagination
|
|
10
|
+
|
|
11
|
+
## Workflow
|
|
12
|
+
|
|
13
|
+
### Step 1: Inject Hook
|
|
14
|
+
|
|
15
|
+
Inject **after the page has finished loading**. The hook is lost on navigation/refresh, so it must be injected after `nav`.
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
scripts/cdp.mjs eval <target> "
|
|
19
|
+
window.__captured = [];
|
|
20
|
+
var _origFetch = window.fetch;
|
|
21
|
+
window.fetch = async function() {
|
|
22
|
+
var url = typeof arguments[0] === 'string' ? arguments[0] : (arguments[0] && arguments[0].url || '');
|
|
23
|
+
var opts = arguments[1] || {};
|
|
24
|
+
var reqBody = '';
|
|
25
|
+
if (opts.body) { try { reqBody = typeof opts.body === 'string' ? opts.body : JSON.stringify(opts.body); } catch(e) {} }
|
|
26
|
+
var resp = await _origFetch.apply(this, arguments);
|
|
27
|
+
try {
|
|
28
|
+
var clone = resp.clone();
|
|
29
|
+
var text = await clone.text();
|
|
30
|
+
window.__captured.push({ url: url, method: opts.method || 'GET', reqBody: reqBody, resBody: text, len: text.length });
|
|
31
|
+
} catch(e) {}
|
|
32
|
+
return resp;
|
|
33
|
+
};
|
|
34
|
+
'hook installed'
|
|
35
|
+
"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Key points:**
|
|
39
|
+
- Must `clone()` the response before reading the body — otherwise the original response stream is consumed and the page breaks
|
|
40
|
+
- Data is stored in `window.__captured` array, read later via `eval`
|
|
41
|
+
- The hook only captures requests made **after** injection — it cannot retroactively capture requests that already completed during page load
|
|
42
|
+
|
|
43
|
+
### Step 2: Trigger API Calls
|
|
44
|
+
|
|
45
|
+
After injecting the hook, interact with the page to trigger new API requests:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Option A: scroll to trigger infinite scroll
|
|
49
|
+
scripts/cdp.mjs eval <target> "window.scrollTo(0, document.body.scrollHeight); 'scrolled'"
|
|
50
|
+
|
|
51
|
+
# Option B: click a "Load More" button
|
|
52
|
+
scripts/cdp.mjs click <target> "button.load-more"
|
|
53
|
+
|
|
54
|
+
# Option C: change sort/filter to trigger a new request
|
|
55
|
+
scripts/cdp.mjs click <target> "select#sort-by"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Wait 1-2 seconds for requests to complete before reading.
|
|
59
|
+
|
|
60
|
+
### Step 3: Read Captured Data
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Overview of captured requests
|
|
64
|
+
scripts/cdp.mjs eval <target> "
|
|
65
|
+
var c = window.__captured || [];
|
|
66
|
+
'Captured: ' + c.length + ' requests\n' + c.map(function(r,i) {
|
|
67
|
+
return i + ': ' + r.method + ' ' + r.url.substring(0,80) + ' (' + r.len + ' bytes)';
|
|
68
|
+
}).join('\n');
|
|
69
|
+
"
|
|
70
|
+
|
|
71
|
+
# Read a specific response body (truncate to avoid token explosion)
|
|
72
|
+
scripts/cdp.mjs eval <target> "window.__captured[0].resBody.substring(0, 2000)"
|
|
73
|
+
|
|
74
|
+
# Read request parameters (to understand API format, pagination cursor, etc.)
|
|
75
|
+
scripts/cdp.mjs eval <target> "window.__captured[0].reqBody"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Step 4: Replay API with Pagination
|
|
79
|
+
|
|
80
|
+
Once you understand the API format, replay calls directly in the page context to fetch all data automatically:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
scripts/cdp.mjs eval <target> "
|
|
84
|
+
(async function() {
|
|
85
|
+
var allItems = [];
|
|
86
|
+
var cursor = null;
|
|
87
|
+
var hasMore = true;
|
|
88
|
+
while (hasMore) {
|
|
89
|
+
var resp = await fetch('https://example.com/api/query', {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: { 'Content-Type': 'application/json' },
|
|
92
|
+
body: JSON.stringify({
|
|
93
|
+
path: 'items:list',
|
|
94
|
+
args: [{ cursor: cursor, numItems: 100 }]
|
|
95
|
+
})
|
|
96
|
+
});
|
|
97
|
+
var data = await resp.json();
|
|
98
|
+
allItems = allItems.concat(data.value.page);
|
|
99
|
+
hasMore = data.value.hasMore;
|
|
100
|
+
cursor = data.value.nextCursor;
|
|
101
|
+
}
|
|
102
|
+
window.__allItems = allItems;
|
|
103
|
+
return 'Total: ' + allItems.length;
|
|
104
|
+
})()
|
|
105
|
+
"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Then read results in batches to avoid oversized output:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# Read first 50
|
|
112
|
+
scripts/cdp.mjs eval <target> "JSON.stringify(window.__allItems.slice(0, 50).map(function(it) { return { name: it.name, author: it.author }; }))"
|
|
113
|
+
|
|
114
|
+
# Read 50-100
|
|
115
|
+
scripts/cdp.mjs eval <target> "JSON.stringify(window.__allItems.slice(50, 100).map(function(it) { return { name: it.name, author: it.author }; }))"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Caveats
|
|
119
|
+
|
|
120
|
+
| Limitation | Details |
|
|
121
|
+
|------------|---------|
|
|
122
|
+
| **Lost on navigation** | `nav` / page refresh clears the hook and `window.__captured` — re-inject after each navigation |
|
|
123
|
+
| **fetch only** | Does not intercept `XMLHttpRequest` by default; see XHR hook below if needed |
|
|
124
|
+
| **Memory growth** | `__captured` array grows indefinitely during long sessions — periodically clear with `window.__captured = []` |
|
|
125
|
+
| **CORS** | Step 4 API replay runs in the page's origin context and is subject to same-origin policy; this is fine if the original request was made by the page itself |
|
|
126
|
+
| **Large responses** | Returning large data via `eval` is token-expensive — use `.substring()` to truncate or `.map()` to extract only the fields you need |
|
|
127
|
+
|
|
128
|
+
## XMLHttpRequest Hook (Optional)
|
|
129
|
+
|
|
130
|
+
If the page uses `XMLHttpRequest` instead of `fetch`:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
scripts/cdp.mjs eval <target> "
|
|
134
|
+
var _origOpen = XMLHttpRequest.prototype.open;
|
|
135
|
+
var _origSend = XMLHttpRequest.prototype.send;
|
|
136
|
+
XMLHttpRequest.prototype.open = function(method, url) {
|
|
137
|
+
this.__method = method;
|
|
138
|
+
this.__url = url;
|
|
139
|
+
return _origOpen.apply(this, arguments);
|
|
140
|
+
};
|
|
141
|
+
XMLHttpRequest.prototype.send = function(body) {
|
|
142
|
+
this.addEventListener('load', function() {
|
|
143
|
+
window.__captured.push({ url: this.__url, method: this.__method, reqBody: body || '', resBody: this.responseText, len: this.responseText.length });
|
|
144
|
+
});
|
|
145
|
+
return _origSend.apply(this, arguments);
|
|
146
|
+
};
|
|
147
|
+
'xhr hook installed'
|
|
148
|
+
"
|
|
149
|
+
```
|