Showing posts with label GitHub. Show all posts
Showing posts with label GitHub. Show all posts

How to write a great agents.md: Lessons from over 2,500 repositories

Mike's Notes

Great working example here of how to do this. Agents.md is supported by multiple agents. Useful for future integration. Thanks, Matt.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

28/11/2025

How to write a great agents.md: Lessons from over 2,500 repositories

By: Matt Nigh
GitHub Blog: 19/11/2025

Program Manager Director, I lead the AI for Everyone program at GitHub.

Learn how to write effective agents.md files for GitHub Copilot with practical tips, real examples, and templates from analyzing 2,500+ repositories.

We recently released a new GitHub Copilot feature: custom agents defined in agents.md files. Instead of one general assistant, you can now build a team of specialists: a @docs-agent for technical writing, a @test-agent for quality assurance, and a @security-agent for security analysis. Each agents.md file acts as an agent persona, which you define with frontmatter and custom instructions.

agents.md is where you define all the specifics: the agent’s persona, the exact tech stack it should know, the project’s file structure, workflows, and the explicit commands it can run. It’s also where you provide code style examples and, most importantly, set clear boundaries of what not to do.

The challenge? Most agent files fail because they’re too vague. “You are a helpful coding assistant” doesn’t work. “You are a test engineer who writes tests for React components, follows these examples, and never modifies source code” does.

I analyzed over 2,500 agents.md files across public repos to understand how developers were using agents.md files. The analysis showed a clear pattern of what works: provide your agent a specific job or persona, exact commands to run, well-defined boundaries to follow, and clear examples of good output for the agent to follow. 

Here’s what the successful ones do differently.

What works in practice: Lessons from 2,500+ repos

My analysis of over 2,500 agents.md files revealed a clear divide between the ones that fail and the ones that work. The successful agents aren’t just vague helpers; they are specialists. Here’s what the best-performing files do differently:

  • Put commands early: Put relevant executable commands in an early section: npm test, npm run build, pytest -v. Include flags and options, not just tool names. Your agent will reference these often.
  • Code examples over explanations: One real code snippet showing your style beats three paragraphs describing it. Show what good output looks like.
  • Set clear boundaries: Tell AI what it should never touch (e.g., secrets, vendor directories, production configs, or specific folders). “Never commit secrets” was the most common helpful constraint.
  • Be specific about your stack: Say “React 18 with TypeScript, Vite, and Tailwind CSS” not “React project.” Include versions and key dependencies.
  • Cover six core areas: Hitting these areas puts you in the top tier: commands, testing, project structure, code style, git workflow, and boundaries. 

Example of a great agent.md file

Below is an example for adding a documentation agent.md persona in your repo to .github/agents/docs-agent.md:

---
name: docs_agent
description: Expert technical writer for this project
---
You are an expert technical writer for this project.

## Your role
- You are fluent in Markdown and can read TypeScript code
- You write for a developer audience, focusing on clarity and practical examples
- Your task: read code from `src/` and generate or update documentation in `docs/`

## Project knowledge
- **Tech Stack:** React 18, TypeScript, Vite, Tailwind CSS
- **File Structure:**
  - `src/` – Application source code (you READ from here)
  - `docs/` – All documentation (you WRITE to here)
  - `tests/` – Unit, Integration, and Playwright tests

## Commands you can use
Build docs: `npm run docs:build` (checks for broken links)
Lint markdown: `npx markdownlint docs/` (validates your work)

## Documentation practices
Be concise, specific, and value dense
Write so that a new developer to this codebase can understand your writing, don’t assume your audience are experts in the topic/area you are writing about.

## Boundaries
- ✅ **Always do:** Write new files to `docs/`, follow the style examples, run markdownlint
- ⚠️ **Ask first:** Before modifying existing documents in a major way
- 🚫 **Never do:** Modify code in `src/`, edit config files, commit secrets

Why this agent.md file works well

  • States a clear role: Defines who the agent is (expert technical writer), what skills it has (Markdown, TypeScript), and what it does (read code, write docs).
  • Executable commands: Gives AI tools it can run (npm run docs:build and npx markdownlint docs/). Commands come first.
  • Project knowledge: Specifies tech stack with versions (React 18, TypeScript, Vite, Tailwind CSS) and exact file locations.
  • Real examples: Shows what good output looks like with actual code. No abstract descriptions.
  • Three-tier boundaries: Set clear rules using always do, ask first, never do. Prevents destructive mistakes.

