claude-task-viewer 1.5.0 → 1.6.0
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.md +6 -0
- package/package.json +1 -1
- package/public/index.html +3 -47
- package/server.js +18 -1
package/README.md
CHANGED
|
@@ -26,6 +26,9 @@ Tasks can block other tasks. The viewer shows these relationships clearly — bl
|
|
|
26
26
|
### Notes
|
|
27
27
|
Add context to any task. Your notes are appended to the task description, so Claude sees them when it reads the task. Use this to clarify requirements, add constraints, or redirect work — all without interrupting Claude's flow.
|
|
28
28
|
|
|
29
|
+
### Search
|
|
30
|
+
Find tasks instantly. Type in the search box to filter across all columns by subject or description. Case-insensitive, real-time results.
|
|
31
|
+
|
|
29
32
|
### Project Filtering
|
|
30
33
|
Filter tasks by project using the dropdown. Working on multiple codebases? See only what's relevant. Combine with the session filter to show just active sessions for a specific project.
|
|
31
34
|
|
|
@@ -90,6 +93,9 @@ PORT=8080 npx claude-task-viewer
|
|
|
90
93
|
|
|
91
94
|
# Open browser automatically
|
|
92
95
|
npx claude-task-viewer --open
|
|
96
|
+
|
|
97
|
+
# Use a different Claude config directory (for multiple accounts)
|
|
98
|
+
npx claude-task-viewer --dir=~/.claude-work
|
|
93
99
|
```
|
|
94
100
|
|
|
95
101
|
## API
|
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -469,26 +469,6 @@
|
|
|
469
469
|
color: var(--accent);
|
|
470
470
|
}
|
|
471
471
|
|
|
472
|
-
.search-input {
|
|
473
|
-
background: var(--bg-elevated);
|
|
474
|
-
border: 1px solid var(--border);
|
|
475
|
-
border-radius: 6px;
|
|
476
|
-
padding: 8px 12px;
|
|
477
|
-
font-family: var(--mono);
|
|
478
|
-
font-size: 12px;
|
|
479
|
-
color: var(--text-primary);
|
|
480
|
-
width: 200px;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
.search-input:focus {
|
|
484
|
-
outline: none;
|
|
485
|
-
border-color: var(--accent);
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
.search-input::placeholder {
|
|
489
|
-
color: var(--text-muted);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
472
|
.icon-btn {
|
|
493
473
|
width: 32px;
|
|
494
474
|
height: 32px;
|
|
@@ -1039,8 +1019,6 @@
|
|
|
1039
1019
|
<p id="session-meta" class="view-meta"></p>
|
|
1040
1020
|
</div>
|
|
1041
1021
|
<div class="view-actions">
|
|
1042
|
-
<input type="text" id="task-search" class="search-input"
|
|
1043
|
-
placeholder="Search tasks..." oninput="searchTasks(this.value)">
|
|
1044
1022
|
<div class="view-progress">
|
|
1045
1023
|
<div class="progress-bar">
|
|
1046
1024
|
<div id="progress-bar" class="progress-fill" style="width: 0%"></div>
|
|
@@ -1112,7 +1090,6 @@
|
|
|
1112
1090
|
let viewMode = 'session';
|
|
1113
1091
|
let sessionFilter = localStorage.getItem('sessionFilter') || 'all'; // 'all' or 'active'
|
|
1114
1092
|
let filterProject = null; // null = all projects, or project path to filter
|
|
1115
|
-
let searchQuery = '';
|
|
1116
1093
|
|
|
1117
1094
|
// DOM
|
|
1118
1095
|
const sessionsList = document.getElementById('sessions-list');
|
|
@@ -1184,7 +1161,6 @@
|
|
|
1184
1161
|
async function fetchTasks(sessionId) {
|
|
1185
1162
|
try {
|
|
1186
1163
|
viewMode = 'session';
|
|
1187
|
-
clearSearch();
|
|
1188
1164
|
const res = await fetch(`/api/sessions/${sessionId}`);
|
|
1189
1165
|
currentTasks = await res.json();
|
|
1190
1166
|
currentSessionId = sessionId;
|
|
@@ -1198,7 +1174,6 @@
|
|
|
1198
1174
|
try {
|
|
1199
1175
|
viewMode = 'all';
|
|
1200
1176
|
currentSessionId = null;
|
|
1201
|
-
clearSearch();
|
|
1202
1177
|
const res = await fetch('/api/tasks/all');
|
|
1203
1178
|
let tasks = await res.json();
|
|
1204
1179
|
if (filterProject) {
|
|
@@ -1336,17 +1311,9 @@
|
|
|
1336
1311
|
}
|
|
1337
1312
|
|
|
1338
1313
|
function renderKanban() {
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
t.subject.toLowerCase().includes(searchQuery) ||
|
|
1343
|
-
(t.description && t.description.toLowerCase().includes(searchQuery))
|
|
1344
|
-
);
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
const pending = filteredTasks.filter(t => t.status === 'pending');
|
|
1348
|
-
const inProgress = filteredTasks.filter(t => t.status === 'in_progress');
|
|
1349
|
-
const completed = filteredTasks.filter(t => t.status === 'completed');
|
|
1314
|
+
const pending = currentTasks.filter(t => t.status === 'pending');
|
|
1315
|
+
const inProgress = currentTasks.filter(t => t.status === 'in_progress');
|
|
1316
|
+
const completed = currentTasks.filter(t => t.status === 'completed');
|
|
1350
1317
|
|
|
1351
1318
|
pendingCount.textContent = pending.length;
|
|
1352
1319
|
inProgressCount.textContent = inProgress.length;
|
|
@@ -1538,17 +1505,6 @@
|
|
|
1538
1505
|
showAllTasks();
|
|
1539
1506
|
}
|
|
1540
1507
|
|
|
1541
|
-
function searchTasks(query) {
|
|
1542
|
-
searchQuery = query.toLowerCase();
|
|
1543
|
-
renderKanban();
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
function clearSearch() {
|
|
1547
|
-
searchQuery = '';
|
|
1548
|
-
const searchInput = document.getElementById('task-search');
|
|
1549
|
-
if (searchInput) searchInput.value = '';
|
|
1550
|
-
}
|
|
1551
|
-
|
|
1552
1508
|
function updateProjectDropdown() {
|
|
1553
1509
|
const dropdown = document.getElementById('project-filter');
|
|
1554
1510
|
const projects = [...new Set(sessions.map(s => s.project).filter(Boolean))].sort();
|
package/server.js
CHANGED
|
@@ -10,7 +10,24 @@ const os = require('os');
|
|
|
10
10
|
|
|
11
11
|
const app = express();
|
|
12
12
|
const PORT = process.env.PORT || 3456;
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
// Parse --dir flag for custom Claude directory
|
|
15
|
+
function getClaudeDir() {
|
|
16
|
+
const dirIndex = process.argv.findIndex(arg => arg.startsWith('--dir'));
|
|
17
|
+
if (dirIndex !== -1) {
|
|
18
|
+
const arg = process.argv[dirIndex];
|
|
19
|
+
if (arg.includes('=')) {
|
|
20
|
+
const dir = arg.split('=')[1];
|
|
21
|
+
return dir.startsWith('~') ? dir.replace('~', os.homedir()) : dir;
|
|
22
|
+
} else if (process.argv[dirIndex + 1]) {
|
|
23
|
+
const dir = process.argv[dirIndex + 1];
|
|
24
|
+
return dir.startsWith('~') ? dir.replace('~', os.homedir()) : dir;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return process.env.CLAUDE_DIR || path.join(os.homedir(), '.claude');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const CLAUDE_DIR = getClaudeDir();
|
|
14
31
|
const TASKS_DIR = path.join(CLAUDE_DIR, 'tasks');
|
|
15
32
|
const PROJECTS_DIR = path.join(CLAUDE_DIR, 'projects');
|
|
16
33
|
|