@ainyc/canonry 4.30.0 → 4.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +15 -13
  2. package/assets/agent-workspace/skills/aero/SKILL.md +2 -2
  3. package/assets/agent-workspace/skills/aero/references/aeo-discovery.md +26 -17
  4. package/assets/agent-workspace/skills/aero/references/memory-patterns.md +9 -9
  5. package/assets/agent-workspace/skills/aero/references/orchestration.md +6 -6
  6. package/assets/agent-workspace/skills/aero/references/reporting.md +3 -3
  7. package/assets/agent-workspace/skills/canonry/SKILL.md +5 -3
  8. package/assets/agent-workspace/skills/canonry/references/aeo-analysis.md +9 -9
  9. package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +203 -200
  10. package/assets/agent-workspace/skills/canonry/references/indexing.md +35 -35
  11. package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +18 -18
  12. package/assets/agent-workspace/skills/canonry/references/wordpress-integration.md +11 -11
  13. package/assets/assets/{index-BnALDZI7.css → index-CNKAwZMB.css} +1 -1
  14. package/assets/assets/index-CUMjedc6.js +302 -0
  15. package/assets/index.html +2 -2
  16. package/dist/{chunk-7UO3EGDB.js → chunk-5M4PP6P4.js} +25 -2
  17. package/dist/{chunk-PTFVEYUX.js → chunk-7I65IXVU.js} +617 -23
  18. package/dist/{chunk-4EDC2P3J.js → chunk-LUAJVZVZ.js} +1 -1
  19. package/dist/{chunk-NIAAHWRF.js → chunk-LVX5TOYA.js} +28 -3
  20. package/dist/cli.js +166 -15
  21. package/dist/index.d.ts +20 -0
  22. package/dist/index.js +4 -4
  23. package/dist/{intelligence-service-ASXADXLF.js → intelligence-service-RSRWDBHS.js} +2 -2
  24. package/dist/mcp.js +2 -2
  25. package/package.json +8 -7
  26. package/assets/assets/index-BYiZYtd9.js +0 -302
package/README.md CHANGED
@@ -8,9 +8,9 @@
8
8
  - Watch AI engines crawl and refer traffic via [server-log ingestion](skills/canonry/references/server-side-traffic.md) — Cloud Run logs and the WordPress Traffic Logger plugin today
9
9
  - Diagnose against real traffic with built-in [GSC](docs/google-search-console-setup.md), [GA4](docs/google-analytics-setup.md), and [Bing Webmaster](docs/bing-webmaster-setup.md)
10
10
  - Execute fixes via [WordPress](docs/wordpress-setup.md), JSON-LD schema, and indexing submissions
11
- - Manage many clients declaratively — config-as-code YAML + `canonry apply`
11
+ - Manage many clients declaratively — config-as-code YAML + `cnry apply`
12
12
  - Schedule recurring visibility checks AND traffic syncs, with webhook alerts on regressions
13
- - Generate client-ready HTML reports — `canonry report <project>`
13
+ - Generate client-ready HTML reports — `cnry report <project>`
14
14
  - Drive from your own agent via the [67-tool MCP adapter](docs/mcp.md) or webhooks
15
15
  - Or use **Aero** — Canonry's built-in agent that wakes up after every run
16
16
 
@@ -22,28 +22,30 @@ Every dashboard view has a matching CLI command and API endpoint. The CLI is the
22
22
 
23
23
  ```bash
24
24
  npm install -g @ainyc/canonry
25
- canonry init
26
- canonry serve
25
+ cnry init
26
+ cnry serve
27
27
  ```
28
28
 
