clairo 0.5.0 → 1.0.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 (3) hide show
  1. package/README.md +15 -10
  2. package/dist/cli.js +144 -98
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -7,29 +7,34 @@ Terminal dashboard for GitHub PRs and Jira tickets.
7
7
  - Node.js 18+
8
8
  - [GitHub CLI](https://cli.github.com/) (`gh`) installed and authenticated
9
9
 
10
- ## Install
10
+ ## Usage
11
11
 
12
12
  ```bash
13
- pnpm install
14
- pnpm build
13
+ npx clairo
15
14
  ```
16
15
 
17
- ## Run
16
+ ### Options
18
17
 
19
- ```bash
20
- pnpm start
18
+ ```
19
+ --cwd <path>, -C Run in a different directory
20
+ --version Show version
21
+ --help Show help
21
22
  ```
22
23
 
23
- Or for development:
24
+ ### Examples
24
25
 
25
26
  ```bash
26
- pnpm dev
27
+ # Run in current directory
28
+ npx clairo
29
+
30
+ # Run in a different repo
31
+ npx clairo --cwd ~/projects/other-repo
27
32
  ```
28
33
 
29
34
  ## Keyboard
30
35
 
31
- - `1-4` - Switch between boxes
36
+ - `1-6` - Switch between boxes
32
37
  - `j/k` - Navigate lists
33
38
  - `Enter` - Select
34
- - `Esc` - Cancel
39
+ - `o` - Open in browser
35
40
  - `Ctrl+C` - Quit
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import { Box as Box16, useApp, useInput as useInput13 } from "ink";
10
10
  // src/components/github/GitHubView.tsx
11
11
  import { exec as exec3 } from "child_process";
12
12
  import { useCallback, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
13
- import { TitledBox as TitledBox4 } from "@mishieck/ink-titled-box";
13
+ import { TitledBox as TitledBox3 } from "@mishieck/ink-titled-box";
14
14
  import { Box as Box5, Text as Text5, useInput as useInput4 } from "ink";
15
15
 
16
16
  // src/lib/config/index.ts
@@ -573,22 +573,22 @@ ${title}
573
573
  entry += "\n";
574
574
  appendToLog(today, entry);
575
575
  }
576
- function logJiraStatusChanged(ticketKey, oldStatus, newStatus) {
576
+ function logJiraStatusChanged(ticketKey, ticketName, oldStatus, newStatus) {
577
577
  const timestamp = formatTimestamp();
578
578
  const today = getTodayDate();
579
579
  const entry = `## ${timestamp} - Updated Jira ticket
580
580
 
581
- ${ticketKey}: ${oldStatus} \u2192 ${newStatus}
581
+ ${ticketKey}: ${ticketName}
582
+ ${oldStatus} \u2192 ${newStatus}
582
583
 
583
584
  `;
584
585
  appendToLog(today, entry);
585
586
  }
586
587
 
587
588
  // src/components/github/PRDetailsBox.tsx
588
- import { useRef } from "react";
589
589
  import open from "open";
590
- import { TitledBox } from "@mishieck/ink-titled-box";
591
- import { Box as Box2, Text as Text2, useInput } from "ink";
590
+ import { useRef } from "react";
591
+ import { Box as Box2, Text as Text2, useInput, useStdout } from "ink";
592
592
  import { ScrollView } from "ink-scroll-view";
593
593
 
594
594
  // src/components/ui/Markdown.tsx
@@ -755,67 +755,88 @@ function PRDetailsBox({ pr, loading, error, isFocused }) {
755
755
  },
756
756
  { isActive: isFocused }
757
757
  );
758
- return /* @__PURE__ */ jsx2(TitledBox, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx2(ScrollView, { ref: scrollRef, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
759
- loading && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Loading details..." }),
760
- error && /* @__PURE__ */ jsx2(Text2, { color: "red", children: error }),
761
- !loading && !error && !pr && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Select a PR to view details" }),
762
- !loading && !error && pr && /* @__PURE__ */ jsxs2(Fragment, { children: [
763
- /* @__PURE__ */ jsx2(Text2, { bold: true, children: pr.title }),
764
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
765
- "by ",
766
- ((_a = pr.author) == null ? void 0 : _a.login) ?? "unknown",
767
- " | ",
768
- ((_b = pr.commits) == null ? void 0 : _b.length) ?? 0,
769
- " commits"
770
- ] }),
771
- /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
772
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Review: " }),
773
- /* @__PURE__ */ jsx2(Text2, { color: reviewColor, children: reviewStatus }),
774
- /* @__PURE__ */ jsx2(Text2, { children: " | " }),
775
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: " }),
776
- /* @__PURE__ */ jsx2(Text2, { color: mergeDisplay.color, children: mergeDisplay.text })
777
- ] }),
778
- (((_c = pr.assignees) == null ? void 0 : _c.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
779
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Assignees: " }),
780
- /* @__PURE__ */ jsx2(Text2, { children: pr.assignees.map((a) => a.login).join(", ") })
781
- ] }),
782
- (((_d = pr.reviews) == null ? void 0 : _d.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
783
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Reviews:" }),
784
- pr.reviews.map((review, idx) => {
785
- const color = review.state === "APPROVED" ? "green" : review.state === "CHANGES_REQUESTED" ? "red" : review.state === "COMMENTED" ? "blue" : "yellow";
786
- const icon = review.state === "APPROVED" ? "\u2713" : review.state === "CHANGES_REQUESTED" ? "\u2717" : review.state === "COMMENTED" ? "\u{1F4AC}" : "\u25CB";
787
- return /* @__PURE__ */ jsxs2(Text2, { color, children: [
788
- " ",
789
- icon,
790
- " ",
791
- review.author.login
792
- ] }, idx);
793
- })
794
- ] }),
795
- (((_e = pr.reviewRequests) == null ? void 0 : _e.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { children: [
796
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Pending: " }),
797
- /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: pr.reviewRequests.map((r) => r.login ?? r.name ?? r.slug ?? "Team").join(", ") })
798
- ] }),
799
- (((_f = pr.statusCheckRollup) == null ? void 0 : _f.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
800
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Checks:" }),
801
- (_g = pr.statusCheckRollup) == null ? void 0 : _g.map((check, idx) => /* @__PURE__ */ jsxs2(Text2, { color: getCheckColor(check), children: [
802
- " ",
803
- getCheckIcon(check),
804
- " ",
805
- check.name ?? check.context
806
- ] }, idx))
807
- ] }),
808
- pr.body && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
809
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Description:" }),
810
- /* @__PURE__ */ jsx2(Markdown, { children: pr.body })
811
- ] })
812
- ] })
813
- ] }) }) }) });
758
+ const { stdout } = useStdout();
759
+ const terminalWidth = (stdout == null ? void 0 : stdout.columns) ?? 80;
760
+ const columnWidth = Math.floor(terminalWidth / 2);
761
+ const titlePart = `\u256D\u2500 ${displayTitle} `;
762
+ const dashCount = Math.max(0, columnWidth - titlePart.length - 1);
763
+ const topBorder = `${titlePart}${"\u2500".repeat(dashCount)}\u256E`;
764
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", flexGrow: 1, children: [
765
+ /* @__PURE__ */ jsx2(Text2, { color: borderColor, children: topBorder }),
766
+ /* @__PURE__ */ jsx2(
767
+ Box2,
768
+ {
769
+ flexDirection: "column",
770
+ flexGrow: 1,
771
+ flexBasis: 0,
772
+ overflow: "hidden",
773
+ borderStyle: "round",
774
+ borderTop: false,
775
+ borderColor,
776
+ children: /* @__PURE__ */ jsx2(ScrollView, { ref: scrollRef, children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
777
+ loading && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Loading details..." }),
778
+ error && /* @__PURE__ */ jsx2(Text2, { color: "red", children: error }),
779
+ !loading && !error && !pr && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Select a PR to view details" }),
780
+ !loading && !error && pr && /* @__PURE__ */ jsxs2(Fragment, { children: [
781
+ /* @__PURE__ */ jsx2(Text2, { bold: true, children: pr.title }),
782
+ /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
783
+ "by ",
784
+ ((_a = pr.author) == null ? void 0 : _a.login) ?? "unknown",
785
+ " | ",
786
+ ((_b = pr.commits) == null ? void 0 : _b.length) ?? 0,
787
+ " commits"
788
+ ] }),
789
+ /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
790
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Review: " }),
791
+ /* @__PURE__ */ jsx2(Text2, { color: reviewColor, children: reviewStatus }),
792
+ /* @__PURE__ */ jsx2(Text2, { children: " | " }),
793
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: " }),
794
+ /* @__PURE__ */ jsx2(Text2, { color: mergeDisplay.color, children: mergeDisplay.text })
795
+ ] }),
796
+ (((_c = pr.assignees) == null ? void 0 : _c.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, children: [
797
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Assignees: " }),
798
+ /* @__PURE__ */ jsx2(Text2, { children: pr.assignees.map((a) => a.login).join(", ") })
799
+ ] }),
800
+ (((_d = pr.reviews) == null ? void 0 : _d.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
801
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Reviews:" }),
802
+ pr.reviews.map((review, idx) => {
803
+ const color = review.state === "APPROVED" ? "green" : review.state === "CHANGES_REQUESTED" ? "red" : review.state === "COMMENTED" ? "blue" : "yellow";
804
+ const icon = review.state === "APPROVED" ? "\u2713" : review.state === "CHANGES_REQUESTED" ? "\u2717" : review.state === "COMMENTED" ? "\u{1F4AC}" : "\u25CB";
805
+ return /* @__PURE__ */ jsxs2(Text2, { color, children: [
806
+ " ",
807
+ icon,
808
+ " ",
809
+ review.author.login
810
+ ] }, idx);
811
+ })
812
+ ] }),
813
+ (((_e = pr.reviewRequests) == null ? void 0 : _e.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { children: [
814
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Pending: " }),
815
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: pr.reviewRequests.map((r) => r.login ?? r.name ?? r.slug ?? "Team").join(", ") })
816
+ ] }),
817
+ (((_f = pr.statusCheckRollup) == null ? void 0 : _f.length) ?? 0) > 0 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
818
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Checks:" }),
819
+ (_g = pr.statusCheckRollup) == null ? void 0 : _g.map((check, idx) => /* @__PURE__ */ jsxs2(Text2, { color: getCheckColor(check), children: [
820
+ " ",
821
+ getCheckIcon(check),
822
+ " ",
823
+ check.name ?? check.context
824
+ ] }, idx))
825
+ ] }),
826
+ pr.body && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
827
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Description:" }),
828
+ /* @__PURE__ */ jsx2(Markdown, { children: pr.body })
829
+ ] })
830
+ ] })
831
+ ] }) })
832
+ }
833
+ )
834
+ ] });
814
835
  }
815
836
 
816
837
  // src/components/github/PullRequestsBox.tsx
817
838
  import { useEffect, useState } from "react";
818
- import { TitledBox as TitledBox2 } from "@mishieck/ink-titled-box";
839
+ import { TitledBox } from "@mishieck/ink-titled-box";
819
840
  import { Box as Box3, Text as Text3, useInput as useInput2 } from "ink";
820
841
 
821
842
  // src/lib/clipboard.ts
@@ -885,7 +906,7 @@ function PullRequestsBox({
885
906
  const title = "[2] Pull Requests";
886
907
  const subtitle = branch ? ` (${branch})` : "";
887
908
  const borderColor = isFocused ? "yellow" : void 0;
888
- return /* @__PURE__ */ jsx3(TitledBox2, { borderStyle: "round", titles: [`${title}${subtitle}`], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
909
+ return /* @__PURE__ */ jsx3(TitledBox, { borderStyle: "round", titles: [`${title}${subtitle}`], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
889
910
  loading && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Loading PRs..." }),
890
911
  error && /* @__PURE__ */ jsx3(Text3, { color: "red", children: error }),
891
912
  !loading && !error && /* @__PURE__ */ jsxs3(Fragment2, { children: [
@@ -893,14 +914,21 @@ function PullRequestsBox({
893
914
  prs.map((pr, idx) => {
894
915
  const isHighlighted = isFocused && idx === highlightedIndex;
895
916
  const isSelected = pr.number === (selectedPR == null ? void 0 : selectedPR.number);
896
- const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
897
- return /* @__PURE__ */ jsxs3(Text3, { color: isSelected ? "green" : void 0, children: [
898
- prefix,
899
- "#",
900
- pr.number,
901
- " ",
902
- pr.isDraft ? "[Draft] " : "",
903
- pr.title
917
+ const cursor = isHighlighted ? ">" : " ";
918
+ const indicator = isSelected ? " *" : "";
919
+ return /* @__PURE__ */ jsxs3(Box3, { children: [
920
+ /* @__PURE__ */ jsxs3(Text3, { color: isHighlighted ? "yellow" : void 0, children: [
921
+ cursor,
922
+ " "
923
+ ] }),
924
+ /* @__PURE__ */ jsxs3(Text3, { color: isSelected ? "green" : void 0, children: [
925
+ "#",
926
+ pr.number,
927
+ " ",
928
+ pr.isDraft ? "[Draft] " : "",
929
+ pr.title
930
+ ] }),
931
+ /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: indicator })
904
932
  ] }, pr.number);
905
933
  }),
906
934
  /* @__PURE__ */ jsxs3(Text3, { color: "blue", children: [
@@ -913,7 +941,7 @@ function PullRequestsBox({
913
941
 
914
942
  // src/components/github/RemotesBox.tsx
915
943
  import { useEffect as useEffect2, useState as useState2 } from "react";
916
- import { TitledBox as TitledBox3 } from "@mishieck/ink-titled-box";
944
+ import { TitledBox as TitledBox2 } from "@mishieck/ink-titled-box";
917
945
  import { Box as Box4, Text as Text4, useInput as useInput3 } from "ink";
918
946
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
919
947
  function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocused }) {
@@ -939,20 +967,27 @@ function RemotesBox({ remotes, selectedRemote, onSelect, loading, error, isFocus
939
967
  );
940
968
  const title = "[1] Remotes";
941
969
  const borderColor = isFocused ? "yellow" : void 0;
942
- return /* @__PURE__ */ jsx4(TitledBox3, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
970
+ return /* @__PURE__ */ jsx4(TitledBox2, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", paddingX: 1, overflow: "hidden", children: [
943
971
  loading && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "Loading..." }),
944
972
  error && /* @__PURE__ */ jsx4(Text4, { color: "red", children: error }),
945
973
  !loading && !error && remotes.length === 0 && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "No remotes configured" }),
946
974
  !loading && !error && remotes.map((remote, idx) => {
947
975
  const isHighlighted = isFocused && idx === highlightedIndex;
948
976
  const isSelected = remote.name === selectedRemote;
949
- const prefix = isHighlighted ? "> " : isSelected ? "\u25CF " : " ";
950
- return /* @__PURE__ */ jsxs4(Text4, { color: isSelected ? "green" : void 0, children: [
951
- prefix,
952
- remote.name,
953
- " (",
954
- remote.url,
955
- ")"
977
+ const cursor = isHighlighted ? ">" : " ";
978
+ const indicator = isSelected ? " *" : "";
979
+ return /* @__PURE__ */ jsxs4(Box4, { children: [
980
+ /* @__PURE__ */ jsxs4(Text4, { color: isHighlighted ? "yellow" : void 0, children: [
981
+ cursor,
982
+ " "
983
+ ] }),
984
+ /* @__PURE__ */ jsxs4(Text4, { color: isSelected ? "green" : void 0, children: [
985
+ remote.name,
986
+ " (",
987
+ remote.url,
988
+ ")"
989
+ ] }),
990
+ /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: indicator })
956
991
  ] }, remote.name);
957
992
  })
958
993
  ] }) });
@@ -1154,7 +1189,7 @@ function GitHubView({ isFocused, onKeybindingsChange, onLogUpdated }) {
1154
1189
  { isActive: isFocused }
1155
1190
  );
1156
1191
  if (isRepo === false) {
1157
- return /* @__PURE__ */ jsx5(TitledBox4, { borderStyle: "round", titles: ["Error"], flexGrow: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "red", children: "Current directory is not a git repository" }) });
1192
+ return /* @__PURE__ */ jsx5(TitledBox3, { borderStyle: "round", titles: ["Error"], flexGrow: 1, children: /* @__PURE__ */ jsx5(Text5, { color: "red", children: "Current directory is not a git repository" }) });
1158
1193
  }
1159
1194
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", flexGrow: 1, children: [
1160
1195
  /* @__PURE__ */ jsx5(
@@ -1197,7 +1232,7 @@ function GitHubView({ isFocused, onKeybindingsChange, onLogUpdated }) {
1197
1232
  // src/components/jira/JiraView.tsx
1198
1233
  import { useCallback as useCallback2, useEffect as useEffect5, useState as useState7 } from "react";
1199
1234
  import open2 from "open";
1200
- import { TitledBox as TitledBox5 } from "@mishieck/ink-titled-box";
1235
+ import { TitledBox as TitledBox4 } from "@mishieck/ink-titled-box";
1201
1236
  import { Box as Box11, Text as Text11, useInput as useInput9 } from "ink";
1202
1237
 
1203
1238
  // src/components/jira/ChangeStatusModal.tsx
@@ -1711,7 +1746,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange, onLogUpdated
1711
1746
  { isActive: isFocused && !showConfigureModal && !showLinkModal && !showStatusModal }
1712
1747
  );
1713
1748
  if (isRepo === false) {
1714
- return /* @__PURE__ */ jsx11(TitledBox5, { borderStyle: "round", titles: ["Jira"], flexShrink: 0, children: /* @__PURE__ */ jsx11(Text11, { color: "red", children: "Not a git repository" }) });
1749
+ return /* @__PURE__ */ jsx11(TitledBox4, { borderStyle: "round", titles: ["Jira"], flexShrink: 0, children: /* @__PURE__ */ jsx11(Text11, { color: "red", children: "Not a git repository" }) });
1715
1750
  }
1716
1751
  if (showConfigureModal) {
1717
1752
  const siteUrl = repoPath ? getJiraSiteUrl(repoPath) : void 0;
@@ -1756,7 +1791,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange, onLogUpdated
1756
1791
  onComplete: (newStatus) => {
1757
1792
  const oldStatus = ticket.status;
1758
1793
  updateTicketStatus(repoPath, currentBranch, ticket.key, newStatus);
1759
- logJiraStatusChanged(ticket.key, oldStatus, newStatus);
1794
+ logJiraStatusChanged(ticket.key, ticket.summary, oldStatus, newStatus);
1760
1795
  onLogUpdated == null ? void 0 : onLogUpdated();
1761
1796
  setShowStatusModal(false);
1762
1797
  refreshTickets();
@@ -1767,7 +1802,7 @@ function JiraView({ isFocused, onModalChange, onKeybindingsChange, onLogUpdated
1767
1802
  }
1768
1803
  const title = "[4] Jira";
1769
1804
  const borderColor = isFocused ? "yellow" : void 0;
1770
- return /* @__PURE__ */ jsx11(TitledBox5, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
1805
+ return /* @__PURE__ */ jsx11(TitledBox4, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
1771
1806
  jiraState === "not_configured" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No Jira site configured" }),
1772
1807
  jiraState === "no_tickets" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No tickets linked to this branch" }),
1773
1808
  jiraState === "has_tickets" && tickets.map((ticket, idx) => /* @__PURE__ */ jsx11(
@@ -1788,7 +1823,7 @@ import { useCallback as useCallback3, useEffect as useEffect6, useState as useSt
1788
1823
  import { Box as Box14, useInput as useInput12 } from "ink";
1789
1824
 
1790
1825
  // src/components/logs/LogsHistoryBox.tsx
1791
- import { TitledBox as TitledBox6 } from "@mishieck/ink-titled-box";
1826
+ import { TitledBox as TitledBox5 } from "@mishieck/ink-titled-box";
1792
1827
  import { Box as Box12, Text as Text12, useInput as useInput10 } from "ink";
1793
1828
  import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1794
1829
  function LogsHistoryBox({
@@ -1819,7 +1854,7 @@ function LogsHistoryBox({
1819
1854
  },
1820
1855
  { isActive: isFocused }
1821
1856
  );
1822
- return /* @__PURE__ */ jsx12(TitledBox6, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, children: [
1857
+ return /* @__PURE__ */ jsx12(TitledBox5, { borderStyle: "round", titles: [title], borderColor, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, children: [
1823
1858
  logFiles.length === 0 && /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "No logs yet" }),
1824
1859
  logFiles.map((file, idx) => {
1825
1860
  const isHighlighted = idx === highlightedIndex;
@@ -1848,7 +1883,7 @@ function LogsHistoryBox({
1848
1883
 
1849
1884
  // src/components/logs/LogViewerBox.tsx
1850
1885
  import { useRef as useRef3 } from "react";
1851
- import { TitledBox as TitledBox7 } from "@mishieck/ink-titled-box";
1886
+ import { TitledBox as TitledBox6 } from "@mishieck/ink-titled-box";
1852
1887
  import { Box as Box13, Text as Text13, useInput as useInput11 } from "ink";
1853
1888
  import { ScrollView as ScrollView2 } from "ink-scroll-view";
1854
1889
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
@@ -1883,7 +1918,7 @@ function LogViewerBox({ date, content, isFocused, onRefresh, onLogCreated }) {
1883
1918
  },
1884
1919
  { isActive: isFocused }
1885
1920
  );
1886
- return /* @__PURE__ */ jsx13(TitledBox7, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx13(Box13, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx13(ScrollView2, { ref: scrollRef, children: /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
1921
+ return /* @__PURE__ */ jsx13(TitledBox6, { borderStyle: "round", titles: [displayTitle], borderColor, flexGrow: 1, children: /* @__PURE__ */ jsx13(Box13, { flexDirection: "column", flexGrow: 1, children: /* @__PURE__ */ jsx13(ScrollView2, { ref: scrollRef, children: /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
1887
1922
  !date && /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Select a log file to view" }),
1888
1923
  date && content === null && /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Log file not found" }),
1889
1924
  date && content !== null && content.trim() === "" && /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Empty log file" }),
@@ -2096,11 +2131,11 @@ function App() {
2096
2131
  import { render as inkRender } from "ink";
2097
2132
 
2098
2133
  // src/lib/Screen.tsx
2099
- import { Box as Box17, useStdout } from "ink";
2134
+ import { Box as Box17, useStdout as useStdout2 } from "ink";
2100
2135
  import { useCallback as useCallback5, useEffect as useEffect7, useState as useState10 } from "react";
2101
2136
  import { jsx as jsx17 } from "react/jsx-runtime";
2102
2137
  function Screen({ children }) {
2103
- const { stdout } = useStdout();
2138
+ const { stdout } = useStdout2();
2104
2139
  const getSize = useCallback5(
2105
2140
  () => ({ height: stdout.rows, width: stdout.columns }),
2106
2141
  [stdout]
@@ -2145,25 +2180,36 @@ function render(node, options) {
2145
2180
 
2146
2181
  // src/cli.tsx
2147
2182
  import { jsx as jsx19 } from "react/jsx-runtime";
2148
- meow(
2183
+ var cli = meow(
2149
2184
  `
2150
2185
  Usage
2151
2186
  $ clairo
2152
2187
 
2153
2188
  Options
2154
- --name Your name
2189
+ --cwd <path> Run in a different directory
2190
+ --version Show version
2191
+ --help Show this help
2155
2192
 
2156
2193
  Examples
2157
- $ clairo --name=Jane
2158
- Hello, Jane
2194
+ $ clairo
2195
+ $ clairo --cwd ~/projects/other-repo
2159
2196
  `,
2160
2197
  {
2161
2198
  importMeta: import.meta,
2162
2199
  flags: {
2163
- name: {
2164
- type: "string"
2200
+ cwd: {
2201
+ type: "string",
2202
+ shortFlag: "C"
2165
2203
  }
2166
2204
  }
2167
2205
  }
2168
2206
  );
2207
+ if (cli.flags.cwd) {
2208
+ try {
2209
+ process.chdir(cli.flags.cwd);
2210
+ } catch {
2211
+ console.error(`Error: Cannot access directory "${cli.flags.cwd}"`);
2212
+ process.exit(1);
2213
+ }
2214
+ }
2169
2215
  render(/* @__PURE__ */ jsx19(App, {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clairo",
3
- "version": "0.5.0",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",