| name | gleam-package-development |
| description | Guides Claude through creating and publishing Gleam packages to Hex.pm. Use when developing libraries, writing documentation, or preparing packages for publication. |
Gleam Package Development Skill
This skill guides Claude Code through creating and publishing Gleam packages.
Primary Sources
- Writing Gleam - Package structure and organization
- gleam.toml Documentation - Package configuration
- Hex.pm - Package repository
- Gleam Package Interface - Package metadata
- Awesome Gleam - Ecosystem reference
Creating a New Package
Initialize Package
gleam new my_package
cd my_package
This creates the standard structure:
my_package/
├── gleam.toml
├── manifest.toml
├── src/
│ └── my_package.gleam
├── test/
│ └── my_package_test.gleam
└── README.md
See: Writing Gleam - Project Structure
Package Configuration
Edit gleam.toml:
name = "my_package"
version = "1.0.0"
description = "A clear, concise description of what the package does"
licences = ["Apache-2.0"]
repository = { type = "github", user = "username", repo = "my_package" }
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
See: gleam.toml Documentation
Package Design
API Design Principles
- Make invalid states impossible - Use types to prevent errors
- Qualified imports - Design for
package.function() usage
- Clear naming - Follow Gleam conventions
- Minimal exports - Only export public API
- Comprehensive documentation - Every public function
See: Coding Standards
Module Organization
For packages, organize by feature/domain:
src/
├── my_package.gleam # Main API
├── my_package/
│ ├── internal.gleam # Internal helpers
│ ├── parser.gleam # Parser functionality
│ └── encoder.gleam # Encoder functionality
See: Conventions - Code Organization
Documentation
Document all public functions:
/// Parses a JSON string into a structured value.
///
/// ## Examples
///
/// ```gleam
/// parse("{\"name\": \"Alice\"}")
/// // -> Ok(Object([#("name", String("Alice"))]))
/// ```
///
/// ## Errors
///
/// Returns `Error(ParseError)` if the input is not valid JSON.
///
pub fn parse(input: String) -> Result(Json, ParseError) {
// Implementation
}
Library vs Application
Library Packages (MANDATORY)
- NEVER panic or use
let assert
- Always return
Result for fallible operations
- Export only public API
- Comprehensive test coverage
- Clear documentation
See: Anti-patterns - Library Panicking
Application Packages
- May panic at top level
- Can use
let assert for unrecoverable errors
- More relaxed about internal structure
Dependencies
Adding Dependencies
gleam add package_name
gleam add --dev test_package
Dependency Constraints
Use semantic versioning constraints:
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
gleam_json = "~> 3.0"
specific_version = "= 1.2.3"
See: gleam.toml - Dependencies
Dependency Best Practices
- Minimize dependencies
- Use well-maintained packages
- Keep versions up to date
- Don't vendor dependencies in published packages
Cross-Platform Packages
Supporting Both Targets
Provide implementations for both Erlang and JavaScript:
@external(erlang, "crypto", "strong_rand_bytes")
@external(javascript, "./crypto_ffi.mjs", "randomBytes")
pub fn random_bytes(n: Int) -> BitArray
Or use Gleam fallback:
@external(erlang, "optimized_module", "fast_function")
pub fn my_function(input: String) -> Result(Output, Error) {
// Gleam implementation (runs on JavaScript)
slow_but_correct_implementation(input)
}
See: External Functions
Target-Specific Code
Use @target attribute when necessary:
@target(erlang)
pub fn erlang_only_function() -> Result(Value, Error) {
// Erlang-specific implementation
}
@target(javascript)
pub fn javascript_only_function() -> Result(Value, Error) {
// JavaScript-specific implementation
}
Testing
Test Coverage
- Test all public functions
- Test edge cases
- Test error conditions
- Test both targets if cross-platform
gleam test
gleam test --target erlang
gleam test --target javascript
See: Testing Skill
Example-Based Tests
Include examples in documentation and test them:
/// ## Examples
///
/// ```gleam
/// add(2, 3)
/// // -> 5
/// ```
pub fn add(a: Int, b: Int) -> Int {
a + b
}
pub fn add_test() {
let assert 5 = add(2, 3)
}
Publishing to Hex.pm
Prerequisites
- Create account on hex.pm
- Authenticate:
gleam hex auth
Pre-publish Checklist
Publishing
gleam hex publish
See: Publishing Packages
Versioning
Follow Semantic Versioning:
- MAJOR: Breaking API changes
- MINOR: New features, backward compatible
- PATCH: Bug fixes, backward compatible
Package Maintenance
Updating Dependencies
Check for outdated dependencies:
gleam deps outdated
Update dependencies:
gleam deps update
See: Gleam v1.10 Features
Deprecation
When deprecating functions, document clearly:
/// **Deprecated**: Use `new_function` instead.
///
/// This function will be removed in version 2.0.0.
@deprecated("Use new_function instead")
pub fn old_function() -> Result(Value, Error) {
new_function()
}
Breaking Changes
When making breaking changes:
- Bump MAJOR version
- Document changes in CHANGELOG
- Provide migration guide
- Consider deprecation period first
Package Quality
README Template
# Package Name
Brief description of what the package does.
## Installation
\`\`\`sh
gleam add package_name
\`\`\`
## Usage
\`\`\`gleam
import package_name
pub fn main() {
package_name.do_something()
}
\`\`\`
## Documentation
[View on HexDocs](https://hexdocs.pm/package_name/)
## Development
\`\`\`sh
gleam test
\`\`\`
## License
[License Name]
CI/CD for Packages
Example GitHub Actions:
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
otp-version: "27.0"
gleam-version: "1.10.0"
- run: gleam deps download
- run: gleam test --target erlang
- run: gleam test --target javascript
- run: gleam format --check src test
Ecosystem Integration
Listing on Awesome Gleam
Submit PR to Awesome Gleam to increase visibility.
Package Categories
Common package categories:
- Web frameworks
- Database clients
- Data formats (JSON, XML, CSV, TOML)
- Cryptography
- Testing utilities
- CLI tools
- Utilities
See: Awesome Gleam
Common Package Patterns
Builder Pattern
pub type Config {
Config(host: String, port: Int, timeout: Int)
}
pub fn new() -> Config {
Config(host: "localhost", port: 8080, timeout: 5000)
}
pub fn host(config: Config, host: String) -> Config {
Config(..config, host: host)
}
pub fn port(config: Config, port: Int) -> Config {
Config(..config, port: port)
}
See: Patterns - Builder
Result Helpers
pub fn try_map(
result: Result(a, e),
f: fn(a) -> Result(b, e)
) -> Result(b, e) {
case result {
Ok(value) -> f(value)
Error(error) -> Error(error)
}
}
Remember: A well-designed package is easy to use correctly and hard to use incorrectly. Focus on clear APIs and excellent documentation.