# gpm publish

Publish a package to the GPM registry.

## Usage

```bash
gpm publish [package-spec] [flags]
```

## Arguments

* `[package-spec]` - Package specification (optional)
  * Current directory (default): `.`
  * Folder containing package.json: `./my-package`
  * Gzipped tarball: `package.tgz`

## Flags

| Flag               | Description                                         | Default     |
| ------------------ | --------------------------------------------------- | ----------- |
| `--access <level>` | Package access level: `public`, `scoped`, `private` | Auto-detect |
| `--tag <dist-tag>` | Distribution tag                                    | `latest`    |
| `--dry-run`        | Simulate publish without uploading                  | `false`     |
| `--registry <url>` | Registry URL to publish to                          | From config |

## Description

Publishes a package to the registry so that it can be installed by name. The command validates the package, creates a tarball, and uploads it to the registry.

### Access Levels

* **public**: Visible and downloadable from any domain without authentication
* **scoped**: Visible only on the current tenant domain without authentication
* **private**: Visible only on the current tenant domain and requires authentication

### Package Specifications

1. **Current Directory** (default): `gpm publish`
2. **Folder**: `gpm publish ./my-package`
3. **Tarball**: `gpm publish package.tgz`

## Examples

### Basic Publishing

```bash
# Publish current directory
gpm publish

# Publish specific folder
gpm publish ./my-package

# Publish tarball
gpm publish package.tgz
```

### Access Level Control

```bash
# Publish as public (requires global registry)
gpm publish --access=public

# Publish as scoped (tenant registry)
gpm publish --access=scoped

# Publish as private (tenant registry + auth)
gpm publish --access=private
```

### Distribution Tags

```bash
# Publish with beta tag
gpm publish --tag=beta

# Publish with alpha tag
gpm publish --tag=alpha

# Publish with release tag
gpm publish --tag=release
```

### Registry and Dry Run

```bash
# Publish to custom registry
gpm publish --registry=https://npmjs.org

# Simulate publish (dry run)
gpm publish --dry-run

# Combine flags
gpm publish --access=scoped --tag=beta --dry-run
```

## Package Requirements

### package.json

Your package must include a valid `package.json` file:

```json
{
  "name": "com.company.mypackage",
  "version": "1.0.0",
  "description": "My awesome package",
  "author": "Company Name",
  "license": "MIT",
  "keywords": ["unity", "game", "analytics"],
  "repository": {
    "type": "git",
    "url": "https://github.com/company/mypackage"
  },
  "unity": "2022.3"
}
```

### Required Fields

* `name`: Package name (must follow reverse-DNS convention)
* `version`: Semantic version (e.g., `1.0.0`)
* `description`: Package description

### Optional Fields

* `author`: Package author
* `license`: License type
* `keywords`: Search keywords
* `repository`: Source repository
* `unity`: Unity version compatibility

## Package Validation

Before publishing, GPM validates:

1. **Package Name**: Must follow reverse-DNS convention
2. **Version**: Must be valid semantic version
3. **Files**: Package contents and structure
4. **Access Level**: Compatibility with registry host
5. **Authentication**: Required for private packages

### Validation Rules

#### Package Name

* Must use reverse-DNS format: `com.company.package`
* Validation regex: `^(?:[a-z0-9]+(?:-[a-z0-9]+)*\.)+[a-z0-9]+(?:-[a-z0-9]+)*$`

#### Access Level Rules

* **public**: Requires global registry (`https://registry.gpm.sh`)
* **scoped/private**: Requires tenant registry (`https://<tenant>.gpm.sh`)

## Output

### Successful Publish

```
📤 Publishing Package
─────────────────────
Package:     com.company.mypackage
Version:     1.0.0
Access Level: Scoped
Tag:         latest
Registry:    https://company.gpm.sh
File:        /tmp/gpm-publish-xyz/com.company.mypackage-1.0.0.tgz
Size:        1024 bytes (1.0 kB)
Files:       15 files
SHA1:        a1b2c3d4e5f6...
Integrity:   sha512-AbCdEfGh...
─────────────────────
✓ Package published successfully!
Package ID:    pkg_1234567890
Version ID:    ver_0987654321
Download URL:  https://company.gpm.sh/com.company.mypackage/-/com.company.mypackage-1.0.0.tgz
File Size:     1024 bytes
Upload Time:   2024-01-01T12:00:00Z
Integrity:     sha512-AbCdEfGh...
```

### Dry Run Output

```
🧪 Dry Run - Simulating Publish
──────────────────────────────
Package:     com.company.mypackage
Version:     1.0.0
Access Level: Scoped
Tag:         latest
Registry:    https://company.gpm.sh
File:        /tmp/gpm-publish-xyz/com.company.mypackage-1.0.0.tgz
Size:        1024 bytes (1.0 kB)
Files:       15 files
SHA1:        a1b2c3d4e5f6...
Integrity:   sha512-AbCdEfGh...
Mode:        DRY RUN
──────────────────────────────
✓ Dry run completed successfully!

📋 What would be published:
  • com.company.mypackage@1.0.0
  • Tagged as 'latest'
  • Access level: Scoped
  • Registry: https://company.gpm.sh
  • 15 files

📁 Files to be published:
    package.json
    README.md
    Runtime/
    Runtime/Scripts/
    Runtime/Scripts/MyScript.cs
    ...

Use 'gpm publish' without --dry-run to actually publish
```

## File Filtering

GPM automatically filters files during packaging:

### Included Files

* Source code files (`.cs`, `.js`, `.ts`, etc.)
* Documentation (`.md`, `.txt`)
* Package metadata (`package.json`, `README.md`)
* Runtime files and scripts

### Excluded Files

* Development files (`.git/`, `node_modules/`)
* Build artifacts (`.dll`, `.so`, `.dylib`)
* IDE files (`.vscode/`, `.idea/`)
* OS files (`.DS_Store`, `Thumbs.db`)

## Error Handling

### Common Errors

* **Not authenticated**: `not authenticated. Run 'gpm login'`
* **Invalid package name**: `invalid package name: must use reverse-DNS format`
* **Invalid access level**: `access level validation failed: public requires global registry`
* **Package validation failed**: `package validation failed`
* **Upload failed**: `publish failed: network error`

### Troubleshooting

1. **Authentication**: Run `gpm login` before publishing
2. **Package name**: Ensure reverse-DNS format (`com.company.package`)
3. **Access level**: Match access level with registry type
4. **Network issues**: Check internet connection and registry availability

## Related Commands

* [`gpm pack`](https://github.com/gpm-sh/docs/blob/main/cli/publishing/pack.md) - Create package tarball without publishing
* [`gpm dist-tag`](https://github.com/gpm-sh/docs/blob/main/cli/publishing/dist-tag.md) - Manage distribution tags
* [`gpm login`](broken://pages/7uZU2aUayAnZQNR0keZG) - Authenticate with registry
* [`gpm config`](https://github.com/gpm-sh/docs/blob/main/cli/configuration/config.md) - Configure registry settings

## See Also

* [Publishing Overview](https://github.com/gpm-sh/docs/blob/main/cli/publishing/README.md)
* [Package Naming Convention](broken://pages/fu7DGrA8lUWtbfbxTDL6)
* [Access Levels](broken://pages/mbfZLqsUrHEp3SxapgjE)
* [Registry Resolution](https://github.com/gpm-sh/docs/blob/main/packages/registry-resolution.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.gpm.sh/cli-reference/cli/publishing/publish.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
