open-index/open-npm huggingface dataset:
npm package: @goyb/cli
Description: GOYB - Track commits, track workouts, achieve balance. Exercise while your AI agent codes autonomously.
Latest version: 0.1.9

# GOYB - Get Off Your Butt Protocol

```bash
   ██████╗   ██████╗  ██╗   ██╗ ██████╗
  ██╔════╝  ██╔═══██╗ ╚██╗ ██╔╝ ██╔══██╗
  ██║  ███╗ ██║   ██║  ╚████╔╝  ██████╔╝
  ██║   ██║ ██║   ██║   ╚██╔╝   ██╔══██╗
  ╚██████╔╝ ╚██████╔╝    ██║    ██████╔╝
   ╚═════╝   ╚═════╝     ╚═╝    ╚═════╝ .dev
```

> A CLI tool to keep you accountable while coding

## Quick Start

```bash
npx @goyb/init
```

This will install GOYB globally and run the setup wizard.

## Manual Install

```bash
npm install -g goyb
goyb init
```

## Commands

### `goyb init`
Run the interactive setup wizard to configure GOYB for your workflow.

```bash
goyb init
# or
goyb install
```

### `goyb start`
Start a new work session with accountability notifications.

```bash
goyb start
```

### `goyb status`
Check your current GOYB configuration.

```bash
goyb status
```

### `goyb stop`
End your current work session.

```bash
goyb stop
```

## Features

