idea-manager 0.7.7 → 0.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # IM (Idea Manager)
2
2
 
3
- [한국어](README.md) | [English](README.en.md) | **日本語** | [中文](README.zh.md)
3
+ [English](README.md) | [한국어](README.ko.md) | **日本語** | [中文](README.zh.md)
4
4
 
5
5
  > アイデアから実行可能なプロンプトまで — マルチプロジェクトワークフローマネージャー
6
6
 
package/README.ko.md ADDED
@@ -0,0 +1,127 @@
1
+ # IM (Idea Manager)
2
+
3
+ [English](README.md) | **한국어** | [日本語](README.ja.md) | [中文](README.zh.md)
4
+
5
+ > 아이디어에서 실행 가능한 프롬프트까지, 멀티 프로젝트 워크플로우 매니저
6
+
7
+ 여러 프로젝트를 동시에 진행하는 개발자를 위한 태스크 관리 도구입니다. 아이디어를 서브 프로젝트와 태스크로 조직화하고, 각 태스크별 프롬프트를 정제하여 Claude Code 등 AI 에이전트에게 전달할 수 있습니다. MCP Server를 내장하고 있어 AI 에이전트가 자율적으로 태스크를 가져가 실행할 수 있습니다.
8
+
9
+ ![IM Workspace](docs/screenshot.png)
10
+
11
+ ## 핵심 워크플로우
12
+
13
+ ```
14
+ 브레인스토밍 → 서브 프로젝트/태스크 조직화 → 프롬프트 정제 → MCP로 AI 실행
15
+ ```
16
+
17
+ ### 계층 구조
18
+
19
+ ```
20
+ 프로젝트
21
+ ├── 서브 프로젝트 A
22
+ │ ├── 태스크 1 → 프롬프트
23
+ │ ├── 태스크 2 → 프롬프트
24
+ │ └── 태스크 3 → 프롬프트
25
+ └── 서브 프로젝트 B
26
+ ├── 태스크 4 → 프롬프트
27
+ └── 태스크 5 → 프롬프트
28
+ ```
29
+
30
+ ### 태스크 상태 흐름
31
+
32
+ ```
33
+ 💡 Idea → ✏️ Writing → 🚀 Submitted → 🧪 Testing → ✅ Done
34
+ 🔴 Problem
35
+ ```
36
+
37
+ ## 설치
38
+
39
+ ```bash
40
+ npm install -g idea-manager
41
+ ```
42
+
43
+ ## 사용법
44
+
45
+ ### 웹 UI 실행
46
+
47
+ ```bash
48
+ im start
49
+ ```
50
+
51
+ `http://localhost:3456`에서 웹 UI가 열립니다.
52
+
53
+ ```bash
54
+ # 포트 변경
55
+ im start -p 4000
56
+ ```
57
+
58
+ ### MCP Server 실행
59
+
60
+ ```bash
61
+ im mcp
62
+ ```
63
+
64
+ #### Claude Desktop 설정 (claude_desktop_config.json)
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "idea-manager": {
70
+ "command": "npx",
71
+ "args": ["-y", "idea-manager", "mcp"]
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ #### Claude Code 설정
78
+
79
+ ```bash
80
+ claude mcp add idea-manager -- npx -y idea-manager mcp
81
+ ```
82
+
83
+ ### MCP 제공 도구
84
+
85
+ | 도구 | 설명 |
86
+ |------|------|
87
+ | `list-projects` | 프로젝트 목록 조회 |
88
+ | `get-project-context` | 서브 프로젝트 + 태스크 트리 전체 조회 |
89
+ | `get-next-task` | 다음 실행할 태스크와 프롬프트 조회 (status=submitted) |
90
+ | `get-task-prompt` | 특정 태스크의 프롬프트 조회 |
91
+ | `update-status` | 태스크 상태 변경 (idea/writing/submitted/testing/done/problem) |
92
+ | `report-completion` | 태스크 완료 보고 |
93
+
94
+ ## 주요 기능
95
+
96
+ - **탭 기반 멀티 프로젝트** — 브라우저/IDE처럼 여러 프로젝트를 탭으로 동시에 열기, 탭 전환 시 상태 보존
97
+ - **3-패널 워크스페이스** — 브레인스토밍 | 프로젝트 트리 | 태스크 상세, 패널 간 드래그로 크기 조절
98
+ - **트리형 프로젝트 구조** — 서브 프로젝트 아래 태스크가 계층적으로 표시
99
+ - **브레인스토밍 패널** — 자유 형식 메모, 접기/펼치기 가능
100
+ - **프롬프트 에디터** — 태스크별 프롬프트 작성/편집/복사, AI 다듬기
101
+ - **AI 채팅** — 태스크별 AI 대화로 프롬프트 구체화
102
+ - **3탭 대시보드** — 진행 중 / 전체 / 오늘 할 일
103
+ - **키보드 단축키** — Ctrl+Tab/Ctrl+Shift+Tab으로 탭 이동, B: 브레인스토밍 토글, N: 서브 프로젝트 추가, T: 태스크 추가, Cmd+1~6: 상태 변경 (한영 전환 상관없이 동작)
104
+ - **PWA 지원** — 앱으로 설치하여 독립 창에서 사용 가능
105
+ - **Watch 모드** — submitted 태스크를 Claude CLI로 자동 실행, 실시간 진행 표시
106
+ - **MCP Server 내장** — AI 에이전트 자율 실행 지원
107
+ - **로컬 우선** — SQLite 기반, 데이터는 `~/.idea-manager/`에 저장
108
+
109
+ ## 기술 스택
110
+
111
+ | 영역 | 기술 |
112
+ |------|------|
113
+ | Frontend | Next.js 15, React 19, TypeScript, Tailwind CSS 4 |
114
+ | Backend | Next.js API Routes |
115
+ | Database | SQLite (better-sqlite3) |
116
+ | AI | Claude CLI (구독 기반, API 키 불필요) |
117
+ | MCP | Model Context Protocol (stdio) |
118
+ | CLI | Commander.js |
119
+
120
+ ## 요구 사항
121
+
122
+ - **Node.js** 18+
123
+ - **Claude CLI** — AI 채팅/다듬기 기능 사용 시 필요 (Claude 구독 필요). 없어도 태스크 관리, 프롬프트 작성 등 기본 기능은 정상 동작합니다.
124
+
125
+ ## 라이선스
126
+
127
+ MIT
package/README.md CHANGED
@@ -1,67 +1,67 @@
1
1
  # IM (Idea Manager)
2
2
 
3
- **한국어** | [English](README.en.md) | [日本語](README.ja.md) | [中文](README.zh.md)
3
+ **English** | [한국어](README.ko.md) | [日本語](README.ja.md) | [中文](README.zh.md)
4
4
 
5
- > 아이디어에서 실행 가능한 프롬프트까지, 멀티 프로젝트 워크플로우 매니저
5
+ > From ideas to executable prompts a multi-project workflow manager
6
6
 
7
- 여러 프로젝트를 동시에 진행하는 개발자를 위한 태스크 관리 도구입니다. 아이디어를 서브 프로젝트와 태스크로 조직화하고, 태스크별 프롬프트를 정제하여 Claude Code AI 에이전트에게 전달할 있습니다. MCP Server 내장하고 있어 AI 에이전트가 자율적으로 태스크를 가져가 실행할 수 있습니다.
7
+ A task management tool for developers juggling multiple projects simultaneously. Organize ideas into sub-projects and tasks, refine prompts for each task, and hand them off to AI agents like Claude Code. With a built-in MCP Server, AI agents can autonomously pick up and execute tasks.
8
8
 
9
9
  ![IM Workspace](docs/screenshot.png)
10
10
 
11
- ## 핵심 워크플로우
11
+ ## Core Workflow
12
12
 
13
13
  ```
14
- 브레인스토밍서브 프로젝트/태스크 조직화프롬프트 정제MCP로 AI 실행
14
+ BrainstormingOrganize into Sub-projects/TasksRefine PromptsExecute via MCP
15
15
  ```
16
16
 
17
- ### 계층 구조
17
+ ### Hierarchy
18
18
 
19
19
  ```
20
- 프로젝트
21
- ├── 서브 프로젝트 A
22
- │ ├── 태스크 1 → 프롬프트
23
- │ ├── 태스크 2 → 프롬프트
24
- │ └── 태스크 3 → 프롬프트
25
- └── 서브 프로젝트 B
26
- ├── 태스크 4 → 프롬프트
27
- └── 태스크 5 → 프롬프트
20
+ Project
21
+ ├── Sub-project A
22
+ │ ├── Task 1 → Prompt
23
+ │ ├── Task 2 → Prompt
24
+ │ └── Task 3 → Prompt
25
+ └── Sub-project B
26
+ ├── Task 4 → Prompt
27
+ └── Task 5 → Prompt
28
28
  ```
29
29
 
30
- ### 태스크 상태 흐름
30
+ ### Task Status Flow
31
31
 
32
32
  ```
33
33
  💡 Idea → ✏️ Writing → 🚀 Submitted → 🧪 Testing → ✅ Done
34
34
  🔴 Problem
35
35
  ```
36
36
 
37
- ## 설치
37
+ ## Installation
38
38
 
39
39
  ```bash
40
40
  npm install -g idea-manager
41
41
  ```
42
42
 
43
- ## 사용법
43
+ ## Usage
44
44
 
45
- ### UI 실행
45
+ ### Start Web UI
46
46
 
47
47
  ```bash
48
48
  im start
49
49
  ```
50
50
 
51
- `http://localhost:3456`에서 웹 UI가 열립니다.
51
+ Opens the web UI at `http://localhost:3456`.
52
52
 
53
53
  ```bash
54
- # 포트 변경
54
+ # Custom port
55
55
  im start -p 4000
56
56
  ```
57
57
 
58
- ### MCP Server 실행
58
+ ### Start MCP Server
59
59
 
60
60
  ```bash
61
61
  im mcp
62
62
  ```
63
63
 
64
- #### Claude Desktop 설정 (claude_desktop_config.json)
64
+ #### Claude Desktop Configuration (claude_desktop_config.json)
65
65
 
66
66
  ```json
67
67
  {
@@ -74,54 +74,54 @@ im mcp
74
74
  }
75
75
  ```
76
76
 
77
- #### Claude Code 설정
77
+ #### Claude Code Configuration
78
78
 
79
79
  ```bash
80
80
  claude mcp add idea-manager -- npx -y idea-manager mcp
81
81
  ```
82
82
 
83
- ### MCP 제공 도구
84
-
85
- | 도구 | 설명 |
86
- |------|------|
87
- | `list-projects` | 프로젝트 목록 조회 |
88
- | `get-project-context` | 서브 프로젝트 + 태스크 트리 전체 조회 |
89
- | `get-next-task` | 다음 실행할 태스크와 프롬프트 조회 (status=submitted) |
90
- | `get-task-prompt` | 특정 태스크의 프롬프트 조회 |
91
- | `update-status` | 태스크 상태 변경 (idea/writing/submitted/testing/done/problem) |
92
- | `report-completion` | 태스크 완료 보고 |
93
-
94
- ## 주요 기능
95
-
96
- - **탭 기반 멀티 프로젝트** 브라우저/IDE처럼 여러 프로젝트를 탭으로 동시에 열기, 전환 상태 보존
97
- - **3-패널 워크스페이스**브레인스토밍 | 프로젝트 트리 | 태스크 상세, 패널 드래그로 크기 조절
98
- - **트리형 프로젝트 구조** 서브 프로젝트 아래 태스크가 계층적으로 표시
99
- - **브레인스토밍 패널**자유 형식 메모, 접기/펼치기 가능
100
- - **프롬프트 에디터**태스크별 프롬프트 작성/편집/복사, AI 다듬기
101
- - **AI 채팅**태스크별 AI 대화로 프롬프트 구체화
102
- - **3 대시보드**진행 / 전체 / 오늘 할 일
103
- - **키보드 단축키** — Ctrl+Tab/Ctrl+Shift+Tab으로 이동, B: 브레인스토밍 토글, N: 서브 프로젝트 추가, T: 태스크 추가, Cmd+1~6: 상태 변경 (한영 전환 상관없이 동작)
104
- - **PWA 지원**앱으로 설치하여 독립 창에서 사용 가능
105
- - **Watch 모드** — submitted 태스크를 Claude CLI 자동 실행, 실시간 진행 표시
106
- - **MCP Server 내장** AI 에이전트 자율 실행 지원
107
- - **로컬 우선** — SQLite 기반, 데이터는 `~/.idea-manager/`에 저장
108
-
109
- ## 기술 스택
110
-
111
- | 영역 | 기술 |
112
- |------|------|
83
+ ### MCP Tools
84
+
85
+ | Tool | Description |
86
+ |------|-------------|
87
+ | `list-projects` | List all projects |
88
+ | `get-project-context` | Get full sub-project + task tree |
89
+ | `get-next-task` | Get next task to execute (status=submitted) |
90
+ | `get-task-prompt` | Get prompt for a specific task |
91
+ | `update-status` | Change task status (idea/writing/submitted/testing/done/problem) |
92
+ | `report-completion` | Report task completion |
93
+
94
+ ## Key Features
95
+
96
+ - **Tab-based Multi-project** Open multiple projects in tabs like a browser/IDE, state preserved on tab switch
97
+ - **3-Panel Workspace**Brainstorming | Project Tree | Task Detail, drag to resize panels
98
+ - **Tree-structured Projects**Tasks displayed hierarchically under sub-projects
99
+ - **Brainstorming Panel**Free-form notes, collapsible
100
+ - **Prompt Editor**Write/edit/copy prompts per task, AI refinement
101
+ - **AI Chat**Per-task AI conversations to refine prompts
102
+ - **3-Tab Dashboard**Active / All / Today
103
+ - **Keyboard Shortcuts** — Ctrl+Tab/Ctrl+Shift+Tab for tab navigation, B: toggle brainstorm, N: add sub-project, T: add task, Cmd+1~6: change status
104
+ - **PWA Support**Install as an app for a standalone window experience
105
+ - **Watch Mode**Auto-execute submitted tasks via Claude CLI with real-time progress
106
+ - **Built-in MCP Server**Supports autonomous AI agent execution
107
+ - **Local-first** — SQLite-based, data stored in `~/.idea-manager/`
108
+
109
+ ## Tech Stack
110
+
111
+ | Area | Technology |
112
+ |------|------------|
113
113
  | Frontend | Next.js 15, React 19, TypeScript, Tailwind CSS 4 |
114
114
  | Backend | Next.js API Routes |
115
115
  | Database | SQLite (better-sqlite3) |
116
- | AI | Claude CLI (구독 기반, API 불필요) |
116
+ | AI | Claude CLI (subscription-based, no API key needed) |
117
117
  | MCP | Model Context Protocol (stdio) |
118
118
  | CLI | Commander.js |
119
119
 
120
- ## 요구 사항
120
+ ## Requirements
121
121
 
122
122
  - **Node.js** 18+
123
- - **Claude CLI** — AI 채팅/다듬기 기능 사용 필요 (Claude 구독 필요). 없어도 태스크 관리, 프롬프트 작성 기본 기능은 정상 동작합니다.
123
+ - **Claude CLI** — Required for AI chat/refinement features (Claude subscription needed). Core features like task management and prompt editing work without it.
124
124
 
125
- ## 라이선스
125
+ ## License
126
126
 
127
127
  MIT
package/README.zh.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # IM (Idea Manager)
2
2
 
3
- [한국어](README.md) | [English](README.en.md) | [日本語](README.ja.md) | **中文**
3
+ [English](README.md) | [한국어](README.ko.md) | [日本語](README.ja.md) | **中文**
4
4
 
5
5
  > 从创意到可执行提示词 — 多项目工作流管理器
6
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idea-manager",
3
- "version": "0.7.7",
3
+ "version": "0.7.9",
4
4
  "description": "AI 기반 브레인스토밍 → 구조화 → 프롬프트 생성 도구. MCP Server 내장.",
5
5
  "keywords": [
6
6
  "brainstorm",
@@ -0,0 +1,118 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { getProject } from '@/lib/db/queries/projects';
3
+ import { execFile } from 'child_process';
4
+ import { existsSync, readdirSync, statSync } from 'fs';
5
+ import path from 'path';
6
+ import type { IGitSyncResult } from '@/types';
7
+
8
+ function gitPull(cwd: string): Promise<{ stdout: string; stderr: string }> {
9
+ return new Promise((resolve, reject) => {
10
+ execFile('git', ['pull'], { cwd, timeout: 15000 }, (err, stdout, stderr) => {
11
+ if (err) reject(err);
12
+ else resolve({ stdout, stderr });
13
+ });
14
+ });
15
+ }
16
+
17
+ async function syncOneRepo(dirPath: string, name: string): Promise<IGitSyncResult> {
18
+ try {
19
+ const { stdout, stderr } = await gitPull(dirPath);
20
+ const message = (stdout || stderr || '').trim().slice(0, 500);
21
+ return {
22
+ projectId: name,
23
+ projectName: name,
24
+ projectPath: dirPath,
25
+ status: 'success',
26
+ message: message || 'Already up to date.',
27
+ };
28
+ } catch (err: unknown) {
29
+ const message = err instanceof Error ? err.message.slice(0, 500) : 'Unknown error';
30
+ return {
31
+ projectId: name,
32
+ projectName: name,
33
+ projectPath: dirPath,
34
+ status: 'error',
35
+ message,
36
+ };
37
+ }
38
+ }
39
+
40
+ function findGitRepos(rootPath: string): { name: string; path: string }[] {
41
+ // If root itself is a git repo
42
+ if (existsSync(path.join(rootPath, '.git'))) {
43
+ return [{ name: path.basename(rootPath), path: rootPath }];
44
+ }
45
+
46
+ // Otherwise scan immediate subdirectories
47
+ const repos: { name: string; path: string }[] = [];
48
+ try {
49
+ const entries = readdirSync(rootPath);
50
+ for (const entry of entries) {
51
+ if (entry.startsWith('.')) continue;
52
+ const fullPath = path.join(rootPath, entry);
53
+ try {
54
+ if (statSync(fullPath).isDirectory() && existsSync(path.join(fullPath, '.git'))) {
55
+ repos.push({ name: entry, path: fullPath });
56
+ }
57
+ } catch {
58
+ // skip inaccessible dirs
59
+ }
60
+ }
61
+ } catch {
62
+ // skip
63
+ }
64
+ return repos;
65
+ }
66
+
67
+ export async function POST(
68
+ _request: NextRequest,
69
+ { params }: { params: Promise<{ id: string }> },
70
+ ) {
71
+ const { id } = await params;
72
+ const project = getProject(id);
73
+
74
+ if (!project) {
75
+ return NextResponse.json({ error: 'Project not found' }, { status: 404 });
76
+ }
77
+
78
+ if (!project.project_path) {
79
+ return NextResponse.json([{
80
+ projectId: project.id,
81
+ projectName: project.name,
82
+ projectPath: '',
83
+ status: 'no-path',
84
+ message: 'No folder linked',
85
+ }] satisfies IGitSyncResult[]);
86
+ }
87
+
88
+ const projectPath = project.project_path;
89
+
90
+ if (!existsSync(projectPath)) {
91
+ return NextResponse.json([{
92
+ projectId: project.id,
93
+ projectName: project.name,
94
+ projectPath,
95
+ status: 'error',
96
+ message: 'Directory not found',
97
+ }] satisfies IGitSyncResult[]);
98
+ }
99
+
100
+ const repos = findGitRepos(projectPath);
101
+
102
+ if (repos.length === 0) {
103
+ return NextResponse.json([{
104
+ projectId: project.id,
105
+ projectName: project.name,
106
+ projectPath,
107
+ status: 'no-git',
108
+ message: 'No git repositories found',
109
+ }] satisfies IGitSyncResult[]);
110
+ }
111
+
112
+ const results: IGitSyncResult[] = [];
113
+ for (const repo of repos) {
114
+ results.push(await syncOneRepo(repo.path, repo.name));
115
+ }
116
+
117
+ return NextResponse.json(results);
118
+ }
@@ -0,0 +1,90 @@
1
+ 'use client';
2
+
3
+ import { useEffect, useRef } from 'react';
4
+ import type { IGitSyncResult } from '@/types';
5
+
6
+ const STATUS_STYLE: Record<IGitSyncResult['status'], { icon: string; color: string }> = {
7
+ success: { icon: '\u2705', color: 'text-success' },
8
+ error: { icon: '\u274C', color: 'text-destructive' },
9
+ 'no-git': { icon: '\u2796', color: 'text-muted-foreground' },
10
+ 'no-path': { icon: '\u2796', color: 'text-muted-foreground' },
11
+ };
12
+
13
+ export default function GitSyncResultsModal({
14
+ open,
15
+ results,
16
+ onClose,
17
+ }: {
18
+ open: boolean;
19
+ results: IGitSyncResult[];
20
+ onClose: () => void;
21
+ }) {
22
+ const overlayRef = useRef<HTMLDivElement>(null);
23
+
24
+ useEffect(() => {
25
+ if (!open) return;
26
+ const handler = (e: KeyboardEvent) => {
27
+ if (e.key === 'Escape') onClose();
28
+ };
29
+ window.addEventListener('keydown', handler);
30
+ return () => window.removeEventListener('keydown', handler);
31
+ }, [open, onClose]);
32
+
33
+ if (!open) return null;
34
+
35
+ const successCount = results.filter(r => r.status === 'success').length;
36
+ const errorCount = results.filter(r => r.status === 'error').length;
37
+ const skipCount = results.filter(r => r.status === 'no-git' || r.status === 'no-path').length;
38
+
39
+ return (
40
+ <div
41
+ ref={overlayRef}
42
+ onClick={(e) => { if (e.target === overlayRef.current) onClose(); }}
43
+ className="fixed inset-0 z-50 flex items-center justify-center"
44
+ style={{ background: 'rgba(0,0,0,0.5)', backdropFilter: 'blur(2px)' }}
45
+ >
46
+ <div className="bg-card border border-border rounded-xl shadow-2xl shadow-black/40
47
+ w-full max-w-md mx-4 animate-dialog-in">
48
+ <div className="p-5 border-b border-border">
49
+ <h3 className="text-sm font-semibold text-foreground">Git Sync Results</h3>
50
+ <p className="text-xs text-muted-foreground mt-1">
51
+ {successCount} synced, {errorCount} failed, {skipCount} skipped
52
+ </p>
53
+ </div>
54
+
55
+ <div className="max-h-64 overflow-y-auto p-3 space-y-1.5">
56
+ {results.length === 0 ? (
57
+ <p className="text-xs text-muted-foreground text-center py-4">
58
+ No projects with linked folders
59
+ </p>
60
+ ) : (
61
+ results.map((r) => {
62
+ const style = STATUS_STYLE[r.status];
63
+ return (
64
+ <div key={r.projectId} className="flex items-start gap-2 p-2 rounded-lg bg-muted/50">
65
+ <span className="text-sm flex-shrink-0">{style.icon}</span>
66
+ <div className="flex-1 min-w-0">
67
+ <div className="text-xs font-medium truncate">{r.projectName}</div>
68
+ <div className={`text-xs ${style.color} truncate`} title={r.message}>
69
+ {r.message}
70
+ </div>
71
+ </div>
72
+ </div>
73
+ );
74
+ })
75
+ )}
76
+ </div>
77
+
78
+ <div className="flex justify-end px-5 pb-4 pt-2">
79
+ <button
80
+ onClick={onClose}
81
+ className="px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground
82
+ bg-muted hover:bg-card-hover border border-border rounded-md transition-colors"
83
+ >
84
+ Close
85
+ </button>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ );
90
+ }
@@ -8,7 +8,8 @@ import TaskDetail from '@/components/task/TaskDetail';
8
8
  import DirectoryPicker from '@/components/DirectoryPicker';
9
9
  import ConfirmDialog from '@/components/ui/ConfirmDialog';
10
10
  import AiPolicyModal from '@/components/ui/AiPolicyModal';
11
- import type { ISubProject, ITask, TaskStatus, ISubProjectWithStats } from '@/types';
11
+ import GitSyncResultsModal from '@/components/dashboard/GitSyncResultsModal';
12
+ import type { ISubProject, ITask, TaskStatus, ISubProjectWithStats, IGitSyncResult } from '@/types';
12
13
 
13
14
  interface IProject {
14
15
  id: string;
@@ -58,6 +59,10 @@ export default function WorkspacePanel({
58
59
  const [showBrainstorm, setShowBrainstorm] = useState(true);
59
60
  const [newSubName, setNewSubName] = useState('');
60
61
  const [showAiPolicy, setShowAiPolicy] = useState(false);
62
+ const [syncing, setSyncing] = useState(false);
63
+ const [syncResults, setSyncResults] = useState<IGitSyncResult[] | null>(null);
64
+ const [lastSyncTime, setLastSyncTime] = useState<Date | null>(null);
65
+ const syncingRef = useRef(false);
61
66
 
62
67
  // Resizable panel widths
63
68
  const [leftWidth, setLeftWidth] = useState(500);
@@ -279,6 +284,35 @@ export default function WorkspacePanel({
279
284
  }
280
285
  };
281
286
 
287
+ const handleGitSync = useCallback(async (silent = false) => {
288
+ if (syncingRef.current) return;
289
+ syncingRef.current = true;
290
+ if (!silent) setSyncing(true);
291
+ try {
292
+ const res = await fetch(`/api/projects/${id}/git-sync`, { method: 'POST' });
293
+ if (res.ok) {
294
+ const results: IGitSyncResult[] = await res.json();
295
+ setLastSyncTime(new Date());
296
+ if (!silent) {
297
+ setSyncResults(results);
298
+ }
299
+ }
300
+ } catch {
301
+ // silent fail
302
+ } finally {
303
+ syncingRef.current = false;
304
+ if (!silent) setSyncing(false);
305
+ }
306
+ }, [id]);
307
+
308
+ // Auto git-sync every 30 minutes
309
+ useEffect(() => {
310
+ if (!project?.project_path) return;
311
+ const INTERVAL_MS = 30 * 60 * 1000;
312
+ const timer = setInterval(() => handleGitSync(true), INTERVAL_MS);
313
+ return () => clearInterval(timer);
314
+ }, [project?.project_path, handleGitSync]);
315
+
282
316
  const handleToggleWatch = async () => {
283
317
  if (!project) return;
284
318
  const res = await fetch(`/api/projects/${id}`, {
@@ -370,7 +404,24 @@ export default function WorkspacePanel({
370
404
  }`}>
371
405
  AI Policy{project.ai_context ? ' *' : ''}
372
406
  </button>
373
- {!project.project_path && (
407
+ {project.project_path ? (
408
+ <div className="flex items-center gap-1.5">
409
+ <button
410
+ onClick={() => handleGitSync(false)}
411
+ disabled={syncing}
412
+ className="px-3 py-1.5 text-xs bg-muted hover:bg-card-hover text-foreground border border-border rounded-md transition-colors disabled:opacity-50 flex items-center gap-1.5"
413
+ title={lastSyncTime ? `Last sync: ${lastSyncTime.toLocaleTimeString()}` : 'Git pull'}
414
+ >
415
+ <span className={syncing ? 'animate-spin' : ''}>&#x21bb;</span>
416
+ {syncing ? 'Syncing...' : 'Git Sync'}
417
+ </button>
418
+ {lastSyncTime && (
419
+ <span className="text-xs text-muted-foreground">
420
+ {lastSyncTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
421
+ </span>
422
+ )}
423
+ </div>
424
+ ) : (
374
425
  <button onClick={() => setShowDirPicker(true)}
375
426
  className="px-3 py-1.5 text-xs bg-muted hover:bg-card-hover text-foreground border border-border rounded-md transition-colors">
376
427
  Link folder
@@ -450,6 +501,11 @@ export default function WorkspacePanel({
450
501
  onConfirm={handleConfirmAction} onCancel={() => setConfirmAction(null)} />
451
502
  <AiPolicyModal open={showAiPolicy} content={project.ai_context || ''}
452
503
  onSave={handleSaveAiPolicy} onClose={() => setShowAiPolicy(false)} />
504
+ <GitSyncResultsModal
505
+ open={!!syncResults}
506
+ results={syncResults || []}
507
+ onClose={() => setSyncResults(null)}
508
+ />
453
509
  </div>
454
510
  );
455
511
  }
@@ -63,6 +63,14 @@ export interface ITaskConversation {
63
63
  created_at: string;
64
64
  }
65
65
 
66
+ export interface IGitSyncResult {
67
+ projectId: string;
68
+ projectName: string;
69
+ projectPath: string;
70
+ status: 'success' | 'error' | 'no-git' | 'no-path';
71
+ message: string;
72
+ }
73
+
66
74
  export interface ISubProjectWithStats extends ISubProject {
67
75
  task_count: number;
68
76
  active_count: number;
package/README.en.md DELETED
@@ -1,127 +0,0 @@
1
- # IM (Idea Manager)
2
-
3
- [한국어](README.md) | **English** | [日本語](README.ja.md) | [中文](README.zh.md)
4
-
5
- > From ideas to executable prompts — a multi-project workflow manager
6
-
7
- A task management tool for developers juggling multiple projects simultaneously. Organize ideas into sub-projects and tasks, refine prompts for each task, and hand them off to AI agents like Claude Code. With a built-in MCP Server, AI agents can autonomously pick up and execute tasks.
8
-
9
- ![IM Workspace](docs/screenshot.png)
10
-
11
- ## Core Workflow
12
-
13
- ```
14
- Brainstorming → Organize into Sub-projects/Tasks → Refine Prompts → Execute via MCP
15
- ```
16
-
17
- ### Hierarchy
18
-
19
- ```
20
- Project
21
- ├── Sub-project A
22
- │ ├── Task 1 → Prompt
23
- │ ├── Task 2 → Prompt
24
- │ └── Task 3 → Prompt
25
- └── Sub-project B
26
- ├── Task 4 → Prompt
27
- └── Task 5 → Prompt
28
- ```
29
-
30
- ### Task Status Flow
31
-
32
- ```
33
- 💡 Idea → ✏️ Writing → 🚀 Submitted → 🧪 Testing → ✅ Done
34
- 🔴 Problem
35
- ```
36
-
37
- ## Installation
38
-
39
- ```bash
40
- npm install -g idea-manager
41
- ```
42
-
43
- ## Usage
44
-
45
- ### Start Web UI
46
-
47
- ```bash
48
- im start
49
- ```
50
-
51
- Opens the web UI at `http://localhost:3456`.
52
-
53
- ```bash
54
- # Custom port
55
- im start -p 4000
56
- ```
57
-
58
- ### Start MCP Server
59
-
60
- ```bash
61
- im mcp
62
- ```
63
-
64
- #### Claude Desktop Configuration (claude_desktop_config.json)
65
-
66
- ```json
67
- {
68
- "mcpServers": {
69
- "idea-manager": {
70
- "command": "npx",
71
- "args": ["-y", "idea-manager", "mcp"]
72
- }
73
- }
74
- }
75
- ```
76
-
77
- #### Claude Code Configuration
78
-
79
- ```bash
80
- claude mcp add idea-manager -- npx -y idea-manager mcp
81
- ```
82
-
83
- ### MCP Tools
84
-
85
- | Tool | Description |
86
- |------|-------------|
87
- | `list-projects` | List all projects |
88
- | `get-project-context` | Get full sub-project + task tree |
89
- | `get-next-task` | Get next task to execute (status=submitted) |
90
- | `get-task-prompt` | Get prompt for a specific task |
91
- | `update-status` | Change task status (idea/writing/submitted/testing/done/problem) |
92
- | `report-completion` | Report task completion |
93
-
94
- ## Key Features
95
-
96
- - **Tab-based Multi-project** — Open multiple projects in tabs like a browser/IDE, state preserved on tab switch
97
- - **3-Panel Workspace** — Brainstorming | Project Tree | Task Detail, drag to resize panels
98
- - **Tree-structured Projects** — Tasks displayed hierarchically under sub-projects
99
- - **Brainstorming Panel** — Free-form notes, collapsible
100
- - **Prompt Editor** — Write/edit/copy prompts per task, AI refinement
101
- - **AI Chat** — Per-task AI conversations to refine prompts
102
- - **3-Tab Dashboard** — Active / All / Today
103
- - **Keyboard Shortcuts** — Ctrl+Tab/Ctrl+Shift+Tab for tab navigation, B: toggle brainstorm, N: add sub-project, T: add task, Cmd+1~6: change status
104
- - **PWA Support** — Install as an app for a standalone window experience
105
- - **Watch Mode** — Auto-execute submitted tasks via Claude CLI with real-time progress
106
- - **Built-in MCP Server** — Supports autonomous AI agent execution
107
- - **Local-first** — SQLite-based, data stored in `~/.idea-manager/`
108
-
109
- ## Tech Stack
110
-
111
- | Area | Technology |
112
- |------|------------|
113
- | Frontend | Next.js 15, React 19, TypeScript, Tailwind CSS 4 |
114
- | Backend | Next.js API Routes |
115
- | Database | SQLite (better-sqlite3) |
116
- | AI | Claude CLI (subscription-based, no API key needed) |
117
- | MCP | Model Context Protocol (stdio) |
118
- | CLI | Commander.js |
119
-
120
- ## Requirements
121
-
122
- - **Node.js** 18+
123
- - **Claude CLI** — Required for AI chat/refinement features (Claude subscription needed). Core features like task management and prompt editing work without it.
124
-
125
- ## License
126
-
127
- MIT