Metadata-Version: 2.4
Name: unlegacy-cli
Version: 0.7.5
Summary: Unlegacy setup CLI for external coding agents
Author: Unlegacy
Project-URL: Homepage, https://app.unlegacy.ai
Project-URL: Repository, https://github.com/unlegacy-ai/unlegacy-core
Keywords: unlegacy,mcp,cli,coding-agents
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: Software Development
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"

# unlegacy-cli

Installable CLI for connecting local coding agents to Unlegacy MCP.

Unlegacy generates repository documentation, API references, knowledge graph
data, and Vault investigation docs in the platform. This CLI configures
external coding agents so they can consume that MCP surface.

## Install

Published package:

```sh
uv tool install unlegacy-cli
```

or:

```sh
pip install unlegacy-cli
```

After install, the command is saved on the user's machine as:

```sh
unlegacy --help
```

From a checkout:

```sh
pip install .
```

or:

```sh
uv tool install .
```

One-shot setup without preinstalling:

```sh
uv tool run --from 'unlegacy-cli>=0.7.5' unlegacy setup
```

## Distribution

Build the package artifacts:

```sh
uv build
```

Version 0.7.0 introduces device sign-in and project scope. Deploy the matching
backend and publish this version before distributing the frontend setup command.
For local verification before publication, use `uv run unlegacy setup` from this
checkout with `--project /path/to/project` and the local `--endpoint`.

The build creates `dist/unlegacy_cli-<version>.tar.gz` and
`dist/unlegacy_cli-<version>-py3-none-any.whl`. Publish those artifacts to the
Python package index used by Unlegacy clients.

## Setup

```sh
unlegacy setup
```

The interactive client picker supports Windows, macOS and Linux. Version 0.7.1
fixes the Windows `termios` import error; Windows users can use the same setup
command without extra flags. To refresh a cached one-shot installation:

```sh
uv tool run --refresh --from 'unlegacy-cli>=0.7.5' unlegacy setup
```

Version 0.7.2 adds actionable MCP and device sign-in transport diagnostics,
including Cloudflare blocks and correlation IDs.
Version 0.7.3 identifies all MCP and device sign-in HTTP requests as
`unlegacy-cli/<installed version>` so proxies can recognize the CLI. Cloudflare
Access policies must still permit the device sign-in flow.

Version 0.7.4 recovers interactive sign-in from rejected environment credentials,
repairs Windows skill integrity, and checks installation destinations before login.
It also fixes Windows redirected output and noninteractive previews.

Version 0.7.5 ships bundle 1.9.2 / skill 1.13.2 for resumable code and documentation
reads, bounded Cypher, and evidence-based search with the matching MCP server.

Keep any existing `--endpoint` option when upgrading a customer installation.

Run setup from your project folder. The wizard chooses **only this project**
by default, or **all projects for this user**, then lets you select clients.
The choice applies to both MCP configuration and the bundled skills.

Setup rejects a filesystem root such as `/` or `C:\` as a project. Before
sign-in, it checks the selected configuration, skills, credential and backup
destinations, including Git's local exclude file where applicable. Temporary
write probes are removed immediately. An unwritable destination stops setup with
its path and guidance before installing clients. Permissions can still change
after these checks; they do not make the whole setup a filesystem transaction.
`--dry-run` skips prompts, write probes, authentication and installation.
If terminal input ends during a prompt, setup reports how to pass explicit scope
and client options without a traceback.

On first setup, the CLI displays an eight-character code and opens the browser
at `/mcp?step=code`. Sign in, choose the organization and approve your code.
The terminal then installs the selected clients and runs doctor. Nothing is
approved merely by opening the page. Use `--no-browser` on a headless terminal.

The credential is saved privately in `~/.config/unlegacy/credentials.json`,
separately for each endpoint. Running setup in another project reuses that
connection after validating it; no new browser approval is needed. An expired
or revoked credential requires approval again. Use `--reconnect` to change the
connected organization: it ignores `UNLEGACY_MCP_TOKEN` and saved credentials
and starts browser approval. It cannot be combined with `--token`.
A network failure does not create another connection.
The production endpoint defaults to `https://app.unlegacy.ai/ai/mcp`.

```sh
# Configure the current project, or another folder, without repeating sign-in.
unlegacy setup --scope project --client claude-code --client codex
unlegacy setup --project /path/to/another-repository --client codex

# Explicitly make MCP and skills available in every project.
unlegacy setup --scope global --client claude-code --client codex

# Preview paths without authentication, network requests or writes.
unlegacy setup --project /path/to/repository --client all --dry-run

# Use this checkout's development server.
unlegacy setup --endpoint http://localhost:25250/ai/mcp
```

