@towles/tool 0.0.16 → 0.0.18
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 +1 -0
- package/dist/index.mjs +259 -28
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ if that works, then you need to add the pnpm global bin directory to your PATH.
|
|
|
75
75
|
- [rolldown-vite](https://voidzero.dev/posts/announcing-rolldown-vite) - A Vite plugin for rolling down your code
|
|
76
76
|
- ~~[zx](https://github.com/google/zx) google created library to write shell scripts in a more powerful and expressive way via the Anthropic API.~~
|
|
77
77
|
- [prompts](https://github.com/terkelg/prompts) - A library for creating beautiful command-line prompts, with fuzzy search and other features.
|
|
78
|
+
- had to patch it so `esc` cancels the selection with [pnpm-patch-i](https://github.com/antfu/pnpm-patch-i)
|
|
78
79
|
- [yargs](https://github.com/yargs/yargs) - A modern, feature-rich command-line argument parser with enhanced error handling, TypeScript support, and flexible command configuration.
|
|
79
80
|
- ~~[ink](https://github.com/vadimdemedes/ink) - React for interactive command-line apps~~
|
|
80
81
|
- wanted hotkey support and more complex UI but this was overkill for this project.
|
package/dist/index.mjs
CHANGED
|
@@ -15,6 +15,9 @@ import prompts from 'prompts';
|
|
|
15
15
|
import { execSync, exec } from 'node:child_process';
|
|
16
16
|
import { promisify } from 'node:util';
|
|
17
17
|
import { DateTime } from 'luxon';
|
|
18
|
+
import { Fzf } from 'fzf';
|
|
19
|
+
import stripAnsi from 'strip-ansi';
|
|
20
|
+
import { exec as exec$1 } from 'tinyexec';
|
|
18
21
|
|
|
19
22
|
async function loadTowlesToolContext({
|
|
20
23
|
cwd,
|
|
@@ -118,8 +121,13 @@ async function loadSettings() {
|
|
|
118
121
|
);
|
|
119
122
|
}
|
|
120
123
|
|
|
121
|
-
const version = "0.0.
|
|
124
|
+
const version = "0.0.18";
|
|
122
125
|
|
|
126
|
+
const JOURNAL_TYPES = {
|
|
127
|
+
DAILY_NOTES: "daily-notes",
|
|
128
|
+
MEETING: "meeting",
|
|
129
|
+
NOTE: "note"
|
|
130
|
+
};
|
|
123
131
|
async function parseArguments(argv) {
|
|
124
132
|
let parsedResult = null;
|
|
125
133
|
const parser = yargs(hideBin(argv)).scriptName(AppInfo.toolName).usage("Usage: $0 <command> [options]").version(version).demandCommand(1, "You need at least one command").recommendCommands().strict().help().wrap(yargs().terminalWidth());
|
|
@@ -132,7 +140,7 @@ async function parseArguments(argv) {
|
|
|
132
140
|
"Weekly files with daily sections for ongoing work and notes",
|
|
133
141
|
{},
|
|
134
142
|
(argv2) => {
|
|
135
|
-
parsedResult = { command: "journal", args: {
|
|
143
|
+
parsedResult = { command: "journal", args: { jouralType: "daily-notes", title: "" } };
|
|
136
144
|
}
|
|
137
145
|
).command(
|
|
138
146
|
["meeting [title]", "m"],
|
|
@@ -144,7 +152,7 @@ async function parseArguments(argv) {
|
|
|
144
152
|
}
|
|
145
153
|
},
|
|
146
154
|
(argv2) => {
|
|
147
|
-
parsedResult = { command: "journal", args: {
|
|
155
|
+
parsedResult = { command: "journal", args: { jouralType: "meeting", title: argv2.title || "" } };
|
|
148
156
|
}
|
|
149
157
|
).command(
|
|
150
158
|
["note [title]", "n"],
|
|
@@ -156,7 +164,7 @@ async function parseArguments(argv) {
|
|
|
156
164
|
}
|
|
157
165
|
},
|
|
158
166
|
(argv2) => {
|
|
159
|
-
parsedResult = { command: "journal", args: {
|
|
167
|
+
parsedResult = { command: "journal", args: { jouralType: "note", title: argv2.title || "" } };
|
|
160
168
|
}
|
|
161
169
|
).demandCommand(1, "You need to specify a journal subcommand").help();
|
|
162
170
|
},
|
|
@@ -178,6 +186,20 @@ async function parseArguments(argv) {
|
|
|
178
186
|
parsedResult = { command: "git-commit", args: { message: argv2.message } };
|
|
179
187
|
}
|
|
180
188
|
);
|
|
189
|
+
parser.command(
|
|
190
|
+
["gh-branch [assignedToMe...]", "branch", "br"],
|
|
191
|
+
"Create git branch from github issue",
|
|
192
|
+
{
|
|
193
|
+
assignedToMe: {
|
|
194
|
+
type: "boolean",
|
|
195
|
+
describe: "filter issues based on if assigned to you by default",
|
|
196
|
+
default: false
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
(argv2) => {
|
|
200
|
+
parsedResult = { command: "gh-branch", args: { assignedToMe: argv2.assignedToMe } };
|
|
201
|
+
}
|
|
202
|
+
);
|
|
181
203
|
parser.command(
|
|
182
204
|
["config", "cfg"],
|
|
183
205
|
"set or show configuration file.",
|
|
@@ -186,6 +208,14 @@ async function parseArguments(argv) {
|
|
|
186
208
|
parsedResult = { command: "config", args: {} };
|
|
187
209
|
}
|
|
188
210
|
);
|
|
211
|
+
parser.command(
|
|
212
|
+
["weather", "w"],
|
|
213
|
+
"Show current weather for Cincinnati, OH",
|
|
214
|
+
{},
|
|
215
|
+
() => {
|
|
216
|
+
parsedResult = { command: "weather", args: {} };
|
|
217
|
+
}
|
|
218
|
+
);
|
|
189
219
|
await parser.parse();
|
|
190
220
|
if (!parsedResult) {
|
|
191
221
|
throw new Error("No command was parsed");
|
|
@@ -321,11 +351,6 @@ function formatDate(date) {
|
|
|
321
351
|
}
|
|
322
352
|
|
|
323
353
|
const execAsync = promisify(exec);
|
|
324
|
-
const JOURNAL_TYPES = {
|
|
325
|
-
DAILY_NOTES: "daily-notes",
|
|
326
|
-
MEETING: "meeting",
|
|
327
|
-
NOTE: "note"
|
|
328
|
-
};
|
|
329
354
|
function ensureDirectoryExists(folderPath) {
|
|
330
355
|
if (!existsSync(folderPath)) {
|
|
331
356
|
consola.info(`Creating journal directory: ${colors.cyan(folderPath)}`);
|
|
@@ -420,7 +445,7 @@ function resolvePathTemplate(template, title, date, mondayDate) {
|
|
|
420
445
|
}
|
|
421
446
|
});
|
|
422
447
|
}
|
|
423
|
-
function generateJournalFileInfoByType({ journalSettings, date = /* @__PURE__ */ new Date(), type
|
|
448
|
+
function generateJournalFileInfoByType({ journalSettings, date = /* @__PURE__ */ new Date(), type, title }) {
|
|
424
449
|
const currentDate = new Date(date);
|
|
425
450
|
let templatePath = "";
|
|
426
451
|
let mondayDate = getMondayOfWeek(currentDate);
|
|
@@ -442,7 +467,7 @@ function generateJournalFileInfoByType({ journalSettings, date = /* @__PURE__ */
|
|
|
442
467
|
break;
|
|
443
468
|
}
|
|
444
469
|
default:
|
|
445
|
-
throw new Error(`Unknown
|
|
470
|
+
throw new Error(`Unknown JournalType: ${type}`);
|
|
446
471
|
}
|
|
447
472
|
const resolvedPath = resolvePathTemplate(templatePath, title, currentDate, mondayDate);
|
|
448
473
|
return {
|
|
@@ -508,34 +533,240 @@ async function configCommand(context) {
|
|
|
508
533
|
consola.log(` ${context.cwd}`);
|
|
509
534
|
}
|
|
510
535
|
|
|
536
|
+
const isGithubCliInstalled = async () => {
|
|
537
|
+
try {
|
|
538
|
+
const proc = await exec$1(`gh`, ["--version"]);
|
|
539
|
+
return proc.stdout.indexOf("https://github.com/cli/cli") > 0;
|
|
540
|
+
} catch (e) {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
const getIssues = async ({ assignedToMe, cwd }) => {
|
|
545
|
+
let issues = [];
|
|
546
|
+
const flags = [
|
|
547
|
+
"issue",
|
|
548
|
+
"list",
|
|
549
|
+
"--json",
|
|
550
|
+
"labels,number,title,state"
|
|
551
|
+
];
|
|
552
|
+
if (assignedToMe) {
|
|
553
|
+
flags.push("--assignee");
|
|
554
|
+
flags.push("@me");
|
|
555
|
+
}
|
|
556
|
+
const result = await exec$1(`gh`, flags);
|
|
557
|
+
const striped = stripAnsi(result.stdout);
|
|
558
|
+
issues = JSON.parse(striped);
|
|
559
|
+
return issues;
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
const createBranch = async ({ branchName }) => {
|
|
563
|
+
const result = await exec$1(`git`, ["checkout", "-b", branchName]);
|
|
564
|
+
return result.stdout;
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
const getTerminalColumns = () => process.stdout?.columns || 80;
|
|
568
|
+
const limitText = (text, maxWidth) => {
|
|
569
|
+
if (text.length <= maxWidth)
|
|
570
|
+
return text;
|
|
571
|
+
return `${text.slice(0, maxWidth - 1)}${colors.dim("\u2026")}`;
|
|
572
|
+
};
|
|
573
|
+
function hexToRgb(hex) {
|
|
574
|
+
const cleanHex = hex.replace("#", "");
|
|
575
|
+
const r = Number.parseInt(cleanHex.slice(0, 2), 16);
|
|
576
|
+
const g = Number.parseInt(cleanHex.slice(2, 4), 16);
|
|
577
|
+
const b = Number.parseInt(cleanHex.slice(4, 6), 16);
|
|
578
|
+
return { r, g, b };
|
|
579
|
+
}
|
|
580
|
+
function printWithHexColor({ msg, hex }) {
|
|
581
|
+
const colorWithHex = hex.startsWith("#") ? hex : `#${hex}`;
|
|
582
|
+
const { r, g, b } = hexToRgb(colorWithHex);
|
|
583
|
+
const colorStart = `\x1B[38;2;${r};${g};${b}m`;
|
|
584
|
+
const colorEnd = "\x1B[0m";
|
|
585
|
+
return `${colorStart}${msg}${colorEnd}`;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const checkPreqrequisites = async () => {
|
|
589
|
+
const cliInstalled = await isGithubCliInstalled();
|
|
590
|
+
if (!cliInstalled) {
|
|
591
|
+
consola.log("Github CLI not installed");
|
|
592
|
+
process.exit(1);
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
function customTrimEnd(str, charsToTrim) {
|
|
596
|
+
let i = str.length - 1;
|
|
597
|
+
while (i >= 0 && charsToTrim.includes(str[i])) {
|
|
598
|
+
i--;
|
|
599
|
+
}
|
|
600
|
+
return str.substring(0, i + 1);
|
|
601
|
+
}
|
|
602
|
+
const createBranchNameFromIssue = (selectedIssue) => {
|
|
603
|
+
let slug = selectedIssue.title.toLowerCase();
|
|
604
|
+
slug = slug.trim();
|
|
605
|
+
slug = slug.replaceAll(" ", "-");
|
|
606
|
+
slug = slug.replace(/[^0-9a-zA-Z_]/g, "-");
|
|
607
|
+
slug = slug.replaceAll("--", "-");
|
|
608
|
+
slug = slug.replaceAll("--", "-");
|
|
609
|
+
slug = slug.replaceAll("--", "-");
|
|
610
|
+
slug = customTrimEnd(slug, ["-"]);
|
|
611
|
+
const branchName = `feature/${selectedIssue.number}-${slug}`;
|
|
612
|
+
return branchName;
|
|
613
|
+
};
|
|
614
|
+
async function githubBranchCommand(context, args) {
|
|
615
|
+
await checkPreqrequisites();
|
|
616
|
+
const assignedToMe = Boolean(args.assignedToMe);
|
|
617
|
+
consola.log("Assigned to me:", assignedToMe);
|
|
618
|
+
const currentIssues = await getIssues({ assignedToMe, cwd: context.cwd });
|
|
619
|
+
if (currentIssues.length === 0) {
|
|
620
|
+
consola.log(colors.yellow("No issues found, check assignments"));
|
|
621
|
+
process.exit(1);
|
|
622
|
+
} else {
|
|
623
|
+
consola.log(colors.green(`${currentIssues.length} Issues found assigned to you`));
|
|
624
|
+
}
|
|
625
|
+
let lineMaxLength = getTerminalColumns();
|
|
626
|
+
const longestNumber = Math.max(...currentIssues.map((i) => i.number.toString().length));
|
|
627
|
+
const longestLabels = Math.max(...currentIssues.map((i) => i.labels.map((x) => x.name).join(", ").length));
|
|
628
|
+
lineMaxLength = lineMaxLength > 130 ? 130 : lineMaxLength;
|
|
629
|
+
const descriptionLength = lineMaxLength - longestNumber - longestLabels - 15;
|
|
630
|
+
const choices = currentIssues.map(
|
|
631
|
+
(i) => {
|
|
632
|
+
const labelText = i.labels.map((l) => printWithHexColor({ msg: l.name, hex: l.color })).join(", ");
|
|
633
|
+
const labelTextNoColor = i.labels.map((l) => l.name).join(", ");
|
|
634
|
+
const labelStartpad = longestLabels - labelTextNoColor.length;
|
|
635
|
+
return {
|
|
636
|
+
title: i.number.toString(),
|
|
637
|
+
value: i.number,
|
|
638
|
+
description: `${limitText(i.title, descriptionLength).padEnd(descriptionLength)} ${"".padStart(labelStartpad)}${labelText}`
|
|
639
|
+
// pads to make sure the labels are aligned, no diea why padStart doesn't work on labelText
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
);
|
|
643
|
+
choices.push({ title: "Cancel", value: "cancel" });
|
|
644
|
+
const fzf = new Fzf(choices, {
|
|
645
|
+
selector: (item) => `${item.value} ${item.description}`,
|
|
646
|
+
casing: "case-insensitive"
|
|
647
|
+
});
|
|
648
|
+
try {
|
|
649
|
+
const result = await prompts({
|
|
650
|
+
name: "issueNumber",
|
|
651
|
+
message: "Github issue to create branch for:",
|
|
652
|
+
type: "autocomplete",
|
|
653
|
+
choices,
|
|
654
|
+
async suggest(input, choices2) {
|
|
655
|
+
consola.log(input);
|
|
656
|
+
const results = fzf.find(input);
|
|
657
|
+
return results.map((r) => choices2.find((c) => c.value === r.item.value));
|
|
658
|
+
}
|
|
659
|
+
}, {
|
|
660
|
+
// when escape is used just cancel
|
|
661
|
+
onCancel: () => {
|
|
662
|
+
consola.info(colors.dim("Canceled"));
|
|
663
|
+
process.exit(0);
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
if (result.issueNumber === "cancel") {
|
|
667
|
+
consola.log(colors.dim("Canceled"));
|
|
668
|
+
process.exit(0);
|
|
669
|
+
}
|
|
670
|
+
const selectedIssue = currentIssues.find((i) => i.number === result.issueNumber);
|
|
671
|
+
consola.log(`Selected issue ${colors.green(selectedIssue.number)} - ${colors.green(selectedIssue.title)}`);
|
|
672
|
+
const branchName = createBranchNameFromIssue(selectedIssue);
|
|
673
|
+
createBranch({ branchName });
|
|
674
|
+
} catch (e) {
|
|
675
|
+
process.exit(1);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const CINCINNATI_LATITUDE = 39.1031;
|
|
680
|
+
const CINCINNATI_LONGITUDE = -84.512;
|
|
681
|
+
const WEATHER_DESCRIPTIONS = {
|
|
682
|
+
0: { description: "Clear sky", emoji: "\u2600\uFE0F" },
|
|
683
|
+
1: { description: "Mainly clear", emoji: "\u{1F324}\uFE0F" },
|
|
684
|
+
2: { description: "Partly cloudy", emoji: "\u26C5" },
|
|
685
|
+
3: { description: "Overcast", emoji: "\u2601\uFE0F" },
|
|
686
|
+
45: { description: "Fog", emoji: "\u{1F32B}\uFE0F" },
|
|
687
|
+
48: { description: "Depositing rime fog", emoji: "\u{1F32B}\uFE0F" },
|
|
688
|
+
51: { description: "Light drizzle", emoji: "\u{1F326}\uFE0F" },
|
|
689
|
+
53: { description: "Moderate drizzle", emoji: "\u{1F326}\uFE0F" },
|
|
690
|
+
55: { description: "Dense drizzle", emoji: "\u{1F327}\uFE0F" },
|
|
691
|
+
56: { description: "Light freezing drizzle", emoji: "\u{1F328}\uFE0F" },
|
|
692
|
+
57: { description: "Dense freezing drizzle", emoji: "\u{1F328}\uFE0F" },
|
|
693
|
+
61: { description: "Slight rain", emoji: "\u{1F327}\uFE0F" },
|
|
694
|
+
63: { description: "Moderate rain", emoji: "\u{1F327}\uFE0F" },
|
|
695
|
+
65: { description: "Heavy rain", emoji: "\u{1F327}\uFE0F" },
|
|
696
|
+
66: { description: "Light freezing rain", emoji: "\u{1F328}\uFE0F" },
|
|
697
|
+
67: { description: "Heavy freezing rain", emoji: "\u{1F328}\uFE0F" },
|
|
698
|
+
71: { description: "Slight snow fall", emoji: "\u{1F328}\uFE0F" },
|
|
699
|
+
73: { description: "Moderate snow fall", emoji: "\u2744\uFE0F" },
|
|
700
|
+
75: { description: "Heavy snow fall", emoji: "\u2744\uFE0F" },
|
|
701
|
+
77: { description: "Snow grains", emoji: "\u{1F328}\uFE0F" },
|
|
702
|
+
80: { description: "Slight rain showers", emoji: "\u{1F326}\uFE0F" },
|
|
703
|
+
81: { description: "Moderate rain showers", emoji: "\u{1F327}\uFE0F" },
|
|
704
|
+
82: { description: "Violent rain showers", emoji: "\u26C8\uFE0F" },
|
|
705
|
+
85: { description: "Slight snow showers", emoji: "\u{1F328}\uFE0F" },
|
|
706
|
+
86: { description: "Heavy snow showers", emoji: "\u2744\uFE0F" },
|
|
707
|
+
95: { description: "Thunderstorm", emoji: "\u26C8\uFE0F" },
|
|
708
|
+
96: { description: "Thunderstorm with slight hail", emoji: "\u26C8\uFE0F" },
|
|
709
|
+
99: { description: "Thunderstorm with heavy hail", emoji: "\u26C8\uFE0F" }
|
|
710
|
+
};
|
|
711
|
+
function getWindDirection(degrees) {
|
|
712
|
+
const directions = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"];
|
|
713
|
+
const index = Math.round(degrees / 22.5) % 16;
|
|
714
|
+
return directions[index];
|
|
715
|
+
}
|
|
716
|
+
function formatWeatherData(data) {
|
|
717
|
+
const { current_weather: weather, current_weather_units: units } = data;
|
|
718
|
+
const weatherInfo = WEATHER_DESCRIPTIONS[weather.weathercode] || {
|
|
719
|
+
description: "Unknown",
|
|
720
|
+
emoji: "\u2753"
|
|
721
|
+
};
|
|
722
|
+
const windDirection = getWindDirection(weather.winddirection);
|
|
723
|
+
const timeOfDay = weather.is_day ? "Day" : "Night";
|
|
724
|
+
consola.info("\u{1F30E} Current Weather in Cincinnati, OH");
|
|
725
|
+
consola.log("");
|
|
726
|
+
consola.log(`${weatherInfo.emoji} ${weatherInfo.description}`);
|
|
727
|
+
consola.log(`\u{1F321}\uFE0F Temperature: ${weather.temperature}${units.temperature}`);
|
|
728
|
+
consola.log(`\u{1F4A8} Wind: ${weather.windspeed} ${units.windspeed} ${windDirection}`);
|
|
729
|
+
consola.log(`\u{1F550} Time: ${new Date(weather.time).toLocaleTimeString()} (${timeOfDay})`);
|
|
730
|
+
}
|
|
731
|
+
async function weatherCommand(context) {
|
|
732
|
+
try {
|
|
733
|
+
consola.start("Fetching current weather for Cincinnati...");
|
|
734
|
+
const url = `https://api.open-meteo.com/v1/forecast?latitude=${CINCINNATI_LATITUDE}&longitude=${CINCINNATI_LONGITUDE}¤t_weather=true&temperature_unit=fahrenheit&windspeed_unit=mph&timezone=America/New_York`;
|
|
735
|
+
const response = await fetch(url);
|
|
736
|
+
if (!response.ok) {
|
|
737
|
+
throw new Error(`Weather API request failed: ${response.status} ${response.statusText}`);
|
|
738
|
+
}
|
|
739
|
+
const data = await response.json();
|
|
740
|
+
if (!data.current_weather) {
|
|
741
|
+
throw new Error("No weather data received from API");
|
|
742
|
+
}
|
|
743
|
+
consola.success("Weather data retrieved successfully!");
|
|
744
|
+
consola.log("");
|
|
745
|
+
formatWeatherData(data);
|
|
746
|
+
} catch (error) {
|
|
747
|
+
consola.error("Failed to fetch weather data:", error instanceof Error ? error.message : String(error));
|
|
748
|
+
process.exit(1);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
511
752
|
async function executeCommand(parsedArgs, context) {
|
|
512
753
|
switch (parsedArgs.command) {
|
|
513
754
|
case "journal": {
|
|
514
|
-
|
|
515
|
-
let journalType;
|
|
516
|
-
switch (subcommand) {
|
|
517
|
-
case "daily-notes":
|
|
518
|
-
case "today":
|
|
519
|
-
journalType = JOURNAL_TYPES.DAILY_NOTES;
|
|
520
|
-
break;
|
|
521
|
-
case "meeting":
|
|
522
|
-
journalType = JOURNAL_TYPES.MEETING;
|
|
523
|
-
break;
|
|
524
|
-
case "note":
|
|
525
|
-
journalType = JOURNAL_TYPES.NOTE;
|
|
526
|
-
break;
|
|
527
|
-
default:
|
|
528
|
-
throw new Error(`Unknown journal subcommand: ${subcommand}`);
|
|
529
|
-
}
|
|
530
|
-
await createJournalFile({ context, type: journalType, title: title || "" });
|
|
755
|
+
await createJournalFile({ context, type: parsedArgs.args.jouralType, title: parsedArgs.args.title || "" });
|
|
531
756
|
break;
|
|
532
757
|
}
|
|
533
758
|
case "git-commit":
|
|
534
759
|
await gitCommitCommand(context, parsedArgs.args.message);
|
|
535
760
|
break;
|
|
761
|
+
case "gh-branch":
|
|
762
|
+
await githubBranchCommand(context, parsedArgs.args);
|
|
763
|
+
break;
|
|
536
764
|
case "config":
|
|
537
765
|
await configCommand(context);
|
|
538
766
|
break;
|
|
767
|
+
case "weather":
|
|
768
|
+
await weatherCommand();
|
|
769
|
+
break;
|
|
539
770
|
default:
|
|
540
771
|
throw new Error(`Unknown command: ${parsedArgs.command}`);
|
|
541
772
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@towles/tool",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.18",
|
|
5
5
|
"description": "One off quality of life scripts that I use on a daily basis.",
|
|
6
6
|
"author": "Chris Towles <Chris.Towles.Dev@gmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -37,11 +37,13 @@
|
|
|
37
37
|
"@anthropic-ai/sdk": "^0.56.0",
|
|
38
38
|
"@clack/prompts": "^0.11.0",
|
|
39
39
|
"comment-json": "^4.2.5",
|
|
40
|
+
"consola": "^3.4.2",
|
|
40
41
|
"fzf": "^0.5.2",
|
|
41
42
|
"luxon": "^3.7.1",
|
|
42
43
|
"neverthrow": "^8.2.0",
|
|
43
44
|
"prompts": "^2.4.2",
|
|
44
|
-
"
|
|
45
|
+
"strip-ansi": "^7.1.0",
|
|
46
|
+
"tinyexec": "^0.3.2",
|
|
45
47
|
"yargs": "^17.7.2",
|
|
46
48
|
"zod": "^4.0.5"
|
|
47
49
|
},
|
|
@@ -55,7 +57,6 @@
|
|
|
55
57
|
"lint-staged": "^15.5.2",
|
|
56
58
|
"oxlint": "^1.7.0",
|
|
57
59
|
"simple-git-hooks": "^2.13.0",
|
|
58
|
-
"tinyexec": "^0.3.2",
|
|
59
60
|
"tsx": "^4.20.3",
|
|
60
61
|
"typescript": "^5.8.3",
|
|
61
62
|
"unbuild": "^3.5.0",
|