feat: Add @mosaic/cli-tools package for git operations
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

New package providing CLI tools that work with both Gitea and GitHub:

Commands:
- mosaic-issue-{create,list,view,assign,edit,close,reopen,comment}
- mosaic-pr-{create,list,view,merge,review,close}
- mosaic-milestone-{create,list,close}

Features:
- Auto-detects platform (Gitea vs GitHub) from git remote
- Unified interface regardless of platform
- Available via `pnpm exec mosaic-*` in monorepo context

Updated docs/claude/orchestrator.md:
- Added CLI Tools section with usage examples
- Updated issue creation to use package commands

This makes Mosaic Stack fully self-contained for orchestration tooling.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jason Woltje
2026-02-05 16:42:35 -06:00
parent 7ae92f3e1c
commit 32c81e96cf
21 changed files with 1730 additions and 7 deletions

View File

@@ -53,6 +53,25 @@ envsubst < docs/templates/orchestrator/orchestrator-learnings.json.template > do
See `docs/templates/README.md` for full documentation.
### CLI Tools
Git operations use `@mosaic/cli-tools` package (auto-detects Gitea vs GitHub):
```bash
# Issue operations
pnpm exec mosaic-issue-create -t "Title" -b "Body" -m "Milestone"
pnpm exec mosaic-issue-list -s open -m "Milestone"
# PR operations
pnpm exec mosaic-pr-create -t "Title" -b "Body" -B develop
pnpm exec mosaic-pr-merge -n 42 -m squash -d
# Milestone operations
pnpm exec mosaic-milestone-create -t "M7-Feature" -d "Description"
```
See `packages/cli-tools/README.md` for full command reference.
---
## Phase 1: Bootstrap
@@ -121,23 +140,25 @@ docs/reports/{report-name}/
### Step 5: Create Gitea Issues (Phase-Level)
Create ONE issue per phase:
Create ONE issue per phase using `@mosaic/cli-tools`:
```bash
# Use tea directly for Mosaic Stack (Gitea)
tea issue create \
--title "Phase 1: Critical Security Fixes" \
--description "## Findings
# Use mosaic CLI tools (auto-detects Gitea vs GitHub)
pnpm exec mosaic-issue-create \
-t "Phase 1: Critical Security Fixes" \
-b "## Findings
- SEC-API-1: Description
- SEC-WEB-2: Description
## Acceptance Criteria
- [ ] All critical findings remediated
- [ ] Quality gates passing" \
--labels "security" \
--milestone "{milestone-name}"
-l "security" \
-m "{milestone-name}"
```
**CLI tools location:** `packages/cli-tools/bin/` - see `packages/cli-tools/README.md` for full documentation.
### Step 6: Create docs/tasks.md
Create the file with this exact schema:

View File

@@ -0,0 +1,126 @@
# @mosaic/cli-tools
CLI tools for Mosaic Stack orchestration - git operations that work with both Gitea and GitHub.
## Overview
These scripts abstract the differences between `tea` (Gitea CLI) and `gh` (GitHub CLI), providing a unified interface for:
- Issue management (create, list, assign, close, comment)
- Pull request management (create, list, merge, review)
- Milestone management (create, list, close)
## Installation
The package is part of the Mosaic Stack monorepo. After `pnpm install`, the commands are available in the monorepo context.
```bash
# From monorepo root
pnpm install
# Commands available via pnpm exec or npx
pnpm exec mosaic-issue-create -t "Title" -b "Body"
```
## Commands
### Issues
| Command | Description |
| ---------------------- | ------------------------------------------- |
| `mosaic-issue-create` | Create a new issue |
| `mosaic-issue-list` | List issues (with filters) |
| `mosaic-issue-view` | View issue details |
| `mosaic-issue-assign` | Assign issue to user |
| `mosaic-issue-edit` | Edit issue (title, body, labels, milestone) |
| `mosaic-issue-close` | Close an issue |
| `mosaic-issue-reopen` | Reopen a closed issue |
| `mosaic-issue-comment` | Add comment to issue |
### Pull Requests
| Command | Description |
| ------------------ | --------------------- |
| `mosaic-pr-create` | Create a pull request |
| `mosaic-pr-list` | List pull requests |
| `mosaic-pr-view` | View PR details |
| `mosaic-pr-merge` | Merge a pull request |
| `mosaic-pr-review` | Review a pull request |
| `mosaic-pr-close` | Close a pull request |
### Milestones
| Command | Description |
| ------------------------- | ------------------ |
| `mosaic-milestone-create` | Create a milestone |
| `mosaic-milestone-list` | List milestones |
| `mosaic-milestone-close` | Close a milestone |
## Usage Examples
### Create an issue with milestone
```bash
mosaic-issue-create \
-t "Fix authentication bug" \
-b "Users cannot log in when..." \
-l "bug,security" \
-m "M6-AgentOrchestration"
```
### List open issues in milestone
```bash
mosaic-issue-list -s open -m "M6-AgentOrchestration"
```
### Create a pull request
```bash
mosaic-pr-create \
-t "Fix authentication bug" \
-b "Resolves #123" \
-B develop \
-H fix/auth-bug
```
### Merge with squash
```bash
mosaic-pr-merge -n 42 -m squash -d
```
## Platform Detection
The scripts automatically detect whether you're working with Gitea or GitHub by examining the git remote URL. No configuration needed.
- `git.mosaicstack.dev` → Gitea (uses `tea`)
- `github.com` → GitHub (uses `gh`)
## Requirements
- **Gitea**: `tea` CLI installed and authenticated
- **GitHub**: `gh` CLI installed and authenticated
- **Both**: `git` available in PATH
## For Orchestrators
When using these tools in orchestrator/worker contexts:
```bash
# In worker prompt, reference via pnpm exec
pnpm exec mosaic-issue-create -t "Title" -m "Milestone"
# Or add to PATH in orchestrator setup
export PATH="$PATH:./node_modules/.bin"
mosaic-issue-create -t "Title" -m "Milestone"
```
## Development
Scripts are plain bash - edit directly in `bin/`.
```bash
# Lint with shellcheck (if installed)
pnpm lint
```

