您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a delete button to Claude projects
// ==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(); } })();