Agent skill
raycast-alfred-project-switcher-integration
Sub-skill of raycast-alfred: Project Switcher Integration.
Install this agent skill to your Project
npx add-skill https://github.com/vamseeachanta/workspace-hub/tree/main/.claude/skills/_archive/operations/devtools/raycast-alfred/project-switcher-integration
SKILL.md
Project Switcher Integration
Project Switcher Integration
// src/project-switcher.tsx
// ABOUTME: Unified project switcher
// ABOUTME: Integrates with multiple project sources
import {
ActionPanel,
Action,
List,
Icon,
LocalStorage,
getPreferenceValues,
} from "@raycast/api";
import { useState, useEffect } from "react";
import { exec } from "child_process";
import { promisify } from "util";
import fs from "fs";
import path from "path";
const execAsync = promisify(exec);
interface Preferences {
projectDirs: string;
githubEnabled: boolean;
gitlabEnabled: boolean;
}
interface Project {
name: string;
path: string;
source: "local" | "github" | "gitlab";
url?: string;
lastAccessed?: number;
}
export default function Command() {
const [projects, setProjects] = useState<Project[]>([]);
const [isLoading, setIsLoading] = useState(true);
const preferences = getPreferenceValues<Preferences>();
useEffect(() => {
loadAllProjects();
}, []);
async function loadAllProjects() {
const allProjects: Project[] = [];
// Load local projects
const dirs = preferences.projectDirs.split(",").map((d) => d.trim());
for (const dir of dirs) {
const expandedDir = dir.replace("~", process.env.HOME || "");
if (fs.existsSync(expandedDir)) {
const entries = fs.readdirSync(expandedDir, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory() && !entry.name.startsWith(".")) {
allProjects.push({
name: entry.name,
path: path.join(expandedDir, entry.name),
source: "local",
});
}
}
}
}
// Load access times
const accessJson = await LocalStorage.getItem<string>("project-access");
const accessTimes = accessJson ? JSON.parse(accessJson) : {};
allProjects.forEach((p) => {
p.lastAccessed = accessTimes[p.path] || 0;
});
// Sort by last accessed
allProjects.sort((a, b) => (b.lastAccessed || 0) - (a.lastAccessed || 0));
setProjects(allProjects);
setIsLoading(false);
}
async function openProject(project: Project, app: string) {
const cmd =
app === "code"
? `code "${project.path}"`
: app === "terminal"
? `open -a Terminal "${project.path}"`
: `open "${project.path}"`;
await execAsync(cmd);
// Update access time
const accessJson = await LocalStorage.getItem<string>("project-access");
const accessTimes = accessJson ? JSON.parse(accessJson) : {};
accessTimes[project.path] = Date.now();
await LocalStorage.setItem("project-access", JSON.stringify(accessTimes));
}
const sourceIcons = {
local: Icon.Folder,
github: Icon.Globe,
gitlab: Icon.Globe,
};
return (
<List isLoading={isLoading} searchBarPlaceholder="Search projects...">
{projects.map((project) => (
<List.Item
key={project.path}
title={project.name}
subtitle={project.path}
icon={sourceIcons[project.source]}
accessories={[
project.lastAccessed
? { text: new Date(project.lastAccessed).toLocaleDateString() }
: {},
]}
actions={
<ActionPanel>
<Action
title="Open in VS Code"
icon={Icon.Code}
onAction={() => openProject(project, "code")}
/>
<Action
title="Open in Terminal"
icon={Icon.Terminal}
onAction={() => openProject(project, "terminal")}
/>
<Action
title="Open in Finder"
icon={Icon.Finder}
onAction={() => openProject(project, "finder")}
/>
</ActionPanel>
}
/>
))}
</List>
);
}
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
gsd-complete-milestone
Archive completed milestone and prepare for next version
gsd-reapply-patches
Reapply local modifications after a GSD update
gsd-verify-work
Validate built features through conversational UAT
gsd-thread
Manage persistent context threads for cross-session work
clinical-trial-protocol
Generate clinical trial protocols for medical devices or drugs through a modular, waypoint-based architecture with research-only and full protocol modes.
single-cell-rna-qc
Performs quality control on single-cell RNA-seq data (.h5ad or .h5 files) using scverse best practices with MAD-based filtering and comprehensive visualizations.
Didn't find tool you were looking for?