// ==UserScript==
// @name Grok Feature Flags
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Toggle feature flags on grok.com to test out new features
// @author Blankspeaker
// @match https://grok.com/*
// @grant none
// @license GNU GPLv3
// ==/UserScript==
(function() {
'use strict';
try {
// Default flags to initialize if local_feature_flags is missing or empty
const defaultFlags = {
"show_favorite_button": false, "SHOW_FAVORITE_BUTTON": false,
"show_followups": false, "SHOW_FOLLOWUPS": false,
"store_long_pastes_as_files": false, "STORE_LONG_PASTES_AS_FILES": false,
"show_sports_cards": false, "SHOW_SPORTS_CARDS": false,
"show_finance_cards": false, "SHOW_FINANCE_CARDS": false,
"show_places_cards": false, "SHOW_PLACES_CARDS": false,
"show_images_cards": false, "SHOW_IMAGES_CARDS": false,
"enable_brave_completions": false, "ENABLE_BRAVE_COMPLETIONS": false,
"suggestions_use_cache": false, "SUGGESTIONS_USE_CACHE": false,
"show_create_report_button_on_attachments": false, "SHOW_CREATE_REPORT_BUTTON_ON_ATTACHMENTS": false,
"enable_report_loading_screen": false, "ENABLE_REPORT_LOADING_SCREEN": false,
"show_artifacts_share_button": false, "SHOW_ARTIFACTS_SHARE_BUTTON": false,
"show_artifacts_inline_button": false, "SHOW_ARTIFACTS_INLINE_BUTTON": false,
"disable_python_artifacts": false, "DISABLE_PYTHON_ARTIFACTS": false,
"enable_code_execution": false, "ENABLE_CODE_EXECUTION": false,
"enable_latex_preview": false, "ENABLE_LATEX_PREVIEW": false,
"show_response_load_timer": false, "SHOW_RESPONSE_LOAD_TIMER": false,
"thinking_auto_open": false, "THINKING_AUTO_OPEN": false,
"enable_anon_cloning": false, "ENABLE_ANON_CLONING": false,
"enable_anon_users": false, "ENABLE_ANON_USERS": false,
"show_grok_2": false, "SHOW_GROK_2": false,
"hide_subscription_flows_from_premium_plus_users": false, "HIDE_SUBSCRIPTION_FLOWS_FROM_PREMIUM_PLUS_USERS": false,
"show_anon_help_link": false, "SHOW_ANON_HELP_LINK": false,
"enable_auto_stream_retry": false, "ENABLE_AUTO_STREAM_RETRY": false,
"enable_browser_notifications": false, "ENABLE_BROWSER_NOTIFICATIONS": false,
"enable_conversation_tabs": false, "ENABLE_CONVERSATION_TABS": false,
"show_artifacts_ask_grok_button": false, "SHOW_ARTIFACTS_ASK_GROK_BUTTON": false,
"show_artifacts_explain_button": false, "SHOW_ARTIFACTS_EXPLAIN_BUTTON": false,
"enable_artifacts_editing": false, "ENABLE_ARTIFACTS_EDITING": false,
"show_x_badge": false, "SHOW_X_BADGE": false,
"show_open_in_app_dialog": false, "SHOW_OPEN_IN_APP_DIALOG": false,
"show_open_in_app_dialog_every_time": false, "SHOW_OPEN_IN_APP_DIALOG_EVERY_TIME": false,
"show_open_in_app_dialog_download_default": false, "SHOW_OPEN_IN_APP_DIALOG_DOWNLOAD_DEFAULT": false,
"enable_grok_analyze_url": false, "ENABLE_GROK_ANALYZE_URL": false,
"show_deeper_search": false, "SHOW_DEEPER_SEARCH": false,
"enable_memory_toggle": false, "ENABLE_MEMORY_TOGGLE": false,
"toggle_search_only": false, "TOGGLE_SEARCH_ONLY": false,
"show_memory_summary": false, "SHOW_MEMORY_SUMMARY": false,
"open_memory_in_new_tab": false, "OPEN_MEMORY_IN_NEW_TAB": false,
"show_orb_icon_memory": false, "SHOW_ORB_ICON_MEMORY": false,
"show_search_deeper": false, "SHOW_SEARCH_DEEPER": false,
"enable_add_text_content": false, "ENABLE_ADD_TEXT_CONTENT": false,
"enable_google_drive": false, "ENABLE_GOOGLE_DRIVE": false,
"enable_microsoft_onedrive": false, "ENABLE_MICROSOFT_ONEDRIVE": false,
"enable_csv_rendering": false, "ENABLE_CSV_RENDERING": false,
"enable_in_app_reporting": false, "ENABLE_IN_APP_REPORTING": false,
"show_artifact_to_workspace_button": false, "SHOW_ARTIFACT_TO_WORKSPACE_BUTTON": false,
"workspace_agent": false, "WORKSPACE_AGENT": false,
"show_youtube_embeds": false, "SHOW_YOUTUBE_EMBEDS": false,
"show_reddit_embeds": false, "SHOW_REDDIT_EMBEDS": false,
"only_use_single_youtube": false, "ONLY_USE_SINGLE_YOUTUBE": false,
"show_x_inline": false, "SHOW_X_INLINE": false,
"enable_think_harder": false, "ENABLE_THINK_HARDER": false,
"enable_conversation_starters": false, "ENABLE_CONVERSATION_STARTERS": false,
"enable_expanded_upsell_banners": false, "ENABLE_EXPANDED_UPSELL_BANNERS": false,
"use_dynamic_suggested_mode_text": false, "USE_DYNAMIC_SUGGESTED_MODE_TEXT": false,
"show_model_config_override": false, "SHOW_MODEL_CONFIG_OVERRIDE": false,
"enable_grok_tasks": false, "ENABLE_GROK_TASKS": false
};
// Read current flags from localStorage, initialize with defaults if empty
let rawFlags = localStorage.getItem("local_feature_flags");
console.log("Raw local_feature_flags:", rawFlags);
let currentFlags = rawFlags ? JSON.parse(rawFlags) : {};
if (Object.keys(currentFlags).length === 0) {
console.log("No flags found in localStorage. Initializing with default flags.");
currentFlags = { ...defaultFlags };
localStorage.setItem("local_feature_flags", JSON.stringify(currentFlags));
}
// Group flags by uppercase name to avoid duplicate display
let flagGroups = {};
Object.keys(currentFlags).forEach(flag => {
const normalized = flag.toUpperCase();
if (!flagGroups[normalized]) {
flagGroups[normalized] = [];
}
flagGroups[normalized].push(flag);
});
let displayFlags = Object.keys(flagGroups);
// Log the number of unique and total flags
console.log("Total flags:", Object.keys(currentFlags).length, "Unique flags (after normalization):", displayFlags.length);
// Create UI element for flag picker
let ui = document.createElement("div");
ui.id = "feature-flags-ui";
ui.style.display = "none"; // Initially hidden
ui.innerHTML = `
<div class="title-bar">
<span>Feature Flags</span>
<button id="minimize-btn">_</button>
<button id="close-btn">X</button>
</div>
<div class="content">
<div class="flag-list">
${displayFlags.length > 0 ? displayFlags.map(normalizedFlag => {
// Use the first original key for checkbox state
const originalKeys = flagGroups[normalizedFlag];
const primaryKey = originalKeys[0];
return `
<label>
<input type="checkbox" data-flag="${normalizedFlag}" ${typeof currentFlags[primaryKey] === 'boolean' && currentFlags[primaryKey] ? 'checked' : ''}>
${normalizedFlag}
</label>
`;
}).join("") : '<p>No feature flags available.</p>'}
</div>
<button id="save-btn">Save</button>
</div>
`;
// Append UI to body
document.body.appendChild(ui);
// Load saved UI state
let uiState = JSON.parse(localStorage.getItem("feature_flags_ui_state") || "{}");
if (uiState.left && uiState.top) {
ui.style.left = uiState.left + "px";
ui.style.top = uiState.top + "px";
}
if (uiState.minimized) {
ui.classList.add("minimized");
}
if (uiState.visible) {
ui.style.display = "block";
}
// Add CSS for styling, dragging, and fixed save button
let style = document.createElement("style");
style.textContent = `
#feature-flags-ui {
position: absolute;
top: 10px;
left: 10px;
width: 400px; /* Wider UI to prevent text wrapping */
background: #333333; /* Dark gray background */
color: #ffffff; /* White text */
border: 1px solid #555555;
box-shadow: 2px 2px 5px rgba(0,0,0,0.5);
font-family: Arial, sans-serif;
z-index: 10000; /* Ensure UI is above other elements */
}
#feature-flags-ui .title-bar {
background: #555555; /* Slightly lighter gray for title bar */
color: #ffffff;
padding: 5px;
cursor: move;
display: flex;
justify-content: space-between;
align-items: center;
}
#feature-flags-ui .title-bar span {
flex-grow: 1;
}
#feature-flags-ui .content {
padding: 10px;
display: flex;
flex-direction: column;
max-height: 400px;
}
#feature-flags-ui .flag-list {
flex: 1;
overflow-y: auto;
padding-bottom: 10px;
}
#feature-flags-ui.minimized .content {
display: none;
}
#feature-flags-ui label {
display: flex; /* Keep checkbox and text inline */
align-items: center;
margin-bottom: 5px;
color: #ffffff; /* White text for labels */
}
#feature-flags-ui label input {
margin-right: 8px; /* Space between checkbox and text */
}
#feature-flags-ui button {
color: #ffffff;
background: #555555;
border: 1px solid #777777;
}
#feature-flags-ui #save-btn {
position: sticky;
bottom: 0;
margin-top: 10px;
padding: 5px;
width: 100%;
box-sizing: border-box;
}
#feature-flags-ui p {
color: #ffffff;
margin: 0;
}
`;
document.head.appendChild(style);
// Add menu item for Feature Flags
const manageSubscriptionItem = document.querySelector('div[role="menuitem"] svg path[d="M21 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h6"]');
if (manageSubscriptionItem) {
const menuItem = document.createElement("div");
menuItem.setAttribute("role", "menuitem");
menuItem.className = "relative flex select-none items-center cursor-pointer px-3 py-2 rounded-xl text-sm outline-none focus:bg-button-ghost-hover";
menuItem.setAttribute("tabindex", "-1");
menuItem.setAttribute("data-orientation", "vertical");
menuItem.setAttribute("data-radix-collection-item", "");
menuItem.innerHTML = `
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="stroke-[2] text-neutral-400 mr-2" stroke-width="2">
<path d="M10 4V4C8.13623 4 7.20435 4 6.46927 4.30448C5.48915 4.71046 4.71046 5.48915 4.30448 6.46927C4 7.20435 4 8.13623 4 10V13.6C4 15.8402 4 16.9603 4.43597 17.816C4.81947 18.5686 5.43139 19.1805 6.18404 19.564C7.03968 20 8.15979 20 10.4 20H14C15.8638 20 16.7956 20 17.5307 19.6955C18.5108 19.2895 19.2895 18.5108 19.6955 17.5307C20 16.7956 20 15.8638 20 14V14" stroke="currentColor" stroke-linecap="square"></path>
<path d="M12.4393 14.5607L19.5 7.5C20.3284 6.67157 20.3284 5.32843 19.5 4.5C18.6716 3.67157 17.3284 3.67157 16.5 4.5L9.43934 11.5607C9.15804 11.842 9 12.2235 9 12.6213V15H11.3787C11.7765 15 12.158 14.842 12.4393 14.5607Z" stroke="currentColor" stroke-linecap="square"></path>
</svg>
Feature Flags
`;
manageSubscriptionItem.parentElement.insertAdjacentElement("afterend", menuItem);
// Toggle flag picker visibility on menu item click
menuItem.addEventListener("click", () => {
ui.style.display = ui.style.display === "none" ? "block" : "none";
uiState.visible = ui.style.display === "block";
localStorage.setItem("feature_flags_ui_state", JSON.stringify(uiState));
});
} else {
console.warn("Manage Subscription menu item not found. Flag picker will be shown by default.");
ui.style.display = "block"; // Fallback to visible if menu item not found
}
// Make UI draggable and save position
let titleBar = ui.querySelector(".title-bar");
let isDragging = false;
let offsetX, offsetY;
titleBar.addEventListener("mousedown", (e) => {
isDragging = true;
offsetX = e.clientX - ui.offsetLeft;
offsetY = e.clientY - ui.offsetTop;
});
document.addEventListener("mousemove", (e) => {
if (isDragging) {
ui.style.left = (e.clientX - offsetX) + "px";
ui.style.top = (e.clientY - offsetY) + "px";
// Update saved position
uiState.left = e.clientX - offsetX;
uiState.top = e.clientY - offsetY;
localStorage.setItem("feature_flags_ui_state", JSON.stringify(uiState));
}
});
document.addEventListener("mouseup", () => {
isDragging = false;
});
// Minimize button and save state
ui.querySelector("#minimize-btn").addEventListener("click", () => {
ui.classList.toggle("minimized");
uiState.minimized = ui.classList.contains("minimized");
localStorage.setItem("feature_flags_ui_state", JSON.stringify(uiState));
});
// Close button
ui.querySelector("#close-btn").addEventListener("click", () => {
ui.style.display = "none";
uiState.visible = false;
localStorage.setItem("feature_flags_ui_state", JSON.stringify(uiState));
});
// Save button with auto-refresh
ui.querySelector("#save-btn").addEventListener("click", () => {
let modifiedFlags = { ...currentFlags };
displayFlags.forEach(normalizedFlag => {
let checkbox = ui.querySelector(`input[data-flag="${normalizedFlag}"]`);
if (checkbox) {
// Update all original keys for this normalized flag
flagGroups[normalizedFlag].forEach(originalKey => {
modifiedFlags[originalKey] = checkbox.checked;
});
}
});
localStorage.setItem("local_feature_flags", JSON.stringify(modifiedFlags));
console.log("Flags saved. Reloading page...");
location.reload(); // Auto-refresh the page
});
console.log("Grok Feature Flags Toggler loaded successfully with", displayFlags.length, "unique flags.");
} catch (error) {
console.error("Error in Grok Feature Flags Toggler:", error);
}
})();