View File

@@ -0,0 +1,80 @@
#!/bin/bash
# detect-platform.sh - Detect git platform (Gitea or GitHub) for current repo
# Usage: source detect-platform.sh && detect_platform
# or: ./detect-platform.sh (prints platform name)
detect_platform() {
local remote_url
remote_url=$(git remote get-url origin 2>/dev/null)
if [[ -z "$remote_url" ]]; then
echo "error: not a git repository or no origin remote" >&2
return 1
fi
# Check for GitHub
if [[ "$remote_url" == *"github.com"* ]]; then
PLATFORM="github"
export PLATFORM
echo "github"
return 0
fi
# Check for common Gitea indicators
# Gitea URLs typically don't contain github.com, gitlab.com, bitbucket.org
if [[ "$remote_url" != *"gitlab.com"* ]] && \
[[ "$remote_url" != *"bitbucket.org"* ]]; then
# Assume Gitea for self-hosted repos
PLATFORM="gitea"
export PLATFORM
echo "gitea"
return 0
fi
PLATFORM="unknown"
export PLATFORM
echo "unknown"
return 1
}
get_repo_info() {
local remote_url
remote_url=$(git remote get-url origin 2>/dev/null)
if [[ -z "$remote_url" ]]; then
echo "error: not a git repository or no origin remote" >&2
return 1
fi
# Extract owner/repo from URL
# Handles: git@host:owner/repo.git, https://host/owner/repo.git, https://host/owner/repo
local repo_path
if [[ "$remote_url" == git@* ]]; then
repo_path="${remote_url#*:}"
else
repo_path="${remote_url#*://}"
repo_path="${repo_path#*/}"
fi
# Remove .git suffix if present
repo_path="${repo_path%.git}"
echo "$repo_path"
}
get_repo_owner() {
local repo_info
repo_info=$(get_repo_info)
echo "${repo_info%%/*}"
}
get_repo_name() {
local repo_info
repo_info=$(get_repo_info)
echo "${repo_info##*/}"
}
# If script is run directly (not sourced), output the platform
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
detect_platform
fi

View File

