Metadata-Version: 2.4
Name: fastws-cli
Version: 0.0.8
Summary: Fast workspace tools for multi-repo management
Author: Jeremy Howard
License: Apache-2.0
Project-URL: Homepage, https://github.com/AnswerDotAI/fastws
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastcore>=1.14.3
Requires-Dist: fastgit>=0.0.7
Requires-Dist: ghapi>=1.0.7
Requires-Dist: packaging
Requires-Dist: tomli; python_version < "3.11"
Provides-Extra: dev
Requires-Dist: fastship; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# fastws

Fast workspace tools for multi-repo management.

## Install

```bash
pip install fastws-cli
```

## Setup

Create a `repos.txt` file listing your repos (one per line):

```
AnswerDotAI/fastcore
AnswerDotAI/fastgit
AnswerDotAI/fastship
AnswerDotAI/fastws
```

## Commands

### `ws-clone`

Clone all repos from your repos file:

```bash
ws-clone
ws-clone --repos-file myrepos.txt
ws-clone --workers 8
```

### `ws-pull`

Pull updates for all repos (parallel):

```bash
ws-pull
```

### `ws-status`

Show uncommitted changes and unpushed commits:

```bash
ws-status
ws-status --branches
```

### `ws-branches`

Check if all repos are on the expected branch:

```bash
ws-branches
ws-branches --expected develop
```

### `ws-sync`

Sync the workspace metadata, pull local repos, and install updates.
By default it uses the active venv parent as the workspace root, so you do not need to `cd` first.
It respects `tool.uv.workspace.members` and `exclude` when scanning local projects, and if any
member directory isn't a Python project yet (no `pyproject.toml`, e.g. a fresh empty clone), it
warns and skips the `uv sync` step instead of letting uv fail on the whole workspace.

At most once per day (tracked by a stamp file inside the workspace's `.git`, so git never
sees it), the sync also floats dependencies: `uv sync -U` instead of plain `uv sync`, plus
a parallel `cargo update` in every member with a `Cargo.toml`, printing what moved. Pass
`--upgrade` to force that pass regardless of when it last ran.

```bash
ws-sync
ws-sync --workspace ~/aai-ws
ws-sync --upgrade
```

### `ws-add`

Add a repo to `repos.txt`, then run `ws-sync`. Given `owner/repo`, it clones; given the
name of an existing local folder (e.g. one just scaffolded with `nbdev-new` or `ship-new`),
it resolves `owner/repo` from the folder's `origin` remote instead, telling you exactly
what's missing if the folder has no git repo, no GitHub origin, or no `pyproject.toml`:

```bash
ws-add AnswerDotAI/fastws
ws-add answerdotai/fastws
ws-add fastws  # existing local folder, resolved via its origin remote
```

### `ws-remove`

Remove a repo: delete its clone, and drop it from `repos.txt` and the workspace
`pyproject.toml`, then run `uv sync`. It refuses if the directory has uncommitted
changes, unpushed commits, no `origin` remote, or isn't a clean git checkout, and
always prompts for confirmation before deleting anything:

```bash
ws-remove AnswerDotAI/fastws
ws-remove fastws  # bare folder name also works if the directory exists
```

### `ws-releases`

Report repos with commits since their newest GitHub release, so nothing reviewed sits unshipped:

```bash
ws-releases                 # sweep every repo in repos.txt
ws-releases solveit         # only solveit's transitive workspace dependencies
ws-releases --skip 'wip'    # extra start-of-message regex for commits that need no release
```

Each pending repo lists its unreleased commit summaries; repos with no releases yet get one quiet `no releases:` line, and fully-released repos appear in `up to date:`. The newest release is picked by version number (publish timestamps can be out of order), and repos whose default branch isn't `main` are handled automatically.

Commits whose message matches a start-anchored regex from the skip set need no release and aren't reported. The built-in set covers version bumps and housekeeping (`bump`, `nbdev regen`, `.gitignore`, `docs`, `CI`, ...: `DEFAULT_SKIP` in `fastws.releases`); `[tool.fastws]` in the workspace root `pyproject.toml` adds to it, and names repos that should never be swept (apps that deploy rather than release):

```toml
[tool.fastws]
release_skip = ["docs only"]
release_exclude = ["solveit", "md_site"]
```

From Python (the primary interface - the CLI is a thin wrapper over `fastws.releases`):

```python
from fastws import check_releases, check_release
await check_releases()            # ReleaseReport: the repr is the report
await check_releases('solveit')   # dependency-closure mode
await check_release('mdhtml')     # one repo: list of unreleased commit summaries (None = no releases)
```
