A field guide to skills in AriRoam.
The skill system is small but expressive. Here's how it actually works — a 40-line example that blocks every cookie banner you'll meet, and a second that turns Wikipedia's reference numbers into proper footnotes.
A skill in AriRoam is a small piece of JavaScript that bends a page to your shape. They live in ~/Application Support/AriRoam/skills.json, sandboxed in a WKUserScript, and they come in three flavours.
The three flavours.
The first is prompt-only. No code at all — just an instruction stored under a name. When you tap it, Ari runs the prompt against the current page. "Summarise this as a Hacker News comment", for instance, or "Argue against the author." Useful when you keep typing the same prompt at the same kind of page.
The second is tap-to-run. A bookmarklet: a one-shot script that runs when you tap. It can do anything a normal script can — read the DOM, modify it, scroll, click. It does not persist across page loads.
The third is always-on. The same JavaScript, but registered as a WKUserScript and re-run every time you land on a matching page. Match by hostname substring — case-insensitive, empty pattern means every page on the open web. This is the interesting one.
The cookie banner blocker.
Easiest example. Most cookie banners share a small vocabulary: a fixed element near the bottom of the screen, an id or class containing cookie, consent, or gdpr, a button labelled Accept or Reject. A skill that hides those is forty lines, and you only have to write it once.
// Skill: nuke-cookie-banners
// Flavour: always-on Pattern: (empty — every page)
const NEEDLES = [
'cookie', 'consent', 'gdpr', 'ccpa',
'banner', 'accept-all', 'privacy-notice'
];
const looksLikeBanner = (el) => {
const s = (el.id + ' ' + el.className).toLowerCase();
return NEEDLES.some(n => s.includes(n));
};
const sweep = () => {
document
.querySelectorAll('div, section, aside, dialog, iframe')
.forEach(el => {
if (!looksLikeBanner(el)) return;
const p = getComputedStyle(el).position;
if (p === 'fixed' || p === 'sticky') el.remove();
});
// Free the body from `overflow: hidden` traps.
document.documentElement.style.overflow = '';
document.body.style.overflow = '';
};
// Once at load, then again whenever the DOM stirs.
sweep();
new MutationObserver(sweep)
.observe(document.body, { childList: true, subtree: true });
Save it, mark it always-on, leave the hostname pattern empty. Done. You will, with great satisfaction, notice the absence.
Wikipedia, in footnotes.
The Wikipedia reference style is a marvel of the citation graph, and an annoyance to read. A reference like [12] sends you to the bottom of the page and back. A long article can do this thirty times. Skills are very good at this.
// Skill: wiki-footnotes-inline
// Flavour: always-on Pattern: wikipedia.org
const refTextFor = (id) => {
const li = document.getElementById(id.slice(1));
if (!li) return '';
const cite = li.querySelector('.reference-text') || li;
return cite.textContent.trim().replace(/\s+/g, ' ');
};
const inline = (a) => {
const href = a.getAttribute('href') || '';
if (!href.startsWith('#cite_note')) return;
const text = refTextFor(href);
if (!text) return;
const note = document.createElement('span');
note.className = 'ari-footnote';
note.textContent = ' (' + text + ') ';
note.style.color = 'rgba(0,0,0,.55)';
note.style.fontStyle = 'italic';
note.style.fontSize = '.9em';
a.parentNode.insertBefore(note, a.nextSibling);
a.style.display = 'none';
};
document
.querySelectorAll('sup.reference a')
.forEach(inline);
This one stays small because Wikipedia is exceptionally well-marked-up. The brittle parts of the web get longer skills. That's the trade.
What skills can't do.
Three rules, all enforced by the runtime, none of which you should try to route around.
- Skills can't talk to Ari. The copilot lives in a different surface; bridging them is a future problem we are not in a hurry to solve.
- Skills can't reach across origins. Each page's skill runs on that page's DOM and no further. This is WebKit's rule, not ours, but we agree with it.
- Skills can't see your other Spaces. The skill store is shared across Spaces but the runtime context isn't.
A small culture.
We are slowly seeding a community of skills inside the app — the starter set you get on first launch is fifteen of them. There's the YouTube cleanup one (hides shorts, hides the mini-player, makes the comment section foldable). There's the Hacker News one that hides the "Show HN" tag because we keep clicking it by accident. There's one Olly wrote that turns Substack's middle column slightly wider.
If you write one you like, send it to support@arilabs.dev. We're cataloguing them.
— A.