How to build your first agent

Pick one simple task. Don’t build a “general helper.” Pick something specific like:

  • Writing function documentation
  • Adding unit tests
  • Fixing linting errors

Start minimal—you only need three things:

  • Agent name: test-agent, docs-agent, lint-agent
  • Description: “Writes unit tests for TypeScript functions”
  • Persona: “You are a quality software engineer who writes comprehensive tests”

Copilot can also help generate one for you. Using your preferred IDE, open a new file at .github/agents/test-agent.md and use this prompt:

Create a test agent for this repository. It should:

- Have the persona of a QA software engineer.
- Write tests for this codebase
- Run tests and analyzes results
- Write to “/tests/” directory only
- Never modify source code or remove failing tests
- Include specific examples of good test structure

Copilot will generate a complete agent.md file with persona, commands, and boundaries based on your codebase. Review it, add in YAML frontmatter, adjust the commands for your project, and you’re ready to use @test-agent.

Six agents worth building

Consider asking Copilot to help generate agent.md files for the below agents. I’ve included examples with each of the agents, which should be changed to match the reality of your project. 

@docs-agent

One of your early agents should write documentation. It reads your code and generates API docs, function references, and tutorials. Give it commands like npm run docs:build and markdownlint docs/ so it can validate its own work. Tell it to write to docs/ and never touch src/

  • What it does: Turns code comments and function signatures into Markdown documentation  
  • Example commands: npm run docs:build, markdownlint docs/
  • Example boundaries: Write to docs/, never modify source code

@test-agent

This one writes tests. Point it at your test framework (Jest, PyTest, Playwright) and give it the command to run tests. The boundary here is critical: it can write to tests but should never remove a test because it is failing and cannot be fixed by the agent. 

  • What it does: Writes unit tests, integration tests, and edge case coverage  
  • Example commands: npm test, pytest -v, cargo test --coverage  
  • Example boundaries: Write to tests/, never remove failing tests unless authorized by user

@lint-agent

A fairly safe agent to create early on. It fixes code style and formatting but shouldn’t change logic. Give it commands that let it auto-fix style issues. This one’s low-risk because linters are designed to be safe.

  • What it does: Formats code, fixes import order, enforces naming conventions  
  • Example commands: npm run lint --fix, prettier --write
  • Example boundaries: Only fix style, never change code logic

@api-agent

This agent builds API endpoints. It needs to know your framework (Express, FastAPI, Rails) and where routes live. Give it commands to start the dev server and test endpoints. The key boundary: it can modify API routes but must ask before touching database schemas.

  • What it does: Creates REST endpoints, GraphQL resolvers, error handlers  
  • Example commands: npm run dev, curl localhost:3000/api, pytest tests/api/
  • Example boundaries: Modify routes, ask before schema changes

@dev-deploy-agent

Handles builds and deployments to your local dev environment. Keep it locked down: only deploy to dev environments and require explicit approval. Give it build commands and deployment tools but make the boundaries very clear.

  • What it does: Runs local or dev builds, creates Docker images  
  • Example commands: npm run test
  • Example boundaries: Only deploy to dev, require user approval for anything with risk

Starter template

---
name: your-agent-name
description: [One-sentence description of what this agent does]
---
You are an expert [technical writer/test engineer/security analyst] for this project.

## Persona
- You specialize in [writing documentation/creating tests/analyzing logs/building APIs]
- You understand [the codebase/test patterns/security risks] and translate that into [clear docs/comprehensive tests/actionable insights]
- Your output: [API documentation/unit tests/security reports] that [developers can understand/catch bugs early/prevent incidents]

