Metadata-Version: 2.4
Name: lexgents-cli
Version: 0.1.2
Summary: A thin CLI client for the LexGents research service
License-Expression: LicenseRef-Proprietary
Project-URL: Repository, https://github.com/Tenfold-ai/LexGents-CLI
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# LexGents CLI

A thin Python client for the LexGents research service. The CLI runs locally;
research runs on the operator-configured server. Requires Python 3.10+ and has
no runtime dependencies. Browser login currently supports macOS and Linux.

This repository contains the CLI and a separately distributed Agent Skill.
Neither the wheel nor the source distribution includes the Skill. The package
name is `lexgents-cli`; the executable is `lexgents`. Stable releases use PyPI;
preview packages use TestPyPI. The Skill marketplace release is separate.

## Install or update

Use a maintained [uv](https://docs.astral.sh/uv/getting-started/installation/) on
macOS/Linux, then install the latest stable CLI in its managed tool environment:

```bash
uv tool install --upgrade --prerelease disallow lexgents-cli
lexgents --version
```

uv exposes `lexgents` on PATH and keeps its dependencies separate from projects.
If the executable is not found, follow uv's tool-directory PATH guidance and
start a new shell. Existing pipx users can install/upgrade with pipx instead;
a normal pip installation inside a virtual environment also works. System or
`pip --user` installs are unsupported: the launcher requires its managed
virtual environment. Do not use `sudo`, combine PyPI with TestPyPI, or substitute
a similarly named package. Use the official PyPI project `lexgents-cli`.

Update at the start of a new workflow and retain that version while research is
running. Compare `lexgents --version` with the current stable version on the
[official PyPI project](https://pypi.org/project/lexgents-cli/): a resolver may
silently select an older release compatible with its Python. If they differ,
resolve the Python/installer requirement before research rather than downgrading.
Follow the installed `--help` for exact flags.

The shipped `lexgents` launcher starts its own environment's Python in isolated
mode before Python imports run. No shell function or virtualenv activation is
needed. This prevents inherited Python startup paths from loading project code;
it is not an OS sandbox and cannot authenticate a different executable selected
by a hostile PATH. Use the executable installed by your trusted tool manager.

## Sign in and use the service

The CLI includes the public production configuration. No configuration file,
AWS account, endpoint variables or API token needs to be copied from a Skill.
The configuration contains service addresses, the public OAuth client ID and
loopback callback, not a password or client secret. CLI 0.1.0 used an external
configuration; this onboarding behavior requires the updated release.

```bash
lexgents auth status --json
lexgents login
lexgents research --query-file question.txt --json
```

Run login only when signed out or reauthentication is required. Research checks
eligibility itself. Use `lexgents doctor --json` for diagnosis and
`lexgents billing status --json` for trial/Credits information or after top-up.

Complete sign-in and MFA in a browser on the same computer. Login uses
authorization code + PKCE S256, then exchanges the identity token with the
configured backend for an application JWT. The callback listener only runs
during login. `--no-browser` prints a URL for this same computer; remote-device
login is not implemented. Callback support must be verified for the intended
identity-provider configuration before production use.

Credentials are saved in `~/.config/lexgents/session.json`, with directory mode
0700 and file mode 0600. Set `LEXGENTS_AUTH_DIR` to choose a different private
directory and reuse it for every command. This is file storage, not an OS
keychain. The CLI does not print stored token values.

Browser login requires a dedicated CLI Cognito client and a backend supporting
the CLI session policy. Its fixed deadline is eight days after authentication;
refresh never extends it. Application JWTs last at most one hour and are capped
at that deadline by the backend. `session_expires_at` reports the login deadline;
`app_expires_at` reports the current JWT's expiry. Existing Portal clients keep
their own policy. The seven-day trial and Credits rules are independent.

At the deadline, the next authenticated command or `auth status` removes the
local cache and requires a new login. There is no background deletion while the
CLI is closed. Earlier preview caches may require one new login. A backend
response without a CLI-specific session deadline is rejected. Configure and
deploy the service policy before upgrading users.

An expired-session response includes the trusted `top_up_url` when `portal_url`
is configured, with `billing_status=unknown`. The agent may offer this link for
sign-in and billing review; it must not claim payment is required without a fresh
billing check. During day seven to day eight, an otherwise valid login can still
read the expired-trial status and display its normal top-up notice.

The backend selects the existing default organization. `--organization-id`
rejects a different result; it does not grant membership or create an account.
Accounts without an organization use the existing Portal setup flow.

`auth status` reads cached state. Research, doctor and billing checks refresh
credentials when needed; `auth refresh --json` forces refresh. A rejected refresh
requires sign-in again. `logout --json` revokes the Cognito refresh token and
removes local credentials. Already-issued application JWTs remain subject to
their existing expiration, and the browser session is not cleared.

### Explicit operator/custom environments

Ordinary commands use production and reject inherited service/token overrides.
If `environment_conflict` is returned, remove stale overrides in the calling
process; do not print their values. The conflicting variables are
`LEXGENTS_AUTH_CONFIG`, `LEXGENTS_ACCESS_TOKEN`, `LEXGENTS_TOKEN_FILE`,
`LEXGENTS_ENDPOINT`, `LEXGENTS_BACKEND_URL`, `LEXGENTS_PORTAL_URL` and
`LANGSMITH_API_KEY`. `LEXGENTS_AUTH_DIR` only selects private credential storage.

Internal Dev or custom service use requires an explicit `--config` on every
command and a separate `LEXGENTS_AUTH_DIR`, distinct from the default production
credential directory. `examples/auth.example.json` is a nonfunctional template;
operators supply trusted targets. Credentials are bound to the chosen OAuth
client and service targets before refresh or revocation. An existing login for
another configuration is rejected, not silently reused or overwritten.

```bash
LEXGENTS_AUTH_DIR=/private/operator-auth lexgents login --config /private/operator-config.json
LEXGENTS_AUTH_DIR=/private/operator-auth lexgents auth status --config /private/operator-config.json --json
```

In this explicit operator mode, a private `LEXGENTS_TOKEN_FILE` or
`LEXGENTS_ACCESS_TOKEN` can supply an application JWT instead of browser login.
Inherited endpoint settings must match the explicit configuration. Credentials
are never command-line arguments and `.env` files are not automatically loaded.
`LANGSMITH_API_KEY`, when explicitly used in this mode, is sent only to the
research service. Ordinary end users do not need any of these overrides.

## Trial, Credits and top-up

Login and doctor include a billing snapshot. `billing status --json` returns a
fresh one. A completed status check is not permission to research: inspect
`billing.can_use`. `doctor` also checks the endpoint and authenticated assistant
availability; it does not execute research.

Before creating a research thread the CLI reads existing trial, feature
availability and Credits endpoints. It reports the server's trial deadline,
never derives a new seven-day period from login or JWT expiry, and preserves
the existing Portal Credits fallback after trial expiry. Credits thresholds and
deductions remain server-owned. The legacy availability response's overall
`canUse` is retained as `server_availability_can_use` for diagnosis.

- A deadline within one day produces `notice.code=trial_ending_soon`.
- Insufficient eligibility produces exit 9 / `payment_required`, a reason and
  `top_up_url` before research submission. The URL is generated from the trusted
  Portal origin and includes the current organization hint, never a token.
- The user chooses an amount and completes payment in Portal. Recheck billing
  afterward and resume the retained question only when `billing.can_use=true`.
  A successful browser return does not prove Credits have arrived.
- Failed, malformed or inconsistent billing reads produce exit 10 /
  `billing_unavailable`; unknown balance is not a request to pay.

The CLI does not create a checkout, pay, or change billing policy. Client-side
preflight is a usability check; server-side authorization and accounting must
enforce access independently. Login return and organization-mismatch protection
depend on the corresponding Portal version deployed by the operator.

## Research

```bash
lexgents research --query-file question.txt --json > result.json
lexgents research --input-file request.json --json
lexgents research --help
```

Questions are UTF-8 text, at most 2,000 characters. `--query-file -` reads stdin.
`--input-file` accepts an object containing `query`, `jurisdiction`, `language`,
`tool_list`, `max_tool_call_num` and optional `research_mode`, without an `input`
wrapper. A generic example is in `examples/research.json` in the repository.
Input-file mode rejects simultaneous override flags. Default jurisdiction is
Taiwan and language is Traditional Chinese. US jurisdictions require a state.
Optional research profiles are `xhigh` and `ultra`; syntax validation does not
establish service coverage for a jurisdiction.

Each command submits an independent question without conversation history. The
CLI creates a thread, waits for the run, and deletes the thread after a known
outcome. A timeout, disconnect or interruption during research leaves it for
operator investigation. No research is automatically replayed.

## Output and failures

`--json`, or piped stdout, emits one JSON object. Success requires exit 0,
`status=completed` and a nonempty `result.answer`. Source arrays and additional
result metadata are preserved. Inspect the answer and cited authorities;
technical completion is not legal-quality certification.

Errors include `error.code`, `error.message` and `error.outcome_unknown`. Keep
`request_id`, `thread_id` and any `run_id` for investigation. Request IDs are
correlation identifiers, not idempotency keys. When outcome is unknown, the
server may already have run the request; do not automatically resubmit it.

`thread_cleanup=deleted` confirms deletion was accepted, `not_attempted` means
no cleanup request was sent, and `unconfirmed` means cleanup was not confirmed.
Cleanup failure never calls for repeating the research. The default research
socket timeout is 600 seconds, not an overall wall-clock deadline. Stopping the
CLI does not cancel server work. HTTP redirects are refused to keep credentials
at the configured origin.

| Exit | Meaning |
|---|---|
| 0 | Command completed; inspect billing eligibility separately |
| 2 | Usage, input or configuration error |
| 3 | Missing/rejected credentials, access denied or account setup required |
| 4 | Rate limited |
| 5 | API/run failure, redirect, unavailable assistant or required input |
| 6 | Timeout |
| 7 | Connection failure |
| 8 | Invalid response |
| 9 | Payment required; show the returned URL and recheck after payment |
| 10 | Billing unavailable; no preflight-authorized research submitted |
| 130 | Client interrupted |

## Separate Agent Skill

The marketplace Skill/plugin is distributed independently. Neither the wheel
nor the source distribution includes it. Installation alone does not authorize
research or payment or change an agent's shell/network permissions. The CLI's
installed `--help` defines its command interface; Skill instructions teach
research selection, authorization, citation interpretation and error handling.

Python distributions contain only the CLI modules, the official POSIX launcher,
the public production configuration and approved package metadata/license. The
release scanner checks this allowlist, scans for credential leaks and requires
the exact reviewed production configuration. Configuration changes require
release review; responses from the research service cannot replace it.

## License

The CLI is proprietary. The included `LICENSE` permits installation and use to
access authorized LexGents services; other rights are reserved. Public package
availability does not grant an open-source license or service access.

## Development and release checks

From a checkout, with build tools available:

```bash
PYTHONPATH=src python -m unittest discover -s tests -v
python -m unittest discover -s infra/test -p 'test_*.py' -v
python -m build
python scripts/check_release.py dist/lexgents_cli-0.1.2-py3-none-any.whl dist/lexgents_cli-0.1.2.tar.gz
```

Tests use local synthetic OAuth, billing and research fixtures. No real account,
payment, deployment or customer data is required. See `SECURITY.md` for release
boundaries. Review the actual archives before uploading them; `.gitignore` does
not control package contents. The release pipeline uses AWS CodePipeline and
CodeBuild: every main push runs tests/build; an explicitly requested release
continues to TestPyPI upload and isolated installation checks
→ manual approval → PyPI upload of the same files and hash readback. Publication
credentials remain separate from builds and installation tests. See
[`docs/unified-release.md`](docs/unified-release.md) for versions, service
acceptance and operation. Infrastructure and operator docs are not included in
the distributions. Each approved batch release requires a stable version unused
on both indexes, reviewed publisher policy and the complete release path.