@@ -0,0 +1,135 @@
#!/bin/bash
# issue-assign.sh - Assign issues on Gitea or GitHub
# Usage: issue-assign.sh -i ISSUE_NUMBER [-a assignee] [-l labels] [-m milestone]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Default values
ISSUE=""
ASSIGNEE=""
LABELS=""
MILESTONE=""
REMOVE_ASSIGNEE=false
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
Assign or update an issue on the current repository (Gitea or GitHub).
Options:
-i, --issue NUMBER Issue number (required)
-a, --assignee USER Assign to user (use @me for self)
-l, --labels LABELS Add comma-separated labels
-m, --milestone NAME Set milestone
-r, --remove-assignee Remove current assignee
-h, --help Show this help message
Examples:
$(basename "$0") -i 42 -a "username"
$(basename "$0") -i 42 -l "in-progress" -m "0.2.0"
$(basename "$0") -i 42 -a @me
EOF
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-i|--issue)
ISSUE="$2"
shift 2
;;
-a|--assignee)
ASSIGNEE="$2"
shift 2
;;
-l|--labels)
LABELS="$2"
shift 2
;;
-m|--milestone)
MILESTONE="$2"
shift 2
;;
-r|--remove-assignee)
REMOVE_ASSIGNEE=true
shift
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
if [[ -z "$ISSUE" ]]; then
echo "Error: Issue number is required (-i)" >&2
usage
fi
PLATFORM=$(detect_platform)
case "$PLATFORM" in
github)
if [[ -n "$ASSIGNEE" ]]; then
gh issue edit "$ISSUE" --add-assignee "$ASSIGNEE"
fi
if [[ "$REMOVE_ASSIGNEE" == true ]]; then
# Get current assignees and remove them
CURRENT=$(gh issue view "$ISSUE" --json assignees -q '.assignees[].login' 2>/dev/null | tr '\n' ',')
if [[ -n "$CURRENT" ]]; then
gh issue edit "$ISSUE" --remove-assignee "${CURRENT%,}"
fi
fi
if [[ -n "$LABELS" ]]; then
gh issue edit "$ISSUE" --add-label "$LABELS"
fi
if [[ -n "$MILESTONE" ]]; then
gh issue edit "$ISSUE" --milestone "$MILESTONE"
fi
echo "Issue #$ISSUE updated successfully"
;;
gitea)
# tea issue edit syntax
CMD="tea issue edit $ISSUE"
NEEDS_EDIT=false
if [[ -n "$ASSIGNEE" ]]; then
# tea uses --assignees flag
CMD="$CMD --assignees \"$ASSIGNEE\""
NEEDS_EDIT=true
fi
if [[ -n "$LABELS" ]]; then
# tea uses --labels flag (replaces existing)
CMD="$CMD --labels \"$LABELS\""
NEEDS_EDIT=true
fi
if [[ -n "$MILESTONE" ]]; then
MILESTONE_ID=$(tea milestones list 2>/dev/null | grep -E "^\s*[0-9]+" | grep "$MILESTONE" | awk '{print $1}' | head -1)
if [[ -n "$MILESTONE_ID" ]]; then
CMD="$CMD --milestone $MILESTONE_ID"
NEEDS_EDIT=true
else
echo "Warning: Could not find milestone '$MILESTONE'" >&2
fi
fi
if [[ "$NEEDS_EDIT" == true ]]; then
eval "$CMD"
echo "Issue #$ISSUE updated successfully"
else
echo "No changes specified"
fi
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,64 @@
#!/bin/bash
# issue-close.sh - Close an issue on GitHub or Gitea
# Usage: issue-close.sh -i <issue_number> [-c <comment>]
set -e
# Source platform detection
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
ISSUE_NUMBER=""
COMMENT=""
while [[ $# -gt 0 ]]; do
case $1 in
-i|--issue)
ISSUE_NUMBER="$2"
shift 2
;;
-c|--comment)
COMMENT="$2"
shift 2
;;
-h|--help)
echo "Usage: issue-close.sh -i <issue_number> [-c <comment>]"
echo ""
echo "Options:"
echo " -i, --issue Issue number (required)"
echo " -c, --comment Comment to add before closing (optional)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$ISSUE_NUMBER" ]]; then
echo "Error: Issue number is required (-i)"
exit 1
fi
# Detect platform and close issue
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
if [[ -n "$COMMENT" ]]; then
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT"
fi
gh issue close "$ISSUE_NUMBER"
echo "Closed GitHub issue #$ISSUE_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
if [[ -n "$COMMENT" ]]; then
tea issue comment "$ISSUE_NUMBER" "$COMMENT"
fi
tea issue close "$ISSUE_NUMBER"
echo "Closed Gitea issue #$ISSUE_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,61 @@
#!/bin/bash
# issue-comment.sh - Add a comment to an issue on GitHub or Gitea
# Usage: issue-comment.sh -i <issue_number> -c <comment>
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
ISSUE_NUMBER=""
COMMENT=""
while [[ $# -gt 0 ]]; do
case $1 in
-i|--issue)
ISSUE_NUMBER="$2"
shift 2
;;
-c|--comment)
COMMENT="$2"
shift 2
;;
-h|--help)
echo "Usage: issue-comment.sh -i <issue_number> -c <comment>"
echo ""
echo "Options:"
echo " -i, --issue Issue number (required)"
echo " -c, --comment Comment text (required)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$ISSUE_NUMBER" ]]; then
echo "Error: Issue number is required (-i)"
exit 1
fi
if [[ -z "$COMMENT" ]]; then
echo "Error: Comment is required (-c)"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT"
echo "Added comment to GitHub issue #$ISSUE_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
tea issue comment "$ISSUE_NUMBER" "$COMMENT"
echo "Added comment to Gitea issue #$ISSUE_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,92 @@
#!/bin/bash
# issue-create.sh - Create issues on Gitea or GitHub
# Usage: issue-create.sh -t "Title" [-b "Body"] [-l "label1,label2"] [-m "milestone"]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Default values
TITLE=""
BODY=""
LABELS=""
MILESTONE=""
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
Create an issue on the current repository (Gitea or GitHub).
Options:
-t, --title TITLE Issue title (required)
-b, --body BODY Issue body/description
-l, --labels LABELS Comma-separated labels (e.g., "bug,feature")
-m, --milestone NAME Milestone name to assign
-h, --help Show this help message
Examples:
$(basename "$0") -t "Fix login bug" -l "bug,priority-high"
$(basename "$0") -t "Add dark mode" -b "Implement theme switching" -m "0.2.0"
EOF
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-t|--title)
TITLE="$2"
shift 2
;;
-b|--body)
BODY="$2"
shift 2
;;
-l|--labels)
LABELS="$2"
shift 2
;;
-m|--milestone)
MILESTONE="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
if [[ -z "$TITLE" ]]; then
echo "Error: Title is required (-t)" >&2
usage
fi
PLATFORM=$(detect_platform)
case "$PLATFORM" in
github)
CMD="gh issue create --title \"$TITLE\""
[[ -n "$BODY" ]] && CMD="$CMD --body \"$BODY\""
[[ -n "$LABELS" ]] && CMD="$CMD --label \"$LABELS\""
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
eval "$CMD"
;;
gitea)
CMD="tea issue create --title \"$TITLE\""
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
[[ -n "$LABELS" ]] && CMD="$CMD --labels \"$LABELS\""
# tea accepts milestone by name directly (verified 2026-02-05)
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
eval "$CMD"
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,84 @@
#!/bin/bash
# issue-edit.sh - Edit an issue on GitHub or Gitea
# Usage: issue-edit.sh -i <issue_number> [-t <title>] [-b <body>] [-l <labels>] [-m <milestone>]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
ISSUE_NUMBER=""
TITLE=""
BODY=""
LABELS=""
MILESTONE=""
while [[ $# -gt 0 ]]; do
case $1 in
-i|--issue)
ISSUE_NUMBER="$2"
shift 2
;;
-t|--title)
TITLE="$2"
shift 2
;;
-b|--body)
BODY="$2"
shift 2
;;
-l|--labels)
LABELS="$2"
shift 2
;;
-m|--milestone)
MILESTONE="$2"
shift 2
;;
-h|--help)
echo "Usage: issue-edit.sh -i <issue_number> [-t <title>] [-b <body>] [-l <labels>] [-m <milestone>]"
echo ""
echo "Options:"
echo " -i, --issue Issue number (required)"
echo " -t, --title New title"
echo " -b, --body New body/description"
echo " -l, --labels Labels (comma-separated, replaces existing)"
echo " -m, --milestone Milestone name"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$ISSUE_NUMBER" ]]; then
echo "Error: Issue number is required (-i)"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
CMD="gh issue edit $ISSUE_NUMBER"
[[ -n "$TITLE" ]] && CMD="$CMD --title \"$TITLE\""
[[ -n "$BODY" ]] && CMD="$CMD --body \"$BODY\""
[[ -n "$LABELS" ]] && CMD="$CMD --add-label \"$LABELS\""
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
eval $CMD
echo "Updated GitHub issue #$ISSUE_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
CMD="tea issue edit $ISSUE_NUMBER"
[[ -n "$TITLE" ]] && CMD="$CMD --title \"$TITLE\""
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
[[ -n "$LABELS" ]] && CMD="$CMD --add-labels \"$LABELS\""
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
eval $CMD
echo "Updated Gitea issue #$ISSUE_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,104 @@
#!/bin/bash
# issue-list.sh - List issues on Gitea or GitHub
# Usage: issue-list.sh [-s state] [-l label] [-m milestone] [-a assignee]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Default values
STATE="open"
LABEL=""
MILESTONE=""
ASSIGNEE=""
LIMIT=30
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
List issues from the current repository (Gitea or GitHub).
Options:
-s, --state STATE Filter by state: open, closed, all (default: open)
-l, --label LABEL Filter by label
-m, --milestone NAME Filter by milestone name
-a, --assignee USER Filter by assignee
-n, --limit N Maximum issues to show (default: 30)
-h, --help Show this help message
Examples:
$(basename "$0") # List open issues
$(basename "$0") -s all -l bug # All issues with 'bug' label
$(basename "$0") -m "0.2.0" # Issues in milestone 0.2.0
EOF
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-s|--state)
STATE="$2"
shift 2
;;
-l|--label)
LABEL="$2"
shift 2
;;
-m|--milestone)
MILESTONE="$2"
shift 2
;;
-a|--assignee)
ASSIGNEE="$2"
shift 2
;;
-n|--limit)
LIMIT="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
PLATFORM=$(detect_platform)
case "$PLATFORM" in
github)
CMD="gh issue list --state $STATE --limit $LIMIT"
[[ -n "$LABEL" ]] && CMD="$CMD --label \"$LABEL\""
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
[[ -n "$ASSIGNEE" ]] && CMD="$CMD --assignee \"$ASSIGNEE\""
eval "$CMD"
;;
gitea)
CMD="tea issues list --state $STATE --limit $LIMIT"
[[ -n "$LABEL" ]] && CMD="$CMD --labels \"$LABEL\""
# tea uses different syntax for milestone filtering
if [[ -n "$MILESTONE" ]]; then
MILESTONE_ID=$(tea milestones list 2>/dev/null | grep -E "^\s*[0-9]+" | grep "$MILESTONE" | awk '{print $1}' | head -1)
if [[ -n "$MILESTONE_ID" ]]; then
CMD="$CMD --milestones $MILESTONE_ID"
else
echo "Warning: Could not find milestone '$MILESTONE'" >&2
fi
fi
# Note: tea may not support assignee filter directly
eval "$CMD"
if [[ -n "$ASSIGNEE" ]]; then
echo "Note: Assignee filtering may require manual review for Gitea" >&2
fi
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,62 @@
#!/bin/bash
# issue-reopen.sh - Reopen a closed issue on GitHub or Gitea
# Usage: issue-reopen.sh -i <issue_number> [-c <comment>]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
ISSUE_NUMBER=""
COMMENT=""
while [[ $# -gt 0 ]]; do
case $1 in
-i|--issue)
ISSUE_NUMBER="$2"
shift 2
;;
-c|--comment)
COMMENT="$2"
shift 2
;;
-h|--help)
echo "Usage: issue-reopen.sh -i <issue_number> [-c <comment>]"
echo ""
echo "Options:"
echo " -i, --issue Issue number (required)"
echo " -c, --comment Comment to add when reopening (optional)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$ISSUE_NUMBER" ]]; then
echo "Error: Issue number is required (-i)"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
if [[ -n "$COMMENT" ]]; then
gh issue comment "$ISSUE_NUMBER" --body "$COMMENT"
fi
gh issue reopen "$ISSUE_NUMBER"
echo "Reopened GitHub issue #$ISSUE_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
if [[ -n "$COMMENT" ]]; then
tea issue comment "$ISSUE_NUMBER" "$COMMENT"
fi
tea issue reopen "$ISSUE_NUMBER"
echo "Reopened Gitea issue #$ISSUE_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# issue-view.sh - View issue details on GitHub or Gitea
# Usage: issue-view.sh -i <issue_number>
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
ISSUE_NUMBER=""
while [[ $# -gt 0 ]]; do
case $1 in
-i|--issue)
ISSUE_NUMBER="$2"
shift 2
;;
-h|--help)
echo "Usage: issue-view.sh -i <issue_number>"
echo ""
echo "Options:"
echo " -i, --issue Issue number (required)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$ISSUE_NUMBER" ]]; then
echo "Error: Issue number is required (-i)"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
gh issue view "$ISSUE_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
tea issue "$ISSUE_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,50 @@
#!/bin/bash
# milestone-close.sh - Close a milestone on GitHub or Gitea
# Usage: milestone-close.sh -t <title>
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
TITLE=""
while [[ $# -gt 0 ]]; do
case $1 in
-t|--title)
TITLE="$2"
shift 2
;;
-h|--help)
echo "Usage: milestone-close.sh -t <title>"
echo ""
echo "Options:"
echo " -t, --title Milestone title (required)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$TITLE" ]]; then
echo "Error: Milestone title is required (-t)"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
gh api -X PATCH "/repos/{owner}/{repo}/milestones/$(gh api "/repos/{owner}/{repo}/milestones" --jq ".[] | select(.title==\"$TITLE\") | .number")" -f state=closed
echo "Closed GitHub milestone: $TITLE"
elif [[ "$PLATFORM" == "gitea" ]]; then
tea milestone close "$TITLE"
echo "Closed Gitea milestone: $TITLE"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,117 @@
#!/bin/bash
# milestone-create.sh - Create milestones on Gitea or GitHub
# Usage: milestone-create.sh -t "Title" [-d "Description"] [--due "YYYY-MM-DD"]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Default values
TITLE=""
DESCRIPTION=""
DUE_DATE=""
LIST_ONLY=false
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
Create or list milestones on the current repository (Gitea or GitHub).
Versioning Convention:
- Features get dedicated milestones
- Pre-release: 0.X.0 for breaking changes, 0.X.Y for patches
- Post-release: X.0.0 for breaking changes
- MVP starts at 0.1.0
Options:
-t, --title TITLE Milestone title/version (e.g., "0.2.0")
-d, --desc DESCRIPTION Milestone description
--due DATE Due date (YYYY-MM-DD format)
--list List existing milestones
-h, --help Show this help message
Examples:
$(basename "$0") --list
$(basename "$0") -t "0.1.0" -d "MVP Release"
$(basename "$0") -t "0.2.0" -d "User Authentication Feature" --due "2025-03-01"
EOF
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-t|--title)
TITLE="$2"
shift 2
;;
-d|--desc)
DESCRIPTION="$2"
shift 2
;;
--due)
DUE_DATE="$2"
shift 2
;;
--list)
LIST_ONLY=true
shift
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
PLATFORM=$(detect_platform)
if [[ "$LIST_ONLY" == true ]]; then
case "$PLATFORM" in
github)
gh api repos/:owner/:repo/milestones --jq '.[] | "\(.number)\t\(.title)\t\(.state)\t\(.open_issues)/\(.closed_issues) issues"'
;;
gitea)
tea milestones list
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac
exit 0
fi
if [[ -z "$TITLE" ]]; then
echo "Error: Title is required (-t) for creating milestones" >&2
usage
fi
case "$PLATFORM" in
github)
# GitHub uses the API for milestone creation
JSON_PAYLOAD="{\"title\":\"$TITLE\""
[[ -n "$DESCRIPTION" ]] && JSON_PAYLOAD="$JSON_PAYLOAD,\"description\":\"$DESCRIPTION\""
[[ -n "$DUE_DATE" ]] && JSON_PAYLOAD="$JSON_PAYLOAD,\"due_on\":\"${DUE_DATE}T00:00:00Z\""
JSON_PAYLOAD="$JSON_PAYLOAD}"
gh api repos/:owner/:repo/milestones --method POST --input - <<< "$JSON_PAYLOAD"
echo "Milestone '$TITLE' created successfully"
;;
gitea)
CMD="tea milestones create --title \"$TITLE\""
[[ -n "$DESCRIPTION" ]] && CMD="$CMD --description \"$DESCRIPTION\""
[[ -n "$DUE_DATE" ]] && CMD="$CMD --deadline \"$DUE_DATE\""
eval "$CMD"
echo "Milestone '$TITLE' created successfully"
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,43 @@
#!/bin/bash
# milestone-list.sh - List milestones on GitHub or Gitea
# Usage: milestone-list.sh [-s <state>]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
STATE="open"
while [[ $# -gt 0 ]]; do
case $1 in
-s|--state)
STATE="$2"
shift 2
;;
-h|--help)
echo "Usage: milestone-list.sh [-s <state>]"
echo ""
echo "Options:"
echo " -s, --state Filter by state: open, closed, all (default: open)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
gh api "/repos/{owner}/{repo}/milestones?state=$STATE" --jq '.[] | "\(.title) (\(.state)) - \(.open_issues) open, \(.closed_issues) closed"'
elif [[ "$PLATFORM" == "gitea" ]]; then
tea milestone list
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,62 @@
#!/bin/bash
# pr-close.sh - Close a pull request without merging on GitHub or Gitea
# Usage: pr-close.sh -n <pr_number> [-c <comment>]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
PR_NUMBER=""
COMMENT=""
while [[ $# -gt 0 ]]; do
case $1 in
-n|--number)
PR_NUMBER="$2"
shift 2
;;
-c|--comment)
COMMENT="$2"
shift 2
;;
-h|--help)
echo "Usage: pr-close.sh -n <pr_number> [-c <comment>]"
echo ""
echo "Options:"
echo " -n, --number PR number (required)"
echo " -c, --comment Comment before closing (optional)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$PR_NUMBER" ]]; then
echo "Error: PR number is required (-n)"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
if [[ -n "$COMMENT" ]]; then
gh pr comment "$PR_NUMBER" --body "$COMMENT"
fi
gh pr close "$PR_NUMBER"
echo "Closed GitHub PR #$PR_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
if [[ -n "$COMMENT" ]]; then
tea pr comment "$PR_NUMBER" "$COMMENT"
fi
tea pr close "$PR_NUMBER"
echo "Closed Gitea PR #$PR_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,164 @@
#!/bin/bash
# pr-create.sh - Create pull requests on Gitea or GitHub
# Usage: pr-create.sh -t "Title" [-b "Body"] [-B base] [-H head] [-l "labels"] [-m "milestone"]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Default values
TITLE=""
BODY=""
BASE_BRANCH=""
HEAD_BRANCH=""
LABELS=""
MILESTONE=""
DRAFT=false
ISSUE=""
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
Create a pull request on the current repository (Gitea or GitHub).
Options:
-t, --title TITLE PR title (required, or use --issue)
-b, --body BODY PR description/body
-B, --base BRANCH Base branch to merge into (default: main/master)
-H, --head BRANCH Head branch with changes (default: current branch)
-l, --labels LABELS Comma-separated labels
-m, --milestone NAME Milestone name
-i, --issue NUMBER Link to issue (auto-generates title if not provided)
-d, --draft Create as draft PR
-h, --help Show this help message
Examples:
$(basename "$0") -t "Add login feature" -b "Implements user authentication"
$(basename "$0") -t "Fix bug" -B main -H feature/fix-123
$(basename "$0") -i 42 -b "Implements the feature described in #42"
$(basename "$0") -t "WIP: New feature" --draft
EOF
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-t|--title)
TITLE="$2"
shift 2
;;
-b|--body)
BODY="$2"
shift 2
;;
-B|--base)
BASE_BRANCH="$2"
shift 2
;;
-H|--head)
HEAD_BRANCH="$2"
shift 2
;;
-l|--labels)
LABELS="$2"
shift 2
;;
-m|--milestone)
MILESTONE="$2"
shift 2
;;
-i|--issue)
ISSUE="$2"
shift 2
;;
-d|--draft)
DRAFT=true
shift
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
# If no title but issue provided, generate title
if [[ -z "$TITLE" ]] && [[ -n "$ISSUE" ]]; then
TITLE="Fixes #$ISSUE"
fi
if [[ -z "$TITLE" ]]; then
echo "Error: Title is required (-t) or provide an issue (-i)" >&2
usage
fi
# Default head branch to current branch
if [[ -z "$HEAD_BRANCH" ]]; then
HEAD_BRANCH=$(git branch --show-current)
fi
# Add issue reference to body if provided
if [[ -n "$ISSUE" ]]; then
if [[ -n "$BODY" ]]; then
BODY="$BODY
Fixes #$ISSUE"
else
BODY="Fixes #$ISSUE"
fi
fi
PLATFORM=$(detect_platform)
case "$PLATFORM" in
github)
CMD="gh pr create --title \"$TITLE\""
[[ -n "$BODY" ]] && CMD="$CMD --body \"$BODY\""
[[ -n "$BASE_BRANCH" ]] && CMD="$CMD --base \"$BASE_BRANCH\""
[[ -n "$HEAD_BRANCH" ]] && CMD="$CMD --head \"$HEAD_BRANCH\""
[[ -n "$LABELS" ]] && CMD="$CMD --label \"$LABELS\""
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
[[ "$DRAFT" == true ]] && CMD="$CMD --draft"
eval "$CMD"
;;
gitea)
# tea pull create syntax
CMD="tea pr create --title \"$TITLE\""
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
[[ -n "$BASE_BRANCH" ]] && CMD="$CMD --base \"$BASE_BRANCH\""
[[ -n "$HEAD_BRANCH" ]] && CMD="$CMD --head \"$HEAD_BRANCH\""
# Handle labels for tea
if [[ -n "$LABELS" ]]; then
# tea may use --labels flag
CMD="$CMD --labels \"$LABELS\""
fi
# Handle milestone for tea
if [[ -n "$MILESTONE" ]]; then
MILESTONE_ID=$(tea milestones list 2>/dev/null | grep -E "^\s*[0-9]+" | grep "$MILESTONE" | awk '{print $1}' | head -1)
if [[ -n "$MILESTONE_ID" ]]; then
CMD="$CMD --milestone $MILESTONE_ID"
else
echo "Warning: Could not find milestone '$MILESTONE', creating without milestone" >&2
fi
fi
# Note: tea may not support --draft flag in all versions
if [[ "$DRAFT" == true ]]; then
echo "Note: Draft PR may not be supported by your tea version" >&2
fi
eval "$CMD"
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,93 @@
#!/bin/bash
# pr-list.sh - List pull requests on Gitea or GitHub
# Usage: pr-list.sh [-s state] [-l label] [-a author]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Default values
STATE="open"
LABEL=""
AUTHOR=""
LIMIT=30
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
List pull requests from the current repository (Gitea or GitHub).
Options:
-s, --state STATE Filter by state: open, closed, merged, all (default: open)
-l, --label LABEL Filter by label
-a, --author USER Filter by author
-n, --limit N Maximum PRs to show (default: 30)
-h, --help Show this help message
Examples:
$(basename "$0") # List open PRs
$(basename "$0") -s all # All PRs
$(basename "$0") -s merged -a username # Merged PRs by user
EOF
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-s|--state)
STATE="$2"
shift 2
;;
-l|--label)
LABEL="$2"
shift 2
;;
-a|--author)
AUTHOR="$2"
shift 2
;;
-n|--limit)
LIMIT="$2"
shift 2
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
PLATFORM=$(detect_platform)
case "$PLATFORM" in
github)
CMD="gh pr list --state $STATE --limit $LIMIT"
[[ -n "$LABEL" ]] && CMD="$CMD --label \"$LABEL\""
[[ -n "$AUTHOR" ]] && CMD="$CMD --author \"$AUTHOR\""
eval "$CMD"
;;
gitea)
# tea pr list - note: tea uses 'pulls' subcommand in some versions
CMD="tea pr list --state $STATE --limit $LIMIT"
# tea filtering may be limited
if [[ -n "$LABEL" ]]; then
echo "Note: Label filtering may require manual review for Gitea" >&2
fi
if [[ -n "$AUTHOR" ]]; then
echo "Note: Author filtering may require manual review for Gitea" >&2
fi
eval "$CMD"
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,110 @@
#!/bin/bash
# pr-merge.sh - Merge pull requests on Gitea or GitHub
# Usage: pr-merge.sh -n PR_NUMBER [-m method] [-d]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Default values
PR_NUMBER=""
MERGE_METHOD="merge" # merge, squash, rebase
DELETE_BRANCH=false
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
Merge a pull request on the current repository (Gitea or GitHub).
Options:
-n, --number NUMBER PR number to merge (required)
-m, --method METHOD Merge method: merge, squash, rebase (default: merge)
-d, --delete-branch Delete the head branch after merge
-h, --help Show this help message
Examples:
$(basename "$0") -n 42 # Merge PR #42
$(basename "$0") -n 42 -m squash # Squash merge
$(basename "$0") -n 42 -m rebase -d # Rebase and delete branch
EOF
exit 1
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-n|--number)
PR_NUMBER="$2"
shift 2
;;
-m|--method)
MERGE_METHOD="$2"
shift 2
;;
-d|--delete-branch)
DELETE_BRANCH=true
shift
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $1" >&2
usage
;;
esac
done
if [[ -z "$PR_NUMBER" ]]; then
echo "Error: PR number is required (-n)" >&2
usage
fi
PLATFORM=$(detect_platform)
case "$PLATFORM" in
github)
CMD="gh pr merge $PR_NUMBER"
case "$MERGE_METHOD" in
merge) CMD="$CMD --merge" ;;
squash) CMD="$CMD --squash" ;;
rebase) CMD="$CMD --rebase" ;;
*)
echo "Error: Invalid merge method '$MERGE_METHOD'" >&2
exit 1
;;
esac
[[ "$DELETE_BRANCH" == true ]] && CMD="$CMD --delete-branch"
eval "$CMD"
;;
gitea)
# tea pr merge syntax
CMD="tea pr merge $PR_NUMBER"
# tea merge style flags
case "$MERGE_METHOD" in
merge) CMD="$CMD --style merge" ;;
squash) CMD="$CMD --style squash" ;;
rebase) CMD="$CMD --style rebase" ;;
*)
echo "Error: Invalid merge method '$MERGE_METHOD'" >&2
exit 1
;;
esac
# Delete branch after merge if requested
if [[ "$DELETE_BRANCH" == true ]]; then
echo "Note: Branch deletion after merge may need to be done separately with tea" >&2
fi
eval "$CMD"
;;
*)
echo "Error: Could not detect git platform" >&2
exit 1
;;
esac
echo "PR #$PR_NUMBER merged successfully"

