@locusai/sdk 0.1.1

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 (2) hide show
  1. package/PACKAGE_GUIDE.md +269 -0
  2. package/package.json +44 -0
@@ -0,0 +1,269 @@
1
+ # Locus Package Author Guide
2
+
3
+ This guide explains how to build, test, and publish a community package for
4
+ the [Locus](https://github.com/locusai/locus) CLI.
5
+
6
+ ---
7
+
8
+ ## Naming convention
9
+
10
+ All Locus packages must be published to npm with the prefix `locus-`:
11
+
12
+ | Short name | npm package name |
13
+ |------------|-------------------|
14
+ | `telegram` | `locus-telegram` |
15
+ | `slack` | `locus-slack` |
16
+ | `jira` | `locus-jira` |
17
+
18
+ Scoped packages (e.g. `@myorg/locus-telegram`) are also accepted and will be
19
+ used as-is.
20
+
21
+ ---
22
+
23
+ ## `package.json` manifest format
24
+
25
+ Every Locus package **must** include a `"locus"` field in its `package.json`.
26
+ This field tells the Locus CLI how to display and invoke your package.
27
+
28
+ ```jsonc
29
+ {
30
+ "name": "locus-telegram",
31
+ "version": "1.0.0",
32
+ "description": "Remote-control Locus via Telegram",
33
+ "bin": {
34
+ "locus-telegram": "./bin/locus-telegram.js"
35
+ },
36
+
37
+ // Required: Locus package manifest
38
+ "locus": {
39
+ "displayName": "Telegram",
40
+ "description": "Remote-control your Locus agent from Telegram",
41
+ "commands": ["telegram"],
42
+ "version": "1.0.0"
43
+ }
44
+ }
45
+ ```
46
+
47
+ | Field | Type | Description |
48
+ |---------------|------------|------------------------------------------------------------------|
49
+ | `displayName` | `string` | Human-readable name shown in `locus packages list`. |
50
+ | `description` | `string` | One-line description shown in `locus packages list`. |
51
+ | `commands` | `string[]` | Sub-commands contributed. Used in `locus pkg <name>` dispatch. |
52
+ | `version` | `string` | Semver version — should mirror the npm package version. |
53
+
54
+ ---
55
+
56
+ ## Binary entry point
57
+
58
+ Your package must expose a binary. Locus discovers it via
59
+ `~/.locus/packages/node_modules/.bin/locus-<name>` after installation.
60
+
61
+ In `package.json`:
62
+
63
+ ```json
64
+ "bin": {
65
+ "locus-telegram": "./bin/locus-telegram.js"
66
+ }
67
+ ```
68
+
69
+ The binary should be executable Node.js (shebang `#!/usr/bin/env node`).
70
+
71
+ When invoked via `locus pkg telegram [args...]`, the remaining args are
72
+ forwarded to your binary verbatim.
73
+
74
+ ---
75
+
76
+ ## Using `@locusai/sdk`
77
+
78
+ Install the SDK as a dev dependency (it is a peer contract, not bundled):
79
+
80
+ ```sh
81
+ npm install --save-dev @locusai/sdk
82
+ ```
83
+
84
+ ### Reading project config
85
+
86
+ ```ts
87
+ import { readLocusConfig } from "@locusai/sdk";
88
+
89
+ // Reads ~/.locus/config.json + ./.locus/config.json and merges them.
90
+ const config = readLocusConfig();
91
+
92
+ console.log(config.github.owner); // "myorg"
93
+ console.log(config.ai.model); // "claude-sonnet-4-6"
94
+ ```
95
+
96
+ ### Invoking `locus` sub-commands
97
+
98
+ ```ts
99
+ import { invokeLocus, invokeLocusStream } from "@locusai/sdk";
100
+
101
+ // Captured output (blocking)
102
+ const result = await invokeLocus(["run", "42"]);
103
+ if (result.exitCode !== 0) {
104
+ console.error("locus run failed:", result.stderr);
105
+ }
106
+
107
+ // Streaming (non-blocking)
108
+ const child = invokeLocusStream(["run", "42"]);
109
+ child.stdout?.on("data", (chunk: Buffer) => process.stdout.write(chunk));
110
+ child.on("exit", (code) => console.log("exited with", code));
111
+ ```
112
+
113
+ ### Structured logger
114
+
115
+ ```ts
116
+ import { createLogger } from "@locusai/sdk";
117
+
118
+ const logger = createLogger("telegram");
119
+
120
+ logger.info("Bot started");
121
+ logger.warn("Rate limit approaching", { remaining: 5 });
122
+ logger.error("Connection failed", { code: 503 });
123
+ logger.debug("Raw update", { update_id: 12345 }); // only shown with LOCUS_DEBUG=1
124
+ ```
125
+
126
+ Output uses the same prefix symbols as the Locus CLI (`●`, `⚠`, `✗`, `⋯`).
127
+
128
+ ---
129
+
130
+ ## Minimal end-to-end example
131
+
132
+ Below is a complete minimal Locus package (`locus-hello`).
133
+
134
+ ### Directory structure
135
+
136
+ ```
137
+ locus-hello/
138
+ ├── bin/
139
+ │ └── locus-hello.js
140
+ ├── src/
141
+ │ └── index.ts
142
+ ├── package.json
143
+ └── tsconfig.json
144
+ ```
145
+
146
+ ### `package.json`
147
+
148
+ ```json
149
+ {
150
+ "name": "locus-hello",
151
+ "version": "1.0.0",
152
+ "description": "Example Locus package",
153
+ "type": "module",
154
+ "bin": {
155
+ "locus-hello": "./bin/locus-hello.js"
156
+ },
157
+ "locus": {
158
+ "displayName": "Hello",
159
+ "description": "A minimal example Locus package",
160
+ "commands": ["hello"],
161
+ "version": "1.0.0"
162
+ },
163
+ "scripts": {
164
+ "build": "tsc"
165
+ },
166
+ "devDependencies": {
167
+ "@locusai/sdk": "^0.1.0",
168
+ "typescript": "^5.0.0"
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### `src/index.ts`
174
+
175
+ ```ts
176
+ import { createLogger, readLocusConfig } from "@locusai/sdk";
177
+
178
+ const logger = createLogger("hello");
179
+
180
+ export async function run(): Promise<void> {
181
+ const config = readLocusConfig();
182
+ logger.info(`Hello from locus-hello! Repo: ${config.github.owner}/${config.github.repo}`);
183
+ }
184
+ ```
185
+
186
+ ### `bin/locus-hello.js`
187
+
188
+ ```js
189
+ #!/usr/bin/env node
190
+ import "../dist/index.js";
191
+
192
+ const { run } = await import("../dist/index.js");
193
+ await run();
194
+ ```
195
+
196
+ Make it executable:
197
+
198
+ ```sh
199
+ chmod +x bin/locus-hello.js
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Testing locally with `npm link`
205
+
206
+ 1. Build your package:
207
+
208
+ ```sh
209
+ npm run build
210
+ ```
211
+
212
+ 2. Link it globally:
213
+
214
+ ```sh
215
+ npm link
216
+ ```
217
+
218
+ 3. Install it into Locus's packages directory:
219
+
220
+ ```sh
221
+ locus install locus-hello
222
+ ```
223
+
224
+ Or, for a faster dev loop, symlink directly:
225
+
226
+ ```sh
227
+ mkdir -p ~/.locus/packages/node_modules
228
+ ln -s $(pwd) ~/.locus/packages/node_modules/locus-hello
229
+ mkdir -p ~/.locus/packages/node_modules/.bin
230
+ ln -s $(pwd)/bin/locus-hello.js ~/.locus/packages/node_modules/.bin/locus-hello
231
+ ```
232
+
233
+ 4. Run your package:
234
+
235
+ ```sh
236
+ locus pkg hello
237
+ ```
238
+
239
+ ---
240
+
241
+ ## Publishing to npm
242
+
243
+ 1. Make sure the `"locus"` field is present in your `package.json`.
244
+ 2. Ensure the binary listed in `"bin"` is executable.
245
+ 3. Build your package.
246
+ 4. Publish:
247
+
248
+ ```sh
249
+ npm publish --access public
250
+ ```
251
+
252
+ After publishing, users can install your package with:
253
+
254
+ ```sh
255
+ locus install hello # short name (locus-hello)
256
+ locus install locus-hello
257
+ ```
258
+
259
+ ---
260
+
261
+ ## Checklist before publishing
262
+
263
+ - [ ] Package name starts with `locus-` (or is scoped)
264
+ - [ ] `"locus"` field present in `package.json` with all required keys
265
+ - [ ] Binary listed in `"bin"` exists and has the shebang line
266
+ - [ ] Binary is executable (`chmod +x`)
267
+ - [ ] Package builds cleanly with no TypeScript errors
268
+ - [ ] Tested locally with `locus pkg <name>`
269
+ - [ ] `README.md` explains what the package does and how to configure it
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@locusai/sdk",
3
+ "version": "0.1.1",
4
+ "description": "SDK for building Locus-compatible community packages",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "PACKAGE_GUIDE.md",
24
+ "README.md"
25
+ ],
26
+ "scripts": {
27
+ "build": "bun build ./src/index.ts --outdir ./dist --target node --format esm && bun build ./src/index.ts --outfile ./dist/index.cjs --target node --format cjs && tsc -p tsconfig.build.json --emitDeclarationOnly",
28
+ "typecheck": "tsc --noEmit",
29
+ "lint": "biome lint .",
30
+ "format": "biome format --write .",
31
+ "clean": "rm -rf dist node_modules"
32
+ },
33
+ "keywords": [
34
+ "locus",
35
+ "sdk",
36
+ "package",
37
+ "plugin",
38
+ "community"
39
+ ],
40
+ "license": "MIT",
41
+ "engines": {
42
+ "node": ">=18"
43
+ }
44
+ }