소스 정보
- 저장소
- Aradotso/hermes-skills
- 최근 소스 활동
- 2026년 5월 18일 10:52
- 감지된 SKILL.md 언어
- 영어
- 스타
- 5
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/Aradotso/hermes-skills --skill hermes-ide-terminal명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | hermes-ide-terminal |
| description | AI-native terminal emulator & IDE built with Tauri, React, and Rust |
| triggers | ["set up hermes ide","how do I use hermes terminal","configure hermes ide with claude","hermes ide git integration","build hermes from source","hermes ide agent mode","troubleshoot hermes terminal","hermes ide project scanning"] |
Skill by ara.so — Hermes Skills collection.
Hermes IDE is an AI-native terminal emulator built with Tauri 2, React 18, and Rust. It provides:
Download from the official website:
# Visit https://www.hermes-ide.com/download
# Choose your platform: macOS (Intel/Apple Silicon), Windows, Linux (.deb/.AppImage/.rpm)
Prerequisites:
# Check versions
node --version # 18+
rustc --version # 1.70+
Platform-specific dependencies:
# Linux (Debian/Ubuntu)
sudo apt install libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
# macOS
xcode-select --install
# Windows
# Install Visual Studio Build Tools with "Desktop development with C++"
# Install WebView2 Runtime from Microsoft
Clone and build:
git clone https://github.com/hermes-hq/hermes-ide.git
cd hermes-ide
npm install
npm run tauri dev # Development mode with hot-reload
npm run tauri build # Production build
Hermes IDE uses a layered architecture:
React Frontend (TypeScript) ← Tauri IPC Bridge → Rust Backend
UI & State PTY, DB, Scanner
Key directories:
src/ - React/TypeScript frontend (components, hooks, state, terminal)src-tauri/ - Rust backend (PTY management, SQLite, project scanning)src/api/ - Tauri IPC command wrapperssrc/terminal/ - Terminal pool & AI intelligence engineHermes uses your existing claude CLI authentication:
# Install Claude CLI first
npm install -g @anthropic-ai/claude-cli
# Authenticate (choose one method)
claude auth login # Pro/Max account
claude auth api-key $ANTHROPIC_API_KEY # API key
In Hermes IDE:
Hermes automatically scans projects to build AI context:
// Project scanning happens automatically when you:
// 1. Open a terminal in a directory
// 2. Attach a project via sidebar
// 3. Use Cmd/Ctrl+Shift+P → "Scan Project"
// Detected information includes:
// - Languages and frameworks
// - Project structure
// - Dependencies
// - Git repository info
Configure shell and environment in settings:
{
"shell": {
"program": "/bin/zsh",
"args": ["-l"]
},
"environment": {
"TERM": "xterm-256color",
"COLORTERM": "truecolor"
},
"fontSize": 14,
"fontFamily": "JetBrains Mono, monospace"
}
// Create new session
// Cmd/Ctrl+T
// Switch sessions
// Cmd/Ctrl+1-9 (first 9 sessions)
// Or use sidebar
// Split panes
// Cmd/Ctrl+D (horizontal)
// Cmd/Ctrl+Shift+D (vertical)
// Close session
// Cmd/Ctrl+W
Access via sidebar panel:
# All git operations available via UI
# - View staged/unstaged/untracked files
# - Click files to see inline diffs
# - Stage/unstage with checkboxes
# - Commit with message input
# - Push/Pull buttons
# Or use git commands directly in terminal
git add .
git commit -m "feat: add new feature"
git push origin main
Hermes provides real-time command suggestions:
# Start typing and ghost text appears
git com█
# Suggestion: git commit -m "message"
# Accept with Tab or Right Arrow
# Reject with Esc or continue typing
Use natural language for autonomous execution:
# Open Prompt Composer: Cmd/Ctrl+Shift+P
# Type natural language instructions:
"Create a new React component called UserProfile with TypeScript"
"Fix all eslint errors in src/"
"Run tests and commit if they pass"
# Hermes executes commands and tracks progress
Access all features quickly:
# Open: Cmd/Ctrl+K
# Fuzzy search for:
# - Commands
# - Settings
# - Projects
# - Sessions
# - Git operations
// src/components/Terminal.tsx
import React, { useEffect, useRef } from 'react';
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
export const TerminalComponent: React.FC = () => {
const terminalRef = useRef<HTMLDivElement>(null);
const xtermRef = useRef<Terminal | null>(null);
useEffect(() => {
if (!terminalRef.current) return;
const term = new Terminal({
fontFamily: 'JetBrains Mono, monospace',
fontSize: 14,
theme: {
background: '#1e1e1e',
foreground: '#d4d4d4',
},
});
const fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(terminalRef.current);
fitAddon.fit();
xtermRef. = term;
{
term.();
};
}, []);
;
};
// src-tauri/src/pty/mod.rs
use portable_pty::{native_pty_system, CommandBuilder, PtySize};
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct PtySession {
pub id: String,
pty: Arc<Mutex<Box<dyn portable_pty::MasterPty + Send>>>,
writer: Arc<Mutex<Box<dyn std::io::Write + Send>>>,
}
impl PtySession {
pub fn new(shell: &str, cwd: &str) -> Result<Self, Box<dyn std::error::Error>> {
let pty_system = native_pty_system();
let pair = pty_system.openpty(PtySize {
rows: 24,
cols: 80,
pixel_width: 0,
pixel_height: 0,
})?;
let mut cmd = CommandBuilder::new(shell);
cmd.cwd(cwd);
let _child = pair.slave.spawn_command(cmd)?;
let writer = pair.master.take_writer()?;
( {
id: uuid::Uuid::().(),
pty: Arc::(Mutex::(pair.master)),
writer: Arc::(Mutex::(writer)),
})
}
(&, data: &[]) <(), < std::error::Error>> {
= .writer.().;
writer.(data)?;
writer.()?;
(())
}
}
// src-tauri/src/commands.rs
use tauri::command;
#[command]
pub async fn create_terminal_session(
shell: String,
cwd: String,
) -> Result<String, String> {
let session = PtySession::new(&shell, &cwd)
.map_err(|e| e.to_string())?;
let session_id = session.id.clone();
// Store session in global state
// ...
Ok(session_id)
}
#[command]
pub async fn write_to_terminal(
session_id: String,
data: String,
) -> Result<(), String> {
// Get session from global state
// ...
session.write(data.as_bytes())
.await
.map_err(|e| e.to_string())?;
Ok(())
}
// src/api/terminal.ts
import { invoke } from '@tauri-apps/api/tauri';
export interface TerminalSession {
id: string;
cwd: string;
shell: string;
}
export async function createTerminalSession(
shell: string,
cwd: string
): Promise<string> {
return await invoke<string>('create_terminal_session', {
shell,
cwd,
});
}
export async function writeToTerminal(
sessionId: string,
data: string
): Promise<void> {
await invoke('write_to_terminal', {
sessionId,
data,
});
}
export async function resizeTerminal(
sessionId: string,
rows: number,
cols: number
): Promise<> {
(, {
sessionId,
rows,
cols,
});
}
Hermes uses React Context + useReducer:
// src/state/AppContext.tsx
import React, { createContext, useReducer } from 'react';
interface AppState {
sessions: TerminalSession[];
activeSessionId: string | null;
projects: Project[];
}
type AppAction =
| { type: 'ADD_SESSION'; session: TerminalSession }
| { type: 'REMOVE_SESSION'; sessionId: string }
| { type: 'SET_ACTIVE_SESSION'; sessionId: string };
const appReducer = (state: AppState, action: AppAction): AppState => {
switch (action.type) {
case 'ADD_SESSION':
return {
...state,
sessions: [...state.sessions, action.session],
};
case 'REMOVE_SESSION':
return {
...state,
sessions: state.sessions.filter(s => s. !== action.),
};
:
{
...state,
: action.,
};
:
state;
}
};
= createContext<{
: ;
: .<>;
} | >();
: . = {
[state, dispatch] = (appReducer, {
: [],
: ,
: [],
});
(
);
};
// src/hooks/useTerminal.ts
import { useContext, useCallback } from 'react';
import { AppContext } from '../state/AppContext';
import { createTerminalSession, writeToTerminal } from '../api/terminal';
export const useTerminal = () => {
const context = useContext(AppContext);
if (!context) throw new Error('useTerminal must be used within AppProvider');
const { state, dispatch } = context;
const createSession = useCallback(async (shell: string, cwd: string) => {
const sessionId = await createTerminalSession(shell, cwd);
dispatch({
type: 'ADD_SESSION',
session: { id: sessionId, shell, cwd },
});
dispatch({ type: 'SET_ACTIVE_SESSION', sessionId });
return sessionId;
}, [dispatch]);
const write = useCallback(async (data: string) => {
(!state.) ;
(state., data);
}, [state.]);
{
: state.,
: state.,
createSession,
write,
};
};
// src-tauri/src/project/scanner.rs
use std::path::Path;
use walkdir::WalkDir;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct ProjectContext {
pub languages: Vec<String>,
pub frameworks: Vec<String>,
pub dependencies: Vec<String>,
pub structure: String,
}
pub fn scan_project(path: &Path) -> Result<ProjectContext, Box<dyn std::error::Error>> {
let mut languages = Vec::new();
let mut frameworks = Vec::new();
let mut dependencies = Vec::new();
// Detect package.json (Node.js)
if path.join("package.json").exists() {
languages.push("JavaScript".to_string());
let package_json = std::fs::(path.())?;
: serde_json::Value = serde_json::(&package_json)?;
(deps) = package.() {
deps.().() {
frameworks.(.());
}
deps.().() {
frameworks.(.());
}
}
}
path.().() {
languages.(.());
}
= std::collections::HashMap::();
WalkDir::(path).() {
(entry) = entry {
(ext) = entry.().() {
*file_counts.(ext.().()).() += ;
}
}
}
(ProjectContext {
languages,
frameworks,
dependencies,
structure: (, file_counts),
})
}
# Run all tests
npm run test
# Run with coverage
npm run test:coverage
# Watch mode
npm run test:watch
// src/components/__tests__/Terminal.test.tsx
import { render, screen } from '@testing-library/react';
import { TerminalComponent } from '../Terminal';
describe('TerminalComponent', () => {
it('renders terminal container', () => {
render(<TerminalComponent />);
const container = screen.getByClassName('terminal-container');
expect(container).toBeInTheDocument();
});
});
cd src-tauri
cargo test
cargo test -- --nocapture # Show output
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pty_session_creation() {
let session = PtySession::new("/bin/bash", "/tmp");
assert!(session.is_ok());
let session = session.unwrap();
assert!(!session.id.is_empty());
}
#[tokio::test]
async fn test_write_to_pty() {
let session = PtySession::new("/bin/bash", "/tmp").unwrap();
let result = session.write(b"echo test\n").await;
assert!(result.is_ok());
}
}
Error: webkit2gtk not found
# Linux
sudo apt install libwebkit2gtk-4.1-dev
# If still failing, check pkg-config
pkg-config --modversion webkit2gtk-4.1
Error: Rust toolchain not found
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
Error: node-gyp failures on Windows
npm install --global windows-build-tools
npm config set msvs_version 2019
Terminal not rendering
// Check terminal element is mounted
useEffect(() => {
console.log('Terminal ref:', terminalRef.current);
if (!terminalRef.current) {
console.error('Terminal container not found');
return;
}
// ...
}, []);
PTY session hangs
// Add timeout to PTY operations
use tokio::time::{timeout, Duration};
let result = timeout(
Duration::from_secs(5),
session.write(data)
).await;
if result.is_err() {
eprintln!("PTY write timed out");
}
Git authentication fails
# Check SSH agent
ssh-add -l
# Or use Git Credential Manager
git config --global credential.helper manager
# Set environment variable in Hermes settings
# GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa"
High CPU usage
# Check terminal rendering settings
# Reduce font size or disable ligatures
# Limit scrollback buffer size in settings
Memory leaks
// Ensure proper cleanup in useEffect
useEffect(() => {
const term = new Terminal();
// ...
return () => {
term.dispose(); // Critical!
};
}, []);
# Claude API configuration
export ANTHROPIC_API_KEY=sk-ant-...
# Custom shell
export HERMES_SHELL=/bin/zsh
# Debug logging
export RUST_LOG=debug
export HERMES_DEBUG=1
# Custom config directory
export HERMES_CONFIG_DIR=$HOME/.config/hermes
# Fork and clone
git clone https://github.com/YOUR_USERNAME/hermes-ide.git
cd hermes-ide
# Create feature branch
git checkout -b feature/my-feature
# Make changes and test
npm run tauri dev
npm run test
cd src-tauri && cargo test
# Type check
npx tsc --noEmit
# Commit (follows conventional commits)
git commit -m "feat: add new terminal feature"
# Push and open PR
git push origin feature/my-feature
# Sign CLA when prompted
Read CONTRIBUTING.md and DESIGN_PRINCIPLES.md before contributing.