- 🎯 Interactive setup wizard
- 🤖 Multiple coding agent support (Claude Code, Cursor, Windsurf, AutoGPT)
- 📱 Notification integrations (Telegram, Slack, native app)
- ⚙️ Config stored at `~/.goyb/config.json`
- 💪 Built with [Ink](https://github.com/vadimdemedes/ink) for a beautiful terminal UI

## Development

```bash
# Install dependencies
bun install

# Build
bun run build

# Watch mode
bun run dev

# Link for local testing
npm link
```

## License

MIT
npm package: @gozala/automerge-backend-wasm
Description: wasm-bindgen bindings to the automerge-backend rust implementation
Latest version: 0.1.3

## automerge-backend-wasm

This is a npm wrapper for the rust implementation of [automerge-backend](https://github.com/automerge/automerge-rs/tree/master/automerge-backend).
It is currently experimental and in development against the Automerge performance branch.  

### building

Make sure you have the latest rust compiler installed  (1.42.0 or later).

```sh
cargo install wasm-pack
yarn install
```

Then build the debug version with

```sh
yarn build
```
or the release build with 

```sh
yarn release
```
npm package: @gozenc/interpolate-html-plugin
Description: InterpolateHtmlPlugin implemented for webpack v5.
Author: Fatih Gözenç
Latest version: 1.0.2

<h1 align="center">InterpolateHtmlPlugin</h1>

<p align="center">Replaces your variable names in your HTML templates.<br> <br><i>Inspired from <a href="https://www.npmjs.com/package/react-dev-utils/v/6.0.0">react-dev-utils/interpolate-html-plugin</a>.<br> Written in <a href="https://www.typescriptlang.org/">TypeScript</a> with <span style="color:red">♥</span> </i></p>

## Overview

It works in combination with latest versions of [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin]) and [`webpack`](https://webpack.js.org/). You can learn more about creating plugins like this [here](https://github.com/jantimon/html-webpack-plugin]).

## Installation

| NPM                                        | YARN                                          |
| ------------------------------------------ | --------------------------------------------- |
| `npm i -D webpack html-webpack-plugin`     | `yarn add -D webpack html-webpack-plugin`     |
| `npm i -D @gozenc/interpolate-html-plugin` | `yarn add -D @gozenc/interpolate-html-plugin` |

## Usage

```js
const HtmlWebpackPlugin = require("html-webpack-plugin")
const InterpolateHtmlPlugin = require("@gozenc/interpolate-html-plugin")
// In the webpack.config file:
...
plugins: [
    new InterpolateHtmlPlugin(HtmlWebpackPlugin, {
        'PUBLIC_URL': "https://example.com",
        // Replaces %PUBLIC_URL% with https://example.com in index.html.
        VARIABLE: 1024,
        // Replaces %VARIABLE% with 1024 in index.html.
    }),
    ...
```

## Development

I know build pipeline looks kinda strange, but I am making some Linux practice with node concurrently for performant build pipelines. I may insert some C calls into it too. I'll develop it further in the future, but of course I am open for discussions for it.

Also just open a ticket for feature requests of course, I'll be glad to resolve them.

## ToDo

-   Add webpack@3 support.
-   Add webpack@4 support.
-   More testing suites for development.
-   Type definitions for hook.tap params.
npm package: @gp-it/gp-auth
Description: Module d'authentification
Author: Geoffrey Pliez
Latest version: 0.0.12

# \<gp-auth>

This webcomponent follows the [open-wc](https://github.com/open-wc/open-wc) recommendation.

## Installation
```bash
npm i gp-auth
```

## Usage
```html
<script type="module">
  import 'gp-auth/gp-auth.js';
</script>

<gp-auth></gp-auth>
```

## Linting with ESLint, Prettier, and Types
To scan the project for linting errors, run
```bash
npm run lint
```

You can lint with ESLint and Prettier individually as well
```bash
npm run lint:eslint
```
```bash
npm run lint:prettier
```

To automatically fix many linting errors, run
```bash
npm run format
```

You can format using ESLint and Prettier individually as well
```bash
npm run format:eslint
```
```bash
npm run format:prettier
```

## Testing with Karma
To run the suite of karma tests, run
```bash
npm run test
```

To run the tests in watch mode (for <abbr title="test driven development">TDD</abbr>, for example), run

```bash
npm run test:watch
```

## Demoing with Storybook
To run a local instance of Storybook for your component, run
```bash
npm run storybook
```

To build a production version of Storybook, run
```bash
npm run storybook:build
```


## Tooling configs

For most of the tools, the configuration is in the `package.json` to reduce the amount of files in your project.

If you customize the configuration a lot, you can consider moving them to individual files.

## Local Demo with `es-dev-server`
```bash
npm start
```
To run a local development server that serves the basic demo located in `demo/index.html`
# Auth
npm package: @gp-technical/material-date-range
Description: React components, that implements material design pickers for material-ui v1
Author: Jonas Hackenberg
Latest version: 0.1.5

# Material Data Range Picker
> Accessible date range picker for material-ui

![Image showing the date picker.](material-date-range-picker.png)

### Installation

The date picker is based on multiple awesome projects and requires following peer dependencies to be installed:

- material-ui
- date-fns (^1.29.0)
- downshift
- kalendaryo
- styled-components

Available as npm package.
```sh
npm i material-date-range-picker
```

```javascript
<DateRangePicker
    fromDate={this.state.fromDate}  //from date
    toDate={this.state.toDate}  //to Date
    onChange={this._handleDateRangeChange}
    closeDialogOnSelection    //close date dialog after selecting both from and to date
/>
```

### Acknowledgments

https://material.angular.io/components/datepicker/overview

https://github.com/geeofree/kalendaryo

https://github.com/paypal/downshift

https://github.com/dmtrKovalenko/material-ui-pickers

### LICENSE
The project is licensed under the terms of [MIT license](https://github.com/jonas-arkulpa/material-date-range-picker/blob/master/LICENSE)
npm package: @gp2f/client-sdk
Description: GP2F client SDK – reconciliation UX components and WebSocket client
Latest version: 1.0.5

# @gp2f/client-sdk

GP2F client SDK – reconciliation UX components and WebSocket client.

## Overview
This SDK provides React components for opportunistic UI state reconciliation, along with a WebSocket client that directly interacts with the GP2F backend server using CRDTs. It is designed to create collaborative, real-time shared experiences seamlessly.

## Installation
```bash
npm install @gp2f/client-sdk
```

## Usage

### 1. WebSocket Client (`Gp2fClient`)
The client provides robust sync over WebSockets with built-in Token Bucket rate-limiting and time-offset tracking.

```typescript
import { Gp2fClient } from '@gp2f/client-sdk';

const client = new Gp2fClient({
  url: 'ws://localhost:3000/ws',
  onMessage: (msg) => {
    console.log('Received from server:', msg);
  },
  onToken: (token, done) => {
    // Helpful for streaming AI responses ("Time to First Token")
    console.log(`Token: ${token}, Done: ${done}`);
  },
  onReloadRequired: (version, reason) => {
    console.warn(`Incompatible AST schema (${version}): ${reason}`);
    window.location.reload();
  }
});

client.connect();

// Send messages (automatically rate-limited)
client.send({
  type: 'SYNC',
  payload: { /* ... */ }
});
```

### 2. Optimistic Updates
Visual indication for optimistic updates or LLM loading limits.

```typescript
import { applyOptimisticUpdate } from '@gp2f/client-sdk';

const container = document.getElementById('my-loader-div');

// Shows a shimmering skeleton loader
const cleanup = applyOptimisticUpdate({
  container,
  confidence: 0.8, // >= 0.7 triggers high-confidence skeleton loader
  thinkingText: "Vibe checking..."
});

// Later, when the update completes:
cleanup();
```

### 3. React Components
The SDK ships with React components to handle state conflicts and reconciliation UX:

```tsx
import React from 'react';
import { ReconciliationBanner, UndoButton, MergeModal } from '@gp2f/client-sdk';

export function EditorHeader() {
  return (
    <header>
      {/* Banner handles showing connection states and sync issues */}
      <ReconciliationBanner 
        status="conflict" 
        onResolve={() => console.log('Resolve clicked')} 
      />
      
      {/* Undo integration */}
      <UndoButton 
        canUndo={true} 
        onUndo={() => console.log('Undo triggered!')} 
      />
    </header>
  );
}
```

### 4. Lazy Policy Evaluation (WASM Engine)
Load the fast WASM policy engine dynamically when needed without blocking the main thread.

```typescript
import { loadPolicyEngine } from '@gp2f/client-sdk';

async function checkPolicy(state: any, ast: any) {
  const engine = await loadPolicyEngine();
  const { result } = engine.evaluate(
    JSON.stringify(state),
    JSON.stringify(ast)
  );
  return result;
}
```

## Peer Dependencies
Please note that you'll need `react` and `react-dom` version `>=18.0.0` installed in your host project.

## Scripts
- **Build**: `npm run build`
- **Test**: `npm run test`

## License
MIT
npm package: @gpa-gemstone/gpa-symbols
Description: UI Symbols for GPA products
Author: GridProtectionAlliance
Latest version: 0.0.60

# gpa-symbol

![gemstone logo](https://raw.githubusercontent.com/gemstone/web/master/docs/img/gemstone-wide-600.png)

The gpa-gemstone/gpa-symbols Library organizes all Gemstone functionality related to web.

[![GitHub license](https://img.shields.io/github/license/gemstone/web?color=4CC61E)](https://github.com/gemstone/web/blob/master/LICENSE)

This library includes helpful npm package component for standarsizing Symbols.

## Symbols
Usage | Symbol
----- | -----
{HeavyCheckMark} | ✔️
{Pencil} | ✏️
{TrashCan} | 🗑️
{CrossMark} | ❌
{Plus} | ➕
{Warning} | ⚠️
{Spinner} | 🔄
{Wrench} | 🔧
{Flag} | 🚩
{UpArrow} | ⬆️
{LeftArrow} | ⬅
{RightArrow} | ➡
{DownArrow} | ⬇️
{DNA} | 🧬
{InputNumbers} | 🔢
{FourWayArrow} | ☩
{MagnifyingGlass} | 🔍
{House} | 🏠
{Scroll} | 📜
{PlayButton} | ▶️
{StopButton} | ⏹️
{PauseButton} | ⏸️
{FastForwardButton} | ⏩
{RewindButton} | ⏪
{Questionmark} | ?
npm package: @gpa-gemstone/react-forms
Description: React Form modules for gpa webapps
Author: GridProtectionAlliance
Latest version: 1.1.119

# react-forms

![gemstone logo](https://raw.githubusercontent.com/gemstone/web/master/docs/img/gemstone-wide-600.png)

The Gemstone Web Library organizes all Gemstone functionality related to web.

[![GitHub license](https://img.shields.io/github/license/gemstone/web?color=4CC61E)](https://github.com/gemstone/web/blob/master/LICENSE)

This library includes helpful npm package for creating strongly typed form components in react.

* Input
* CheckBox
* TextArea
* DatePicker
* Select
* EnumCheckBoxes
* DateRangePicker
* ArrayCheckBoxes
* ArrayMultiSelect
* MultiCheckBoxSelect
* DoubleInput

## Usage

```ts
    interface iType = { Field1: string, Field2: number, Field3: boolean, Field4: string, Field5: string, EnumField: number, FromField: string, ToField: string}
    let record:iType = {Field1: 'Hello', Field2: 1, Field3: false, Field4: 'alot of text blah blah blah', Field5: '01/01/2021', FromField: '01/01/2020', ToField: '01/01/2021'}
    let options = [{Value: 1, Label: 'first'}, {Value:2, Label: 'second'}]

    <Input<iType> Record={record} Field="Field1" Setter={(event) => record.Field1 = event.target.value} Valid={(field) => /*some criteria*/}>
    <CheckBox<iType> Record={record} Field="Field3" Setter={(event) => record.Field3 = event.target.value}}>
    <Select<iType> Record={record} Field="Field2" Setter={(event) => record.Field3 = event.target.value}} Options={options}>
    <TextArea<iType> Record={record} Field="Field4" Setter={(event) => record.Field1 = event.target.value} Valid={(field) => /*some criteria*/}>
    <DatePicker<iType> Record={record} Field="Field5" Setter={(event) => record.Field1 = event.target.value}>
    <DateRangePicker<iType> Record={record} FromField="FromField" ToField="ToField" Label="Date Range" Setter={(event) => record.Field1 = event.target.value}>
    <EnumCheckBoxes<iType> Record={record} Field="EnumField" Setter={(event) => record.Field3 = event.target.value}} Enum={['Monday', 'Tuesday','Wednesday']}>
	<DoubleInput<iType> Record={record} Field1="Field4" Field1="Field5" Setter={(r) => record = r} Valid={(field) => /*some criteria*/}>
```
npm package: @gpa-gemstone/react-table
Description: Table for GPA web applications
Author: GridProtectionAlliance
Latest version: 1.2.107

# react-table

![gemstone logo](https://raw.githubusercontent.com/gemstone/web/master/docs/img/gemstone-wide-600.png)

The Gemstone Web Library organizes all Gemstone functionality related to web.

[![GitHub license](https://img.shields.io/github/license/gemstone/web?color=4CC61E)](https://github.com/gemstone/web/blob/master/LICENSE)

This library includes helpful npm package component for creating strongly typed tables in react.

## Usage Table

```ts
    interface iType = { Field1: string, Field2: number, Field3: boolean, Field4: string, Field5: string}
    let records:iType[] = [{Field1: 'Hello', Field2: 1, Field3: false, Field4: 'alot of text blah blah blah', Field5: '01/01/2021'}]
    let ascending: boolean = true;

    <Table<iType>
    cols={[
        { key: 'Field1', label: 'Field1' },
        { key: 'Field2', label: 'Field2', content: (item, key, style) => item[key] },
        { key: 'Field3', label: 'Field3' },
        { key: 'Field4', label: 'Field4' },
        { key: 'Field5', label: 'Field5' },
    ]}
    tableClass="table table-hover"
    theadStyle={{ fontSize: 'smaller', display: 'table', tableLayout: 'fixed', width: '100%', height: 50 }}
    tbodyStyle={{ display: 'block', overflowY: 'scroll', width: '100%' }}
    rowStyle={{ fontSize: 'smaller', display: 'table', tableLayout: 'fixed', width: '100%' }}
    sortField={''}
    onClick={() => { }}
    onSort={() => { }}
    data={records}
    ascending={ascending}
        />

```

## Usage SelectTable

```ts
    interface iType = { Field1: string, Field2: number, Field3: boolean, Field4: string, Field5: string}
    let records:iType[] = [{Field1: 'Hello', Field2: 1, Field3: false, Field4: 'alot of text blah blah blah', Field5: '01/01/2021'}]
    let ascending: boolean = true;
	let selectedItems: iType[] = [];
	
    <SelectTable<iType>
    cols={[
        { key: 'Field1', label: 'Field1' },
        { key: 'Field2', label: 'Field2', content: (item, key, style) => item[key] },
        { key: 'Field3', label: 'Field3' },
        { key: 'Field4', label: 'Field4' },
        { key: 'Field5', label: 'Field5' },
    ]}
    tableClass="table table-hover"
    theadStyle={{ fontSize: 'smaller', display: 'table', tableLayout: 'fixed', width: '100%', height: 50 }}
    tbodyStyle={{ display: 'block', overflowY: 'scroll', width: '100%' }}
    rowStyle={{ fontSize: 'smaller', display: 'table', tableLayout: 'fixed', width: '100%' }}
	KeyField={'Field1'}
    data={records}
	onSelection={(d) => {selectedItems = d}}
        />

```
npm package: @gpa-lab/prettier-config
Description: A shared Prettier configuration conforming to the GPA/LAB style guide.
Author: Marek Rewers, U.S. Department of State, Global Public Affairs
Latest version: 1.1.0
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# GPA/LAB Prettier Config

This package extends [Prettier](https://prettier.io/) with a custom configuration so that code can be automatically formatted to conform to the GPA/LAB style guide.

## Installation

Run the following command from the root of your project to install the custom configuration and the base Prettier package on which it is dependent:

```bash
npm install prettier @gpa-lab/prettier-config --save-dev
```

## Usage

Once installed, you can specify `@gpa-lab/prettier-config` as your preferred prettier configuration. There are several ways to to this:

1. Add the line `"prettier": "@gpa-lab/prettier-config"` to your project's `package.json`;
1. Export the string `"@gpa-lab/prettier-config"` from one of the supported config file types (`.prettierrc`, `.prettierrc.toml`, `prettier.config.js`, or `.prettierrc.js`);

## Extend

To add to or modify the rules implemented by the package, import the package into a `.prettierrc.js` file, modifies the rules you would like to change, and export your modifications.

For example, to keep all the rules defined by the package with the exception of the semicolon rule, your `.prettierrc.js` would look like so:

```js
module.exports = {
  ...require('@gpa-lab/prettier-config'),
  semi: false
};
```
npm package: @gpa/simple-typed-env
Description: Simple type-safe environment variable parser
Author: Guillaume Pascal
Latest version: 1.0.0

# @gpa/simple-typed-env
> Simple environment variable parser providing an automatically typed object from the passed configuration

Very basic implementation, for more complex use cases you can check out [envalid](https://www.npmjs.com/package/envalid) and [env-var](https://www.npmjs.com/package/env-var).

## Install

```sh
npm install @gpa/simple-typed-env
```

## Usage

```ts
import { parseEnv } from '@gpa/simple-typed-env';

// process.env.STRING = 'a string'
// process.env.STRING_ARRAY = 'string1,string2'
// process.env.BOOL = true
// process.env.NUMBER = -123.4

const env = parseEnv({
  STRING: 'string',
  STRING_ARRAY: 'string[]',
  BOOL: 'boolean',
  NUMBER: 'number',
  OPTIONAL: 'string?',
});

// => typeof env = {
//      STRING: string;
//      STRING_ARRAY: string[],
//      BOOL: boolean,
//      NUMBER: number,
//      OPTIONAL: string | undefined,
//    }

// => env === {
//      STRING: 'a string',
//      STRING_ARRAY: ['string1', 'string2'],
//      BOOL: true,
//      NUMBER: -123.4,
//      OPTIONAL: undefined,
//    }
```

## API

### parseEnv(config)

#### config

Type: `object`

- The keys of this object are the names of the environment variables to be parsed, and the corresponding values are the
expected type. 
- The accepted values for the types are `string`, `number` and `boolean`. 
- Square brackets can be appended to expect an array of value (comma separated): `string[]`. 
- A question mark can be appended to denote an optional value: `number?`.
- Brackets and question mark can be combined: `string[]?`.
- Any value not marked as optional will result in an error being thrown when calling `parseEnv()` if the related 
 environment variable does not exist or is an empty string.

#### Returned value

Type: `object`

A simple object with a key-value pair for each declared variable in the `config` parameter.

- Accepted values for booleans are `true`, `yes` and `1` for `true`, and `false`, `no` and `0` for `false` (case-insensitive).
- Optional values for which no environment variable exists, or for which the environment variable is empty will be returned as `undefined`.
- The returned object will be correctly typed according to the passed configuration.
npm package: @gparency/authorizer
Description: Implementation of authorization logic for the GParency Lambda functions
Author: Forwardslash
Latest version: 2.2.6

# GParency Authorize Decorator
![Release to NPMJS Status](https://github.com/gparency/authorizer/actions/workflows/release.yaml/badge.svg)
[![Npm package version](https://badgen.net/npm/v/@gparency/authorizer)](https://npmjs.com/package/@gparency/authorizer)
[![Minimum node.js version](https://badgen.net/npm/node/@gparency/authorizer)](https://npmjs.com/package/@gparency/authorizer)

## About

This is NPM package containing the `@Authorize` decorator that is used for authorizing access to GParency lambda functions. The authorizer injects the authorized user payload in the `event` if user is authorized.

`requestContext.authorizer` injected into API Gateway `event`:
```json
{
    "loanTrackerId": 123456789, 
    "email": "user@email.com", 
    "isGpPaid": "true | false",  
    "isMapUser": "true | false",  
    "isPaidMapUser": "true | false",  
    "isLenderPaid": "true | false",
    "isLender": "true | false",
    "isAdmin": "true | false",
    "rateAdmin": "true | false",
    "userId": "google-oauth2|103010667649373229274"
}
```

## How to use

1. Install the package

```shell
$ npm install @gparency/authorizer
```

2. Add decorator to handler methods

```typescript
class Handler {
    /**
     * Get Profile
     * @param event APIGatewayProxyEvent
     * @param _context Context
     */
    @Authorize(AuthorizationLevel.IS_GP_PAID)
    public async getProfile(event: APIGatewayProxyEvent, _context: Context): Promise<APIGatewayProxyStructuredResultV2> {
        const service = await this.getService({ event });
        try {
            return GatewayResponse.ok(await service.getProfile());
        } catch (exception) {
            Logger.error(exception);
            return GatewayErrorResponse.fromError(exception);
        }
    }
}
```

## Levels of authorization

There are six levels of authorization:

1. `@Authorize()`: This is only checking if the user is authenticated and has a valid JWT.
2. `@Authorize(AuthorizationLevel.IS_GP_PAID)`: This checks if the user is GP Paid member.
3. `@Authorize(AuthorizationLevel.IS_MAP_USER)`: This checks if the user is registered for the Map.
4. `@Authorize(AuthorizationLevel.IS_PAID_MAP_USER)`: This checks if the user is paid for the Map.
5. `@Authorize(AuthorizationLevel.IS_LENDER_PAID)`: This checks if the user is Lender Paid member.
6. `@Authorize(AuthorizationLevel.IS_LENDER)`: This checks if the user is a Lender member.

## Additional claims:
- userId - Id of the logged in user.

## Required Environment Variables

```dotenv
AUTH0_AUDIENCE="..."
AUTH0_ISSUER="..."
AUTH0_SIGNING_CERT="..."
```
npm package: @gpaucot/build-ng-packagr
Description: Angular Build Architect for ng-packagr
Author: Gaetan Paucot
Latest version: 9.0.4

# Angular Build Architect for ng-packagr

This is a modified version of the official build-ng-packagr builder to include a post-processing.

## Configuration
The post-build.js file must be in the same folder as ng-package.json
Example to copy all scss files to output:
```js
// The postBuild function MUST return a promise.

const { copyAssets } = require('@angular-devkit/build-angular/src/utils/copy-assets');
const path = require('path');

module.exports = async function postBuild(options, context) {
    let metadata = await context.getProjectMetadata(context.target.project);
    await copyAssets(
        [
            {
                glob: '**/*.scss',
                ignore: ['**/demo/*', '**/demo/**/*'],
                input: metadata.sourceRoot,
                output: '',
            },
        ],
        [path.resolve(context.workspaceRoot, 'dist', context.target.project)],
        context.workspaceRoot
    );
};
```


## v9.0.2
- Compatibility from v9 and up

## v9.0.1
- post-build.js support
npm package: @gpc-cli/plugin-ci
Description: CI/CD helpers for GPC
Latest version: 0.9.8

# @gpc-cli/plugin-ci

CI/CD helpers for [GPC](https://github.com/yasserstudio/gpc). Auto-detects your CI environment and writes formatted step summaries — so your GitHub Actions jobs show clean, readable release results instead of raw terminal output.

## Install

```bash
npm install @gpc-cli/plugin-ci
```

## Setup

Add to your `.gpcrc.json`:

```json
{
  "plugins": ["@gpc-cli/plugin-ci"]
}
```

The plugin activates automatically when running in a CI environment.

## What It Does

- **Detects CI provider** — GitHub Actions, GitLab CI, Jenkins, CircleCI, Bitrise
- **Writes step summaries** — Markdown tables in `$GITHUB_STEP_SUMMARY` after each command
- **Reports errors** — Structured error output in step summaries when commands fail

## Usage in GitHub Actions

```yaml
- name: Install GPC
  run: npm install -g @gpc-cli/cli @gpc-cli/plugin-ci

- name: Upload Release
  env:
    GPC_SERVICE_ACCOUNT: ${{ secrets.GPC_SERVICE_ACCOUNT }}
    GPC_APP: com.example.myapp
  run: gpc releases upload app.aab --track internal
  # Step summary is written automatically
```

## Programmatic Usage

```typescript
import { detectCIEnvironment, writeStepSummary } from "@gpc-cli/plugin-ci";

const ci = detectCIEnvironment();

if (ci.isCI) {
  console.log(`Running in ${ci.provider}`);
  console.log(`Branch: ${ci.branch}`);
  console.log(`Commit: ${ci.commitSha}`);
}

if (ci.hasStepSummary) {
  writeStepSummary("| Command | Status |\n|---------|--------|\n| upload | ok |");
}
```

## CI Detection

| Provider       | Detected By      |
| -------------- | ---------------- |
| GitHub Actions | `GITHUB_ACTIONS` |
| GitLab CI      | `GITLAB_CI`      |
| Jenkins        | `JENKINS_URL`    |
| CircleCI       | `CIRCLECI`       |
| Bitrise        | `BITRISE_IO`     |
| Generic CI     | `CI`             |

## Part of the GPC Monorepo

This is the first-party CI plugin for [GPC](https://github.com/yasserstudio/gpc). See the [CI/CD Guide](https://yasserstudio.github.io/gpc/ci-cd/) for pipeline recipes.

## License

MIT