29
+ The CLI installs as `cnry` (short form) and `canonry` — the two are interchangeable.
30
+
29
31
  Open [http://localhost:4100/setup](http://localhost:4100/setup). A guided wizard walks you through provider keys, project setup, queries, and your first visibility check.
30
32
 
31
33
  Prefer the terminal?
32
34
 
33
35
  ```bash
34
- canonry project create my-site --domain example.com
35
- canonry query add my-site "your first query" "second query"
36
- canonry run my-site --wait
37
- canonry evidence my-site
38
- canonry insights my-site
36
+ cnry project create my-site --domain example.com
37
+ cnry query add my-site "your first query" "second query"
38
+ cnry run my-site --wait
39
+ cnry evidence my-site
40
+ cnry insights my-site
39
41
  ```
40
42
 
41
43
  ## If you get stuck
42
44
 
43
45
  | Problem | Fix |
44
46
  |---------|-----|
45
- | No provider key configured | Grab a free [Gemini key](https://aistudio.google.com/apikey), set `GEMINI_API_KEY`, restart `canonry serve`. |
46
- | No results after a run | Visibility checks are async — check the Runs tab or use `canonry run <project> --wait`. |
47
+ | No provider key configured | Grab a free [Gemini key](https://aistudio.google.com/apikey), set `GEMINI_API_KEY`, restart `cnry serve`. |
48
+ | No results after a run | Visibility checks are async — check the Runs tab or use `cnry run <project> --wait`. |
47
49
  | Not sure what queries to test | The setup wizard auto-generates them by analyzing your site. |
48
50
  | `npm install` fails on `node-gyp` | Install build tools for `better-sqlite3` ([guide](https://github.com/WiseLibs/better-sqlite3/blob/master/docs/troubleshooting.md)). |
49
51
 
@@ -57,7 +59,7 @@ canonry insights my-site
57
59
  | Perplexity | [perplexity.ai/settings/api](https://www.perplexity.ai/settings/api) | `PERPLEXITY_API_KEY` |
58
60
  | Local LLMs | Any OpenAI-compatible endpoint | `LOCAL_LLM_URL` |
59
61
 
60
- Configure during `canonry init`, in the dashboard `/settings`, or as env vars.
62
+ Configure during `cnry init`, in the dashboard `/settings`, or as env vars.
61
63
 
62
64
  ## Documentation
63
65
 
@@ -69,7 +71,7 @@ Configure during `canonry init`, in the dashboard `/settings`, or as env vars.
69
71
  | **Integrations** | [GSC](docs/google-search-console-setup.md) · [GA4](docs/google-analytics-setup.md) · [Bing](docs/bing-webmaster-setup.md) · [WordPress](docs/wordpress-setup.md) · [Server-side traffic (Cloud Run + WordPress logs)](skills/canonry/references/server-side-traffic.md) |
70
72
  | **Deployment** — Docker, Railway, Render, systemd, Tailscale | [docs/deployment.md](docs/deployment.md) |
71
73
  | **API** — 118+ endpoints | `GET /api/v1/openapi.json` (no auth) |
72
- | **Skills bundle** for Claude Code / Codex | `canonry skills install` ([details](skills/canonry/SKILL.md)) |
74
+ | **Skills bundle** for Claude Code / Codex | `cnry skills install` ([details](skills/canonry/SKILL.md)) |
73
75
  | **Roadmap & ADRs** | [docs/roadmap.md](docs/roadmap.md) · [docs/adr/](docs/adr/) |
74
76
  | **All docs** | [docs/README.md](docs/README.md) |
75
77
 
@@ -9,12 +9,12 @@ repository: https://github.com/AINYC/aero
9
9
  # Aero Orchestration Skill
10
10
 
11
11
  You coordinate across two tools to deliver comprehensive AEO monitoring:
12
- - **canonry** — the source of truth for project state (runs, snapshots, timelines, insights, audit log, **GA4 traffic + AI/social referrals**). Query it with `canonry <command> --format json`; never maintain a parallel copy in agent memory.
12
+ - **canonry** — the source of truth for project state (runs, snapshots, timelines, insights, audit log, **GA4 traffic + AI/social referrals**). Query it with `cnry <command> --format json` (the CLI is also installed as `canonry` — the two are interchangeable); never maintain a parallel copy in agent memory.
13
13
  - **aeo-audit** — on-demand site analysis and fix generation.
14
14
 
15
15
  Persist only *user-scoped* context (operator preferences, communication style) in your platform's native memory. Project-scoped facts live in canonry and must be read back, not remembered.
16
16
 
17
- When a project has GA4 connected, traffic is a first-class signal alongside citations. Use `canonry ga traffic` / `canonry ga attribution --trend` for the current snapshot, `canonry ga ai-referral-history` and `canonry ga social-referral-history` for daily series. Reads query a local DB synced by `canonry ga sync` — confirm `canonry ga status` shows a recent `lastSyncedAt` before quoting numbers; if stale, re-sync first. Full command reference and return shapes live in the co-installed `canonry/references/canonry-cli.md` (look for the "Google Analytics 4" section).
17
+ When a project has GA4 connected, traffic is a first-class signal alongside citations. Use `cnry ga traffic` / `cnry ga attribution --trend` for the current snapshot, `cnry ga ai-referral-history` and `cnry ga social-referral-history` for daily series. Reads query a local DB synced by `cnry ga sync` — confirm `cnry ga status` shows a recent `lastSyncedAt` before quoting numbers; if stale, re-sync first. Full command reference and return shapes live in the co-installed `canonry/references/canonry-cli.md` (look for the "Google Analytics 4" section).
18
18
 
19
19
  ## Judgment Rules
20
20
 
@@ -11,7 +11,15 @@ Discovery turns a free-text ICP description into a deduped basket of representat
11
11
  - **wasted-surface** — a tracked competitor is cited but the project is not
12
12
  - **aspirational** — neither the project nor a tracked competitor is cited (greenfield)
13
13
 
14
- Plus a competitor map: every non-canonical domain that shows up in probe citations, ranked by hit count, so the operator can spot recurring competitors that aren't yet on the watchlist.
14
+ Plus a competitor map: every non-canonical domain that shows up in probe citations, ranked by hit count and classified by type, so the operator can spot recurring competitors that aren't yet on the watchlist.
15
+
16
+ After probing, one Gemini call classifies every recurring cited domain into a `competitorType`:
17
+
18
+ - **direct-competitor** — a business competing for the same customers (another hotel, another tool in the category). The only type promoted by default.
19
+ - **ota-aggregator** — OTAs, marketplaces, directories, review aggregators (expedia.com, booking.com, g2.com). Suppressed from competitor tracking.
20
+ - **editorial-media** — news, blogs, "best of" round-ups (timeout.com, a personal blog). A *channel* to earn placement in, not a competitor — suppressed by default.
21
+ - **other** — government sites, social platforms, off-topic domains. Suppressed.
22
+ - **unknown** — classification failed, or a session that pre-dates classification. Excluded from the default promote.
15
23
 
16
24
  ## When discovery is the right move
17
25
 
@@ -24,7 +32,7 @@ Plus a competitor map: every non-canonical domain that shows up in probe citatio
24
32
  The operator runs:
25
33
 
26
34
  ```bash
27
- canonry discover run <project> --icp "..." --wait
35
+ cnry discover run <project> --icp "..." --wait
28
36
  ```
29
37
 
30
38
  Or the MCP equivalent: `canonry_discover_run_start` with `{ project, request: { icpDescription, dedupThreshold?, maxProbes? } }`. The endpoint returns `{ runId, sessionId, status: "running" }` immediately and finishes the work in the background. Poll `canonry_discover_session_get` until `status` is `completed` or `failed`.
@@ -39,13 +47,13 @@ Per session: ~$1 at the default probe budget (100 queries × 1 Gemini grounded c
39
47
 
40
48
  `canonry_discover_session_get` returns:
41
49
 
42
- - Session-level: `seedCountRaw` vs `seedCount` (proves embedding dedup did real work), bucket counts, `competitorMap` (top recurring non-tracked domains).
50
+ - Session-level: `seedCountRaw` vs `seedCount` (proves embedding dedup did real work), bucket counts, `competitorMap` (top recurring non-tracked domains, each with `hits` and `competitorType`).
43
51
  - Per-probe: query, bucket, citation state, the cited domains list.
44
52
 
45
53
  Things to call out without being asked:
46
54
 
47
55
  - **High wasted-surface ratio** (≥ 40% of probes, or > cited count at ≥ 20%) → the project is missing from its own competitive space. The auto-written `discovery.basket-divergence` insight flags this as `high` severity.
48
- - **Recurring new competitor domains** in `competitorMap` that aren't already in the project's tracked competitor list → `canonry discover promote` adopts domains with at least 2 hits automatically alongside the queries; or add them à la carte with `canonry competitor add <project> <domain>`.
56
+ - **Recurring `direct-competitor` domains** in `competitorMap` that aren't already in the project's tracked competitor list → `cnry discover promote` adopts `direct-competitor` domains with at least 2 hits automatically alongside the queries; or add them à la carte with `cnry competitor add <project> <domain>`. Domains classified `ota-aggregator` / `editorial-media` / `other` are surfaced but **not** promoted by default — flag a recurring `editorial-media` site as a placement opportunity, not a competitor.
49
57
  - **Aspirational greenfield** queries with no tracked competitor and no canonical cite → low-friction content opportunities.
50
58
 
51
59
  ## Promoting a session into the tracked basket
@@ -53,7 +61,7 @@ Things to call out without being asked:
53
61
  Once a session is `completed`, preview first unless the operator has already approved the write:
54
62
 
55
63
  ```bash
56
- canonry discover promote preview <project> <session-id>
64
+ cnry discover promote preview <project> <session-id>
57
65
  ```
58
66
 
59
67
  Or the MCP equivalent: `canonry_discover_promote_preview` with `{ project, sessionId }`.
@@ -63,15 +71,16 @@ The preview returns every bucket so you can explain the tradeoff:
63
71
  - `cited` — already grounded to the project, safe to track.
64
72
  - `aspirational` — greenfield ICP-fit opportunities, safe to track as a growth basket.
65
73
  - `wasted-surface` — competitor-cited but project-missing. Treat as content-planning evidence first; do not add it to the weekly tracked basket unless the operator explicitly wants those off-ICP competitor gaps tracked.
66
- - `suggestedCompetitors` — recurring domains not already tracked. The promote path only auto-adopts domains with at least 2 hits.
74
+ - `suggestedCompetitors` — recurring domains (≥ 2 hits) not already tracked, of **every** classified type, each tagged with `competitorType`. The default promote adopts only the `direct-competitor` ones; the others are shown so you can recommend a `--competitor-types` widening.
67
75
 
68
76
  Promote with one of these paths:
69
77
 
70
78
  ```bash
71
- canonry discover promote <project> <session-id> # cited + aspirational buckets + recurring competitor domains
72
- canonry discover promote <project> <session-id> --bucket aspirational # scope to a bucket subset (repeatable / comma-separated)
73
- canonry discover promote <project> <session-id> --bucket wasted-surface # explicitly track off-ICP competitor gaps
74
- canonry discover promote <project> <session-id> --no-competitors # queries only, skip the competitor merge
79
+ cnry discover promote <project> <session-id> # cited + aspirational buckets + direct-competitor domains
80
+ cnry discover promote <project> <session-id> --bucket aspirational # scope to a bucket subset (repeatable / comma-separated)
81
+ cnry discover promote <project> <session-id> --bucket wasted-surface # explicitly track off-ICP competitor gaps
82
+ cnry discover promote <project> <session-id> --competitor-types direct-competitor,editorial-media # widen the competitor merge to other classified types
83
+ cnry discover promote <project> <session-id> --no-competitors # queries only, skip the competitor merge
75
84
  ```
76
85
 
77
86
  Or the MCP equivalent:
@@ -80,14 +89,14 @@ Or the MCP equivalent:
80
89
  { "project": "<project>", "sessionId": "<session-id>" }
81
90
  ```
82
91
 
83
- That default request promotes `cited` + `aspirational` queries and recurring competitors. For scoped writes, pass `request`:
92
+ That default request promotes `cited` + `aspirational` queries and `direct-competitor` domains. For scoped writes, pass `request`:
84
93
 
85
94
  ```json
86
- { "project": "<project>", "sessionId": "<session-id>", "request": { "buckets": ["aspirational"], "includeCompetitors": false } }
95
+ { "project": "<project>", "sessionId": "<session-id>", "request": { "buckets": ["aspirational"], "competitorTypes": ["direct-competitor", "editorial-media"], "includeCompetitors": false } }
87
96
  ```
88
97
 
89
98
  - **Default is cited + aspirational.** `wasted-surface` queries are off-ICP competitor gaps; promote them only when the operator explicitly wants those tracked in the weekly basket.
90
- - **Competitor promotion requires recurrence.** Default competitor merge ignores one-off domains and adopts only domains with at least 2 hits.
99
+ - **Competitor promotion requires recurrence + a promotable type.** The default competitor merge ignores one-off domains (< 2 hits) and adopts only domains classified `direct-competitor`. Pass `competitorTypes` (CLI: `--competitor-types`) to also adopt `editorial-media` channels, or `competitorTypes: ["unknown"]` to recover a legacy session promoted before classification existed.
91
100
  - **Add-only and idempotent.** Queries and competitor domains already tracked are returned under `skipped`, never inserted twice. Re-running a promote is safe.
92
101
  - **Completed sessions only.** Promoting a `queued`/`seeding`/`probing`/`failed` session is rejected — the buckets aren't final.
93
102
  - Promoted rows carry `provenance="discovery:<sessionId>"`, so a tracked query can always be traced back to the session that surfaced it.
@@ -106,8 +115,8 @@ Respond with:
106
115
 
107
116
  1. A one-line headline naming the dominant bucket.
108
117
  2. The top 2-3 wasted-surface queries (call `canonry_discover_session_get` to fetch them — don't guess).
109
- 3. The top 1-2 recurring new competitor domains worth tracking, ignoring one-hit domains unless the operator asks for the full long tail.
110
- 4. A single recommended next step. Examples: "preview and promote cited + aspirational findings (`canonry discover promote preview`, then `canonry discover promote`)", "the wasted-surface set warrants a content plan around X before tracking", "the aspirational set is greenfield — pick the 3 with highest commercial intent and write content".
118
+ 3. The top 1-2 recurring `direct-competitor` domains worth tracking, ignoring one-hit domains unless the operator asks for the full long tail. If a recurring `editorial-media` domain stands out, mention it separately as a placement opportunity — not a competitor.
119
+ 4. A single recommended next step. Examples: "preview and promote cited + aspirational findings (`cnry discover promote preview`, then `cnry discover promote`)", "the wasted-surface set warrants a content plan around X before tracking", "the aspirational set is greenfield — pick the 3 with highest commercial intent and write content".
111
120
 
112
121
  Do not recommend "promote everything" as the default. The safe path is: inspect session detail, preview promotion candidates, then promote the default cited + aspirational set. Escalate `wasted-surface` to tracking only when the operator deliberately chooses that tradeoff.
113
122
 
@@ -120,7 +129,7 @@ Keep it tight. The operator wakes to a short, decision-ready summary, not a full
120
129
 
121
130
  ## Failure modes
122
131
 
123
- - **Gemini not configured** → orchestrator throws early; `runs.status='failed'` with `Gemini provider is not configured.` Surface as "configure Gemini before running discovery" — link to `canonry init` or `~/.canonry/config.yaml`.
132
+ - **Gemini not configured** → orchestrator throws early; `runs.status='failed'` with `Gemini provider is not configured.` Surface as "configure Gemini before running discovery" — link to `cnry init` or `~/.canonry/config.yaml`.
124
133
  - **Vertex-only Gemini** → embeddings step throws (Vertex embeddings deferred). Same surface, "use a Gemini API key for now."
125
134
  - **ICP missing** → route returns 400 with `VALIDATION_ERROR`. Ask the operator for the ICP description in plain language.
126
135
  - **Seed collapse (hyperlocal/niche businesses)** → 40 raw seeds collapse to 1-2 canonical queries after embedding+clustering, even at low dedup thresholds. This happens when Gemini generates seed queries that all live in the same semantic pocket (e.g. all variants of "boutique hotel Venice Beach"). The embedding model sees them as near-identical, so clustering produces one representative.
@@ -130,7 +139,7 @@ Keep it tight. The operator wakes to a short, decision-ready summary, not a full
130
139
  **Remediation:** break the ICP into 3-5 distinct purchase-intent angles and run one session per angle via `--icp-angle`:
131
140
 
132
141
  ```bash
133
- canonry discover run <project> \
142
+ cnry discover run <project> \
134
143
  --icp-angle "romantic anniversary stay in Venice Beach" \
135
144
  --icp-angle "best rooftop bars and dining hotels LA" \
136
145
  --icp-angle "walkable Venice Beach hotels near Abbot Kinney" \
@@ -22,12 +22,12 @@ Aero ships with a built-in durable notes store — the `canonry_memory_set`, `ca
22
22
  Prefer Aero's read tools (`canonry_project_overview`, `canonry_health_latest`, `canonry_timeline_get`, `canonry_insights_list`, `canonry_queries_list`, `canonry_competitors_list`, `canonry_run_get`) over shelling out, but the CLI exists for operators too:
23
23
 
24
24
  ```bash
25
- canonry status <project> --format json
26
- canonry health <project> --format json
27
- canonry timeline <project> --since <YYYY-MM-DD> --format json
28
- canonry insights <project> --format json
29
- canonry evidence <project> --format json
30
- canonry audit <project> --format json
25
+ cnry status <project> --format json
26
+ cnry health <project> --format json
27
+ cnry timeline <project> --since <YYYY-MM-DD> --format json
28
+ cnry insights <project> --format json
29
+ cnry evidence <project> --format json
30
+ cnry audit <project> --format json
31
31
  ```
32
32
 
33
33
  If the data you need isn't reachable with a single read tool or CLI call, that's a bug in canonry's API surface — file it rather than working around it in memory.
@@ -47,9 +47,9 @@ Derived interpretations (trend summaries, correlations between events) are cheap
47
47
  **CLI parity.** Operators can manage memory without talking to you:
48
48
 
49
49
  ```bash
50
- canonry agent memory list <project> --format json
51
- canonry agent memory set <project> --key <k> --value <v>
52
- canonry agent memory forget <project> --key <k>
50
+ cnry agent memory list <project> --format json
51
+ cnry agent memory set <project> --key <k> --value <v>
52
+ cnry agent memory forget <project> --key <k>
53
53
  ```
54
54
 
55
55
  ## Good remember candidates
@@ -10,7 +10,7 @@ description: Workflow recipes — baseline, regression response, weekly review,
10
10
  Trigger: First sweep completes for a new project
11
11
 
12
12
  Steps:
13
- 1. `canonry evidence <project> --format json` → get initial citation data
13
+ 1. `cnry evidence <project> --format json` → get initial citation data
14
14
  2. Compute baseline: cited rate, provider breakdown, top/bottom queries
15
15
  3. `npx @ainyc/aeo-audit "<domain>" --format json` → site readiness score
16
16
  4. Identify top 3 gaps (uncited queries with fixable site issues)
@@ -22,9 +22,9 @@ Steps:
22
22
  Trigger: Comparison shows decline or webhook fires regression.detected
23
23
 
24
24
  Steps:
25
- 1. `canonry evidence <project> --format json` → current state
26
- 2. `canonry history <project>` → trend for affected query
27
- 3. Check indexing: `canonry google coverage <project>` → is the page still indexed?
25
+ 1. `cnry evidence <project> --format json` → current state
26
+ 2. `cnry history <project>` → trend for affected query
27
+ 3. Check indexing: `cnry google coverage <project>` → is the page still indexed?
28
28
  4. Check competitor: did a competitor gain the citation we lost?
29
29
  5. Audit the page: `npx @ainyc/aeo-audit "<page-url>" --format json`
30
30
  6. Diagnose cause: indexing issue / content issue / competitive displacement
@@ -37,7 +37,7 @@ Steps:
37
37
  Trigger: Scheduled (weekly, or on-demand)
38
38
 
39
39
  Steps:
40
- 1. `canonry evidence <project> --format json` → current metrics
40
+ 1. `cnry evidence <project> --format json` → current metrics
41
41
  2. Compare to baseline/prior week from memory
42
42
  3. Compute deltas: citations gained, lost, stable
43
43
  4. Flag any new regressions not yet addressed
@@ -49,7 +49,7 @@ Steps:
49
49
  Trigger: User asks "why aren't we cited for X?" or multiple uncited queries detected
50
50
 
51
51
  Steps:
52
- 1. `canonry evidence <project>` → confirm uncited
52
+ 1. `cnry evidence <project>` → confirm uncited
53
53
  2. Check if a relevant page exists on the domain
54
54
  3. If no page: recommend content creation (topic, target queries)
55
55
  4. If page exists: `npx @ainyc/aeo-audit "<page-url>"` → diagnose why uncited
@@ -10,9 +10,9 @@ description: Weekly and monthly report templates with metric tables, regression/
10
10
  When a client asks for a "current state" or "AEO report" without a specific custom narrative, prefer the bundled report instead of hand-rolling sections:
11
11
 
12
12
  ```bash
13
- canonry report <project> # writes canonry-report-<project>-YYYY-MM-DD.html in cwd
14
- canonry report <project> --output dist/aeo.html # custom path
15
- canonry report <project> --format json # raw payload, useful for narrating in chat
13
+ cnry report <project> # writes canonry-report-<project>-YYYY-MM-DD.html in cwd
14
+ cnry report <project> --output dist/aeo.html # custom path
15
+ cnry report <project> --format json # raw payload, useful for narrating in chat
16
16
  ```
17
17
 
18
18
  The HTML is self-contained (inline CSS + SVG charts, no network dependencies) and covers: executive summary, per-query × per-provider citation matrix, competitor landscape, AI citation sources, GSC + GA4 performance, social and AI referrals, indexing health, citations trend, prioritized insights, and recommended next steps. Same payload is available via `GET /api/v1/projects/<name>/report` and the `canonry_report` MCP tool — use `--format json` when you want to summarize specific numbers in a thread instead of attaching the file.
@@ -36,6 +36,8 @@ Agent-first open-source AEO (Answer Engine Optimization) operating platform. Tra
36
36
 
37
37
  **Website:** [ainyc.ai](https://ainyc.ai) | **Docs:** [github.com/AINYC/canonry](https://github.com/AINYC/canonry)
38
38
 
39
+ **CLI:** invoke as `cnry` (short form) or `canonry` — both ship with the npm package and are interchangeable. Examples in this skill use `cnry`.
40
+
39
41
  ## When to Use
40
42
 
41
43
  - Tracking query citations across AI providers
@@ -56,11 +58,11 @@ Agent-first open-source AEO (Answer Engine Optimization) operating platform. Tra
56
58
 
57
59
  A canonry engagement follows the same loop regardless of project size:
58
60
 
59
- 1. **Diagnose** — Run a baseline sweep (`canonry run <project> --wait`) and a technical audit (`npx @ainyc/aeo-audit@latest <url> --format json`). See `references/aeo-analysis.md` for interpretation.
61
+ 1. **Diagnose** — Run a baseline sweep (`cnry run <project> --wait`) and a technical audit (`npx @ainyc/aeo-audit@latest <url> --format json`). See `references/aeo-analysis.md` for interpretation.
60
62
  2. **Prioritize** — Triage by impact: indexing gaps → schema gaps → content gaps → query strategy. Branded-term losses are urgent.
61
63
  3. **Execute** — Apply fixes via the canonry CLI or platform integrations. See `references/canonry-cli.md` for the full command catalog and `references/wordpress-integration.md` for the WordPress workflow.
62
64
  4. **Monitor** — Re-run sweeps weekly. Correlate visibility shifts with deployments and competitor moves.
63
- 5. **Report** — Lead with data, not interpretation: "Lost `<query>` on Gemini between <date> and <date> — two competitors moved in. Here's what to fix." For a one-command client-facing summary, run `canonry report <project>` to generate a self-contained HTML bundle (executive summary, citation scorecard, competitor landscape, GSC + GA4 performance, insights). Same payload is available via `--format json` and the `canonry_report` MCP tool.
65
+ 5. **Report** — Lead with data, not interpretation: "Lost `<query>` on Gemini between <date> and <date> — two competitors moved in. Here's what to fix." For a one-command client-facing summary, run `cnry report <project>` to generate a self-contained HTML bundle (executive summary, citation scorecard, competitor landscape, GSC + GA4 performance, insights). Same payload is available via `--format json` and the `canonry_report` MCP tool.
64
66
 
65
67
  ## Common Starting Points
66
68
 
@@ -70,7 +72,7 @@ A canonry engagement follows the same loop regardless of project size:
70
72
 
71
73
  ## Google Analytics 4
72
74
 
73
- GA4 is a first-class signal alongside citation tracking. Connect once with `canonry ga connect <project> --property-id <id> --key-file <path>`; `canonry ga sync` then pulls daily landing-page traffic, AI-referral sessions across 10 known providers (chatgpt, perplexity, claude, gemini, openai, anthropic, copilot, phind, you.com, meta.ai), and social referrals split into Organic vs Paid via GA4's `channelGroup` — and persists everything into four DB tables (`gaTrafficSnapshots`, `gaAiReferrals`, `gaSocialReferrals`, `gaTrafficSummaries`). All read commands query that local store, so they are fast and quotaless once a sync has run. AI referrals are tracked across three GA4 attribution dimensions (session source / first-user source / manual UTM) and joined to landing pages, so you can see which page each AI provider sent traffic to. Use `canonry ga traffic` for the current snapshot, `canonry ga attribution --trend` for a unified channel-share overview with biggest-mover deltas, and `canonry ga ai-referral-history` / `canonry ga social-referral-history` for daily series. See `references/canonry-cli.md` for the full command catalog and return-shape details.
75
+ GA4 is a first-class signal alongside citation tracking. Connect once with `cnry ga connect <project> --property-id <id> --key-file <path>`; `cnry ga sync` then pulls daily landing-page traffic, AI-referral sessions across 10 known providers (chatgpt, perplexity, claude, gemini, openai, anthropic, copilot, phind, you.com, meta.ai), and social referrals split into Organic vs Paid via GA4's `channelGroup` — and persists everything into four DB tables (`gaTrafficSnapshots`, `gaAiReferrals`, `gaSocialReferrals`, `gaTrafficSummaries`). All read commands query that local store, so they are fast and quotaless once a sync has run. AI referrals are tracked across three GA4 attribution dimensions (session source / first-user source / manual UTM) and joined to landing pages, so you can see which page each AI provider sent traffic to. Use `cnry ga traffic` for the current snapshot, `cnry ga attribution --trend` for a unified channel-share overview with biggest-mover deltas, and `cnry ga ai-referral-history` / `cnry ga social-referral-history` for daily series. See `references/canonry-cli.md` for the full command catalog and return-shape details.
74
76
 
75
77
  ## Boundaries & Safety
76
78
 
@@ -57,7 +57,7 @@ Shows which source categories AI models cite for your queries. Helps identify:
57
57
  ### Step 1: Check indexing first
58
58
  Not cited ≠ bad content. Often the page isn't indexed yet.
59
59
  ```bash
60
- canonry google coverage <project>
60
+ cnry google coverage <project>
61
61
  ```
62
62
  If key pages are "unknown to Google," submit them before drawing conclusions.
63
63
 
@@ -70,28 +70,28 @@ For competitive queries, if others are cited and the client isn't:
70
70
  - Do they have stronger schema/structured data?
71
71
  - Are they more established in the index?
72
72
 
73
- Run `canonry evidence <project> --format json` and check `competitorOverlap` in snapshots.
73
+ Run `cnry evidence <project> --format json` and check `competitorOverlap` in snapshots.
74
74
 
75
75
  ### Step 4: Check across providers
76
76
  Gemini, OpenAI, Claude, and Perplexity may behave differently. One citing a domain while another doesn't is normal — each has its own knowledge base and update schedule.
77
77
 
78
78
  ### Step 5: Check analytics trends
79
79
  ```bash
80
- canonry analytics <project> --feature gaps --window 30d
80
+ cnry analytics <project> --feature gaps --window 30d
81
81
  ```
82
82
  Look for patterns: are gaps growing or shrinking? Are new competitors appearing?
83
83
 
84
84
  ### Step 6: Check GA4 traffic for impact
85
85
  A lost citation isn't always a lost user. Before declaring a regression real, confirm whether AI-referral traffic actually fell on the same window:
86
86
  ```bash
87
- canonry ga status <project> # confirm lastSyncedAt is recent; re-sync if stale
88
- canonry ga ai-referral-history <project> --format json
87
+ cnry ga status <project> # confirm lastSyncedAt is recent; re-sync if stale
88
+ cnry ga ai-referral-history <project> --format json
89
89
  # daily {date, source, medium, attribution, sessions, users}
90
- canonry ga attribution <project> --trend # 7d/30d direction per channel + biggest mover
90
+ cnry ga attribution <project> --trend # 7d/30d direction per channel + biggest mover
91
91
  ```
92
92
  Read the result against the citation loss window:
93
93
  - **AI sessions flat or up** → the citation loss may be sweep-side noise (provider variance, query refresh). Track for one more cycle before alarming the client.
94
- - **AI sessions dropped on the same date** → real outage; escalate. Cross-reference `aiReferrals[]` from `canonry ga traffic` to identify which provider lost traffic.
94
+ - **AI sessions dropped on the same date** → real outage; escalate. Cross-reference `aiReferrals[]` from `cnry ga traffic` to identify which provider lost traffic.
95
95
  - **Organic dropped but AI held** → the citation loss is masking a separate indexing issue. Re-run Step 1.
96
96
 
97
97
  GA4 also covers the inverse case: a *gain* on `attribution --trend` for the AI channel that isn't reflected in citation count usually means a provider expanded an existing citation's exposure (more queries triggering it) — a quiet win worth flagging in the next report.
@@ -106,14 +106,14 @@ GA4 also covers the inverse case: a *gain* on `attribution --trend` for the AI c
106
106
  - Did a competitor page launch?
107
107
  - Did the page get deindexed or go down?
108
108
  - Did the model update?
109
- - Check `canonry google deindexed <project>` for index losses
109
+ - Check `cnry google deindexed <project>` for index losses
110
110
 
111
111
  **Fluctuation** (cited in some runs, not others) — normal for competitive queries. Track trend over 5+ runs before drawing conclusions. AI answers are non-deterministic.
112
112
 
113
113
  ## What to Recommend
114
114
 
115
115
  ### Low overall citation (< 50%)
116
- 1. Audit indexing — `canonry google coverage <project>`
116
+ 1. Audit indexing — `cnry google coverage <project>`
117
117
  2. Submit unindexed pages to Google Indexing API
118
118
  3. Submit sitemap to Bing WMT + send IndexNow batch
119
119
  4. Check core pages for schema (LocalBusiness / Organization / FAQPage)