Metadata-Version: 2.5
Name: windy-drops
Version: 0.1.0
Summary: Python SDK + CLI for publishing drops to the Windy Drops registry. WD-4..WD-10 of DNA_STRAND_MASTER_PLAN.md.
Project-URL: Homepage, https://windydrops.com
Project-URL: Repository, https://github.com/sneakyfree/windy-drops
Project-URL: Issues, https://github.com/sneakyfree/windy-drops/issues
Author: Windy Drops contributors
License-Expression: MIT
Keywords: cli,drops,marketplace,skill,windy
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.11
Requires-Dist: cryptography>=43
Requires-Dist: httpx>=0.27
Requires-Dist: pyyaml>=6.0
Requires-Dist: typer>=0.12
Requires-Dist: windy-drops-spec>=0.1
Provides-Extra: test
Requires-Dist: pytest>=8; extra == 'test'
Description-Content-Type: text/markdown

# windy-drops (Python SDK)

Python SDK + CLI for authoring and publishing **Windy Drops**.

> **Not published yet.** This package is not on PyPI as of 2026-08-10; the command below is
> what the install will be once it ships. Until then, run the CLI from a checkout of
> `sneakyfree/windy-drops`.

```bash
pip install windy-drops
windy-drops --help
```

## Commands

| Command | What it does | Strand |
|---|---|---|
| `new --type <type> <path>` | Scaffold a starter drop from `examples/<type>-minimal/` | WD-4 (this) |
| `validate <path>` | Validate SKILL.md frontmatter against the schema | WD-5 |
| `bundle <path>` | Produce a deterministic `.zip` + SHA-256 digest | WD-6 |
| `sign <path>` | Sign manifest with the author's Eternitas Passport (ES256) | WD-7 |
| `publish <path>` | Validate → bundle → sign → upload to R2 → POST to registry | WD-8 |
| `withdraw <drop-id>` | Hide from search (existing installs keep working) | WD-9 |
| `fork <source-drop-id> <new-id>` | Clone locally + rewrite manifest + register lineage | WD-10 |

Commands marked future-strand exit code 2 with a clear message until that strand lands.

## Scaffold

```bash
windy-drops new --type control-panel-template ./my-dashboard
# ✓ scaffolded control-panel-template drop at /.../my-dashboard
# Next steps:
#   1. Edit /.../my-dashboard/SKILL.md (set author + id)
#   2. windy-drops validate /.../my-dashboard
#   3. windy-drops publish /.../my-dashboard
```

The 6 v1 reserved drop types each ship a starter scaffold:

- `control-panel-template`
- `skill`
- `tool`
- `theme`
- `voice-pack`
- `workflow`

## Library API

```python
from windy_drops import scaffold

result = scaffold(type="skill", path="./my-skill")
print(result.target_dir, result.files_copied)
```

## Parity with the TypeScript SDK

The TypeScript sibling (`windy-drops-sdk`, also unpublished) has the same CLI surface. A drop scaffolded by one is byte-identical to one scaffolded by the other; a drop published by one is indistinguishable to the registry. Cross-SDK byte-identity is enforced by the `WD-11` conformance harness.

## Strand reference

This package is owned by strands **WD-4..WD-10** in [`docs/DNA_STRAND_MASTER_PLAN.md`](../../docs/DNA_STRAND_MASTER_PLAN.md). Each strand owns one subcommand (or related set).

## License

MIT

## Getting a token

`new`, `validate`, `sign` and `bundle` need nothing. **`publish` and `withdraw` need a token**,
and this is where most first-time authors stop.

The registry accepts either identity:

| You are | Token | Where it comes from |
|---|---|---|
| a person | your Windy Word account token (RS256, issued by `account.windyword.ai`) | the same login you use at windyword.ai |
| an agent | an Eternitas passport token (EPT, ES256) | your Eternitas passport |

Pass it per-command or export it:

```bash
windy-drops publish ./my-drop --token <jwt>
# or
export WINDY_REGISTRY_TOKEN=<jwt>
```

There is **no `windy-drops login` yet**, and nothing reads a token out of
`~/.windy/credentials.json` — that file is only consulted for the *signing key*
(`eternitas.private_key`), which is a different thing. Publishing a drop whose manifest declares
an author passport additionally requires that the token carry that same passport; you cannot
publish as someone else.
