# Plugin Exclusion Guide

## Quick Reference

**What is plugin exclusion?**: A mechanism to prevent certain plugins (like `nu_plugin_example`) from being included in distributions and installations, while keeping them available for development and testing.

**Who should read this?**:
- 📦 Release managers
- 👨‍💻 Plugin developers
- 🔧 Maintainers
- 📚 Users who want to understand the distribution process

---

## Quick Start

### For Users

**Question**: I found `nu_plugin_example` but it's not in my installation. Why?

**Answer**: The example plugin is intentionally excluded from distributions. It's a reference implementation for plugin developers, not a user-facing tool.

**If you want to use it**:
1. Clone the repository
2. Build it: `just build`
3. Use the binary directly: `./nushell/target/release/nu_plugin_example`

---

### For Developers

**Question**: I want to exclude my plugin from distributions. How?

**Answer**: Add it to the exclusion list in `etc/plugin_registry.toml`:

```toml
[distribution]
excluded_plugins = [
    "nu_plugin_example",
    "nu_plugin_my_new_plugin"  # ← Add your plugin here
]
```

That's it! The collection and packaging systems will automatically skip it.

---

### For Release Managers

**Checklist before release**:

1. **Verify exclusion list is correct**:
   ```bash
   nu -c "open ./etc/plugin_registry.toml | get distribution.excluded_plugins"
   ```

2. **Verify collection respects it**:
   ```bash
   just collect
   find distribution -name "*example*"  # Should find nothing
   ```

3. **Verify packaging respects it**:
   ```bash
   just pack-full
   tar -tzf bin_archives/*.tar.gz | grep example  # Should find nothing
   ```

4. **Verify builds still include everything** (for testing):
   ```bash
   just build
   ls nushell/target/release/ | grep example  # Should find the binary
   ```

---

## Common Tasks

### Task 1: Add a Plugin to Exclusion List

**Scenario**: You have a new reference plugin that shouldn't be shipped to users.

**Steps**:
1. Create your plugin in `nushell/crates/nu_plugin_myref/`
2. Update `etc/plugin_registry.toml`:
   ```toml
   [distribution]
   excluded_plugins = [
       "nu_plugin_example",
       "nu_plugin_myref"  # ← Add here
   ]
   ```
3. Update `scripts/templates/default_config.nu` - remove it from the `plugin_binaries` list if it was there
4. Test:
   ```bash
   just collect && find distribution -name "*myref*"  # Should be empty
   ```

---

### Task 2: Remove a Plugin from Exclusion List

**Scenario**: Your reference plugin is now stable and ready for distribution.

**Steps**:
1. Update `etc/plugin_registry.toml`:
   ```toml
   [distribution]
   excluded_plugins = [
       "nu_plugin_example"  # ← Removed your plugin
   ]
   ```
2. Update `scripts/templates/default_config.nu` - add it to the `plugin_binaries` list if you want auto-loading
3. Test:
   ```bash
   just collect && find distribution -name "*myref*"  # Should exist now
   ```

---

### Task 3: Check Current Build Includes Excluded Plugin

**Scenario**: You want to verify that excluded plugins are still being built.

**Steps**:
```bash
# Build everything including excluded plugins
just build

# Verify excluded plugin was built
ls nushell/target/release/nu_plugin_example
# Output: nushell/target/release/nu_plugin_example
```

**Why?** Excluded plugins are still useful for:
- Testing and validation
- Reference implementations
- Developer documentation
- Internal reference

---

### Task 4: Understand Distribution Workflow

**Scenario**: You want to understand how plugins flow through the build/collect/package process.

**Diagram**:
```
SOURCE (all plugins built)
├── nu_plugin_example (excluded)
├── nu_plugin_auth
├── nu_plugin_kms
└── ... others

  ↓ (just build - NO filtering)

BUILD OUTPUT (target/release)
├── nu_plugin_example ✅ (built)
├── nu_plugin_auth ✅ (built)
├── nu_plugin_kms ✅ (built)
└── ... others ✅ (built)

  ↓ (just collect - WITH filtering)

COLLECTION (distribution/)
├── nu_plugin_example ❌ (excluded)
├── nu_plugin_auth ✅ (collected)
├── nu_plugin_kms ✅ (collected)
└── ... others ✅ (collected)

  ↓ (just pack - WITH filtering)

PACKAGING (bin_archives/)
├── nushell-0.109.0-linux-x64.tar.gz
│   ├── nu
│   ├── nu_plugin_auth ✅
│   ├── nu_plugin_kms ✅
│   └── ... (no example plugin)
└── nushell-0.109.0-darwin-arm64.tar.gz
    ├── nu
    ├── nu_plugin_auth ✅
    ├── nu_plugin_kms ✅
    └── ... (no example plugin)

  ↓ (installation)

USER SYSTEM
├── ~/.local/bin/nu ✅
├── ~/.local/bin/nu_plugin_auth ✅
├── ~/.local/bin/nu_plugin_kms ✅
├── ~/.config/nushell/env.nu
└── ~/.config/nushell/config.nu (auto-loads auth, kms; example not in list)
```

---

## Technical Details

### How Exclusion Works

**Mechanism**: The system reads `etc/plugin_registry.toml` and filters at two points:

