Claude Project Delete Button

Add a delete button to Claude projects

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(У мене вже є менеджер скриптів, дайте мені встановити його!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        Claude Project Delete Button
// @namespace   Violentmonkey Scripts
// @match       https://claude.ai/project/*
// @grant       none
// @version     1.0
// @author      Elias Benbourenane
// @description Add a delete button to Claude projects
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    function getProjectId() {
        const path = window.location.pathname;
        const match = path.match(/\/project\/([^\/]+)/);
        return match ? match[1] : null;
    }

    function getOrgId() {
        return window.intercomSettings?.lastActiveOrgUUID;
    }

    function createDeleteButton() {
        const deleteButton = document.createElement('button');
        deleteButton.className = `inline-flex
            items-center
            justify-center
            relative
            shrink-0
            can-focus
            select-none
            disabled:pointer-events-none
            disabled:opacity-50
            disabled:shadow-none
            disabled:drop-shadow-none
            text-text-300
            border-transparent
            transition
            font-styrene
            duration-300
            ease-[cubic-bezier(0.165,0.85,0.45,1)]
            hover:bg-bg-400
            aria-pressed:bg-bg-400
            aria-checked:bg-bg-400
            aria-expanded:bg-bg-300
            hover:text-text-100
            aria-pressed:text-text-100
            aria-checked:text-text-100
            aria-expanded:text-text-100
            h-8 w-8 rounded-md active:scale-95`.replace(/\s+/g, ' ');

        deleteButton.type = 'button';
        deleteButton.title = 'Delete Project';

        // Trash icon SVG
        deleteButton.innerHTML = `
            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" viewBox="0 0 256 256" class="-translate-y-[0.5px]">
                <path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"></path>
            </svg>
        `;

        deleteButton.addEventListener('click', handleDeleteClick);

        return deleteButton;
    }

    async function handleDeleteClick(event) {
        event.preventDefault();

        const projectId = getProjectId();
        const orgId = getOrgId();

        if (!projectId || !orgId) {
            alert('Unable to determine project or organization ID');
            return;
        }

        if (!confirm('Are you sure you want to delete this project? This action cannot be undone.')) {
            return;
        }

        try {
            const response = await fetch(`https://claude.ai/api/organizations/${orgId}/projects/${projectId}`, {
                method: 'DELETE',
                credentials: 'include',
                headers: {
                    'Content-Type': 'application/json',
                }
            });

            if (response.ok) {
                alert('Project deleted successfully');
                window.location.href = 'https://claude.ai/';
            } else {
                throw new Error(`Delete failed: ${response.status} ${response.statusText}`);
            }
        } catch (error) {
            console.error('Error deleting project:', error);
            alert('Failed to delete project. Please try again.');
        }
    }

    function addDeleteButton() {
        // Look for the container with the star and menu buttons
        const buttonContainer = document.querySelector('.flex.items-center.gap-1.ml-auto');

        if (buttonContainer && !buttonContainer.querySelector('[title="Delete Project"]')) {
            const deleteButton = createDeleteButton();

            // Insert the delete button before the menu button (last button)
            const menuButton = buttonContainer.lastElementChild;
            buttonContainer.insertBefore(deleteButton, menuButton);
        }
    }

    let currentUrl = window.location.href;

    function isProjectPage() {
        return window.location.pathname.startsWith('/project/');
    }

    function handleUrlChange() {
        const newUrl = window.location.href;
        if (newUrl !== currentUrl) {
            currentUrl = newUrl;

            if (isProjectPage()) {
                // Delay to allow page content to load
                setTimeout(addDeleteButton, 500);
                setTimeout(addDeleteButton, 1500);
                setTimeout(addDeleteButton, 3000);
            }
        }
    }

    // Override history methods to detect programmatic navigation
    const originalPushState = history.pushState;
    const originalReplaceState = history.replaceState;

    history.pushState = function(...args) {
        originalPushState.apply(history, args);
        setTimeout(handleUrlChange, 0);
    };

    history.replaceState = function(...args) {
        originalReplaceState.apply(history, args);
        setTimeout(handleUrlChange, 0);
    };

    function init() {
        if (isProjectPage()) {
            // Try to add the button immediately
            addDeleteButton();

            // Also try after delays in case the page is still loading
            setTimeout(addDeleteButton, 500);
            setTimeout(addDeleteButton, 1500);
            setTimeout(addDeleteButton, 3000);
        }

        // Set up a mutation observer to handle dynamic content loading
        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    // Only try to add button if we're on a project page
                    if (isProjectPage()) {
                        addDeleteButton();
                    }
                }
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        // Listen for browser back/forward navigation
        window.addEventListener('popstate', handleUrlChange);

        // Periodic check to ensure button is present (fallback)
        setInterval(() => {
            if (isProjectPage()) {
                addDeleteButton();
            }
        }, 2000);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();