View File

@@ -0,0 +1,115 @@
#!/bin/bash
# pr-review.sh - Review a pull request on GitHub or Gitea
# Usage: pr-review.sh -n <pr_number> -a <action> [-c <comment>]
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
PR_NUMBER=""
ACTION=""
COMMENT=""
while [[ $# -gt 0 ]]; do
case $1 in
-n|--number)
PR_NUMBER="$2"
shift 2
;;
-a|--action)
ACTION="$2"
shift 2
;;
-c|--comment)
COMMENT="$2"
shift 2
;;
-h|--help)
echo "Usage: pr-review.sh -n <pr_number> -a <action> [-c <comment>]"
echo ""
echo "Options:"
echo " -n, --number PR number (required)"
echo " -a, --action Review action: approve, request-changes, comment (required)"
echo " -c, --comment Review comment (required for request-changes)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$PR_NUMBER" ]]; then
echo "Error: PR number is required (-n)"
exit 1
fi
if [[ -z "$ACTION" ]]; then
echo "Error: Action is required (-a): approve, request-changes, comment"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
case $ACTION in
approve)
gh pr review "$PR_NUMBER" --approve ${COMMENT:+--body "$COMMENT"}
echo "Approved GitHub PR #$PR_NUMBER"
;;
request-changes)
if [[ -z "$COMMENT" ]]; then
echo "Error: Comment required for request-changes"
exit 1
fi
gh pr review "$PR_NUMBER" --request-changes --body "$COMMENT"
echo "Requested changes on GitHub PR #$PR_NUMBER"
;;
comment)
if [[ -z "$COMMENT" ]]; then
echo "Error: Comment required"
exit 1
fi
gh pr review "$PR_NUMBER" --comment --body "$COMMENT"
echo "Added review comment to GitHub PR #$PR_NUMBER"
;;
*)
echo "Error: Unknown action: $ACTION"
exit 1
;;
esac
elif [[ "$PLATFORM" == "gitea" ]]; then
case $ACTION in
approve)
tea pr approve "$PR_NUMBER" ${COMMENT:+--comment "$COMMENT"}
echo "Approved Gitea PR #$PR_NUMBER"
;;
request-changes)
if [[ -z "$COMMENT" ]]; then
echo "Error: Comment required for request-changes"
exit 1
fi
tea pr reject "$PR_NUMBER" --comment "$COMMENT"
echo "Requested changes on Gitea PR #$PR_NUMBER"
;;
comment)
if [[ -z "$COMMENT" ]]; then
echo "Error: Comment required"
exit 1
fi
tea pr comment "$PR_NUMBER" "$COMMENT"
echo "Added comment to Gitea PR #$PR_NUMBER"
;;
*)
echo "Error: Unknown action: $ACTION"
exit 1
;;
esac
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# pr-view.sh - View pull request details on GitHub or Gitea
# Usage: pr-view.sh -n <pr_number>
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/detect-platform.sh"
# Parse arguments
PR_NUMBER=""
while [[ $# -gt 0 ]]; do
case $1 in
-n|--number)
PR_NUMBER="$2"
shift 2
;;
-h|--help)
echo "Usage: pr-view.sh -n <pr_number>"
echo ""
echo "Options:"
echo " -n, --number PR number (required)"
echo " -h, --help Show this help"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$PR_NUMBER" ]]; then
echo "Error: PR number is required (-n)"
exit 1
fi
detect_platform
if [[ "$PLATFORM" == "github" ]]; then
gh pr view "$PR_NUMBER"
elif [[ "$PLATFORM" == "gitea" ]]; then
tea pr "$PR_NUMBER"
else
echo "Error: Unknown platform"
exit 1
fi

