Claude Project Delete Button

Add a delete button to Claude projects

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

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

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==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();
    }
})();