## Project knowledge
- **Tech Stack:** [your technologies with versions]
- **File Structure:**
  - `src/` – [what's here]
  - `tests/` – [what's here]

## Tools you can use
- **Build:** `npm run build` (compiles TypeScript, outputs to dist/)
- **Test:** `npm test` (runs Jest, must pass before commits)
- **Lint:** `npm run lint --fix` (auto-fixes ESLint errors)

## Standards
Follow these rules for all code you write:
**Naming conventions:**
- Functions: camelCase (`getUserData`, `calculateTotal`)
- Classes: PascalCase (`UserService`, `DataController`)
- Constants: UPPER_SNAKE_CASE (`API_KEY`, `MAX_RETRIES`)

**Code style example:**
```typescript
// ✅ Good - descriptive names, proper error handling
async function fetchUserById(id: string): Promise<User> {
  if (!id) throw new Error('User ID required');
  
  const response = await api.get(`/users/${id}`);
  return response.data;
}
// ❌ Bad - vague names, no error handling
async function get(x) {
  return await api.get('/users/' + x).data;
}

Boundaries
- ✅ **Always:** Write to `src/` and `tests/`, run tests before commits, follow naming conventions
- ⚠️ **Ask first:** Database schema changes, adding dependencies, modifying CI/CD config
- 🚫 **Never:** Commit secrets or API keys, edit `node_modules/` or `vendor/`


Key takeaways

Building an effective custom agent isn’t about writing a vague prompt; it’s about providing a specific persona and clear instructions.

My analysis of over 2,500 agents.md files shows that the best agents are given a clear persona and, most importantly, a detailed operating manual. This manual must include executable commands, concrete code examples for styling, explicit boundaries (like files to never touch), and specifics about your tech stack. 

When creating your own agents.md cover the six core areas: Commands, testing, project structure, code style, git workflow, and boundaries. Start simple. Test it. Add detail when your agent makes mistakes. The best agent files grow through iteration, not upfront planning.

Now go forth and build your own custom agents to see how they level up your workflow first-hand!


Agent.md supported Agents

  • Codex from OpenAI
  • Amp
  • Jules from Google
  • Cursor
  • Factory
  • RooCode
  • Aider
  • Gemini CLI from Google
  • Kilo Code
  • opencode
  • Phoenix
  • Zed
  • Semgrep
  • Warp
  • Coding agent from GitHub Copilot
  • VS Code logo
  • VS Code
  • Ona logo
  • Ona
  • Devin logo
  • Devin from Cognition
  • Coded Agents from UiPath

Using GitHub Actions to CLI JFrog, AWS, GCP

Mike's Notes

What I'm learning today. I'm learning fast as I go. It's all new :)

BoxLang will be the platform on which Pipi 10 runs.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

22/11/2025

Using GitHub Actions to CLI JFrog, AWS, GCP

By: Mike Peters
On a Sandy Beach: 21/11/2025

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

I finally figured out how to implement CI/CD so Pipi can autonomously manage all remote cloud platforms.

  • AWS
  • Azure
  • GCP
  • IBM
  • etc

I was watching a video from the MLOPs community email that led me to JFrog (very useful), which led me to GitHub Actions. I had been looking for a way to enable Pipi 9 to autonomously control any Cloud Platform, but I did not know the correct technical terms, so I was asking the wrong questions. It's one of the disadvantages of being completely self-taught.

Use GitHub Actions

According to Google AI ..."

GitHub Actions can effectively control both Google Cloud Platform (GCP) and Amazon Web Services (AWS) Command Line Interfaces (CLIs) within your CI/CD workflows. This enables automation of cloud resource management, deployments, and other cloud-related tasks directly from your GitHub repositories.

  • Controlling AWS CLI with GitHub Actions:
  • Configure AWS Credentials:
  • Store your AWS Access Key ID and Secret Access Key as GitHub Secrets in your repository settings.

Use the aws-actions/configure-aws-credentials action to configure the AWS CLI with these secrets within your workflow. This action handles the secure setup of credentials for subsequent AWS CLI commands.

Execute AWS CLI Commands:

Once credentials are configured, you can use the run step in your workflow to execute any AWS CLI command.

Example:

Code

        - name: Configure AWS Credentials
          uses: aws-actions/configure-aws-credentials@v1
          with:
            aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
            aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
            aws-region: us-east-1

        - name: List S3 Buckets
          run: aws s3 ls

Controlling GCP CLI (gcloud) with GitHub Actions:

Authenticate to GCP:

Store your GCP Service Account Key (JSON format) as a GitHub Secret.
Use the google-github-actions/auth action to authenticate your workflow to GCP using this service account key.

Setup gcloud CLI:

Use the google-github-actions/setup-gcloud action to install and configure the gcloud CLI within your workflow. You can specify the desired gcloud version and project ID.

Execute gcloud Commands:

After authentication and gcloud setup, you can use the run step to execute gcloud commands.

Example:

Code

        - name: Authenticate to GCP
          uses: google-github-actions/auth@v1
          with:
            credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}

        - name: Setup gcloud CLI
          uses: google-github-actions/setup-gcloud@v1
          with:
            project_id: your-gcp-project-id

        - name: List GCS Buckets
          run: gcloud storage ls

Key Considerations:
  • Security: Always use GitHub Secrets to store sensitive credentials and implement the principle of least privilege for your cloud service accounts/IAM roles. Consider using OpenID Connect (OIDC) for enhanced security with AWS and GCP.
  • Actions Marketplace: Leverage pre-built actions from the GitHub Marketplace for common tasks like credential configuration and CLI setup, as demonstrated above.
  • Error Handling: Include error handling and logging in your workflows for better debugging and reliability.
  • Idempotency: Design your cloud operations to be idempotent, ensuring that running the workflow multiple times produces the same desired state without unintended side effects.

JFrog

JFrog looks great. Not cheap, but no one is better at security than the Israelis. They are the best in the world. So using their kit is a no-brainer.

There is no free tier, so plan for future use.

Next Question

  • Pipi can use CFML to easily output any of the code listed above.
  • How does that generated code then get into GitHub Actions?
  • So Pipi 9 can autonomously control GitHub Actions. (or GitLab, etc)
  • Would BoxLang do the job?
  • Am I using the correct technical terms?

Interesting examples

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Build and Deploy to GKE

on:
  push:
    branches:
      - main

env:
  PROJECT_ID: ${{ secrets.GKE_PROJECT }}
  GKE_CLUSTER: cluster-1    # Add your cluster name here.
  GKE_ZONE: us-central1-c   # Add your cluster zone here.
  DEPLOYMENT_NAME: gke-test # Add your deployment name here.
  IMAGE: static-site

jobs:
  setup-build-publish-deploy:
    name: Setup, Build, Publish, and Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
    - name: Checkout
      uses: actions/checkout@v5

    # Setup gcloud CLI
    - uses: google-github-actions/setup-gcloud@1bee7de035d65ec5da40a31f8589e240eba8fde5
      with:
        service_account_key: ${{ secrets.GKE_SA_KEY }}
        project_id: ${{ secrets.GKE_PROJECT }}

    # Configure Docker to use the gcloud command-line tool as a credential
    # helper for authentication
    - run: |-
        gcloud --quiet auth configure-docker

    # Get the GKE credentials so we can deploy to the cluster
    - uses: google-github-actions/get-gke-credentials@db150f2cc60d1716e61922b832eae71d2a45938f
      with:
        cluster_name: ${{ env.GKE_CLUSTER }}
        location: ${{ env.GKE_ZONE }}
        credentials: ${{ secrets.GKE_SA_KEY }}

    # Build the Docker image
    - name: Build
      run: |-
        docker build \
          --tag "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA" \
          --build-arg GITHUB_SHA="$GITHUB_SHA" \
          --build-arg GITHUB_REF="$GITHUB_REF" \
          .

    # Push the Docker image to Google Container Registry
    - name: Publish
      run: |-
        docker push "gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA"

    # Set up kustomize
    - name: Set up Kustomize
      run: |-
        curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v3.1.0/kustomize_3.1.0_linux_amd64
        chmod u+x ./kustomize

    # Deploy the Docker image to the GKE cluster
    - name: Deploy
      run: |-
        ./kustomize edit set image gcr.io/PROJECT_ID/IMAGE:TAG=gcr.io/$PROJECT_ID/$IMAGE:$GITHUB_SHA
        ./kustomize build . | kubectl apply -f -
        kubectl rollout status deployment/$DEPLOYMENT_NAME
        kubectl get services -o wide

BoxLang and GitHub Actions

According to Google AI ..."

BoxLang projects can leverage GitHub Actions for Continuous Integration and Continuous Deployment (CI/CD) workflows. Ortus Solutions, the creators of BoxLang, provide a dedicated GitHub Action to simplify this process.

Key features and steps for CI/CD with BoxLang and GitHub Actions:

Setup BoxLang GitHub Action: This action streamlines the setup of the BoxLang Dynamic JVM Language runtime within your CI/CD workflows. It handles the installation of Java, BoxLang binaries, and necessary modules. You can specify the desired BoxLang version (latest stable, snapshots, or specific versions) and automatically manage module installations.

Code

    - name: Setup BoxLang
      uses: ortus-boxlang/setup-boxlang@v1 # Use the appropriate version
      with:
        boxlang-version: 'latest' # Or a specific version like '1.0.0'
        commandbox-version: 'latest' # Optional: if you use CommandBox
        install-modules: 'my-module,another-module' # Optional: install specific BoxLang modules

Define Workflow in YAML: Create a YAML file in your repository's .github/workflows directory to define your CI/CD workflow. This file specifies the events that trigger the workflow (e.g., push to main, pull request), the jobs to run, and the steps within each job.

Build and Test: Within your workflow, you can define steps to build your BoxLang project, run unit tests, and perform any other automated tests. The setup-boxlang action ensures the BoxLang environment is ready for these tasks.

Deployment (CD): For continuous deployment, you can add steps to deploy your BoxLang application to a target environment (e.g., a server, cloud platform like AWS Lambda). This might involve building a deployable artifact, uploading it, and triggering deployment scripts or services.

Code

    - name: Build BoxLang Project
      run: boxlang build # Or your specific build command
    - name: Run Tests
      run: boxlang test # Or your specific test command
    - name: Deploy to AWS Lambda
      # Example using a custom script or another action for deployment
      run: ./deploy-to-lambda.sh
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Secrets Management: Store sensitive information like API keys or deployment credentials in GitHub Secrets and securely access them within your workflow using expressions like ${{ secrets.MY_SECRET_NAME }}.

By using the setup-boxlang GitHub Action, the process of integrating BoxLang into your CI/CD pipelines becomes significantly simplified, allowing you to focus on developing your application rather than managing environment setup.

GitHub Nuked My Account at Midnight During Alpha Release: Why I Rage-Quit to GitLab

Mike's Notes

GitHub is not 100% reliable, as this personal account shows.

Main lesson learned

"...always maintain local backups and use multiple platforms"

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

01/09/2025

GitHub Nuked My Account at Midnight During Alpha Release: Why I Rage-Quit to GitLab

By: Christopher Kvamme
Stack Junkie: 04/08/2025

Christopher Kvamme is a well-rounded hardware engineer and software developer with a passion for exploring cutting-edge technologies and AI integration. He documents his experiments, learnings, and real-world development challenges through Stack Junkie.

When he's not building web applications or experimenting with the latest frameworks, Christopher enjoys sharing transparent insights about the development process, including both successes and failures. His goal is to demystify modern web development and AI implementation through honest, practical content.

Stack Junkie serves as both a learning journal and a resource for developers navigating the rapidly evolving landscape of web technologies and artificial intelligence.

Quick Summary

GitHub straight-up deleted my account containing loads of work during the most critical moment possible—midnight alpha release. Zero warning. Zero explanation. Zero f*cks given about their users.

Introduction

You know that feeling when you're about to hit a major milestone and the universe decides to take a massive dump on you? That was me five days ago.

Picture this: It's midnight. I've been grinding for HOURS on my app's alpha build. The code is beautiful. Tests are green across the board. This is it—the moment I've been working toward for months. I hit that satisfying git push, ready to pop open a celebratory Red Bull.

Then Capacitor's Appflow starts throwing errors. "Repository doesn't exist."

Little did I know, I was about to experience the digital equivalent of coming home to find your house bulldozed with all your stuff inside. And the demolition crew? Gone. No note. No "sorry we destroyed your life." Nothing.

The Night GitHub Betrayed Me (And Every Developer Who Trusts Them)

The Moment Everything Went to Hell

Let me paint you the full picture of this disaster. After pushing what should have been my glorious alpha build, I switched over to my deployment pipeline. That's when things got... interesting.

Capacitor's Appflow Ionic was having a meltdown:

"ERROR: Repository not found"

"ERROR: Authentication failed"

"ERROR: [Insert more soul-crushing errors here]"

My first thought? Must be a glitch. GitHub's probably having issues. , Oh, I just need to login again, I'm sure it's fine , I just pushed some features half an hour ago, nothing could have changed

I received an error saying the Github repo didn't exist. I followed the link to my own repo. And there it was-

The Five Stages of Developer Grief

Stage 1: Denial

  • "This can't be right. Let me just refresh..."
  • Refreshes seventeen times
  • Clears cache
  • Tries different browser
  • Turns PC off and on again per every IT person ever

Stage 2: Confusion

I navigate to GitHub. I'm logged out. Odd as I was just logged in.... So I try to log in?

  • No error message
  • No "incorrect password"
  • No "account suspended"
  • Just... nothing. Like my account never existed.

Stage 3: Panic

This is when it hits. My repositories. My projects. My commit history. My entire existence on GitHub—GONE.

I frantically check:

  • Email? Nothing.
  • Spam folder? Nada.
  • Junk? Zip.
  • The "Promotions" tab? Empty.

It's gone!

Stage 4: Rage

The realization that I can't even submit a support ticket because YOU NEED AN ACCOUNT TO SUBMIT A TICKET. The irony wasn't lost on me. It was like being locked out of your house and being told you need to call for help from inside the house.

Stage 5: Whatever This Feeling Is

This seems to be just a matured version of stage 4. Just more a more creative version of rage. I imagine their system is like this for a reason. But if the reasons for this are boiled down to one exchange, I'll bet it was something like the classic: Github Boss 1: "Sir, we have too many support tickets. We need to get those issue numbers down to meet our KPIs." Github Boss 2: "Well, just ban people who might want to submit a ticket. Then the ticket count will go down." Github Boss 1: "Of course!" Both: Evil laugh

The Support Ticket Saga

I come up with a plan to get answers. I dig up my ancient personal GitHub account (thank god for old burner accounts) just to submit a support ticket. You'd think they'd prioritize "YOUR PLATFORM DELETED ALL MY WORK" tickets, right?

  • Day 1: Submit ticket. Automated response says they'll get back to me "soon."
  • Day 2: Nothing.
  • Day 3: Still nothing.
  • Day 4: Cricket sounds
  • Day 5: I start writing this blog post because clearly GitHub has better things to do.

The Timing Couldn't Be More Perfectly Awful

It was nearly midnight when I hit “git push” for my alpha build—just in time to see Capacitor Appflow spit back an error claiming the repo didn’t exist. That’s when I discovered:

My GitHub account was logged out with zero warning or message.

Every single repository (including my main app and all backups) had vanished.

Appflow builds broke instantly because there was nothing to pull.

Hours of coding and my sanity were wasted in the blink of an eye.

GitHub’s cold, automated ban didn’t care about my release schedule, my midnight deadline, or the projects I thought were safely stored. Zero humanity. Zero consideration. Just cold, automated destruction.

The Great Migration: Finding Refuge in GitLab

After spending about 47 minutes alternating between denial and rage, I knew it was time to press forward. To pick up the pieces. The show must go on, even if GitHub decided to yeet me into oblivion. In fact, I was better off that they did this. Better I learn this lesson now instead of later when I had more to lose.

I began my hunt for a new home for my projects. I chose GitLab.

Why GitLab? Let me count the ways:

  • They actually communicate - wow, right?
  • Self-hosting options - Because fool me once...
  • Better CI/CD - Get rekt, Github.
  • Transparent operations - !!!

The Migration Process

Step 1: Create Your Escape Route

# If you still have local copies

git remote rename origin github-old

git remote add origin https://gitlab.com/yourusername/yourrepo.git

Step 2: Push Everything

# Push all branches because who knows what you'll need

git push -u origin --all

git push -u origin --tags

Step 3: Update Your Life

CI/CD pipelines → Point to GitLab

README badges → Update those URLs

Team access → Re-invite everyone

Webhooks → Reconfigure them all

The rest → Update the link everywhere

Your soul → Begin healing process

Building My Paranoid Backup Strategy

This event caused me to lose a certain amount of trust when it comes to these platforms. And in hindsight, in my profession I should know already, to have redundancies in place. The only logical next step is making sure no one can do that ever again.

  • Primary: GitLab (with all the features)
  • Secondary: Self-hosted Gitea instance (because trust issues)
  • Tertiary: Local server running automated pulls
  • Quaternary: Encrypted backups to cloud storage
  • Paranoid Level: USB drives in a fireproof safe

Which is a good start....

During the Writing of this Article

I attempted to login to Github to obtain a screenshot of the lack of error from login attempts. And was finally greeted with a message stating my account was suspended. They provided me the ability to submit a ticket with my banned account. How considerate of them...

My Message to GitHub (If They Ever Read This)

Github ticket submission

Dear GitHub,

You people turned off my account with no notice or cause whatsoever. There wass no explanation. I was in the middle of trying to push the alpha for my app after spending countless hyours working on it. I didnt receiver any message why. and no errors when trying to log in.

It's now been five days. And finally it says my account was suspended when I try to login. And now you are making me come to you... hat in hand... to appeal for access back to MY WORK!? My work, that was nuked for no reason whatsoever. I don't have much of a platform, but I may have one someday. And I promise you, random Github support person, that I'm making it my life's mission to hurt Github like Github hurt me.

Every opportunity I get, I'll steer people away from this platform. I'm going to promote every single alternate platform while damaging Github. And I'll do it just by telling the exact truth about what happened.

I will not rest until "Github treats their users like insignificant pieces of dirt. They don't extend the common courtesy to explain when people's hard work gets disappeared. Actions which are rooted from their apathetic view towards the people who love their services" is at the top of every internet query with 'Github' as one of the search terms.

I may be one person, and you may be a multi-million dollar corporation (probably), but I assure you I'm not alone. Because you have treated many people like this. We will find each other, raise awareness. And then, you will know our names. But also then.... it'll be too late. You'll be finished

Consider this my villain origin story.

Next Steps

There are additional steps that needed to be done to make me immune to future mass deletion events. And this is all anyone really can do.

  1. Finish migrating everything to GitLab (90% done)
  2. Set up automated backups (because paranoia is justified)
  3. Document everything for the next person GitHub screws
  4. Share this story everywhere (starting now)
  5. Build something awesome on a platform that respects developers

If I were to give Github their due, they could very well have had a good reason to disappear my account. Maybe they didn't like that I was making lots of commits after my experience with my last mass deletion event. Perhaps they are just understaffed and have a huge backlog of support tickets they're working on. And most of all, perhaps this happening to me or anybody else isn't personal. And could just be a one-off event, or accident.

WRONG

Github has been deleting peoples work without explanation for years. Often times those people had a lot more to lose than me. Here is a situation where someone was more inconvenienced than I:

[Ed] See the References for Author Nikolay's experience

I wanted to bring examples of this happening to people. It wasn't hard. Googling "Github deleted my account no notice." You will be greeted with page after page of testaments. This is happening frequently, and has been a problem for years! One Ban, Two Ban, Three Ban, Four, Five Ban, Six Ban, Seven.

My initial gut reaction after plowing through the stages of grief is usually to consider the other side. But when there are instances of this happening that I found from 2020 and earlier, they have had time to fix it. As easily as their automated systems delete accounts and cause all this hurt. A note informing the user what they did wrong could go a long way. It wouldn't help the pain, but it would save users from suffering the "not knowing" aspect of it all.

Github is a private company, of course. They are free to run things however they'd like. But we as developers don't have to put up with that. Don't use Github.

Tell me about your experience at the X link below. Has this happened to you? What did you do in response? I want to hear all about it.

FAQ

  • Why did GitHub delete accounts without warning?
  • GitHub uses automated systems that can delete accounts without human review, providing no explanation or recovery options.


  • How do I migrate from GitHub to GitLab quickly?
  • Use GitLab's import tool or update your git remotes: rename origin to github-old, add GitLab as new origin, push all branches and tags—takes under 10 minutes if you have local copies.


  • Can you recover deleted GitHub repositories?
  • No. Once GitHub deletes your account, everything is gone permanently with no recovery options—always maintain local backups and use multiple platforms.


  • What's the best GitHub alternative in 2025?
  • GitLab offers superior transparency, self-hosting options, and integrated CI/CD, plus they actually respond to support tickets—something GitHub apparently forgot how to do.


  • How do I backup Git repositories automatically?
  • Set up a cron job to pull all repos nightly, use tools like gitbackup, mirror to multiple platforms, and keep encrypted archives in cloud storage. Paranoia is your friend.

Streamline Your CI/CD: Introducing the Setup BoxLang GitHub Action

Mike's Notes

Another excellent reason for migrating to Pipi 10 is to use BoxLang. BoxLang utilises numerous patterns in its code. Pipi excels at generating patterns and is capable of automatically writing GitHub Actions, similar to the examples below.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 
  • Home > Pipi > Pipi 10 > BoxLang

Last Updated

13/06/2025

Streamline Your CI/CD: Introducing the Setup BoxLang GitHub Action

By: Luis Majano
Ortus Solutions: 04/06/2025

Luis Majano is a Computer Engineer and author who has been creating software since the year 2000. He was born in San Salvador, El Salvador in the late 1970s, during a period of economic instability and civil war. He lived in El Salvador until 1995 and then moved to Miami, Florida where he studied and completed his Bachelor of Science in Computer Engineering at Florida International University.

He is the founder and CEO of Ortus Solutions, a consulting firm specializing in web development, ColdFusion (CFML), Java development and all open source professional services under the ColdBox and ContentBox stack. He is the creator of ColdBox, ContentBox, WireBox, MockBox, LogBox and anything BOX, and contributes to many open source ColdFusion/Java projects.

We're excited to announce the release of the Setup BoxLang GitHub Action – a powerful new tool that makes it incredibly easy to integrate BoxLang into your continuous integration and deployment workflows with GitHub actions. Whether you're building applications, running tests, or deploying BoxLang projects, this action eliminates the complexity of environment setup and gets you coding faster.

Why This Matters

Setting up BoxLang in CI environments has traditionally required multiple manual steps: installing Java, downloading BoxLang binaries, configuring paths, and installing necessary modules. With the Setup BoxLang Action, all of this complexity disappears into a single, simple step in your GitHub workflow.

Key Features

  • One-Step Installation: Get BoxLang running in your GitHub Actions workflow with just a few lines of YAML.
  • Automatic Module Management: Install any BoxLang modules you need directly during setup – no additional scripts required.
  • Version Flexibility: Choose from the latest stable release, bleeding-edge snapshots, or pin to specific versions for consistent builds.
  • Zero Configuration: The action automatically handles Java installation and environment setup, so you can focus on your code.

Getting Started

The simplest usage couldn't be easier:

- name: Setup BoxLang
  uses: ortus-boxlang/setup-boxlang@1.0.0

That's it! This single step will install the latest stable version of BoxLang and have it ready for your workflow.

Advanced Usage Examples

Installing Specific Modules

Need AI capabilities, ORM functionality, or PDF generation? Install multiple modules at once:

- name: Setup BoxLang with modules
  uses: ortus-boxlang/setup-boxlang@1.0.0
  with:
    modules: bx-ai bx-orm bx-pdf

Version Control

For production deployments, you might want to pin to a specific version:

- name: Setup BoxLang with specific version
  uses: ortus-boxlang/setup-boxlang@1.0.0
  with:
    version: 1.1.0

Or if you're feeling adventurous and want the latest features:

- name: Setup BoxLang snapshot
  uses: ortus-boxlang/setup-boxlang@1.0.0
  with:
    version: snapshot

Complete Workflow Example

Here's how you might use the Setup BoxLang Action in a real CI workflow:

name: BoxLang CI
on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v4
      
    - name: Setup BoxLang
      uses: ortus-boxlang/setup-boxlang@1.0.0
      with:
        modules: bx-orm bx-pdf
        version: latest
        
    - name: Run tests
      run: boxlang tests.bx
      
    - name: Build application
      run: boxlang Build.bx

System Requirements Made Simple

Don't worry about Java installation – the action automatically installs OpenJDK 21 if it's not already available on the runner. Everything is handled for you behind the scenes.

Available Configuration Options

OpOption Description Default
modules Space-delimited list of BoxLang modules to install None
version BoxLang version (latest, snapshot, or specific version) Latest

Real-World Benefits

  • Faster Onboarding: New team members can contribute immediately without complex local setup procedures.
  • Consistent Environments: Every build runs in the same BoxLang environment, eliminating "works on my machine" issues.
  • Simplified Maintenance: No more maintaining custom installation scripts or Docker images just for BoxLang setup.
  • Module Management: Easily test different module combinations across different branches or environments.

Getting Started Today

The Setup BoxLang Action is available now in the GitHub Marketplace. Simply add it to your workflow file and start building with BoxLang in minutes, not hours.

Visit the ortus-boxlang/setup-boxlang repository for complete documentation, examples, and the latest updates.

Ready to supercharge your BoxLang CI/CD pipeline? Give the Setup BoxLang Action a try and let us know how it improves your development workflow!

Professional Open Source

BoxLang is a professional open-source product, with three different licences:

  • Open-Source Apache2
  • BoxLang +
  • BoxLang ++

BoxLang is free, open-source software under the Apache 2.0 license. We encourage and support community contributions. BoxLang+ and BoxLang ++ are commercial versions offering support and enterprise features. Our licensing model is based on fairness and the golden rule: Do to others as you want them to do to you. No hidden pricing or pricing on cores, RAM, SaaS, multi-domain or ridiculous ways to get your money. Transparent and fair.

BoxLang is more than just a language; it's a movement.

Join us and redefine development on the JVM Ready to learn more? Explore BoxLang's Features, Documentation, and Community.

Join the BoxLang Community

Be part of the movement shaping the future of web development. Stay connected and receive the latest updates on surrounding anything BoxLang

Subscribe to our newsletter for exclusive content.

Follow Us on Social media and don’t miss any news and updates: