Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/klariti-os/klariti-os/llms.txt

Use this file to discover all available pages before exploring further.

The Gray Engine is Klariti’s content mediation layer. Given your active goal and the rules attached to it, the engine classifies the URLs on a page and applies visual modifications in the browser extension — for example, covering YouTube video thumbnails with a gray overlay when your goal is FOCUS or WORK. It doesn’t replace platform recommendation algorithms or run heavy AI analysis on every page — it operates predictably, explains what it’s doing, and lets you reverse any modification at any time.

How it works

The engine operates in two steps:
  1. Classify — the URL of a video is sent to the classification API, which returns a category describing the type of content.
  2. Mediate — given the category and the user’s active goal, the extension’s content script decides whether to apply a gray overlay over that video’s thumbnail.
This separation keeps the classification logic centralized on the server while the overlay logic lives in the extension, close to the DOM.

URL classification

The classification endpoint accepts a URL and returns a category string:
POST /api/classify
Content-Type: application/json

{
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
Response:
{
  "category": "Music"
}
The category value maps to a human-readable content label — for YouTube, this corresponds directly to the YouTube Data API video category for that video (e.g. "Education", "Gaming", "Science & Technology").
The classifier currently handles YouTube URLs only (youtube.com/watch?v= and youtu.be/ formats). For all other URLs, the endpoint returns null for category. The content script only runs on youtube.com — no other sites are mediated at this time.

Goals that drive mediation

The active goal on the current challenge or intent determines which mediation rules apply. The four supported goals represent different modes of focus:
GoalFocus mode
FOCUSMaximum distraction reduction
WORKProfessional task context
STUDYReading and research mode
CASUALLight mediation, lower friction
The current mediation rules work as follows on the YouTube homepage and subscriptions feed:
GoalBehaviour
FOCUSGray overlay applied to all video thumbnails
WORKSame as FOCUS — all thumbnails overlaid
STUDYOverlay applied only to videos whose category is not Education
CASUALNo overlays applied
If classification returns null (API error or unsupported URL), no overlay is applied — the engine never blocks content it cannot confidently classify.

The browser extension

The Gray Engine runs inside the Klariti MV3 browser extension. The extension background script handles two message types from content scripts and the web dashboard:
// From apps/extension/entrypoints/background.ts

const API_URL = "http://localhost:4200";

/** Classify a URL via the API */
async function classifyUrl(url: string): Promise<string | null> {
  try {
    const res = await apiFetch("/api/classify/", {
      method: "POST",
      body: JSON.stringify({ url }),
    });
    if (!res.ok) {
      console.warn("[klariti] classify failed:", res.status, await res.text());
      return null;
    }
    const data = await res.json();
    console.log("[klariti] classify result:", url, data);
    return data?.category ?? null;
  } catch (err) {
    console.error("[klariti] classify error:", err);
    return null;
  }
}

/** Get the currently active intent's goal */
async function getActiveGoal(): Promise<string | null> {
  try {
    const res = await apiFetch("/api/users/me/challenges");
    if (!res.ok) return null;
    const intents: Intent[] = await res.json();
    const active = intents.find(
      (i) => i.status === "active" && i.participant_status === "active"
    );
    return active?.goal ?? null;
  } catch {
    return null;
  }
}

export default defineBackground(() => {
  browser.runtime.onMessage.addListener((message, _sender, sendResponse) => {
    if (message?.type === "CLASSIFY_URL" && message.url) {
      classifyUrl(message.url).then((category) => sendResponse({ category }));
      return true; // keep channel open for async response
    }

    if (message?.type === "GET_ACTIVE_GOAL") {
      getActiveGoal().then((goal) => sendResponse({ goal }));
      return true;
    }
  });
});

Message types

Message typePayloadResponse
CLASSIFY_URL{ url: string }{ category: string | null }
GET_ACTIVE_GOAL{ goal: string | null }
The background script keeps the message channel open (return true) for both handlers since the API calls are asynchronous. Content scripts send these messages and receive the response to decide whether to apply a gray overlay to video thumbnails.

Design principles

Predictable

The same URL and goal always produce the same classification and the same rule set. No black-box decisions.

Explainable

Category labels are human-readable. Every overlay shows the video’s category so you can see exactly why it was blocked.

Reversible

Any page modification can be undone. Turning off an intent restores the page immediately.

Lightweight

No always-on AI analysis. Classification only runs for pages in supported categories and only when an intent is active.

Out of scope

The following are explicitly outside the Gray Engine’s current design:
  • Mobile browser support — the extension runs on desktop browsers only
  • Replacing platform algorithms — the engine modifies page presentation, not recommendation feeds
  • Always-on heavy AI analysis — classification is on-demand and limited to supported URL types

Build docs developers (and LLMs) love