Claude.ai | Remove active (current) chat by CTRL+SHIFT+BACKSPACE

Delete active chat in Claude.ai sidebar using Ctrl+Shift+Backspace

// ==UserScript==
// @name         Claude.ai | Remove active (current) chat by CTRL+SHIFT+BACKSPACE
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Delete active chat in Claude.ai sidebar using Ctrl+Shift+Backspace
// @author       Saymonn
// @match        https://claude.ai/chat*
// @icon         https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQO8QnSw5ArwqF8PsafiMQ3EsH0Xr9LFLgNpwutam6-FN7UhoQvXeyqIHyNvj907vU5BKU&usqp=CAU
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const DELETE_AUTOCONFIRM = true;

    function waitForElement(selector, timeout = 5000) {
        return new Promise((resolve, reject) => {
            const startTime = Date.now();
            function check() {
                const element = document.querySelector(selector);
                if (element) {
                    resolve(element);
                } else if (Date.now() - startTime > timeout) {
                    reject(new Error(`Element ${selector} not found within ${timeout}ms`));
                } else {
                    setTimeout(check, 50);
                }
            }
            check();
        });
    }

    function simulateRealClick(element) {
        if (!element) return;

        const rect = element.getBoundingClientRect();
        const x = rect.left + rect.width / 2;
        const y = rect.top + rect.height / 2;

        const events = [
            new PointerEvent('pointerdown', { bubbles: true, cancelable: true, pointerId: 1, clientX: x, clientY: y, button: 0 }),
            new MouseEvent('mousedown', { bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0 }),
            new PointerEvent('pointerup', { bubbles: true, cancelable: true, pointerId: 1, clientX: x, clientY: y, button: 0 }),
            new MouseEvent('mouseup', { bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0 }),
            new MouseEvent('click', { bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0 })
        ];

        events.forEach(event => element.dispatchEvent(event));
    }

    function findActiveMenuButton() {
        const listItems = document.querySelectorAll('li');
        for (let listItem of listItems) {
            const link = listItem.querySelector('a');
            if (link && link.classList.contains('!bg-bg-400')) {
                const menuButton = listItem.querySelector('button[aria-haspopup="menu"]');
                if (menuButton) {
                    return { button: menuButton, listItem: listItem };
                }
            }
        }
        return null;
    }

    function findDeleteButton() {
        const selectors = [
            '[data-testid="delete-chat-trigger"]',
            '[data-testid*="delete"]',
            'button[aria-label*="Delete"]',
            'button[aria-label*="delete"]',
            '[role="menuitem"]'
        ];

        for (let selector of selectors) {
            const elements = document.querySelectorAll(selector);
            for (let element of elements) {
                if (element.textContent.toLowerCase().includes('delete') ||
                    element.getAttribute('aria-label')?.toLowerCase().includes('delete')) {
                    return element;
                }
            }
        }

        const menuItems = document.querySelectorAll('[role="menuitem"]');
        for (let item of menuItems) {
            if (item.textContent.toLowerCase().includes('delete')) {
                return item;
            }
        }

        return null;
    }

    async function deleteActiveChat() {
        try {
            const activeElement = findActiveMenuButton();
            if (!activeElement) {
                console.log('No active chat found');
                return;
            }

            const { button: activeMenuButton, listItem } = activeElement;
            console.log('Found active chat, clicking menu button');

            simulateRealClick(activeMenuButton);
            await new Promise(resolve => setTimeout(resolve, 300));

            const deleteButton = findDeleteButton();
            if (!deleteButton) {
                console.log('Delete button not found, trying alternative approach');

                await new Promise(resolve => setTimeout(resolve, 100));
                simulateRealClick(activeMenuButton);
                await new Promise(resolve => setTimeout(resolve, 300));

                const deleteButtonRetry = findDeleteButton();
                if (deleteButtonRetry) {
                    deleteButtonRetry.click();
                } else {
                    console.log('Still no delete button found');
                    return;
                }
            } else {
                deleteButton.click();
            }

            if (DELETE_AUTOCONFIRM) {
                try {
                    console.log('Waiting for confirmation modal...');
                    const confirmButton = await waitForElement('[data-testid="delete-modal-confirm"]', 3000);
                    console.log('Found confirmation button, clicking...');
                    confirmButton.click();
                } catch (error) {
                    console.log('Confirmation button not found:', error.message);

                    const fallbackConfirmButton = document.querySelector('button[data-testid="delete-modal-confirm"]');
                    if (fallbackConfirmButton) {
                        console.log('Found confirmation button with fallback method');
                        fallbackConfirmButton.click();
                    } else {
                        console.log('No confirmation button found with any method');
                    }
                }
            }

        } catch (error) {
            console.error('Error during chat deletion:', error.message);
        }
    }

    document.addEventListener('keydown', function(event) {
        if (event.ctrlKey && event.shiftKey && event.code === 'Backspace') {
            event.preventDefault();
            console.log('Delete shortcut triggered');
            deleteActiveChat();
        }
    });

    console.log('Claude.ai chat deletion script loaded');

})();