invoket 0.1.9 → 0.1.10

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/CLAUDE.md ADDED
@@ -0,0 +1,57 @@
1
+ # CLAUDE.md
2
+
3
+ Add reusable commands to `tasks.ts`. invoket gives them typed args, `--help`, and error handling.
4
+
5
+ Use invoket when a command will be reused. Write a raw script for throwaway one-offs.
6
+
7
+ ## Task skeleton
8
+
9
+ ```typescript
10
+ import { Context } from "invoket/context";
11
+
12
+ export class Tasks {
13
+ /** Description (required — no JSDoc = not discovered) */
14
+ async taskName(c: Context, required: string, optional: number = 1) {}
15
+ }
16
+ ```
17
+
18
+ `async` + JSDoc + `c: Context` first param. `_prefix` = private.
19
+
20
+ ## Types → CLI
21
+
22
+ `string` as-is, `number` rejects NaN, `boolean` accepts `true/false/1/0/--flag/--no-flag`, `Interface` and `Record` expect JSON string, `type[]` expects JSON array, `...args: string[]` collects remaining, `= default` and `| null` make optional.
23
+
24
+ ## Flags
25
+
26
+ Auto: `--paramName`. For short flags add `@flag` in JSDoc:
27
+
28
+ ```typescript
29
+ /** @flag env -e --environment */
30
+ async deploy(c: Context, env: string) {}
31
+ ```
32
+
33
+ ## Namespaces
34
+
35
+ ```typescript
36
+ class Db {
37
+ /** Migrate */
38
+ async migrate(c: Context, direction: string = "up") {}
39
+ }
40
+ export class Tasks {
41
+ db = new Db(); // invt db:migrate up
42
+ }
43
+ ```
44
+
45
+ ## Context
46
+
47
+ ```typescript
48
+ await c.run(cmd); // throw on failure
49
+ await c.run(cmd, { warn: true }); // don't throw
50
+ const { stdout } = await c.run(cmd, { hide: true }); // capture
51
+ await c.run(cmd, { stream: true }); // real-time output
52
+ await c.run(cmd, { echo: true }); // print command first
53
+ await c.sudo(cmd); // sudo prefix
54
+ for await (const _ of c.cd(dir)) { } // temp cd
55
+ ```
56
+
57
+ Result: `{ stdout, stderr, code, ok, failed }`. Failure throws `CommandError` with `.result`.
package/README.md CHANGED
@@ -28,13 +28,21 @@ One script solves one problem. A `tasks.ts` file is a project's command centre.
28
28
  ## Installation
29
29
 
30
30
  ```bash
31
- bun add -d invoket # Add to project
32
- bun link invoket # Or link globally for development
31
+ bun add -d invoket # Add to project (use bunx invt to run)
32
+ bun add -g invoket # Or install globally (invt available on PATH)
33
33
  ```
34
34
 
35
+ Then scaffold your project:
36
+
37
+ ```bash
38
+ bunx invt --init # Creates tasks.ts and CLAUDE.md
39
+ ```
40
+
41
+ `--init` creates a starter `tasks.ts` and copies the `CLAUDE.md` reference card into your project so AI agents know how to write tasks.
42
+
35
43
  ## Quick Start
36
44
 
37
- Create `tasks.ts`:
45
+ Edit `tasks.ts`:
38
46
 
39
47
  ```typescript
40
48
  import { Context } from "invoket/context";
@@ -153,6 +161,7 @@ Flags and positional args can be freely mixed in any order.
153
161
  | `<task> -h` | Help for a specific task |
154
162
  | `-l`, `--list` | List tasks |
155
163
  | `--version` | Show version |
164
+ | `--init` | Scaffold `tasks.ts` and `CLAUDE.md` |
156
165
 
157
166
  ## Context API
158
167
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "invoket",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "type": "module",
5
5
  "description": "TypeScript task runner for Bun - uses type annotations to parse CLI arguments",
6
6
  "bin": {
@@ -10,7 +10,8 @@
10
10
  "./context": "./src/context.ts"
11
11
  },
12
12
  "files": [
13
- "src"
13
+ "src",
14
+ "CLAUDE.md"
14
15
  ],
15
16
  "keywords": [
16
17
  "task-runner",
package/src/cli.ts CHANGED
@@ -27,13 +27,18 @@ async function main() {
27
27
  return;
28
28
  }
29
29
 
30
- // Find tasks.ts
31
- let tasksPath: string;
32
- try {
33
- tasksPath = Bun.resolveSync("./tasks.ts", process.cwd());
34
- } catch {
35
- console.log("No tasks.ts found. Create one to get started:\n");
36
- console.log(`import { Context } from "invoket/context";
30
+ // --init flag: scaffold tasks.ts and CLAUDE.md
31
+ if (args[0] === "--init") {
32
+ const { existsSync } = await import("fs");
33
+ const cwd = process.cwd();
34
+
35
+ const tasksFile = `${cwd}/tasks.ts`;
36
+ if (existsSync(tasksFile)) {
37
+ console.log("tasks.ts already exists, skipping.");
38
+ } else {
39
+ await Bun.write(
40
+ tasksFile,
41
+ `import { Context } from "invoket/context";
37
42
 
38
43
  export class Tasks {
39
44
  /** Say hello */
@@ -41,7 +46,36 @@ export class Tasks {
41
46
  console.log("Hello, World!");
42
47
  }
43
48
  }
44
- `);
49
+ `,
50
+ );
51
+ console.log("Created tasks.ts");
52
+ }
53
+
54
+ const claudeFile = `${cwd}/CLAUDE.md`;
55
+ const claudeMdPath = new URL("../CLAUDE.md", import.meta.url).pathname;
56
+ const claudeMd = await Bun.file(claudeMdPath).text();
57
+ if (existsSync(claudeFile)) {
58
+ const existing = await Bun.file(claudeFile).text();
59
+ if (existing.includes("invoket")) {
60
+ console.log("CLAUDE.md already has invoket section, skipping.");
61
+ } else {
62
+ await Bun.write(claudeFile, existing.trimEnd() + "\n\n" + claudeMd);
63
+ console.log("Appended invoket guide to CLAUDE.md");
64
+ }
65
+ } else {
66
+ await Bun.write(claudeFile, claudeMd);
67
+ console.log("Created CLAUDE.md");
68
+ }
69
+
70
+ return;
71
+ }
72
+
73
+ // Find tasks.ts
74
+ let tasksPath: string;
75
+ try {
76
+ tasksPath = Bun.resolveSync("./tasks.ts", process.cwd());
77
+ } catch {
78
+ console.log("No tasks.ts found. Run 'invt --init' to get started.");
45
79
  process.exit(1);
46
80
  }
47
81