@closedloop-ai/cli 0.3.0 → 0.3.2
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 +89 -7
- package/dist/closedloop.js +133 -113
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,14 +25,16 @@ The npm package is `@closedloop-ai/cli`; users of the earlier `cl` CLI can updat
|
|
|
25
25
|
## Commands
|
|
26
26
|
|
|
27
27
|
- `closedloop login` (also `closedloop signup`): sign in, or create an account on the Free plan, with a code sent to your email.
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
- `
|
|
28
|
+
- Which sign-in an account uses: an account with a password signs in with the password, and one whose workspace signs in with SSO uses SSO; both sign in through the browser with `closedloop login --sso`. Only a new email, or an account with neither (such as one made with `closedloop signup`), gets an emailed code. For any other account the code request is refused before an email is sent: `password_sign_in` for a password, `sso_required` for SSO, each naming `closedloop login --sso`.
|
|
29
|
+
- In a terminal, `closedloop login` asks for the email and the code. Before creating a new account it asks for the data region: United States (US, the default) or European Union (EU). Existing accounts keep their region and are not asked to choose another one.
|
|
30
|
+
- `--region us|eu` explicitly selects where a new account's data should live. For an agent creating an account, two runs: `closedloop signup --email you@example.com --region eu` sends the code; `closedloop login --email you@example.com --region eu --code BCDFG-HJKLM` finishes. Use `us` for the United States. Without a region, an agent creating a new account is refused with `region_required` before an email code is requested; existing accounts can still sign in without the flag. Add `--totp <code>` (or `--backup-code <code>`) when the account uses two-factor authentication.
|
|
31
|
+
- `closedloop login --sso`: sign in through your browser instead, for accounts with a password and for workspaces that sign in with SSO (Entra, Okta). Add `--region eu` or `--region us` to choose the initial sign-in region. It prints a link and a short code; open the link, sign in to the app, type the code and approve. An existing account automatically completes sign-in in its home region, even when the command started elsewhere. In a terminal it also copies the code to your clipboard and opens the link when you press Enter, then waits; an agent runs the printed command again after you approve, keeping its `--region` flag.
|
|
31
32
|
- An email whose account is in the other region (US or EU) signs in there, and the session stays with that region.
|
|
33
|
+
- `--region` never moves an existing account. A saved sign-in and `closedloop whoami` show the account's actual region. If a connection fails after browser approval in another region, repeat the same printed command: the CLI retains that pending sign-in and its original expiry. A rejected or expired request starts again with a fresh link and code.
|
|
32
34
|
- A new account gets its own Free workspace unless the email was invited to one. One network can create three such accounts a day.
|
|
33
35
|
- A new account is asked for its company website right after the code (in a terminal), or takes `--website <url>` (an agent passes it with `--code`). ClosedLoop AI researches the company from it before it analyses anything you send in; without it, imports run but nothing becomes insights. A website that cannot be saved does not undo the sign-in: the result names it and says to run `closedloop company --website <url>`.
|
|
34
36
|
- Then its email domains: the domains of your colleagues' work addresses, which tell ClosedLoop AI who is a colleague and who is a customer. In a terminal it suggests them (from the website and your own address, never a personal one such as gmail.com) and you confirm or correct them, or type `none` and confirm that your company has none. An agent gets `domains_instructions`: plain sentences telling it what to ask its user and which command to run with their answer. Nothing in a new workspace is analysed until a person has confirmed them.
|
|
35
|
-
- The session is saved in `credentials.json` in the config folder,
|
|
37
|
+
- The session is saved in `credentials.json` in the config folder. Tokens are stored as local JSON, not in an OS keychain; passwords are not saved. Unix directories use mode `0700` and files `0600`; Windows uses the account's local application-data folder and its inherited access permissions.
|
|
36
38
|
- The API checks the session on every call. The CLI renews it once it is past half its 30 days, so it stays signed in while you use it; if the API refuses it, the CLI renews once more, and otherwise asks you to sign in again.
|
|
37
39
|
- `closedloop whoami`: who you are signed in as, your workspace (role and plan), the other workspaces you belong to, the region, when and how this computer signed in (an email code, or Google, Microsoft, Okta or SAML SSO, or a password, in the browser), and when the sign-in ends if the CLI is not used.
|
|
38
40
|
- `closedloop status`: what is running now (company research, history imports with what is left and when they should finish, your own data still waiting or processing) and the onboarding checklist: company website, company research, email domains, product structure, a source, history imported, and the optional goal and team. Each open step names the command or the place in the app for it; a part the CLI could not read shows as unknown. No insights here: see `closedloop insights`.
|
|
@@ -42,6 +44,14 @@ The npm package is `@closedloop-ai/cli`; users of the earlier `cl` CLI can updat
|
|
|
42
44
|
- `--domains acme.example,acme.example.org` confirms your colleagues' email domains and `--no-domains` confirms your company has none (every colleague then counts as a customer, so results are wrong). Only a person confirms them: in a terminal the CLI asks you to type `yes`; anyone else adds `--confirmed-by-user`, which an agent does only after its user said yes. Without it nothing is saved and the result's `instructions` say what to ask. A personal email domain (gmail.com and the like) is refused. Needs the right to change the workspace's settings.
|
|
43
45
|
- As JSON, a workspace whose domains still wait carries `instructions`: what an agent should ask its user.
|
|
44
46
|
- `--watch` checks every 30 seconds until the research is done or fails, for up to an hour.
|
|
47
|
+
- The research reads your website to learn your company, its products and its market; it is the basis for the suggested product structure and for analysing your insights, and usually takes a few minutes. Once it is done, `closedloop company` says what it learned (its description of your company and the other parts it covers: products and features, use cases, target persona, integrations, pricing) and, while products it suggested wait to be confirmed, how many and how to confirm them. As JSON the summary is `research.summary` and the count `products_suggested` (null when it could not be read).
|
|
48
|
+
- `--research` shows everything the research found, the whole research text (as JSON, the profile with `research.text`).
|
|
49
|
+
- `closedloop products`: your product structure, the products, areas (parts of a product) and features (parts of the product that exist, never planned work) your insights are filed against, with insight counts, then the products your company research suggested and has not had confirmed. As JSON it is the API's answer, whose `structure` can be edited and saved.
|
|
50
|
+
- `products confirm [name...]` adds the suggested products (all, or the ones named) to the structure; `products save --file <structure.json>` (or `--file -` for standard input) saves a structure of your own, either the whole `closedloop products --json` answer or only its `structure`. Products, areas and features left out are archived, never deleted. `--check` only checks.
|
|
51
|
+
- Both check the structure first and list every change. In a terminal the CLI asks you to type `yes`; anyone else adds `--yes`, which an agent does only after its user agreed. Without it nothing is saved and the result's `instructions` say what to ask. Saving needs an owner or admin; the next nightly recalculation then re-places needs and insights, charged in credits.
|
|
52
|
+
- `closedloop competitors`: the competitors ClosedLoop AI watches for in your insights, the same list as Settings, Company, Competitors in the app: each with its website, whether it is a direct competitor, how many times customers mentioned it, and where it came from (your company research, your insights, or added or changed by your team). Insights that name one count as competitor mentions, shown on opportunities, features, customer profiles and the weekly brief. As JSON it is the API's `competitors` and `can_change`.
|
|
53
|
+
- `competitors add <name> [--website <url>] [--description <text>]` adds one as a direct competitor (adding one that was removed restores it); `competitors edit <name-or-id> [--name <name>] [--website <url>] [--description <text>]` changes only what you give (an empty value clears the website or description); `competitors remove <name-or-id>` marks it as not a competitor and takes it off the list, keeping the customer mentions behind it. A name matches in any case; one that matches none or several is refused with the candidates.
|
|
54
|
+
- A removal asks you to type `yes` in a terminal; anyone else adds `--yes`, which an agent does only after its user agreed. Without it nothing is removed and the result's `instructions` say what to ask. Adding, editing and removing need the right to change the workspace's settings (an owner or admin).
|
|
45
55
|
- `closedloop ingest [text]`: sends your own data in (feedback, notes, survey answers, transcripts) for the pipeline to turn into insights.
|
|
46
56
|
- One record from the words given, from `--stdin`, or from a text file; `--title`, `--from`, `--email` (ties the insight to their company when it matches a CRM contact), `--customer`, `--date`, `--url`, `--id` (a record with an id already sent is skipped) and `--tag` describe it.
|
|
47
57
|
- Many records from `--file` with a CSV (a header row; a `content` column, and any of `title, reporter_name, reporter_email, customer, date, url, id, tags` with tags separated by `;`), a JSON object or list, or JSON Lines. Sent in batches of 100 records or 4 MB.
|
|
@@ -76,7 +86,7 @@ The npm package is `@closedloop-ai/cli`; users of the earlier `cl` CLI can updat
|
|
|
76
86
|
- In the browser (OAuth), it opens the app's connect page and waits until the connection shows; an agent gets the link and runs the command again to check.
|
|
77
87
|
- Asana, Attio, Discord, Front, Granola, Pipedrive, Plaud, Read.ai, Stripe, Zendesk and Microsoft Teams connect in the browser without signing in to the app. The CLI opens a one-time link (valid for up to 10 minutes) that names the workspace; Continue there sends your browser back to the CLI on this computer, which finishes the connect, so a link someone forwards connects nothing. The command waits up to 15 minutes for the connection: in a terminal it shows the link and opens it when you press Enter; otherwise (an agent, a pipe) it opens the browser itself and prints one answer at the end, so an agent runs it with a long timeout or in the background. Asana needs `--field asana_workspace_gid=<id>` and Zendesk `--field zendesk_subdomain=<subdomain>` (a terminal asks for them).
|
|
78
88
|
- When the browser cannot come back to this computer, it gives the app's connect page instead (`status: browser_needed`, exit 0), with a `reason`: `remote_browser` (over SSH, in a Codespace, dev container, Gitpod, Cloud Shell, a container or Kubernetes), `no_local_listener` (the CLI could not listen on 127.0.0.1) or `browser_not_opened` (the browser could not be opened). `--in-app` asks for the app's connect page directly, for example when the confirm page's next step does not load. Settings given with `--field` are not used there; the app asks for them.
|
|
79
|
-
- Integrations set up only in the app get a link to it.
|
|
89
|
+
- Integrations set up only in the app get a link to it. Wherever the CLI sends you to the app it says how to sign in there: with your email address, since an account made in the CLI has no password: choose "Email me a code" and the app emails you a sign-in code.
|
|
80
90
|
- `--reconnect` connects again, for example with a new key.
|
|
81
91
|
- `closedloop integrations pause <name>` / `resume <name>`: stop syncing without disconnecting, and start again.
|
|
82
92
|
- `closedloop integrations disconnect <name>`: stops syncing after confirmation (`--yes` for agents); what was already imported stays.
|
|
@@ -86,6 +96,7 @@ The npm package is `@closedloop-ai/cli`; users of the earlier `cl` CLI can updat
|
|
|
86
96
|
- `usage by-source [--month 2026-10]`: a month's credits per integration or feature, largest first.
|
|
87
97
|
- `usage export [--month 2026-10] [--output file] [--force]`: saves the month's usage per day and integration as a CSV, never over an existing file unless `--force`.
|
|
88
98
|
- `closedloop plan`: your plan and what it includes; `plan upgrade` opens Plan & billing (payment happens in the browser), or gives an agent the link.
|
|
99
|
+
- `closedloop glossary`: what the words mean (product structure, product, area, feature, insight, opportunity, need, customer, competitor), as ClosedLoop AI defines them.
|
|
89
100
|
- `closedloop logout`: forgets the saved sign-in on this computer. Your other sessions, the web app included, stay signed in.
|
|
90
101
|
|
|
91
102
|
## How it looks
|
|
@@ -98,8 +109,79 @@ Every command does only what the person may do in the app, and the API decides:
|
|
|
98
109
|
|
|
99
110
|
## Settings
|
|
100
111
|
|
|
101
|
-
- `CLOSEDLOOP_API_URL`: the API to talk to. Defaults to the production API (`https://api.closedloop.sh`); existing EU accounts sign in through the EU API automatically. Use `http://localhost:3017` for an API running on your machine.
|
|
102
|
-
- `CLOSEDLOOP_CONFIG_DIR`:
|
|
112
|
+
- `CLOSEDLOOP_API_URL`: the API to talk to. Defaults to the production API (`https://api.closedloop.sh`); existing EU accounts sign in through the EU API automatically. Use `http://localhost:3017` for an API running on your machine. An explicit API selects the deployment for sign-up and skips the production region question. Combining it with `--region` is a usage error; unset it to choose a production region.
|
|
113
|
+
- `CLOSEDLOOP_CONFIG_DIR`: explicitly selects the folder for saved sign-in and settings; it takes precedence over every default.
|
|
114
|
+
- `XDG_CONFIG_HOME`: when explicitly set, retains the existing `$XDG_CONFIG_HOME/closedloop` location on every platform.
|
|
115
|
+
- Otherwise the default is `~/.config/closedloop` on Linux, `~/Library/Application Support/closedloop` on macOS, and `%LOCALAPPDATA%\closedloop` on Windows (falling back to the account's `AppData\Local` folder).
|
|
116
|
+
|
|
117
|
+
On the first use of a new native default, the CLI copies an existing
|
|
118
|
+
`~/.config/closedloop` folder to the new location if that location does not yet
|
|
119
|
+
exist. The copy is published only when complete; original files remain in place.
|
|
120
|
+
An existing destination is authoritative, including after logout, so an old
|
|
121
|
+
copy cannot silently restore a removed sign-in. Explicit directory overrides do
|
|
122
|
+
not trigger migration. Treat retained copies and backups as credentials too.
|
|
123
|
+
|
|
124
|
+
The earlier API-key CLI's `config.json` is retained during installation and
|
|
125
|
+
upgrades, but its team API key does not prove a person's identity: run
|
|
126
|
+
`closedloop login` to sign in. Existing person sessions from version 0.3.0
|
|
127
|
+
are preserved; team API keys are never converted into a person's session.
|
|
128
|
+
|
|
129
|
+
## Upgrade and troubleshoot
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
npm install --global @closedloop-ai/cli@latest
|
|
133
|
+
closedloop --version
|
|
134
|
+
cl --version
|
|
135
|
+
closedloop whoami --json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Upgrading replaces the installed package and preserves the separate config
|
|
139
|
+
folder. Uninstalling the package also leaves that folder intact; use
|
|
140
|
+
`closedloop logout` when you want this computer to forget its current sign-in.
|
|
141
|
+
Logout also cancels pending email and browser sign-in requests. It does not
|
|
142
|
+
revoke sessions on other computers or remove retained migration backups.
|
|
143
|
+
|
|
144
|
+
To return to an earlier compatible version, install its explicit version with
|
|
145
|
+
`npm install --global @closedloop-ai/cli@<version>`. The API can require a newer
|
|
146
|
+
minimum version; in that case follow the `upgrade_required` hint. If npm fails
|
|
147
|
+
during an upgrade, check both commands' versions and repeat the installation
|
|
148
|
+
before assuming the package changed successfully.
|
|
149
|
+
|
|
150
|
+
- `not_signed_in` or `session_expired`: run `closedloop login`; the CLI renews an existing session automatically when possible.
|
|
151
|
+
- `region_required`: choose `--region us` or `--region eu` before creating a new account in a noninteractive flow. `region_check_failed` means the CLI could not establish whether an account already exists; retry or choose a region explicitly. Existing accounts still sign in in their original region.
|
|
152
|
+
- `config_invalid`: back up the named JSON file and follow the recovery hint; the error never prints its contents. `closedloop logout` can remove damaged credentials and pending sign-in files.
|
|
153
|
+
- `config_write_failed`: check folder permissions and free disk space; a failed replacement keeps the previous saved file.
|
|
154
|
+
- `config_busy`: wait for other CLI commands to finish and retry. If a process stopped while holding a lock, inspect the named lock and confirm no CLI process is using it before removing it.
|
|
155
|
+
- `config_migration_failed`: use `CLOSEDLOOP_CONFIG_DIR` to select the original folder; the original files were kept.
|
|
156
|
+
- `session_changed`: a logout or newer sign-in took precedence while a request was running; repeat the command with the current sign-in. A delayed response does not restore a cancelled login.
|
|
157
|
+
- `unknown_number`: list again in the current account and workspace, then select its number; saved numbers are not portable across accounts or workspaces.
|
|
158
|
+
- `api_unreachable` or `api_timeout`: check connectivity and retry; inspect an ingestion failure's accepted-record hint before resending a partially sent batch.
|
|
159
|
+
- `rate_limited`: wait for the delay in the hint; the CLI does not automatically repeat a write.
|
|
160
|
+
|
|
161
|
+
On Windows desktop editions, Windows PowerShell 5.1 starts with the `Restricted`
|
|
162
|
+
execution policy, which refuses the `closedloop.ps1` launcher npm installs:
|
|
163
|
+
`closedloop` in PowerShell then fails with "running scripts is disabled on this
|
|
164
|
+
system". Run `closedloop.cmd` (or `cl.cmd`) in PowerShell, use Command Prompt,
|
|
165
|
+
where `closedloop` works as is, or allow local scripts for your account once with
|
|
166
|
+
`Set-ExecutionPolicy -Scope CurrentUser RemoteSigned`.
|
|
167
|
+
|
|
168
|
+
The JSON options (`--rule`, `--segment` and `--calc`) take inline JSON, a file path,
|
|
169
|
+
or `-` for standard input. On Windows, give a file. Windows PowerShell 5.1, any
|
|
170
|
+
PowerShell running `closedloop.cmd`, and Command Prompt remove the double quotes from
|
|
171
|
+
JSON typed in a command: in Windows PowerShell 5.1, `--rule '{"of":"customer"}'`
|
|
172
|
+
arrives as `{of:customer}` and fails with `invalid_rule`. Save the JSON in a UTF-8
|
|
173
|
+
file instead, for example with
|
|
174
|
+
`Set-Content rule.json '{"of":"customer"}' -Encoding UTF8` in PowerShell, then run
|
|
175
|
+
`closedloop segments preview --rule rule.json`. The commands the CLI suggests on
|
|
176
|
+
Windows pipe their JSON in, as in `'{"of":"customer"}' | closedloop segments preview --rule -`,
|
|
177
|
+
and write it in plain ASCII with other characters as `\u` escapes, because Windows
|
|
178
|
+
PowerShell 5.1 sends piped text to a program as ASCII.
|
|
179
|
+
|
|
180
|
+
Browser and clipboard helpers need the OS tools and a desktop session. On a
|
|
181
|
+
headless host or in a restricted session, follow the printed sign-in link and
|
|
182
|
+
code instead. Path simulations alone do not verify desktop behavior on every
|
|
183
|
+
OS edition; Windows Server guest coverage does not establish Windows desktop
|
|
184
|
+
coverage.
|
|
103
185
|
|
|
104
186
|
## Principles
|
|
105
187
|
|