@lotics/cli 0.34.0 → 0.36.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
@@ -39,42 +39,57 @@ lotics auth signup a@b.com --name "Agent" # non-interactive
39
39
  lotics auth web
40
40
  ```
41
41
 
42
- **`lotics auth api-key`** — Saves an existing API key directly (e.g. one created in the Lotics web app).
42
+ **`lotics auth api-key`** — Saves an API key (e.g. one created in the Lotics web app). The key belongs to one org, so this **registers that org as a profile** — run it once per org. Registering a second key adds a profile; it does not overwrite the first.
43
43
 
44
44
  ```bash
45
45
  lotics auth api-key # interactive prompt
46
- lotics auth api-key ltk_... # non-interactive
46
+ lotics auth api-key ltk_... # registers the key's org as a profile (now active)
47
47
  ```
48
48
 
49
- API key is saved to the config file. Run `lotics auth logout` to remove saved credentials.
49
+ Run `lotics auth logout [<name|id>]` to remove a profile (default: the active org), or `lotics auth logout --all` to wipe the store.
50
50
 
51
- Auth priority: `--api-key` flag > `LOTICS_API_KEY` env > config file.
51
+ ## Organizations
52
52
 
53
- ### Config file location
53
+ Each saved API key belongs to one org. Register a key per org once, then switch freely — no re-pasting:
54
54
 
55
- The CLI resolves `.lotics/config.json` by walking up from the current working directory — the first ancestor that has one wins, otherwise the global `~/.lotics/config.json`. A per-directory config lets a project or worktree pin its own account and workspace; commands run from a subdirectory still resolve to it.
55
+ ```bash
56
+ lotics org # list saved orgs (marks the active one)
57
+ lotics org use acme # switch active org by name (or org id)
58
+ lotics org use "Acme Corp" # names are case-insensitive
59
+ ```
60
+
61
+ ### Working in parallel (worktrees)
56
62
 
57
- Create one by passing `--local` to `lotics auth`:
63
+ Pin a directory to its own org/workspace so a global `org use` elsewhere never disturbs it. The pin is a pointer — the key still comes from the global store, so there's nothing to paste:
58
64
 
59
65
  ```bash
60
66
  cd my-worktree
61
- lotics auth api-key ltk_... --local # writes ./.lotics/config.json
62
- lotics workspace select wks_... # auto-resolves to the local config
67
+ lotics org use acme --local # writes ./.lotics/config.json { active_org }
68
+ lotics workspace select wks_... # records the workspace in the local pin
63
69
  ```
64
70
 
65
- `.lotics/` should be gitignored. Note: an exported `LOTICS_API_KEY` overrides the config file's key.
71
+ Each worktree resolves independently; switching the global default in another shell leaves pinned worktrees untouched. Use `lotics auth whoami` to see the active org, workspace, and which source resolved them. `.lotics/` should be gitignored.
72
+
73
+ ### Resolution precedence
74
+
75
+ ```
76
+ --api-key flag > LOTICS_API_KEY env > LOTICS_ORG env (name|id)
77
+ > local .lotics/config.json > global active profile
78
+ ```
79
+
80
+ `LOTICS_WORKSPACE` (or `--workspace <id>` / `-w`) overrides the workspace at any level. For ephemeral or CI use, set `LOTICS_API_KEY` instead of saving anything.
66
81
 
67
82
  ## Workspaces
68
83
 
69
- If your organization has multiple workspaces, select one before running tools:
84
+ Workspaces live inside the active org. If the org has more than one, select before running tools:
70
85
 
71
86
  ```bash
72
- lotics workspace # list workspaces (marks current)
73
- lotics workspace select wks_... # switch to a workspace
87
+ lotics workspace # list workspaces in the active org (marks current)
88
+ lotics workspace select wks_... # set the workspace for the active scope (pin or profile)
74
89
  lotics workspace create "Sales" # create a new workspace (admin only)
75
90
  ```
76
91
 
77
- Single-workspace organizations auto-select on first use.
92
+ Single-workspace organizations auto-select on first use. The selection is remembered per org, so switching back lands where you left off.
78
93
 
79
94
  ## CLI
80
95
 
@@ -97,8 +112,11 @@ lotics upload ./report.pdf ./data.csv ./documents/
97
112
  lotics run generate_excel_from_template '{"..."}'
98
113
  lotics download <file_id> -o ./reports/
99
114
 
100
- # CI / non-interactive
115
+ # CI / non-interactive (key inline)
101
116
  LOTICS_API_KEY=ltk_... lotics run query_tables '{}'
117
+
118
+ # One-off against a saved org/workspace, no switching
119
+ LOTICS_ORG=acme LOTICS_WORKSPACE=wks_... lotics run query_tables '{}'
102
120
  ```
103
121
 
104
122
  ## Local .xlsx and .docx authoring
