agenthud 0.7.1 → 0.7.2
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 +3 -3
- package/dist/index.js +1 -1
- package/dist/{main-LKANZYXL.js → main-I7XDIQE3.js} +106 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -156,15 +156,15 @@ Shows activity from your other Claude Code projects:
|
|
|
156
156
|
|
|
157
157
|
```
|
|
158
158
|
┌─ Other Sessions ─────────────────────────────────────┐
|
|
159
|
-
│
|
|
159
|
+
│ dotfiles, pain-radar, myapp +4 | * 1 active │
|
|
160
160
|
│ │
|
|
161
|
-
│
|
|
161
|
+
│ * dotfiles (2m ago) │
|
|
162
162
|
│ "Updated the config file as requested..." │
|
|
163
163
|
└──────────────────────────────────────────────────────┘
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
- **Project names**: Shows up to 3 recent projects, +N for more
|
|
167
|
-
- **Active indicator**:
|
|
167
|
+
- **Active indicator**: `*` active (within 5 min), `o` inactive
|
|
168
168
|
- **Last message**: Most recent assistant response from that session
|
|
169
169
|
|
|
170
170
|
## Keyboard
|
package/dist/index.js
CHANGED
|
@@ -199,16 +199,18 @@ function runInit(cwd = process.cwd()) {
|
|
|
199
199
|
} else {
|
|
200
200
|
result.skipped.push(".agenthud/config.yaml");
|
|
201
201
|
}
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
} else {
|
|
206
|
-
const content = readFileSync3(".gitignore", "utf-8");
|
|
207
|
-
if (!content.includes(".agenthud/")) {
|
|
208
|
-
appendFileSync(".gitignore", "\n.agenthud/\n");
|
|
202
|
+
if (existsSync2(".git")) {
|
|
203
|
+
if (!existsSync2(".gitignore")) {
|
|
204
|
+
writeFileSync(".gitignore", ".agenthud/\n");
|
|
209
205
|
result.created.push(".gitignore");
|
|
210
206
|
} else {
|
|
211
|
-
|
|
207
|
+
const content = readFileSync3(".gitignore", "utf-8");
|
|
208
|
+
if (!content.includes(".agenthud/")) {
|
|
209
|
+
appendFileSync(".gitignore", "\n.agenthud/\n");
|
|
210
|
+
result.created.push(".gitignore");
|
|
211
|
+
} else {
|
|
212
|
+
result.skipped.push(".gitignore");
|
|
213
|
+
}
|
|
212
214
|
}
|
|
213
215
|
}
|
|
214
216
|
if (!existsSync2(".git")) {
|
|
@@ -226,7 +228,7 @@ function runInit(cwd = process.cwd()) {
|
|
|
226
228
|
}
|
|
227
229
|
|
|
228
230
|
// src/data/sessionAvailability.ts
|
|
229
|
-
import { existsSync as existsSync4 } from "fs";
|
|
231
|
+
import { existsSync as existsSync4, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
|
|
230
232
|
import { homedir as homedir3 } from "os";
|
|
231
233
|
import { basename as basename2, join as join4 } from "path";
|
|
232
234
|
|
|
@@ -507,10 +509,82 @@ function getOtherSessionsData(currentProjectPath, options = {}) {
|
|
|
507
509
|
}
|
|
508
510
|
|
|
509
511
|
// src/data/sessionAvailability.ts
|
|
512
|
+
function shortenPath(path) {
|
|
513
|
+
const home = homedir3();
|
|
514
|
+
if (path === home) {
|
|
515
|
+
return "~";
|
|
516
|
+
}
|
|
517
|
+
if (path.startsWith(home + "/") || path.startsWith(home + "\\")) {
|
|
518
|
+
return "~" + path.slice(home.length);
|
|
519
|
+
}
|
|
520
|
+
return path;
|
|
521
|
+
}
|
|
522
|
+
var PROJECT_INDICATORS = [
|
|
523
|
+
".git",
|
|
524
|
+
// Git repository
|
|
525
|
+
"package.json",
|
|
526
|
+
// Node.js
|
|
527
|
+
"Cargo.toml",
|
|
528
|
+
// Rust
|
|
529
|
+
"pyproject.toml",
|
|
530
|
+
// Python (modern)
|
|
531
|
+
"setup.py",
|
|
532
|
+
// Python (legacy)
|
|
533
|
+
"go.mod",
|
|
534
|
+
// Go
|
|
535
|
+
"Makefile",
|
|
536
|
+
// Make-based projects
|
|
537
|
+
"CMakeLists.txt",
|
|
538
|
+
// CMake projects
|
|
539
|
+
"pom.xml",
|
|
540
|
+
// Java Maven
|
|
541
|
+
"build.gradle",
|
|
542
|
+
// Java Gradle
|
|
543
|
+
"Gemfile",
|
|
544
|
+
// Ruby
|
|
545
|
+
"composer.json"
|
|
546
|
+
// PHP
|
|
547
|
+
];
|
|
548
|
+
function isDevProject(projectPath) {
|
|
549
|
+
for (const indicator of PROJECT_INDICATORS) {
|
|
550
|
+
if (existsSync4(join4(projectPath, indicator))) {
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
510
556
|
function getSessionPath(projectPath) {
|
|
511
557
|
const encoded = projectPath.replace(/[/\\]/g, "-");
|
|
512
558
|
return join4(homedir3(), ".claude", "projects", encoded);
|
|
513
559
|
}
|
|
560
|
+
function getProjectMostRecentMtime(encodedPath) {
|
|
561
|
+
const projectDir = join4(homedir3(), ".claude", "projects", encodedPath);
|
|
562
|
+
if (!existsSync4(projectDir)) {
|
|
563
|
+
return 0;
|
|
564
|
+
}
|
|
565
|
+
let files;
|
|
566
|
+
try {
|
|
567
|
+
files = readdirSync2(projectDir);
|
|
568
|
+
} catch {
|
|
569
|
+
return 0;
|
|
570
|
+
}
|
|
571
|
+
const jsonlFiles = files.filter((f) => f.endsWith(".jsonl"));
|
|
572
|
+
if (jsonlFiles.length === 0) {
|
|
573
|
+
return 0;
|
|
574
|
+
}
|
|
575
|
+
let latestMtime = 0;
|
|
576
|
+
for (const file of jsonlFiles) {
|
|
577
|
+
const filePath = join4(projectDir, file);
|
|
578
|
+
try {
|
|
579
|
+
const stat = statSync2(filePath);
|
|
580
|
+
if (stat.mtimeMs && stat.mtimeMs > latestMtime) {
|
|
581
|
+
latestMtime = stat.mtimeMs;
|
|
582
|
+
}
|
|
583
|
+
} catch {
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return latestMtime;
|
|
587
|
+
}
|
|
514
588
|
function hasCurrentProjectSession(cwd) {
|
|
515
589
|
const sessionPath = getSessionPath(cwd);
|
|
516
590
|
return existsSync4(sessionPath);
|
|
@@ -518,7 +592,13 @@ function hasCurrentProjectSession(cwd) {
|
|
|
518
592
|
function getProjectsWithSessions(currentPath) {
|
|
519
593
|
const allProjects = getAllProjects();
|
|
520
594
|
const currentEncoded = currentPath.replace(/[/\\]/g, "-");
|
|
521
|
-
|
|
595
|
+
const projectsWithMtime = allProjects.filter((p) => p.encodedPath !== currentEncoded).filter((p) => existsSync4(p.decodedPath)).filter((p) => isDevProject(p.decodedPath)).map((p) => ({
|
|
596
|
+
name: basename2(p.decodedPath),
|
|
597
|
+
path: p.decodedPath,
|
|
598
|
+
mtime: getProjectMostRecentMtime(p.encodedPath)
|
|
599
|
+
}));
|
|
600
|
+
projectsWithMtime.sort((a, b) => b.mtime - a.mtime);
|
|
601
|
+
return projectsWithMtime.map(({ name, path }) => ({ name, path }));
|
|
522
602
|
}
|
|
523
603
|
function checkSessionAvailability(cwd) {
|
|
524
604
|
const hasCurrentSession = hasCurrentProjectSession(cwd);
|
|
@@ -787,7 +867,7 @@ function parseConfig() {
|
|
|
787
867
|
}
|
|
788
868
|
|
|
789
869
|
// src/data/claude.ts
|
|
790
|
-
import { existsSync as existsSync6, readdirSync as
|
|
870
|
+
import { existsSync as existsSync6, readdirSync as readdirSync3, readFileSync as readFileSync6, statSync as statSync3 } from "fs";
|
|
791
871
|
import { homedir as homedir4 } from "os";
|
|
792
872
|
import { basename as basename3, join as join5 } from "path";
|
|
793
873
|
|
|
@@ -826,7 +906,7 @@ function findActiveSession(sessionDir, sessionTimeout) {
|
|
|
826
906
|
if (!existsSync6(sessionDir)) {
|
|
827
907
|
return null;
|
|
828
908
|
}
|
|
829
|
-
const files =
|
|
909
|
+
const files = readdirSync3(sessionDir);
|
|
830
910
|
const jsonlFiles = files.filter((f) => f.endsWith(".jsonl"));
|
|
831
911
|
if (jsonlFiles.length === 0) {
|
|
832
912
|
return null;
|
|
@@ -836,7 +916,7 @@ function findActiveSession(sessionDir, sessionTimeout) {
|
|
|
836
916
|
let latestSize = 0;
|
|
837
917
|
for (const file of jsonlFiles) {
|
|
838
918
|
const filePath = join5(sessionDir, file);
|
|
839
|
-
const stat =
|
|
919
|
+
const stat = statSync3(filePath);
|
|
840
920
|
if (stat.mtimeMs > latestMtime || stat.mtimeMs === latestMtime && stat.size > latestSize) {
|
|
841
921
|
latestMtime = stat.mtimeMs;
|
|
842
922
|
latestSize = stat.size;
|
|
@@ -875,12 +955,12 @@ function getSubagentFiles(sessionFile) {
|
|
|
875
955
|
return [];
|
|
876
956
|
}
|
|
877
957
|
try {
|
|
878
|
-
const files =
|
|
958
|
+
const files = readdirSync3(subagentsDir).filter(
|
|
879
959
|
(f) => f.endsWith(".jsonl")
|
|
880
960
|
);
|
|
881
961
|
const fileInfos = files.map((file) => {
|
|
882
962
|
const filePath = join5(subagentsDir, file);
|
|
883
|
-
const stat =
|
|
963
|
+
const stat = statSync3(filePath);
|
|
884
964
|
return { filePath, mtimeMs: stat.mtimeMs };
|
|
885
965
|
});
|
|
886
966
|
fileInfos.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
@@ -1084,7 +1164,7 @@ function parseSessionState(sessionFile, maxActivities = DEFAULT_MAX_ACTIVITIES)
|
|
|
1084
1164
|
const subagentsDir = join5(sessionFile.replace(/\.jsonl$/, ""), "subagents");
|
|
1085
1165
|
if (existsSync6(subagentsDir)) {
|
|
1086
1166
|
try {
|
|
1087
|
-
const subagentFiles2 =
|
|
1167
|
+
const subagentFiles2 = readdirSync3(subagentsDir).filter(
|
|
1088
1168
|
(f) => f.endsWith(".jsonl")
|
|
1089
1169
|
);
|
|
1090
1170
|
for (const file of subagentFiles2) {
|
|
@@ -3985,12 +4065,16 @@ function main() {
|
|
|
3985
4065
|
const sessionAvailability = checkSessionAvailability(cwd);
|
|
3986
4066
|
if (!sessionAvailability.hasCurrentSession) {
|
|
3987
4067
|
if (sessionAvailability.otherProjects.length > 0) {
|
|
3988
|
-
console.log("\
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
);
|
|
3993
|
-
|
|
4068
|
+
console.log("\nProjects with Claude Code sessions:");
|
|
4069
|
+
sessionAvailability.otherProjects.forEach((project, index) => {
|
|
4070
|
+
const shortPath = shortenPath(project.path);
|
|
4071
|
+
console.log(` ${index + 1}. ${project.name} (${shortPath})`);
|
|
4072
|
+
});
|
|
4073
|
+
const firstProject = sessionAvailability.otherProjects[0];
|
|
4074
|
+
const firstShortPath = shortenPath(firstProject.path);
|
|
4075
|
+
console.log(`
|
|
4076
|
+
Run: cd ${firstShortPath} && agenthud
|
|
4077
|
+
`);
|
|
3994
4078
|
} else {
|
|
3995
4079
|
console.log("\nCould not find any projects with Claude Code sessions.\n");
|
|
3996
4080
|
console.log("Start a Claude Code session in a project directory first:");
|
package/package.json
CHANGED