agenthud 0.1.1 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +120 -14
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,10 +3,11 @@
3
3
  // src/index.ts
4
4
  import React2 from "react";
5
5
  import { render } from "ink";
6
+ import { existsSync } from "fs";
6
7
 
7
8
  // src/ui/App.tsx
8
9
  import { useState, useEffect, useCallback } from "react";
9
- import { Box as Box4, Text as Text4, useApp, useInput } from "ink";
10
+ import { Box as Box5, Text as Text5, useApp, useInput } from "ink";
10
11
 
11
12
  // src/ui/GitPanel.tsx
12
13
  import { Box, Text } from "ink";
@@ -249,6 +250,24 @@ function TestPanel({
249
250
  ] });
250
251
  }
251
252
 
253
+ // src/ui/WelcomePanel.tsx
254
+ import { Box as Box4, Text as Text4 } from "ink";
255
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
256
+ function WelcomePanel() {
257
+ return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "single", paddingX: 1, width: PANEL_WIDTH, children: [
258
+ /* @__PURE__ */ jsx4(Box4, { marginTop: -1, children: /* @__PURE__ */ jsx4(Text4, { children: " Welcome to agenthud " }) }),
259
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
260
+ /* @__PURE__ */ jsx4(Text4, { children: " No .agent/ directory found." }),
261
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
262
+ /* @__PURE__ */ jsx4(Text4, { children: " Quick setup:" }),
263
+ /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: " npx agenthud init" }),
264
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
265
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: " Or visit: github.com/neochoon/agenthud" }),
266
+ /* @__PURE__ */ jsx4(Text4, { children: " " }),
267
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: " Press q to quit" })
268
+ ] });
269
+ }
270
+
252
271
  // src/data/git.ts
253
272
  import { execSync as nodeExecSync } from "child_process";
254
273
  var execFn = (command, options2) => nodeExecSync(command, options2);
@@ -398,7 +417,7 @@ function getTestData(dir = process.cwd()) {
398
417
  }
399
418
 
400
419
  // src/ui/App.tsx
401
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
420
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
402
421
  var REFRESH_INTERVAL = 5e3;
403
422
  var REFRESH_SECONDS = REFRESH_INTERVAL / 1e3;
404
423
  function useGitData() {
@@ -432,7 +451,10 @@ function useTestData() {
432
451
  }, []);
433
452
  return [data, refresh];
434
453
  }
435
- function App({ mode }) {
454
+ function WelcomeApp() {
455
+ return /* @__PURE__ */ jsx5(WelcomePanel, {});
456
+ }
457
+ function DashboardApp({ mode }) {
436
458
  const { exit } = useApp();
437
459
  const [gitData, refreshGit] = useGitData();
438
460
  const [planData, refreshPlan] = usePlanData();
@@ -458,7 +480,6 @@ function App({ mode }) {
458
480
  }, [mode]);
459
481
  useInput(
460
482
  (input) => {
461
- if (mode !== "watch") return;
462
483
  if (input === "q") {
463
484
  exit();
464
485
  }
@@ -468,8 +489,8 @@ function App({ mode }) {
468
489
  },
469
490
  { isActive: mode === "watch" }
470
491
  );
471
- return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
472
- /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(
492
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
493
+ /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsx5(
473
494
  GitPanel,
474
495
  {
475
496
  branch: gitData.branch,
@@ -478,7 +499,7 @@ function App({ mode }) {
478
499
  uncommitted: gitData.uncommitted
479
500
  }
480
501
  ) }),
481
- /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(
502
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(
482
503
  PlanPanel,
483
504
  {
484
505
  plan: planData.plan,
@@ -486,7 +507,7 @@ function App({ mode }) {
486
507
  error: planData.error
487
508
  }
488
509
  ) }),
489
- /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(
510
+ /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(
490
511
  TestPanel,
491
512
  {
492
513
  results: testData.results,
@@ -495,17 +516,23 @@ function App({ mode }) {
495
516
  error: testData.error
496
517
  }
497
518
  ) }),
498
- mode === "watch" && /* @__PURE__ */ jsx4(Box4, { marginTop: 1, width: PANEL_WIDTH, children: /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
519
+ mode === "watch" && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, width: PANEL_WIDTH, children: /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
499
520
  "\u21BB ",
500
521
  countdown,
501
522
  "s \xB7 ",
502
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "q:" }),
523
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "q:" }),
503
524
  " quit \xB7 ",
504
- /* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "r:" }),
525
+ /* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "r:" }),
505
526
  " refresh"
506
527
  ] }) })
507
528
  ] });
508
529
  }
530
+ function App({ mode, agentDirExists: agentDirExists2 = true }) {
531
+ if (!agentDirExists2) {
532
+ return /* @__PURE__ */ jsx5(WelcomeApp, {});
533
+ }
534
+ return /* @__PURE__ */ jsx5(DashboardApp, { mode });
535
+ }
509
536
 
