gitdog 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.
package/README.md CHANGED
@@ -17,29 +17,31 @@
17
17
  </p>
18
18
 
19
19
  <p align="center">
20
- <img src="https://raw.githubusercontent.com/hyodotdev/gitdog-cli/main/.github/assets/terminal.svg?v=0.1.1" alt="Gitdog terminal: connect a project, configure automation and review pending actions" width="800">
20
+ <img src="https://raw.githubusercontent.com/hyodotdev/gitdog-cli/main/.github/assets/terminal.svg?v=0.2.0" alt="Gitdog terminal: connect a project, configure automation and review pending actions" width="800">
21
21
  </p>
22
22
 
23
- Connect repositories, configure Gitdog's issue and discussion assistants, review
24
- AI actions, and automate project tasks from your terminal or CI.
23
+ Connect repositories, configure issue, discussion and PR automation, review
24
+ AI actions, and manage project tasks from your terminal or CI.
25
25
 
26
- ## Install
26
+ ## Run with npx
27
27
 
28
- Requires **Node.js 22.14+**.
28
+ Requires **Node.js 22.14+**. No global installation needed.
29
29
 
30
30
  ```sh
31
- npm install --global gitdog
31
+ npx gitdog@latest --help
32
32
  ```
33
33
 
34
34
  ## Quick start
35
35
 
36
36
  ```sh
37
- gitdog login
38
- gitdog github install
39
- gitdog github recover
40
- gitdog init owner/repo
41
- gitdog config set requireApproval true
42
- gitdog config push
37
+ npx gitdog@latest login
38
+ npx gitdog@latest github install
39
+ npx gitdog@latest github recover
40
+ npx gitdog@latest init owner/repo
41
+ npx gitdog@latest config set requireApproval true
42
+ npx gitdog@latest config set pullRequestReviewsEnabled true
43
+ npx gitdog@latest config set requireApprovalForPullRequests true
44
+ npx gitdog@latest config push
43
45
  ```
44
46
 
45
47
  GitHub App setup is only needed once. A project connects an existing GitHub
@@ -47,23 +49,23 @@ repository to Gitdog.
47
49
 
48
50
  ## Everyday commands
49
51
 
50
- | Task | Command |
51
- | ------------------------ | ---------------------------- |
52
- | List projects | `gitdog projects list` |
53
- | Read automation settings | `gitdog config get --remote` |
54
- | Review pending actions | `gitdog tickets pending` |
55
- | Check code indexing | `gitdog index status` |
56
- | List team members | `gitdog team members` |
57
- | Check usage | `gitdog usage summary` |
52
+ | Task | Command |
53
+ | ------------------------ | --------------------------------------- |
54
+ | List projects | `npx gitdog@latest projects list` |
55
+ | Read automation settings | `npx gitdog@latest config get --remote` |
56
+ | Review pending actions | `npx gitdog@latest tickets pending` |
57
+ | Check code indexing | `npx gitdog@latest index status` |
58
+ | List team members | `npx gitdog@latest team members` |
59
+ | Check usage | `npx gitdog@latest usage summary` |
58
60
 
59
- Use `gitdog --help` to explore commands. Add `--json` for scripts.
61
+ Use `npx gitdog@latest --help` to explore commands. Add `--json` for scripts.
60
62
 
61
63
  ## Use in CI
62
64
 
63
65
  ```sh
64
- gitdog keys create --name ci
65
- gitdog --key-file /path/to/key.json projects list --json
66
- gitdog keys revoke KEY_ID --yes
66
+ npx gitdog@latest keys create --name ci
67
+ npx --yes gitdog@0.2.0 --key-file /path/to/key.json projects list --json
68
+ npx gitdog@latest keys revoke KEY_ID --yes
67
69
  ```
68
70
 
69
71
  `keys create` prints the private key file's path. Keys are project-scoped and