1. **Collection** (`just collect` / `just collect-full`):
   - Reads exclusion list from registry
   - Skips excluded plugins during binary collection
   - Result: `distribution/` dir doesn't have excluded plugins

2. **Packaging** (`just pack` / `just pack-full`):
   - Reads exclusion list from registry
   - Skips excluded plugins during package creation
   - Result: `bin_archives/*.tar.gz` don't have excluded plugins

3. **Installation** (auto-load configuration):
   - `scripts/templates/default_config.nu` manually removes excluded plugins from the auto-load list
   - Result: User installations don't auto-load excluded plugins

### Files Involved

| File | Role |
|------|------|
| `etc/plugin_registry.toml` | Source of truth for exclusion list |
| `scripts/collect_full_binaries.nu` | Implements collection-time filtering |
| `scripts/create_distribution_packages.nu` | Implements packaging-time filtering |
| `scripts/templates/default_config.nu` | Defines auto-load list (manually edited) |
| `justfile` + `justfiles/*.just` | Provides build/collect/pack commands |

### Registry Format

```toml
[distribution]
excluded_plugins = [
    "nu_plugin_example"        # Plugin directory name
]
reason = "Reference plugin"    # Documentation (optional)
```

**Key Points**:
- `excluded_plugins` is a list of plugin directory names (not binary names)
- Must match the `nu_plugin_*` directory in the repo
- Case-sensitive
- Empty list `[]` means no exclusions

---

## Troubleshooting

### Problem: Excluded Plugin Still Appears in Distribution

**Possible Causes**:
1. Registry file not saved properly
2. Collection script using cached data
3. Plugin name mismatch

**Solution**:
```bash
# Verify registry is correct
nu -c "open ./etc/plugin_registry.toml | get distribution.excluded_plugins"

# Clean and rebuild
rm -rf distribution bin_archives
just collect
find distribution -name "*example*"  # Should be empty
```

---

### Problem: Can't Find Excluded Plugin After Build

**Expected Behavior**: Excluded plugins ARE still built (just not distributed)

**Verification**:
```bash
just build
ls nushell/target/release/nu_plugin_example  # Should exist

# If it doesn't, the plugin may not be in the build system
just build-nushell --verbose
```

---

### Problem: Manual Plugin Registration Failing

**Issue**: User manually adds excluded plugin but it doesn't work

**Cause**: Plugin binary not in PATH

**Solution**:
```bash
# Build the plugin
just build

# Use full path
./nushell/target/release/nu_plugin_example --version

# Or install it manually
cp ./nushell/target/release/nu_plugin_example ~/.local/bin/
nu -c "plugin add ~/.local/bin/nu_plugin_example"
```

---

## FAQs

**Q: Will my excluded plugin still be tested?**
A: Yes. Excluded plugins are still built and tested. They're only excluded from user-facing distributions.

**Q: Can I exclude a plugin from builds but not distributions?**
A: No, the current system doesn't support this. The exclusion system only affects distribution. To exclude from builds, use Cargo features.

**Q: Can different distributions have different exclusion lists?**
A: Not currently, but this is planned as a future enhancement (profile-based exclusions).

**Q: What happens if I exclude a plugin that doesn't exist?**
A: It's ignored. The filtering works by checking if a plugin name is in the exclusion list, so non-existent plugins are silently skipped.

**Q: Can I exclude plugins selectively (e.g., exclude from macOS but not Linux)?**
A: Not currently. This would require platform-based exclusion profiles (future enhancement).

---

## Best Practices

### ✅ DO

- **Update the comment** in config when excluding/including plugins
- **Test after changes**: `just collect && just pack-full && just build`
- **Document the reason** in `plugin_registry.toml` (optional but recommended)
- **Run verification** before releases (see Release Manager checklist)
- **Keep registry clean** - don't exclude plugins you won't maintain

### ❌ DON'T

- **Edit multiple files** - only touch `etc/plugin_registry.toml` for the core change
- **Assume exclusion happens at build time** - it only happens during collect/pack
- **Forget to test** - exclusion changes should be verified before release
- **Add plugins to exclusion list without documenting why** in the code
- **Exclude plugins that users depend on** - use this only for reference/experimental plugins

---

## Integration with CI/CD

### GitHub Actions Example

```yaml
name: Distribution Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      # Verify exclusion list
      - name: Verify Exclusion List
        run: |
          nu -c "open ./etc/plugin_registry.toml | get distribution.excluded_plugins"

      # Build (includes all plugins)
      - name: Build
        run: just build-full-release

      # Collect (excludes specified plugins)
      - name: Collect
        run: just collect-full

      # Verify excluded plugins not in distribution
      - name: Verify Exclusions
        run: |
          ! find distribution -name "*example*"

      # Package
      - name: Package
        run: just pack-full-checksums

      # Release
      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          files: bin_archives/*
```

---

## See Also

- **Architecture Details**: [`docs/architecture/PLUGIN_EXCLUSION_SYSTEM.md`](./architecture/PLUGIN_EXCLUSION_SYSTEM.md)
- **Build System**: [`docs/BUILDING.md`](./BUILDING.md)
- **Plugin Development**: `nushell/crates/nu_plugin_example/` (reference implementation)
- **Registry Configuration**: `etc/plugin_registry.toml`

---

**Version**: 1.0.0
**Last Updated**: 2025-12-03
**Status**: Stable