@@ -86,6 +86,15 @@ export declare function appCreate(client: LoticsClient, args: {
86
86
  export declare function appSetSubdomain(client: LoticsClient, args: {
87
87
  subdomain: string;
88
88
  }): Promise<void>;
89
+ /**
90
+ * `lotics app rename <name>` — change the current app's display name (the
91
+ * launcher/title shown in the workspace). The app_id comes from the local
92
+ * `package.json` manifest. Wraps the `update_app` tool — the public address
93
+ * (`lotics app subdomain`) and the code (`lotics app deploy`) are unchanged.
94
+ */
95
+ export declare function appRename(client: LoticsClient, args: {
96
+ name: string;
97
+ }): Promise<void>;
89
98
  export declare function appPull(client: LoticsClient, args: {
90
99
  app_id: string;
91
100
  targetPath?: string;
@@ -238,6 +238,19 @@ export async function appSetSubdomain(client, args) {
238
238
  const result = await client.setAppSubdomain(meta.app_id, args.subdomain);
239
239
  console.error(`Public address set: https://${result.public_subdomain}.lotics.app`);
240
240
  }
241
+ /**
242
+ * `lotics app rename <name>` — change the current app's display name (the
243
+ * launcher/title shown in the workspace). The app_id comes from the local
244
+ * `package.json` manifest. Wraps the `update_app` tool — the public address
245
+ * (`lotics app subdomain`) and the code (`lotics app deploy`) are unchanged.
246
+ */
247
+ export async function appRename(client, args) {
248
+ const meta = readAppMeta(process.cwd());
249
+ const res = await client.execute("update_app", { app_id: meta.app_id, name: args.name });
250
+ if (res.error)
251
+ throw new Error(res.error);
252
+ console.error(`App renamed: "${args.name}" (${meta.app_id})`);
253
+ }
241
254
  export async function appPull(client, args) {
242
255
  const app = await client.getApp(args.app_id);
243
256
  if (!app.current_version_id) {
package/dist/args.d.ts CHANGED
@@ -21,11 +21,13 @@ export declare function parseArgs(argv: string[]): {
21
21
  output?: string;
22
22
  as?: string;
23
23
  apiKey?: string;
24
+ workspace?: string;
24
25
  name?: string;
25
26
  timezone?: string;
26
27
  message?: string;
27
28
  forceWorkflowSync: boolean;
28
29
  local: boolean;
30
+ all: boolean;
29
31
  version: boolean;
30
32
  help: boolean;
31
33
  };
package/dist/args.js CHANGED
@@ -17,11 +17,13 @@ export function parseArgs(argv) {
17
17
  output: undefined,
18
18
  as: undefined,
19
19
  apiKey: undefined,
20
+ workspace: undefined,
20
21
  name: undefined,
21
22
  timezone: undefined,
22
23
  message: undefined,
23
24
  forceWorkflowSync: false,
24
25
  local: false,
26
+ all: false,
25
27
  version: false,
26
28
  help: false,
27
29
  };
@@ -49,6 +51,10 @@ export function parseArgs(argv) {
49
51
  case "--api-key":
50
52
  flags.apiKey = argv[++i];
51
53
  break;
54
+ case "--workspace":
55
+ case "-w":
56
+ flags.workspace = argv[++i];
57
+ break;
52
58
  case "--name":
53
59
  flags.name = argv[++i];
54
60
  break;
@@ -65,6 +71,9 @@ export function parseArgs(argv) {
65
71
  case "--local":
66
72
  flags.local = true;
67
73
  break;
74
+ case "--all":
75
+ flags.all = true;
76
+ break;
68
77
  case "--version":
69
78
  case "-v":
70
79
  flags.version = true;
package/dist/args.test.js CHANGED
@@ -34,4 +34,32 @@ describe("parseArgs", () => {
34
34
  expect(r.flags.forceWorkflowSync).toBe(false);
35
35
  expect(r.flags.message).toBeUndefined();
36
36
  });
37
+ it("parses --workspace as a value flag", () => {
38
+ const r = parseArgs(["run", "query_tables", "{}", "--workspace", "wsp_123"]);
39
+ expect(r.flags.workspace).toBe("wsp_123");
40
+ expect(r.command).toBe("run");
41
+ expect(r.subcommand).toBe("query_tables");
42
+ expect(r.toolArgs).toBe("{}");
43
+ });
44
+ it("parses -w as the workspace alias", () => {
45
+ const r = parseArgs(["run", "query_tables", "-w", "wsp_123"]);
46
+ expect(r.flags.workspace).toBe("wsp_123");
47
+ });
48
+ it("parses --all as a boolean flag", () => {
49
+ const r = parseArgs(["auth", "logout", "--all"]);
50
+ expect(r.flags.all).toBe(true);
51
+ expect(r.command).toBe("auth");
52
+ expect(r.subcommand).toBe("logout");
53
+ });
54
+ it("defaults workspace to undefined and all to false", () => {
55
+ const r = parseArgs(["org"]);
56
+ expect(r.flags.workspace).toBeUndefined();
57
+ expect(r.flags.all).toBe(false);
58
+ });
59
+ it("treats `org use <name>` as command / subcommand / positional", () => {
60
+ const r = parseArgs(["org", "use", "Acme Corp"]);
61
+ expect(r.command).toBe("org");
62
+ expect(r.subcommand).toBe("use");
63
+ expect(r.toolArgs).toBe("Acme Corp");
64
+ });
37
65
  });