View File

@@ -0,0 +1,44 @@
{
"name": "@mosaic/cli-tools",
"version": "0.0.1",
"description": "CLI tools for Mosaic Stack orchestration - git operations for Gitea/GitHub",
"private": true,
"bin": {
"mosaic-detect-platform": "./bin/detect-platform.sh",
"mosaic-issue-assign": "./bin/issue-assign.sh",
"mosaic-issue-close": "./bin/issue-close.sh",
"mosaic-issue-comment": "./bin/issue-comment.sh",
"mosaic-issue-create": "./bin/issue-create.sh",
"mosaic-issue-edit": "./bin/issue-edit.sh",
"mosaic-issue-list": "./bin/issue-list.sh",
"mosaic-issue-reopen": "./bin/issue-reopen.sh",
"mosaic-issue-view": "./bin/issue-view.sh",
"mosaic-milestone-close": "./bin/milestone-close.sh",
"mosaic-milestone-create": "./bin/milestone-create.sh",
"mosaic-milestone-list": "./bin/milestone-list.sh",
"mosaic-pr-close": "./bin/pr-close.sh",
"mosaic-pr-create": "./bin/pr-create.sh",
"mosaic-pr-list": "./bin/pr-list.sh",
"mosaic-pr-merge": "./bin/pr-merge.sh",
"mosaic-pr-review": "./bin/pr-review.sh",
"mosaic-pr-view": "./bin/pr-view.sh"
},
"scripts": {
"lint": "shellcheck bin/*.sh || true",
"test": "echo 'No tests yet'"
},
"keywords": [
"cli",
"git",
"gitea",
"github",
"orchestration"
],
"engines": {
"node": ">=18"
},
"os": [
"linux",
"darwin"
]
}