For automation, an existing credential can still be supplied with
`UNLEGACY_MCP_TOKEN` (or `--token`). The CLI never prints the token. HTTPS is
required except on loopback development hosts, and credential requests do not
follow redirects.

An explicit `--token` takes precedence over the environment and saved sign-in.
If it is rejected, setup stops and identifies that source. An environment token
also takes precedence, but an interactive setup recovers from its HTTP 401 by
trying saved sign-in for the same endpoint, then browser approval if needed.
Without an interactive terminal, a rejected environment token stops setup with
instructions; it never silently switches credentials. `--reconnect` explicitly
requests browser approval even without an interactive terminal.

Setup does not modify `UNLEGACY_MCP_TOKEN`. Update or unset a stale variable to
avoid repeated failures, including when running `doctor`, which continues to
validate the supplied credential. No token value is printed in these messages.

### Moving an existing global installation

Project setup detects global Unlegacy configuration and skills. The wizard asks
to migrate them; unattended setup requires `--remove-global`. Global entries are
removed only after project setup and doctor succeed. Other MCP servers and
unrelated skills are preserved; backups go under `~/.config/unlegacy/backups`.
Shared compatibility skill directories are included, so moving one may also
remove the global Unlegacy skill from another client that reads the same folder.
The wizard explains this before proceeding. Restart affected clients afterward.

```sh
unlegacy setup --scope project --client codex --remove-global
```

### Native installation locations

`PROJECT` means the enclosing Git repository root, or the specified/current
folder outside Git. `HOME` means your user profile. Client trust prompts still
apply; Codex loads project configuration only for trusted projects.

| Client | Project MCP | Global MCP | Project skills | Global skills |
| --- | --- | --- | --- | --- |
| Claude Code | Private project entry in `HOME/.claude.json` | `HOME/.claude.json` | `.claude/skills` | `HOME/.claude/skills` |
| Codex | `.codex/config.toml` | `HOME/.codex/config.toml` | `.agents/skills` | `HOME/.agents/skills` |
| Cursor | `.cursor/mcp.json` | `HOME/.cursor/mcp.json` | `.cursor/skills` | `HOME/.cursor/skills` |
| VS Code Copilot | `.vscode/mcp.json` | Default user profile `mcp.json` | `.github/skills` | `HOME/.copilot/skills` |
| OpenCode | `opencode.json` | `HOME/.config/opencode/opencode.json` | `.opencode/skills` | `HOME/.config/opencode/skills` |

The VS Code default user profile is `Library/Application Support/Code/User` on
macOS, `%APPDATA%/Code/User` on Windows and `.config/Code/User` on Linux.
Custom profiles, portable installs and custom client directory overrides are
not detected by this release. Scope controls where clients load Unlegacy; it
does not narrow the credential's organization/repository permissions.

Credential-bearing config files and backups use owner-only permissions on
POSIX. Project configs are added to Git's local `info/exclude`; setup refuses
tracked config files instead of inserting credentials into version control.
Untrack a personal config before setup, or keep a shared config and configure
credentials manually. Symlinked project targets outside the project are refused.
Packaged skills contain no credentials and may be versioned if desired.