@@ -267,7 +267,7 @@
267
267
  {
268
268
  "path": "repositories/mutation:updateSettings",
269
269
  "kind": "mutation",
270
- "args": "{\n repositoryId: v.id(\"repositories\"),\n settings: v.object({\n issueAssistantEnabled: v.boolean(),\n autoFormatIssue: v.boolean(),\n autoAnswerQuestions: v.boolean(),\n tagMaintainersForCodeChanges: v.boolean(),\n issueResponseStyle: v.optional(v.string()),\n requireApproval: v.boolean(),\n discussionAssistantEnabled: v.boolean(),\n autoFormatDiscussion: v.boolean(),\n autoAnswerDiscussionQuestions: v.boolean(),\n tagMaintainersForDiscussionCodeChanges: v.boolean(),\n discussionResponseStyle: v.optional(v.string()),\n requireApprovalForDiscussions: v.boolean(),\n }),\n }"
270
+ "args": "{\n repositoryId: v.id(\"repositories\"),\n settings: v.object({\n issueAssistantEnabled: v.boolean(),\n autoFormatIssue: v.boolean(),\n autoAnswerQuestions: v.boolean(),\n tagMaintainersForCodeChanges: v.boolean(),\n issueResponseStyle: v.optional(v.string()),\n requireApproval: v.boolean(),\n discussionAssistantEnabled: v.boolean(),\n autoFormatDiscussion: v.boolean(),\n autoAnswerDiscussionQuestions: v.boolean(),\n tagMaintainersForDiscussionCodeChanges: v.boolean(),\n discussionResponseStyle: v.optional(v.string()),\n requireApprovalForDiscussions: v.boolean(),\n pullRequestReviewsEnabled: v.optional(v.boolean()),\n pullRequestSuggestionsEnabled: v.optional(v.boolean()),\n requireApprovalForPullRequests: v.optional(v.boolean()),\n }),\n }"
271
271
  },