510
537
  // src/cli.ts
511
538
  var clearFn = () => console.clear();
@@ -515,18 +542,97 @@ function clearScreen() {
515
542
  function parseArgs(args) {
516
543
  const hasOnce = args.includes("--once");
517
544
  const hasWatch = args.includes("--watch") || args.includes("-w");
545
+ const command = args[0] === "init" ? "init" : void 0;
518
546
  if (hasOnce) {
519
- return { mode: "once" };
547
+ return { mode: "once", command };
520
548
  }
521
- return { mode: "watch" };
549
+ return { mode: "watch", command };
550
+ }
551
+
552
+ // src/commands/init.ts
553
+ import {
554
+ existsSync as nodeExistsSync,
555
+ mkdirSync as nodeMkdirSync,
556
+ writeFileSync as nodeWriteFileSync,
557
+ readFileSync as nodeReadFileSync3,
558
+ appendFileSync as nodeAppendFileSync
559
+ } from "fs";
560
+ var fs = {
561
+ existsSync: nodeExistsSync,
562
+ mkdirSync: nodeMkdirSync,
563
+ writeFileSync: nodeWriteFileSync,
564
+ readFileSync: (path) => nodeReadFileSync3(path, "utf-8"),
565
+ appendFileSync: nodeAppendFileSync
566
+ };
567
+ var AGENT_STATE_SECTION = `## Agent State
568
+
569
+ Maintain \`.agent/\` directory:
570
+ - Update \`plan.json\` when plan changes
571
+ - Append to \`decisions.json\` for key decisions
572
+ `;
573
+ function runInit() {
574
+ const result = {
575
+ created: [],
576
+ skipped: []
577
+ };
578
+ if (!fs.existsSync(".agent")) {
579
+ fs.mkdirSync(".agent", { recursive: true });
580
+ result.created.push(".agent/");
581
+ } else {
582
+ result.skipped.push(".agent/");
583
+ }
584
+ if (!fs.existsSync(".agent/plan.json")) {
585
+ fs.writeFileSync(".agent/plan.json", "{}\n");
586
+ result.created.push(".agent/plan.json");
587
+ } else {
588
+ result.skipped.push(".agent/plan.json");
589
+ }
590
+ if (!fs.existsSync(".agent/decisions.json")) {
591
+ fs.writeFileSync(".agent/decisions.json", "[]\n");
592
+ result.created.push(".agent/decisions.json");
593
+ } else {
594
+ result.skipped.push(".agent/decisions.json");
595
+ }
596
+ if (!fs.existsSync("CLAUDE.md")) {
597
+ fs.writeFileSync("CLAUDE.md", AGENT_STATE_SECTION);
598
+ result.created.push("CLAUDE.md");
599
+ } else {
600
+ const content = fs.readFileSync("CLAUDE.md");
601
+ if (!content.includes("## Agent State")) {
602
+ fs.appendFileSync("CLAUDE.md", "\n" + AGENT_STATE_SECTION);
603
+ result.created.push("CLAUDE.md");
604
+ } else {
605
+ result.skipped.push("CLAUDE.md");
606
+ }
607
+ }
608
+ return result;
522
609
  }
523
610
 
524
611
  // src/index.ts
525
612
  var options = parseArgs(process.argv.slice(2));
613
+ if (options.command === "init") {
614
+ const result = runInit();
615
+ console.log("\n\u2713 agenthud initialized\n");
616
+ if (result.created.length > 0) {
617
+ console.log("Created:");
618
+ result.created.forEach((file) => console.log(` ${file}`));
619
+ }
620
+ if (result.skipped.length > 0) {
621
+ console.log("\nSkipped (already exists):");
622
+ result.skipped.forEach((file) => console.log(` ${file}`));
623
+ }
624
+ console.log("\nNext steps:");
625
+ console.log(" 1. Edit .agent/plan.json to add your project plan");
626
+ console.log(" 2. Run: npx agenthud\n");
627
+ process.exit(0);
628
+ }
629
+ var agentDirExists = existsSync(".agent");
526
630
  if (options.mode === "watch") {
527
631
  clearScreen();
528
632
  }
529
- var { waitUntilExit } = render(React2.createElement(App, { mode: options.mode }));
633
+ var { waitUntilExit } = render(
634
+ React2.createElement(App, { mode: options.mode, agentDirExists })
635
+ );
530
636
  if (options.mode === "once") {
531
637
  setTimeout(() => process.exit(0), 100);
532
638
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agenthud",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "CLI tool to monitor agent status in real-time. Works with Claude Code, multi-agent workflows, and any AI agent system.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",