@towles/tool 0.0.55 → 0.0.56

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@towles/tool",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "description": "CLI tool with auto-claude pipeline, developer tools, and journaling via markdown.",
5
5
  "keywords": [
6
6
  "auto-claude",
@@ -14,6 +14,7 @@ import {
14
14
  git,
15
15
  initConfig,
16
16
  log,
17
+ logBanner,
17
18
  runPipeline,
18
19
  sleep,
19
20
  stepRefresh,
@@ -140,7 +141,7 @@ export default class AutoClaude extends BaseCommand {
140
141
  iteration++;
141
142
 
142
143
  if (loopMode) {
143
- consola.box({ title: `Iteration #${iteration}`, message: new Date().toISOString() });
144
+ logBanner(`Iteration #${iteration} ${new Date().toISOString()}`);
144
145
  }
145
146
 
146
147
  try {
@@ -30,6 +30,7 @@ export default class Doctor extends BaseCommand {
30
30
  this.checkCommand("gh", ["--version"], /gh version ([\d.]+)/),
31
31
  this.checkCommand("node", ["--version"], /v?([\d.]+)/),
32
32
  this.checkCommand("bun", ["--version"], /([\d.]+)/),
33
+ this.checkCommand("pnpm", ["--version"], /([\d.]+)/),
33
34
  ]);
34
35
 
35
36
  // Display results
@@ -10,5 +10,6 @@ export {
10
10
  ensureBranch,
11
11
  git,
12
12
  log,
13
+ logBanner,
13
14
  sleep,
14
15
  } from "./utils.js";
@@ -11,7 +11,7 @@ import { stepPlan } from "./steps/plan.js";
11
11
  import { stepRemoveLabel } from "./steps/remove-label.js";
12
12
  import { stepResearch } from "./steps/research.js";
13
13
  import { stepReview } from "./steps/review.js";
14
- import { ensureDir, fileExists, git, log, writeFile } from "./utils.js";
14
+ import { ensureDir, fileExists, git, log, readFile, writeFile } from "./utils.js";
15
15
  import type { IssueContext } from "./utils.js";
16
16
 
17
17
  const STEP_RUNNERS: Record<StepName, (ctx: IssueContext) => Promise<boolean>> = {
@@ -55,7 +55,10 @@ export async function runPipeline(ctx: IssueContext, untilStep?: StepName): Prom
55
55
  }
56
56
  }
57
57
 
58
- log(`Pipeline complete for ${ctx.repo}#${ctx.number}`);
58
+ const prUrlPath = join(ctx.issueDir, ARTIFACTS.prUrl);
59
+ const prUrl = fileExists(prUrlPath) ? readFile(prUrlPath).trim() : "";
60
+ const prSuffix = prUrl ? ` — ${prUrl}` : "";
61
+ log(`Pipeline complete for ${ctx.repo}#${ctx.number}${prSuffix}`);
59
62
  await checkoutMain();
60
63
  }
61
64
 
@@ -134,12 +134,13 @@ describe("ARTIFACTS", () => {
134
134
  "planImplementation",
135
135
  "completedSummary",
136
136
  "review",
137
+ "prUrl",
137
138
  ]);
138
139
  });
139
140
 
140
- it("all values should be .md filenames", () => {
141
+ it("all values should be valid filenames", () => {
141
142
  for (const filename of Object.values(ARTIFACTS)) {
142
- expect(filename).toMatch(/^[\w-]+\.md$/);
143
+ expect(filename).toMatch(/^[\w-]+\.\w+$/);
143
144
  }
144
145
  });
145
146
  });
@@ -41,4 +41,5 @@ export const ARTIFACTS = {
41
41
  planImplementation: "plan-implementation.md",
42
42
  completedSummary: "completed-summary.md",
43
43
  review: "review.md",
44
+ prUrl: "pr-url.txt",
44
45
  } as const;
@@ -4,7 +4,7 @@ import consola from "consola";
4
4
 
5
5
  import { getConfig } from "../config.js";
6
6
  import { ARTIFACTS, STEP_LABELS } from "../prompt-templates/index.js";
7
- import { fileExists, ghRaw, git, log, logStep, readFile } from "../utils.js";
7
+ import { fileExists, ghRaw, git, log, logStep, readFile, writeFile } from "../utils.js";
8
8
  import type { IssueContext } from "../utils.js";
9
9
 
10
10
  export async function stepCreatePR(ctx: IssueContext): Promise<boolean> {
@@ -62,7 +62,9 @@ export async function stepCreatePR(ctx: IssueContext): Promise<boolean> {
62
62
  ]);
63
63
 
64
64
  if (prUrl) {
65
- log(`PR created: ${prUrl}`);
65
+ const url = prUrl.trim();
66
+ writeFile(join(ctx.issueDir, ARTIFACTS.prUrl), url);
67
+ log(`PR created: ${url}`);
66
68
  } else {
67
69
  consola.error("Failed to create PR");
68
70
  return false;
@@ -3,6 +3,7 @@ import { dirname, join, relative } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
 
5
5
  import consola from "consola";
6
+ import pc from "picocolors";
6
7
  import { x } from "tinyexec";
7
8
 
8
9
  import { getConfig } from "./config.js";
@@ -83,15 +84,15 @@ export async function runClaude(opts: {
83
84
 
84
85
  try {
85
86
  const parsed = JSON.parse(stdout) as ClaudeResult;
86
- consola.success(`Done — $${parsed.total_cost_usd.toFixed(4)} | ${parsed.num_turns} turns`);
87
+ consola.success(`Done — ${parsed.num_turns} turns`);
87
88
  if (parsed.result) {
88
- consola.box(parsed.result);
89
+ consola.log(parsed.result);
89
90
  }
90
91
  return parsed;
91
92
  } catch {
92
93
  consola.warn("Done — failed to parse Claude output");
93
94
  if (stdout.trim()) {
94
- consola.box(stdout.trim());
95
+ consola.log(stdout.trim());
95
96
  }
96
97
  return { result: stdout.trim(), is_error: false, total_cost_usd: 0, num_turns: 0 };
97
98
  }
@@ -246,9 +247,21 @@ export function log(msg: string): void {
246
247
  consola.info(`[auto-claude] ${msg}`);
247
248
  }
248
249
 
250
+ export function logBanner(label: string, width = 60): void {
251
+ const inner = ` ${label} `;
252
+ const totalDashes = Math.max(0, width - inner.length - 2);
253
+ const left = Math.ceil(totalDashes / 2);
254
+ const right = Math.floor(totalDashes / 2);
255
+ const dashes = pc.cyan;
256
+ consola.log(
257
+ `${dashes("#" + "-".repeat(left))}${pc.bold(inner)}${dashes("-".repeat(right) + "#")}`,
258
+ );
259
+ }
260
+
249
261
  export function logStep(step: string, ctx: IssueContext, skipped = false): void {
250
- const tag = skipped ? "SKIP" : "RUN";
251
- consola.box({ title: `[${tag}] ${step}`, message: `${ctx.repo}#${ctx.number} — ${ctx.title}` });
262
+ const tag = skipped ? pc.yellow("SKIP") : pc.green("RUN");
263
+ logBanner(`[${tag}] ${step}`);
264
+ consola.log(pc.dim(`${ctx.repo}#${ctx.number} — ${ctx.title}`));
252
265
  }
253
266
 
254
267
  // ── Git branch helpers ──