272
272
  {
273
273
  "path": "repositories/query:get",
@@ -387,12 +387,12 @@
387
387
  {
388
388
  "path": "tickets/query:list",
389
389
  "kind": "query",
390
- "args": "{\n githubRepo: v.optional(v.string()),\n status: v.optional(v.union(v.literal(\"open\"), v.literal(\"closed\"))),\n ticketType: v.optional(\n v.union(v.literal(\"issue\"), v.literal(\"discussion\")),\n ),\n search: v.optional(v.string()),\n limit: v.optional(v.number()),\n offset: v.optional(v.number()),\n }"
390
+ "args": "{\n githubRepo: v.optional(v.string()),\n status: v.optional(v.union(v.literal(\"open\"), v.literal(\"closed\"))),\n ticketType: v.optional(\n v.union(\n v.literal(\"issue\"),\n v.literal(\"discussion\"),\n v.literal(\"pull_request\"),\n ),\n ),\n search: v.optional(v.string()),\n limit: v.optional(v.number()),\n offset: v.optional(v.number()),\n }"
391
391
  },
392
392
  {
393
393
  "path": "tickets/query:listPendingApproval",
394
394
  "kind": "query",
395
- "args": "{\n githubRepo: v.optional(v.string()),\n ticketType: v.optional(\n v.union(v.literal(\"issue\"), v.literal(\"discussion\")),\n ),\n search: v.optional(v.string()),\n limit: v.optional(v.number()),\n offset: v.optional(v.number()),\n }"
395
+ "args": "{\n githubRepo: v.optional(v.string()),\n ticketType: v.optional(\n v.union(\n v.literal(\"issue\"),\n v.literal(\"discussion\"),\n v.literal(\"pull_request\"),\n ),\n ),\n search: v.optional(v.string()),\n limit: v.optional(v.number()),\n offset: v.optional(v.number()),\n }"
396
396
  },
397
397
  {
398
398
  "path": "tokenUsage/query:getCurrentMonthUsage",
package/dist/auth.js CHANGED
@@ -112,7 +112,7 @@ export async function createLoginListener(timeoutMs = 300_000) {
112
112
  response.end("Gitdog received your sign-in. Return to your terminal to finish. You can close this tab.");
113
113
  finish(undefined, value);
114
114
  });
115
- const timer = setTimeout(() => finish(new Error("Sign-in timed out. Run gitdog login to try again.")), timeoutMs);
115
+ const timer = setTimeout(() => finish(new Error("Sign-in timed out. Run npx gitdog@latest login to try again.")), timeoutMs);
116
116
  try {
117
117
  await new Promise((resolve, reject) => {
118
118
  server.once("error", reject);
@@ -195,11 +195,11 @@ export async function login(apiUrl, siteUrl, ui, noBrowser = false) {
195
195
  }
196
196
  catch {
197
197
  listener.signal.throwIfAborted();
198
- throw new Error("Could not finish sign-in. Check that the CLI loopback callback is deployed, then run gitdog login again.");
198
+ throw new Error("Could not finish sign-in. Check that the CLI loopback callback is deployed, then run npx gitdog@latest login again.");
199
199
  }
200
200
  const tokens = asRecord(exchange)?.tokens;
201
201
  if (!validTokens(tokens))
202
- throw new Error("Sign-in did not return a session. Run gitdog login again.");
202
+ throw new Error("Sign-in did not return a session. Run npx gitdog@latest login again.");
203
203
  client.setAuth(tokens.token);
204
204
  const user = asRecord(await invoke(client, "query", "users/query:getCurrentUser"));
205
205
  if (!user)
@@ -210,7 +210,7 @@ export async function login(apiUrl, siteUrl, ui, noBrowser = false) {
210
210
  ui.output(`✓ Signed in as ${String(user.name ?? "GitHub user")}.`);
211
211
  if (user.requiresCurrentLegalAttestation)
212
212
  ui.info(`Complete account consent at ${siteUrl}/legal/consent before running AI workflows.`);
213
- ui.info("Next: gitdog init");
213
+ ui.info("Next: npx gitdog@latest init");
214
214
  }
215
215
  finally {
216
216
  await listener.close();
package/dist/catalog.js CHANGED
@@ -3,6 +3,6 @@ export const API_CATALOG = catalog;
3
3
  export function publicOperation(path) {
4
4
  const operation = API_CATALOG.find((entry) => entry.path === path);
5
5
  if (!operation)
6
- throw new Error("Unknown public operation. Run gitdog api list. Internal functions cannot be called.");
6
+ throw new Error("Unknown public operation. Run npx gitdog@latest api list. Internal functions cannot be called.");
7
7
  return operation;
8
8
  }
package/dist/client.js CHANGED
@@ -60,15 +60,15 @@ export class GitdogApi {
60
60
  }
61
61
  const initial = await this.store.read();
62
62
  if (!initial)
63
- throw new Error("You are not logged in. Run gitdog login.");
63
+ throw new Error("You are not logged in. Run npx gitdog@latest login.");
64
64
  if (initial.apiUrl !== this.apiUrl)
65
- throw new Error("This session belongs to another API URL. Run gitdog login --api-url <url> first.");
65
+ throw new Error("This session belongs to another API URL. Run npx gitdog@latest login --api-url <url> first.");
66
66
  this.session = initial;
67
67
  if (tokenExpiresSoon(initial.token)) {
68
68
  this.session = await this.store.locked(async () => {
69
69
  const current = await this.store.read();
70
70
  if (!current || current.apiUrl !== this.apiUrl)
71
- throw new Error("Session changed. Run gitdog login again.");
71
+ throw new Error("Session changed. Run npx gitdog@latest login again.");
72
72
  if (!tokenExpiresSoon(current.token))
73
73
  return current;
74
74
  let result;
@@ -78,11 +78,11 @@ export class GitdogApi {
78
78
  });
79
79
  }
80
80
  catch {
81
- throw new Error("Could not refresh your session. Check your connection or run gitdog login again.");
81
+ throw new Error("Could not refresh your session. Check your connection or run npx gitdog@latest login again.");
82
82
  }
83
83
  const tokens = asRecord(result)?.tokens;
84
84
  if (!validTokens(tokens))
85
- throw new Error("Your session expired. Run gitdog login again.");
85
+ throw new Error("Your session expired. Run npx gitdog@latest login again.");
86
86
  const updated = { ...current, ...tokens };
87
87
  await this.store.save(updated);
88
88
  return updated;
package/dist/commands.js CHANGED
@@ -44,7 +44,7 @@ export function createProgram(dependencies = {}) {
44
44
  .option("-y, --yes", "Confirm the requested operation without prompting")
45
45
  .showHelpAfterError()
46
46
  .showSuggestionAfterError()
47
- .addHelpText("after", `\nGetting started:\n gitdog login\n gitdog init\n gitdog config set requireApproval true\n gitdog config push --dry-run\n gitdog config push\n\nFirebase-style aliases also work: projects:list, projects:create, config:push.\nRun gitdog <command> --help for details.`);
47
+ .addHelpText("after", `\nGetting started:\n npx gitdog@latest login\n npx gitdog@latest init\n npx gitdog@latest config set requireApproval true\n npx gitdog@latest config push --dry-run\n npx gitdog@latest config push\n\nFirebase-style aliases also work: projects:list, projects:create, config:push.\nRun npx gitdog@latest <command> --help for details.`);
48
48
  async function context(command) {
49
49
  const options = command.optsWithGlobals();
50
50
  const ui = dependencies.ui ?? new Ui(flag(options.json));
@@ -104,10 +104,14 @@ export function createProgram(dependencies = {}) {
104
104
  ui.output({
105
105
  name: "gitdog",
106
106
  version: VERSION,
107
- next: ["gitdog login", "gitdog init", "gitdog --help"],
107
+ next: [
108
+ "npx gitdog@latest login",
109
+ "npx gitdog@latest init",
110
+ "npx gitdog@latest --help",
111
+ ],
108
112
  });
109
113
  else
110
- ui.output("Get started\n 1. gitdog login Sign in with GitHub\n 2. gitdog init Connect a project\n 3. gitdog status Check your assistant\n\nRun gitdog --help to explore all commands.");
114
+ ui.output("Get started\n 1. npx gitdog@latest login Sign in with GitHub\n 2. npx gitdog@latest init Connect a project\n 3. npx gitdog@latest status Check your assistant\n\nRun npx gitdog@latest --help to explore all commands.");
111
115
  });
112
116
  command(program, "login", "Sign in with GitHub using your browser", async ({ apiUrl, siteUrl, ui }, _args, opts) => login(apiUrl, siteUrl, ui, opts.browser === false)).option("--no-browser", "Print the sign-in URL without opening a browser");
113
117
  command(program, "logout", "Revoke this session and remove saved credentials", async ({ ui }, _args, opts) => logout(ui, flag(opts.local))).option("--local", "Remove local credentials without contacting the server");
@@ -120,7 +124,7 @@ export function createProgram(dependencies = {}) {
120
124
  !process.env.GITDOG_API_KEY &&
121
125
  !(await new SessionStore().read())) {
122
126
  if (!process.stdin.isTTY || ui.json)
123
- throw new Error("Run gitdog login before gitdog init.");
127
+ throw new Error("Run npx gitdog@latest login before npx gitdog@latest init.");
124
128
  await login(apiUrl, siteUrl, ui);
125
129
  }
126
130
  await project.init(args[0], text(opts.alias) ?? "default", flag(opts.force));
@@ -212,7 +216,7 @@ export function createProgram(dependencies = {}) {
212
216
  expiresAt: issued.expiresAt,
213
217
  keyFile,
214
218
  });
215
- ui.info(`Key saved privately. Use: gitdog --key-file ${JSON.stringify(keyFile)} projects list`);
219
+ ui.info(`Key saved privately. Use: npx gitdog@latest --key-file ${JSON.stringify(keyFile)} projects list`);
216
220
  })
217
221
  .option("--name <name>", "Key name", "CLI key")
218
222
  .option("--write", "Grant project settings and ticket write access (read access is always included)")
@@ -324,7 +328,7 @@ export function createProgram(dependencies = {}) {
324
328
  do {
325
329
  const remaining = deadline - Date.now();
326
330
  if (flag(opts.wait) && remaining <= 0)
327
- throw new Error("Timed out waiting for indexing. Indexing continues on the server; check gitdog index status.");
331
+ throw new Error("Timed out waiting for indexing. Indexing continues on the server; check npx gitdog@latest index status.");
328
332
  const state = await api.call("query", "repoIndexing/query:getIndexingStatus", { repositoryId: repo._id }, flag(opts.wait) ? { timeoutMs: remaining } : undefined);
329
333
  const record = asRecord(state);
330
334
  if (!record)
@@ -339,14 +343,14 @@ export function createProgram(dependencies = {}) {
339
343
  last = fingerprint;
340
344
  }
341
345
  if (record.status === "failed" || record.ragStatus === "failed")
342
- throw new Error("Indexing failed. Run gitdog index logs for details.");
346
+ throw new Error("Indexing failed. Run npx gitdog@latest index logs for details.");
343
347
  if (record.status === "completed" &&
344
348
  ["completed", "skipped"].includes(String(record.ragStatus))) {
345
349
  ui.output(state);
346
350
  return;
347
351
  }
348
352
  if (Date.now() >= deadline)
349
- throw new Error("Timed out waiting for indexing. Indexing continues on the server; check gitdog index status.");
353
+ throw new Error("Timed out waiting for indexing. Indexing continues on the server; check npx gitdog@latest index status.");
350
354
  await new Promise((resolve) => setTimeout(resolve, Math.min(2000, Math.max(1, deadline - Date.now()))));
351
355
  } while (true);
352
356
  })
@@ -376,11 +380,11 @@ export function createProgram(dependencies = {}) {
376
380
  }));
377
381
  const tickets = program
378
382
  .command("tickets")
379
- .description("Browse issues, discussions and pending approvals");
383
+ .description("Browse issues, discussions, PR reviews and pending approvals");
380
384
  for (const pending of [false, true]) {
381
385
  command(tickets, pending ? "pending" : "list", pending
382
386
  ? "List tickets awaiting approval"
383
- : "List issues and discussions", async ({ api, project, ui }, _args, opts) => {
387
+ : "List issues, discussions and PR reviews", async ({ api, project, ui }, _args, opts) => {
384
388
  const githubRepo = flag(opts.all)
385
389
  ? undefined
386
390
  : (await project.repository()).githubRepo;
@@ -401,6 +405,7 @@ export function createProgram(dependencies = {}) {
401
405
  .addOption(new Option("--type <type>", "Ticket type").choices([
402
406
  "issue",
403
407
  "discussion",
408
+ "pull_request",
404
409
  ]))
405
410
  .option("--search <text>", "Search title, repository or GitHub number")
406
411
  .option("--limit <n>", "Page size (1–500)", limitParser, 20)
@@ -516,7 +521,7 @@ export function createProgram(dependencies = {}) {
516
521
  await openBrowser(url);
517
522
  ui.output({
518
523
  url,
519
- next: "After GitHub authorization, run gitdog github recover, then gitdog projects available.",
524
+ next: "After GitHub authorization, run npx gitdog@latest github recover, then npx gitdog@latest projects available.",
520
525
  });
521
526
  })
522
527
  .option("--app <slug>", "GitHub App slug (use gitdogbot-dev for development)", "gitdogbot")
@@ -527,7 +532,7 @@ export function createProgram(dependencies = {}) {
527
532
  if (result?.status !== "recovered") {
528
533
  ui.output({ ...result, recoveredCount: count });
529
534
  if (result?.status === "reauth_required")
530
- throw new Error("Refresh GitHub authorization with gitdog login, then run github recover again.");
535
+ throw new Error("Refresh GitHub authorization with npx gitdog@latest login, then run github recover again.");
531
536
  return;
532
537
  }
533
538
  ui.info(`Recovered installation ${String(result.installationId)}.`);
@@ -568,7 +573,7 @@ export function createProgram(dependencies = {}) {
568
573
  if (operation.path === "apiKeys/action:create")
569
574
  throw new Error("Use keys create to issue API keys securely into a private file.");
570
575
  if (!operation.path.startsWith("admin/"))
571
- throw new Error("Use gitdog api call for non-admin operations.");
576
+ throw new Error("Use npx gitdog@latest api call for non-admin operations.");
572
577
  const data = await jsonArguments(text(opts.data) ?? "{}");
573
578
  if (operation.kind !== "query") {
574
579
  if (!ui.json)
@@ -1,6 +1,6 @@
1
1
  import { type Ui } from "./ui.js";
2
2
  import type { Api } from "./client.js";
3
- export declare const BOOLEAN_SETTINGS: readonly ["issueAssistantEnabled", "autoFormatIssue", "autoAnswerQuestions", "tagMaintainersForCodeChanges", "requireApproval", "discussionAssistantEnabled", "autoFormatDiscussion", "autoAnswerDiscussionQuestions", "tagMaintainersForDiscussionCodeChanges", "requireApprovalForDiscussions"];
3
+ export declare const BOOLEAN_SETTINGS: readonly ["pullRequestReviewsEnabled", "pullRequestSuggestionsEnabled", "requireApprovalForPullRequests", "issueAssistantEnabled", "autoFormatIssue", "autoAnswerQuestions", "tagMaintainersForCodeChanges", "requireApproval", "discussionAssistantEnabled", "autoFormatDiscussion", "autoAnswerDiscussionQuestions", "tagMaintainersForDiscussionCodeChanges", "requireApprovalForDiscussions"];
4
4
  export declare const STYLE_SETTINGS: readonly ["issueResponseStyle", "discussionResponseStyle"];
5
5
  export type Settings = Record<(typeof BOOLEAN_SETTINGS)[number], boolean> & Partial<Record<(typeof STYLE_SETTINGS)[number], string>>;
6
6
  export type Project = {
package/dist/projects.js CHANGED
@@ -5,6 +5,9 @@ import { dirname, join, resolve } from "node:path";
5
5
  import { exists, readJson, writeJson } from "./storage.js";
6
6
  import { asRecord, integer } from "./ui.js";
7
7
  export const BOOLEAN_SETTINGS = [
8
+ "pullRequestReviewsEnabled",
9
+ "pullRequestSuggestionsEnabled",
10
+ "requireApprovalForPullRequests",
8
11
  "issueAssistantEnabled",
9
12
  "autoFormatIssue",
10
13
  "autoAnswerQuestions",
@@ -48,12 +51,19 @@ export function validateSettings(value, complete = false) {
48
51
  throw new Error(`${key} must be a string.`);
49
52
  }
50
53
  else
51
- throw new Error(`Unknown setting: ${key}. Run gitdog config keys.`);
54
+ throw new Error(`Unknown setting: ${key}. Run npx gitdog@latest config keys.`);
52
55
  settings[key] = item;
53
56
  }
54
57
  if (complete &&
55
- BOOLEAN_SETTINGS.some((key) => typeof settings[key] !== "boolean"))
58
+ BOOLEAN_SETTINGS.filter((key) => key !== "pullRequestReviewsEnabled" &&
59
+ key !== "pullRequestSuggestionsEnabled" &&
60
+ key !== "requireApprovalForPullRequests").some((key) => typeof settings[key] !== "boolean"))
56
61
  throw new Error("The server returned incomplete project settings. Update Gitdog before applying settings.");
62
+ if (complete) {
63
+ settings.pullRequestReviewsEnabled ??= false;
64
+ settings.pullRequestSuggestionsEnabled ??= true;
65
+ settings.requireApprovalForPullRequests ??= true;
66
+ }
57
67
  return settings;
58
68
  }
59
69
  export function validateProjectConfig(value) {
@@ -63,7 +73,7 @@ export function validateProjectConfig(value) {
63
73
  typeof config.defaultProject !== "string" ||
64
74
  !projects ||
65
75
  !Object.hasOwn(projects, config.defaultProject))
66
- throw new Error("Invalid gitdog.json. Run gitdog init in a new directory, or repair the project configuration.");
76
+ throw new Error("Invalid gitdog.json. Run npx gitdog@latest init in a new directory, or repair the project configuration.");
67
77
  const result = {};
68
78
  for (const [alias, value] of Object.entries(projects)) {
69
79
  aliasName(alias);
@@ -114,10 +124,10 @@ export class ProjectContext {
114
124
  async config() {
115
125
  const path = await findConfig(this.configOption);
116
126
  if (!path)
117
- throw new Error("No gitdog.json found. Run gitdog init, or pass --project owner/repo.");
127
+ throw new Error("No gitdog.json found. Run npx gitdog@latest init, or pass --project owner/repo.");
118
128
  const value = await readJson(path);
119
129
  if (value === undefined)
120
- throw new Error(`No project configuration at ${path}. Run gitdog init.`);
130
+ throw new Error(`No project configuration at ${path}. Run npx gitdog@latest init.`);
121
131
  return { path, value: validateProjectConfig(value) };
122
132
  }
123
133
  async target(override) {
@@ -134,7 +144,7 @@ export class ProjectContext {
134
144
  const { value } = await this.config();
135
145
  const alias = selection ?? value.defaultProject;
136
146
  if (!Object.hasOwn(value.projects, alias))
137
- throw new Error(`Unknown project alias ${alias}. Run gitdog use --list.`);
147
+ throw new Error(`Unknown project alias ${alias}. Run npx gitdog@latest use --list.`);
138
148
  return value.projects[alias].repository;
139
149
  }
140
150
  async repository(override) {
@@ -143,7 +153,7 @@ export class ProjectContext {
143
153
  ? await this.api.call("query", "repositories/query:get", { owner: target.split("/")[0], repo: target.split("/")[1] })
144
154
  : await this.api.call("query", "repositories/query:getById", { repositoryId: target });
145
155
  if (!repository)
146
- throw new Error(`Project ${target} is not connected or accessible. Run gitdog projects create ${target}.`);
156
+ throw new Error(`Project ${target} is not connected or accessible. Run npx gitdog@latest projects create ${target}.`);
147
157
  return repository;
148
158
  }
149
159
  async available(reconnectRepositoryId) {
@@ -174,7 +184,7 @@ export class ProjectContext {
174
184
  const available = await this.available(reconnectRepositoryId);
175
185
  const matches = available.filter((item) => String(item.fullName).toLowerCase() === name.toLowerCase());
176
186
  if (matches.length !== 1)
177
- throw new Error(`Repository ${name} is unavailable. Run gitdog github install, authorize it, then gitdog github recover. Check projects available.`);
187
+ throw new Error(`Repository ${name} is unavailable. Run npx gitdog@latest github install, authorize it, then npx gitdog@latest github recover. Check projects available.`);
178
188
  const item = matches[0];
179
189
  if (typeof item.installationId !== "number" || typeof item.id !== "number")
180
190
  throw new Error("GitHub returned invalid repository identifiers.");
@@ -196,7 +206,7 @@ export class ProjectContext {
196
206
  join(process.cwd(), "gitdog.json");
197
207
  const previous = await readJson(path);
198
208
  if (previous !== undefined && !force)
199
- throw new Error(`Project configuration already exists at ${path}. Use gitdog use --add, or --force to replace it.`);
209
+ throw new Error(`Project configuration already exists at ${path}. Use npx gitdog@latest use --add, or --force to replace it.`);
200
210
  if (!name) {
201
211
  let detected;
202
212
  try {
@@ -231,14 +241,14 @@ export class ProjectContext {
231
241
  alias,
232
242
  config: path,
233
243
  });
234
- this.ui.info("✓ Ready. Try gitdog status, gitdog config get, or gitdog tickets list.");
244
+ this.ui.info("✓ Ready. Try npx gitdog@latest status, npx gitdog@latest config get, or npx gitdog@latest tickets list.");
235
245
  }
236
246
  async use(selection, add, list = false) {
237
247
  const { path, value } = await this.config();
238
248
  if (add) {
239
249
  aliasName(add);
240
250
  if (!selection)
241
- throw new Error("Use gitdog use owner/repo --add alias.");
251
+ throw new Error("Use npx gitdog@latest use owner/repo --add alias.");
242
252
  if (Object.hasOwn(value.projects, add))
243
253
  throw new Error(`Alias ${add} already exists. Choose a new alias.`);
244
254
  const repo = await this.repository(selection);
@@ -274,7 +284,7 @@ export class ProjectContext {
274
284
  : Object.keys(value.projects).find((key) => value.projects[key].repository.toLowerCase() ===
275
285
  alias.toLowerCase());
276
286
  if (!match)
277
- throw new Error("This project has no local settings. Add it with gitdog use owner/repo --add alias.");
287
+ throw new Error("This project has no local settings. Add it with npx gitdog@latest use owner/repo --add alias.");
278
288
  return { path, value, alias: match, project: value.projects[match] };
279
289
  }
280
290
  async configGet(key, remote = false) {
@@ -298,7 +308,7 @@ export class ProjectContext {
298
308
  local.project.settings = { ...local.project.settings, ...patch };
299
309
  await writeJson(local.path, local.value);
300
310
  this.ui.output({ saved: true, settings: patch });
301
- this.ui.info("Saved locally. Run gitdog config push to apply.");
311
+ this.ui.info("Saved locally. Run npx gitdog@latest config push to apply.");
302
312
  }
303
313
  async configPull(force = false) {
304
314
  const local = await this.localProject();
package/dist/storage.js CHANGED
@@ -80,7 +80,7 @@ export class SessionStore {
80
80
  if (!validTokens(value) ||
81
81
  typeof item?.apiUrl !== "string" ||
82
82
  typeof item.siteUrl !== "string")
83
- throw new Error("Invalid saved session. Run gitdog logout, then gitdog login.");
83
+ throw new Error("Invalid saved session. Run npx gitdog@latest logout, then npx gitdog@latest login.");
84
84
  return {
85
85
  ...value,
86
86
  apiUrl: validateUrl(item.apiUrl, "Saved API URL"),
package/dist/ui.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "0.1.1";
1
+ export declare const VERSION = "0.2.0";
2
2
  export declare const DOG: string;
3
3
  export declare function redactSecrets(value: string): string;
4
4
  export declare function clean(value: string): string;
package/dist/ui.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createInterface } from "node:readline/promises";
2
2
  import { stripVTControlCharacters } from "node:util";
3
- export const VERSION = "0.1.1";
3
+ export const VERSION = "0.2.0";
4
4
  export const DOG = String.raw `
5
5
  ▗██▄▄ ▄▄██▖
6
6
  ██▀▜██▙▄ ▙▄ ▄▟██▛▀██
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitdog",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Manage Gitdog projects, GitHub automation and API keys from your terminal",
5
5
  "type": "module",
6
6
  "bin": {