Nothing else. Alkeyword reads the site, mines the questions people actually ask, measures what AI engines say back β and hands you research briefs built from your own claims. You write. It does everything before that.
Runs on your machine, on your Claude subscription. The crawl is plain Python and costs nothing. Every panel on this page is real output β you can regenerate all of it from the download.
Stage 1 output, verbatim, from a real crawl of a live site. Deterministic Python β no model was called to produce any of it.
Alchemy transmutes existing material. It does not conjure from nothing β and neither does this. That single constraint is what the whole tool is built around, and it is why this page can be made of real output instead of screenshots of a demo.
Guesses your niche and writes net-new articles about it. That is why the output is generic, why it gets facts about your business wrong, and why it trips Google's scaled-content-abuse detection.
Does the research and stops. Every number, price, process and quote your site already publishes, matched to the questions people really ask β handed to you as a brief. Nothing is invented, because nothing is written.
This is not a mockup and it is not sample copy. It is stage-1 output from an actual crawl of our own portfolio β 100 pages, 77,859 words, 4,506 claims β rendered by the same numbers the terminal prints. Two more surfaces were crawled and dropped here because they returned nothing; one 404s and one does not resolve, which is itself a finding.
Rows are ordered by measured citation
value, not by count β quantity is the strongest lever whether or not
it is the largest bar. The dotted rule is 38, where the
terminal stops drawing its ASCII bar; this chart keeps going, because a bar that
does not encode its number is a legend with no chart under it.
Regenerate every number above with
python3 prototype/runs/site_dataset.py. It reads the crawl JSON and refuses
to build if crawl.py's thresholds have drifted from the ones this page
publishes.
Every form has a material threshold. Below it, the tool refuses to
generate and says exactly what is missing β and the refusal is not a warning you can
click past, it is the answer. Drag the slider and watch the verdict flip at the
threshold. These are the real numbers from crawl.py Β§4.2, not
illustrations of them.
This is deliberate, and relaxing it under revenue pressure is the one change that would turn this into the thing it was built against.
Worth being precise about what the risk actually is, because the scary version is wrong. Google does not prohibit AI-assisted content. Its scaled content abuse policy β introduced with the March 2024 spam update β targets producing many pages primarily to manipulate rankings, and says so βno matter how it's created.β Human, automated or generated is not the test; volume of low-value pages is. So a tool that hands one person one grounded brief is not walking up to that line, and a tool that publishes thirty a month is, regardless of who typed them.
Research without a target is just a dashboard, and dashboards are what people churn out of. Every brief carries the raw material with it, so writing is assembly β not another research job handed back to you.
Deterministic, free, and where everything starts. Fetches
the site with the standard library only β there is nothing to pip install
β and builds a typed claim graph plus six findings that cost no model calls at all.
If robots.txt blocks AI crawlers it stops here and says so, because
nothing downstream matters until that is fixed.
Real queries, free, no API key β mined from Google and DuckDuckGo autocomplete, which is what people actually typed. Then the column no keyword tool has: each query cross-referenced against the site's own claim graph to answer can this site answer it today? A keyword list without that column is a to-do list someone else still has to research.
A real run: six seeds, 457 queries, verdicts computed against the claim graph above. The demand you don't serve rows are not assignments β they are a strategy question for a human to answer.
Ask the engine what it actually says about you. Questions are generated from the claim graph β brand, category, and each high-value claim inverted into the question it answers β then asked N times, because engines are non-deterministic and a single sample is not a rate.
A real run, 2026-08-10: 9 questions Γ 3 runs = 27 calls, $0.1424
total, perplexity/sonar. Cached responses are on disk in the repo.
The product is the research. The human writes. Briefs cluster queries by the claims they share, pick the highest-value form the material actually supports, and attach the material verbatim with its source URL. The bet is that research, not text generation, is the scarce input β one experiment worth citing rather than asserting: NP Digital published 744 articles across 68 sites and found the human-written set at 5.44Γ the traffic by month five. One agency, one study, pointing the same way as the argument; not a law.
If you want a draft, ask for one brief at a time. It is never the default and there is no bulk mode.
The crawl noticed one number stated prominently and a different, correct number stated once and buried. It did not need an engine to see that β it is a positioning fact, visible in the claim graph. Both of these are real claims from the same site, pulled straight out of the crawl by the same code that built the explorer above:
The second one looks like scraped noise, and that is the finding rather than a flaw in the excerpt. It is the site's own navigation β βThe 103 lawsβ as a link label, on every page. The correct figure appears once, in a sentence, on one page. Four prominent placements against one buried one; an engine weighs position, not correctness.
From signal dominance alone, stage 1 predicted the engine would learn the wrong total. Stage 2 asked, three times:
βOpenSentience's homepage says the box-and-box kernel has 103 laws Γ 2,000 trials.β
perplexity/sonar β 3 of 3 runs, citing opensentience.org. The authoritative number is 116.
A true fact, positioned so weakly the model learned the wrong one. No keyword tool surfaces that, because it is not a keyword problem β it is a signal-dominance problem, and you can only see it by comparing what a site says against what engines repeat back.
The same run turned up something a single-site crawl structurally cannot see: a second property, under the same owner, told the engine 15 laws Γ 1,000 trials. Three numbers, three sources, and the engine returns whichever page it lands on.
Three days ago this crawler reported that our three documentation hosts served one document with no canonical between them, and filed the fix as a portfolio work item: pick one canonical host, 301 the others.
It had never parsed <link rel="canonical">. The word appeared once
in the entire crawler, inside a docstring. All three hosts already declared
<link rel="canonical" href="https://docs.ampersandboxdesign.com/">.
The work item was an artifact of a tool asserting the absence of something it had never
looked for.
An unevidenced claim is not safe just because it happens to be true. Of the nine within-host duplicate groups, all nine really were missing a canonical β the guess was right every time it went unpublished, and wrong in the one case that became a work item.
Being right by luck is not being right, and it is not a reason to keep guessing.
What changed: canonical is now an observation. Each URL's declared target is recorded, and a duplicate group reports agree, disagree, partial or absent. Disagreement is the case worth having and the old wording could not express it β two URLs each naming themselves as the original is a worse problem than neither doing so.
The retraction is published in the same document that carried the claim, by name,
because a quiet correction is a second error. Three other faults were repaired in the
same release: claim anchors pointed at the page's last heading rather than the section
the claim came from, robots.txt was read case-sensitively so a lowercase
user-agent: gptbot blocking everything registered as unblocked, and the
configuration layer described limits the running code never read. Each has a regression
test that was watched failing first.
Then it happened again, one release later, in a subtler form. The robots repair
delegated to Python's urllib.robotparser and a code comment credited it with
standards-level rule handling. That was true on the machine it was written on and false
on four of the five interpreters we tested β 3.9 through 3.12 have no longest-match
precedence, no wildcards and no end anchors; 3.13.14 has all three. Same error class
as the canonical bug: a capability asserted rather than observed, this time because the
standard library sounded authoritative. The rules are implemented locally now, every
artifact records which engine produced it, and five more tests pin the semantics so the
answer cannot depend on which Python a reader happens to have installed.
And a third time, for the least flattering reason of the three: nobody had ever run
the whole pipeline in one pass. Every stage had tests, the corpus had twenty-two
sites in it, and the loop from crawl to brief had never once been walked end to end
against a live site. Doing that took under a minute and found three defects no unit test
could reach. The worst: brief.py keyed probe results by question ID
and then looked them up by question text, so the two never met β measuring what
engines said about you contributed nothing to any brief, silently, and the rule
that treats a measured citation miss as the strongest signal available was unreachable
code. Alongside it, the line naming which engine a rate was measured on had that engine's
name hard-coded, and the function that reduces a URL to a comparable domain stripped
www. with lstrip β which removes characters, turning a
bare wikipedia.org into ikipedia.org and an encyclopedia into a
competitor.
A test suite is evidence that the parts agree with themselves. It is not evidence that the thing runs.
Three green stages, one dead join between them, and fifteen passing tests.
Three more regression tests, each watched failing first. The same release also made the download archives build from a script that unpacks what it just built and diffs it against the tree β which immediately caught stray bytecode caches riding along inside the shipped tarball, visible only because the archive came out 68% heavier than the release before it.
The Python claim extractor is heuristic and has one root failure: it does
not resolve subjects. So it over-fires on definition, dumps most claims into
attribute, and cannot trust its own contradiction detection. That is not a
footnote β it changes the output enough that the tool tells you to supply the seeds
yourself. Measured on a live site, identical code and identical claim graph, only the
seeds differing:
Ranked by reach Γ winnability Γ material_sufficiency Γ· effort.
Three of them need no generation at all β they are link and markup fixes that cost
nothing and are found for free.
robots.txt blocks AI crawlers. Nothing downstream matters until this is cleared.| Stage | Runs on | Cost |
|---|---|---|
| Crawl, claim graph, free findings | Your machine, plain Python | Nothing |
| Keyword and question expansion | Google + DuckDuckGo autocomplete | Nothing, no key |
| Extraction, probing, generation | Your Claude subscription | Subscription usage |
| Multi-engine probing (optional) | Your own API keys | Real per-probe cost, quoted first |
No keys to paste for the default path, no per-token bill. The parts that are expensive to compute are deterministic code; the model is used only where judgment is actually needed.
One caveat, stated plainly. Probing through your Claude session covers the web-search surface it reaches β that is one engine. Cross-engine citation overlap is only about 11%, so it implies nothing about ChatGPT, Perplexity or Google AI Overviews.
Engines are never blended into one score. Rates are reported per engine, or not reported.
There is no testimonial wall on this page and no logo strip, because a tool that refuses to fabricate output cannot fabricate its own marketing. So here is the honest state, in the same three categories the tool would use.
The known ceiling is named above and in the skill file that ships with it: the heuristic extractor cannot resolve subjects, and that single fault is the root cause of all four of its failure modes.
A Claude Code skill plus eight Python files. No package manager, no build
step, no lockfile, nothing to pip install β the standard library and a
Claude Code session you already have.
tar xzf alkeyword-0.6.2.tar.gz cd alkeyword ./install.sh # then, in a new Claude Code session: /alkeyword yourdomain.com
Requires Claude Code and python3.
./install.sh --project installs into one repo instead of your user account.
There is no Alkeyword server and no Alkeyword account: every artifact it produces lives in
~/.alkeyword on your machine. Requests do leave the machine, and they go where
the analysis requires β the site being crawled, Google and DuckDuckGo autocomplete, and
whichever engine you probe. Nothing is routed through us, because there is no us to route
it through.
Bring a domain name. Get back what your own site already proves, matched to what people are actually asking β and an honest refusal where the material isn't there.