Warning: fopen(/www/sites/update.greasyfork.icu/index/store/temp/b41cf8226ca7fb17bdbd130ee941844b.js): failed to open stream: No space left on device in /www/sites/update.greasyfork.icu/index/scriptControl.php on line 65
// ==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
// @downloadURL https://update.greasyfork.icu/scripts/539259/Claude%20Project%20Delete%20Button.user.js
// @updateURL https://update.greasyfork.icu/scripts/539259/Claude%20Project%20Delete%20Button.meta.js
// ==/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 = `
`;
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();
}
})();