Native behavior references: [Claude scopes](https://code.claude.com/docs/en/mcp),
[Codex configuration](https://developers.openai.com/codex/config-basic/),
[Codex skills](https://developers.openai.com/codex/skills/),
[Cursor skills](https://cursor.com/docs/skills),
[VS Code skills](https://code.visualstudio.com/docs/agent-customization/agent-skills),
and [OpenCode MCP](https://opencode.ai/docs/mcp-servers/).

Skill files are installed as the UTF-8 bytes checked by the manifest, preserving
LF line endings on Windows, macOS and Linux. Rerunning setup or `install-skills`
repairs a skill installed with CRLF line endings; doctor still rejects modified
files. Windows redirected terminal output uses UTF-8 so the interface does not
fail under a legacy output encoding.

Supported client values:

- `claude-code`
- `codex`
- `cursor`
- `vscode-copilot`
- `opencode`
- `all`

## Commands

```sh
unlegacy setup
unlegacy doctor
unlegacy install-skills --client codex
unlegacy status
```

## Bundled skill

`unlegacy setup` and `unlegacy install-skills` install one versioned skill bundle:

- `unlegacy` - authorized repository Knowledge and content retrieval

The bundle is self-contained; installing the external Superpowers plugin is not
required.

The skill is used only when you explicitly ask to consult Unlegacy: for example,
"ask Unlegacy about authentication", "pergunte ao legacy", "faça um legacy", or
`$unlegacy`. General code questions, mentions of legacy code, and work on the
Unlegacy project itself do not activate it. The request covers the current task
and its follow-ups, not unrelated later tasks. Codex also receives
`agents/openai.yaml` with implicit invocation disabled; use `$unlegacy` to
explicitly load the skill there. Natural-language selection depends on the
client's skill discovery behavior.

## Canonical MCP contract

The bundled skill targets Backend-authorized Catalog, Knowledge and content
reads. `list_repos`, `find_repos` and `repo_brief` resolve repository names and
availability. `search` and `org_survey` discover evidence in one
repository, a project or the organization. Survey coverage is the top 20
rank-fused hits, not an exhaustive inventory or confidence estimate.

`get_symbol` returns literal symbols and canonical entity refs. Pass those
complete refs to `symbol_context` and `impact`. File and docs tools use
canonical version IDs, paths, revisions and page cursors. Bundle 1.9.2 / skill
1.13.2 teaches resumable scans, directory filtering, recursive source inventories
and line/column continuation. It checks connected schemas before using newer
parameters. Inspecting the exact client-persisted MCP response with native Read
or bounded local parsing preserves MCP provenance; unread output still is not
evidence. Preserve returned provenance fields without inventing missing ones.
For unavailable or cut-off saved file reads, `get_code`/`read_doc` can request
smaller max_chars or line bounds; other tools use only advertised parameters.
A semantic KNOWLEDGE_UNAVAILABLE response permits one recorded sequential retry
only after repo_brief confirms available Knowledge for the same repository/version;
a 503 alone does not identify the cause. Literal lookup is reported separately.
Unique corpus counts come from inventory paths, not summed scan-page counters.
File pages default to 12,000 characters with a configurable 48,000-character cap.
Install it with the matching MCP server; these
arguments are unavailable on older deployments. Behavioral questions start with
`search`; `search_docs` ranks literal keyword counts within each bounded batch,
with `top_k` from 1 to 20 (default 5). Missing graph edges do not prove no
dependency; verify behavior in cited code. No client constructs
object-store keys or sends physical graph identifiers.

`cypher` supports a bounded single-node read-only subset translated to authorized
canonical symbol lookup, with name/path predicates, projections and complete
counts up to 200 matches. Relationships and arbitrary Cypher are unsupported;
use `symbol_context` and `impact` with returned refs. No raw query reaches KG. Vault-specific tools are not registered by this MCP server. `unlegacy
doctor` checks the repository tool inventory, not permissions or the full
runtime pipeline. Install this skill version with the matching server.

## Troubleshooting connection errors

CLI MCP requests and device sign-in requests identify themselves with
`User-Agent: unlegacy-cli/<installed version>`. This identifies the application
instead of relying on Python's generic HTTP identity. It is not a credential:
Cloudflare Access and other proxy policies must still permit the CLI's
authentication flow without an interactive browser challenge on these routes.

HTTP and network failures during MCP validation and device sign-in show the
request method and route, a suggested next step, and the UTC time. Valid
Cloudflare Ray IDs and application request IDs are included when returned.
Share these details with the installation administrator to correlate logs.
Response bodies, authorization headers, device codes and URL query parameters
are not included in these transport diagnostics.

For example, a confirmed Cloudflare 1010 response reports:

```text
Cloudflare blocked this request (HTTP 403, error 1010: browser_signature_banned).
Request: POST https://your-installation.example/ai/mcp/
Ask the Cloudflare administrator to review Browser Integrity Check and allow CLI access to this route without browser challenges.
Cloudflare Ray ID: <returned Ray ID>
Time (UTC): <request failure time>
```

A Cloudflare header alone does not establish that Cloudflare blocked the
request. Generic 403 responses ask the administrator to check both application
permissions and proxy/access policies. Explicit browser challenges and Access
login redirects have separate guidance. Credential requests never follow
redirects, and TLS certificate verification remains enabled.

A 403 does not discard a saved connection or start another approval. Only a
401 during saved MCP credential validation, or environment credential validation
in an interactive setup, triggers automatic recovery. Device
approval can also fail if the server returns an approval URL on a different
origin; the message asks the administrator to configure the public domain.
DNS failures, timeouts, TLS failures, missing routes and unavailable servers
have their own messages. This change improves diagnosis; it does not change
Cloudflare policies or repair server configuration.

## Development

```sh
uv run pytest
```

The `unlegacy-cli` GitHub Actions workflow runs the full suite and builds the
package on Windows, macOS and Linux with Python 3.11 and 3.12. It also runs the
suite against the installed wheel from a temporary directory. Authentication
tests use a local HTTP server; browser approval and keyboard input are simulated.
POSIX permission checks run on Unix; Windows uses its native read-only file test
and injected directory-access failures. This does not exercise a customer's
Windows console, domain ACLs or Cloudflare policies.
