Skip to content

Phase 1: Create monorepo structure with git history#7

Merged
rianjs merged 142 commits intomainfrom
feature/monorepo-structure
Jan 29, 2026
Merged

Phase 1: Create monorepo structure with git history#7
rianjs merged 142 commits intomainfrom
feature/monorepo-structure

Conversation

@rianjs
Copy link
Copy Markdown
Contributor

@rianjs rianjs commented Jan 29, 2026

Summary

  • Import confluence-cli (cfl) and jira-ticket-cli (jtk) into monorepo using git subtrees
  • Preserve full git history from both source repositories (142 commits total)
  • Create Go workspace (go.work) for unified development
  • Add root CLAUDE.md documenting the monorepo structure

Verification

All acceptance criteria from the issue have been verified:

  • git log --oneline shows both repos' history (142 commits)
  • go work sync succeeds
  • go build ./tools/cfl/cmd/cfl produces working binary
  • go build ./tools/jtk/cmd/jtk produces working binary
  • go test ./tools/cfl/... passes
  • go test ./tools/jtk/... passes

Test plan

  • Verify builds work: go build ./tools/cfl/cmd/cfl && go build ./tools/jtk/cmd/jtk
  • Verify tests pass: go test ./tools/cfl/... && go test ./tools/jtk/...
  • Verify history preserved: git log --oneline | wc -l shows 142+ commits

Closes #1

rianjs and others added 30 commits January 2, 2026 06:54
- Fix silent errors by printing error message before exit in main.go
- Add comprehensive Command Reference section to README with all flags
- Update .gitignore to exclude bin/ and dist/ directories

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add bare binary name (cfl) to prevent accidental commits
- Add debug files (*.dSYM/, __debug_bin*)
- Add temporary files (*.tmp, *.bak, *.swp, *~)
- Add OS files (.DS_Store, Thumbs.db)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add goldmark library for markdown-to-HTML conversion
- Create pkg/md/converter.go with ToConfluenceStorage function
- Add comprehensive test suite for markdown conversion (19 tests)
- Update page create command with --no-markdown flag
- Auto-detect format by file extension (.md → markdown, .html → XHTML)
- Default to markdown for stdin and editor input
- Update README with markdown documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix gofmt formatting in api/pages.go, api/types.go, internal/cmd/space/list.go
- Replace deprecated filepath.HasPrefix with strings.HasPrefix in config_test.go
- Add explicit ignore for cmd.MarkFlagRequired error in create.go

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add html-to-markdown library for HTML → Markdown conversion
- Create FromConfluenceStorage function with comprehensive test suite
- Update page view to display content as markdown by default
- Use --raw flag to see original Confluence storage format (XHTML)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 'cfl page delete <page-id>' command
- Confirmation prompt before deletion (use --force to skip)
- Shows page title before deletion for verification
- Supports JSON output format

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 'cfl attachment list --page <id>' to list attachments
- Add 'cfl attachment upload --page <id> --file <path>' to upload files
- Add 'cfl attachment download <id>' to download attachments
- Support JSON output and custom output file paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add page delete command documentation
- Add attachment list/upload/download commands documentation
- Update page view to note markdown output is default
- Update features list with new capabilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Uses homebrew_casks instead of brews (formulas) with a post-install
hook that removes the quarantine attribute for unsigned binaries.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- BUG-006 (CRITICAL): Change --output-file shorthand from -o to -O to
  avoid conflict with global --output flag in attachment download
- BUG-003 (HIGH): Move pagination message to stderr to keep stdout clean
  for JSON piping
- BUG-001/002 (MEDIUM): Add limit validation - negative values error,
  zero returns empty list
- BUG-004 (LOW): Add output format validation with helpful error message
- BUG-005 (LOW): Strip Confluence macros from markdown output by default,
  add --show-macros flag to opt-in to placeholders like [TOC]
* Fix flag collision in attachment upload command

The -c shorthand was used for both the global --config flag and the
local --comment flag, causing a panic when the upload subcommand was
invoked.

Changed the comment flag shorthand from -c to -m (for message) to
avoid the collision.

* Add page edit command

Adds the ability to edit existing Confluence pages:
- Edit page content from file, stdin, or interactive editor
- Update page title without changing content
- Maintains markdown-first approach like page create

Also updates README documentation for the new command and fixes
the attachment upload comment flag documentation (-m instead of -c).

* Fix unchecked error returns in list commands
Update .golangci.yml for golangci-lint v2 format and fix all lint issues:
- Move gofmt/goimports to formatters section
- Fix unchecked error returns (errcheck) with _ assignments
- Fix unused parameters by renaming to _
- Add missing package comments

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fix: resolve golangci-lint v2 issues
Migrate from deprecated allowedTools format to permissions.allow/deny.
Add Go ecosystem tools (go, golangci-lint, goimports, make, goreleaser),
git/gh commands, and documentation domains (go.dev, Atlassian docs).
Deny destructive operations like git rebase and production releases.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merge the separate test and build jobs into a single build job
for faster CI runs. The lint job remains separate.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
fix: pin golangci-lint to v2 in CI
Attachment filenames from the Confluence API were being used directly
as output paths without sanitization. A malicious filename containing
path traversal sequences (e.g., ../../../etc/passwd) could write files
outside the intended directory.

Now uses filepath.Base() to extract only the base filename, stripping
any directory components. Also validates that the resulting filename
is not empty, ".", or "..".

Adds unit tests to verify path traversal attack vectors are properly
sanitized.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, attachment downloads would silently overwrite existing files
using os.Create(). This could lead to accidental data loss.

Now the download command checks if the output file already exists and
returns an error with a helpful message. Users can use --force (-f) to
explicitly allow overwriting.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix attachment download security and usability issues
Adds `cfl attachment delete <id>` command with confirmation prompt.
Use --force (-f) to skip confirmation.

- Add DeleteAttachment method to API layer
- Create delete command following page delete pattern
- Register command in attachment.go
- Document in README.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add API layer tests for DeleteAttachment (success, not found)
- Refactor delete.go to inject stdin for testability
- Add command layer tests covering:
  - Force delete (skips prompt)
  - Confirm with 'y' / 'Y' (deletes)
  - Cancel with 'n' / empty / other (cancelled)
  - GetAttachment fails (error before prompt)
  - DeleteAttachment fails (error after confirm)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Separate internal package imports from external package imports
per golangci-lint goimports requirements.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add attachment delete command
Add `cfl page copy` command to duplicate Confluence pages using the
native v1 REST API copy endpoint (POST /rest/api/content/{id}/copy).

Features:
- Copy page with new title (required)
- Copy to different space with --space flag
- Skip attachments with --no-attachments flag
- Skip labels with --no-labels flag
- Infers source space if destination not specified

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
rianjs and others added 28 commits January 18, 2026 07:26
## Summary
Create CLAUDE.md with:
- Project overview
- Quick build/test commands
- Architecture overview
- Key patterns (Options struct, Register, View)
- Commit conventions with release trigger table
- CI & Release Workflow section

Closes #14

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary

- Adds `comments delete` command to remove comments from issues
- Usage: `jira-ticket-cli comments delete <issue-key> <comment-id>`

## Test plan

- [x] Tested locally with real Jira instance
- [x] Build passes
## [#18]

## Summary

- Adds a markdown-to-ADF converter that properly transforms markdown
syntax into Atlassian Document Format
- Supports headings (h1-h6), bold, italic, strikethrough, inline code,
fenced code blocks with language hints, bullet lists, numbered lists,
nested lists, links, blockquotes, horizontal rules, tables, and hard
line breaks
- `NewADFDocument()` now parses markdown instead of wrapping text in a
single paragraph

## Problem

The CLI was sending plain text descriptions to Jira's REST API v3, which
expects Atlassian Document Format (ADF). This caused markdown formatting
like `## Heading` or ` ```code``` ` to appear as literal text instead of
being rendered properly.

## Solution

Uses the [goldmark](https://github.com/yuin/goldmark) library with table
and strikethrough extensions to parse markdown and convert it to the ADF
JSON structure that Jira expects.

## Test plan

- [x] Unit tests for all supported markdown elements
- [x] Integration test with complex multi-element documents  
- [x] Verified JSON output matches Jira's expected ADF schema
- [x] Comprehensive tests adapted from confluence-cli
- [x] Manual testing with `jira-ticket-cli issues create`

Fixes #18
…#22)

## Summary

Adds a new `issues types` command to list valid issue types for a
project.

- Helps users discover available issue types before creating tickets
- Uses existing `GetProject` API which returns issue types
- Supports table and JSON output formats

**Usage:**
```
jira-ticket-cli issues types --project MYPROJ
jira-ticket-cli issues types -p MYPROJ -o json
```

**Example output:**
```
ID      NAME    SUBTASK  DESCRIPTION
10001   Bug     no       A problem which impairs product functionality
10002   Task    no       A small unit of work
10003   Story   no       A user story
```

Closes #17

## Test plan

- [x] Build passes
- [x] All existing tests pass
- [x] `go vet` passes
- [x] Manual test with real Jira project
## Summary

Migrate Go module path and all imports from
`github.com/piekstra/jira-ticket-cli` to
`github.com/open-cli-collective/jira-ticket-cli` to reflect the
repository's new organization home.

## Changes

- **go.mod**: Updated module declaration
- **Build config**: Updated Makefile, .goreleaser.yml, .golangci.yml
- **Go source files**: Updated all import statements (27 files)
- **Documentation**: Updated CLAUDE.md, README.md

## Test Plan

- [x] `go mod tidy` succeeds
- [x] `make build` succeeds
- [x] `make test` passes (all 85 tests)
- [x] `make lint` passes (0 issues)
- [x] No piekstra references remaining in codebase

Closes #38
## Summary
- **Number fields (#25)**: Convert numeric values to `float64` instead
of sending as strings, fixing API rejection errors like "Specify a
number for the custom field"
- **Textarea fields (#28)**: Automatically convert textarea/paragraph
custom field values to Atlassian Document Format (ADF), fixing API
errors requiring ADF format

## Changes
- Added `api.FormatFieldValue()` as a shared function for consistent
field formatting across commands
- Extended field type detection to handle:
  - `number` schema type → converts to `float64`
- Textarea custom type
(`com.atlassian.jira.plugin.system.customfieldtypes:textarea`) →
converts to ADF
- Applied field formatting to `issues update` command (was previously
missing)
- Moved tests from transitions package to api package

## Test plan
- [x] All existing tests pass
- [x] Added tests for number field conversion (integer, decimal,
invalid)
- [x] Added test for textarea field ADF conversion
- [ ] Manual testing with real Jira instance recommended

Closes #25, #28
)

## Summary
Show the user's display name (e.g., "John Smith") instead of their
opaque account ID (e.g., "5b10ac8d82e05b22cc7d4ef5") in the success
message when assigning an issue.

Before:
```
✓ Assigned issue PROJ-123 to 5b10ac8d82e05b22cc7d4ef5
```

After:
```
✓ Assigned issue PROJ-123 to John Smith
```

## Changes
- Added `api.GetUser(accountID)` function to look up user details by
account ID
- Updated assign command to fetch and display the user's display name
- Falls back gracefully to account ID if the lookup fails

## Test plan
- [x] All existing tests pass
- [x] Added tests for GetUser, GetCurrentUser, and SearchUsers API
functions
- [ ] Manual testing with real Jira instance recommended

Closes #24
## Summary
Add a new `users search` command to search for Jira users by name,
email, or username. This makes it easier to find account IDs needed for
issue assignment.

## Usage
```bash
# Search for users named "john"
jira-ticket-cli users search john

# Output
ACCOUNT_ID                    NAME           EMAIL                  ACTIVE
5b10ac8d82e05b22cc7d4ef5      John Smith     john@example.com       yes

# Get results as JSON
jira-ticket-cli users search john -o json

# Limit results
jira-ticket-cli users search john --max 5
```

## Changes
- Added new `users` command with `search` subcommand
- Leverages existing `SearchUsers` API function
- Supports table, JSON, and plain output formats
- Configurable max results (default: 10)

## Test plan
- [x] All existing tests pass
- [x] Verified command help output
- [ ] Manual testing with real Jira instance recommended

Closes #23
Closes #26

Adds a `--fields` flag to the `transitions list` command that displays
required fields for each transition. This helps users understand what
fields they need to provide when performing a transition.

## Changes

- Added `--fields` flag to `transitions list` command
- Added `GetTransitionsWithFields` API method that uses
`expand=transitions.fields` parameter
- Added `TransitionField` and `FieldOption` types for field metadata
- Display required fields in a "REQUIRED FIELDS" column when `--fields`
is specified

## Usage

```bash
# List transitions with required fields
jira-ticket-cli transitions list PROJ-123 --fields
```

Example output:
```
ID   NAME         TO STATUS     REQUIRED FIELDS
11   To Do        To Do         -
21   In Progress  In Progress   -
31   Done         Done          Resolution
```

## Test plan
- [x] Added unit tests for `GetTransitionsWithFields`
- [x] Added unit tests for `getRequiredFields` helper
- [x] Verified all tests pass
Closes #27

Adds a new `field-options` command that displays allowed values for
option/select fields. This makes it easier to know what values are valid
when setting fields during issue creation, updates, or transitions.

## Changes

- Added `field-options` command under `issues` subcommand
- Added `GetFieldOptionsFromEditMeta` API method to fetch allowed values
from issue edit metadata
- Added `FieldOptionValue` type for option values
- Field names can be resolved to IDs automatically

## Usage

```bash
# List options for a field using issue context (recommended)
jira-ticket-cli issues field-options "Priority" --issue PROJ-123

# List options using field ID
jira-ticket-cli issues field-options customfield_10001 --issue PROJ-123
```

Example output:
```
Allowed values for field 'Priority':
VALUE    ID
Highest  1
High     2
Medium   3
Low      4
Lowest   5
```

## Test plan
- [x] Added unit tests for `GetFieldOptionsFromEditMeta`
- [x] Verified all tests pass
Closes #29

Custom fields (e.g., `customfield_10001`, Story Points, Sprint, etc.)
are now preserved when fetching and serializing issues. This enables
users to inspect custom field values when using JSON output.

## Changes

- Modified `IssueFields` struct to capture custom fields during
unmarshaling
- Added custom `UnmarshalJSON` and `MarshalJSON` methods to handle
custom fields
- Custom fields are stored in a `CustomFields map[string]interface{}`
field
- Fields are automatically included in JSON output alongside standard
fields

## Usage

```bash
# Custom fields are now automatically included in JSON output
jira-ticket-cli issues get PROJ-123 -o json | jq '.fields | keys'
```

Now shows custom fields like:
```json
["assignee", "created", "customfield_10001", "customfield_10002", "description", "issuetype", "priority", "project", "reporter", "status", "summary", "updated"]
```

## Test plan
- [x] Added unit tests for custom fields unmarshaling
- [x] Added unit tests for custom fields marshaling
- [x] Added round-trip test to verify custom fields are preserved
- [x] Verified all existing tests pass
## Summary

Rename the CLI binary from `jira-ticket-cli` to `jtk` following the
ripgrep pattern (descriptive package name, short binary name for daily
use).

### Changes
- **Binary**: `jira-ticket-cli` → `jtk`
- **Archive names**: `jira-ticket-cli_...` → `jtk_...`
- **Package name**: unchanged (`jira-ticket-cli`)

### Distribution Updates
- **Homebrew**: Cask installs `jtk` binary
- **Chocolatey**: Package installs `jtk.exe`
- **Winget**: PortableCommandAlias set to `jtk`, download URLs updated

### Additional
- Adds `test-chocolatey.yml` workflow for Windows package testing

## Test Plan
- [x] `make build` passes
- [x] `make test` passes
- [x] `make lint` passes
- [x] `goreleaser release --snapshot --skip=publish --clean` builds all
platforms with correct archive names

Closes #40

🤖 Generated with [Claude Code](https://claude.ai/code)
* feat: add .deb and .rpm package generation via nfpms

Configure GoReleaser to generate Linux packages for direct download.
Users can install via:

  # Debian/Ubuntu
  sudo dpkg -i cfl_<version>_linux_amd64.deb

  # Fedora/RHEL
  sudo rpm -i cfl-<version>.x86_64.rpm

Part of #95

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add Snap package support

Add snapcraft.yaml for publishing to the Snapcraft Store.

Configuration:
- Strict confinement (no classic approval needed)
- Interfaces: home, network, personal-files (~/.config/cfl)
- Builds from source with Go 1.24
- Architectures: amd64, arm64

Users will install via:
  snap install cfl

Prerequisites for publishing:
- Snapcraft Store account
- Register 'cfl' snap name
- Add SNAPCRAFT_STORE_CREDENTIALS secret

Part of #95

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: add Snap and linux-packages publishing to release workflow

Add two new jobs to the release workflow:

1. snap: Builds and publishes to Snapcraft Store
   - Requires SNAPCRAFT_STORE_CREDENTIALS secret

2. linux-packages: Triggers the org-level linux-packages repo
   - Dispatches package-release event with version info
   - Requires LINUX_PACKAGES_DISPATCH_TOKEN secret
   - linux-packages repo will update APT/RPM repositories

Both jobs run in parallel after goreleaser completes.

Part of #95

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: rename snap to ocli-confluence

The 'cfl' snap name was already taken on the Snapcraft Store.
Registered as 'ocli-confluence' instead.

Users install with: snap install ocli-confluence
Command is still 'cfl' via alias.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* docs: reorganize installation section by platform

- Group installation methods by macOS, Windows, Linux
- Add Snap, APT, and RPM instructions for Linux
- Note that Homebrew tap and APT/RPM repos are third-party (not official)
- Add direct .deb/.rpm download examples
- Move "Go install" to "From Source" section

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
Update all documentation and code examples to reference the new `jtk`
binary name instead of `jira-ticket-cli`.

## Changes
- **Issue templates**: version check commands and example usage
- **Cobra Example fields**: all cmd packages updated via bulk
replacement
- **Shell completion**: script paths and examples in completion.go
- **README.md**: completion file paths (e.g., `_jtk`, `jtk.fish`)
- **CONTRIBUTING.md**: build/run examples and directory structure
- **Chocolatey**: uninstall user messages

Closes #40
## Summary
Update CHANGELOG to document recent changes including:

- Binary rename to `jtk`
- Module path migration to open-cli-collective
- New commands: `field-options`, `types`, `users search`
- Required fields shown for transitions
- Custom fields in JSON output
- Bug fixes for field formatting and display

All entries reference their associated PRs.
- Chocolatey: v0.9.9 still pending moderation approval
- Snap: waiting for personal-files interface approval

Both jobs will be re-enabled once respective approvals are received.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Make APT the recommended installation method (it's working)
- Simplify APT instructions for clarity
- Note Snap is pending store approval

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Summary

Add Linux distribution support for jira-ticket-cli, enabling users to
install via:
- **Snap Store** (as `ocli-jira`, aliased to `jtk`)
- **APT** (Debian/Ubuntu) via open-cli-collective linux-packages repo
- **DNF/YUM** (Fedora/RHEL/CentOS) via open-cli-collective
linux-packages repo
- **Direct download** of `.deb` and `.rpm` packages from GitHub Releases

## Changes

- **`.goreleaser.yml`**: Added `nfpms` section to generate `.deb` and
`.rpm` packages
- **`snap/snapcraft.yaml`**: New file for Snap package definition with:
  - `personal-files` interface for `~/.config/jira-ticket-cli` access
  - Go 1.24 build with version ldflags
- **`.github/workflows/release.yml`**: Added two new jobs:
- `snap`: Build and publish to Snap Store (disabled with `if: false`
pending personal-files interface approval)
- `linux-packages`: Trigger APT/RPM repo update via repository dispatch
- **`README.md`**: Comprehensive Linux installation instructions

## Required Secrets (to be added before release)

| Secret | Purpose |
|--------|---------|
| `SNAPCRAFT_STORE_CREDENTIALS` | Publish to Snap Store |
| `LINUX_PACKAGES_DISPATCH_TOKEN` | Trigger linux-packages workflow |

## Notes

- Snap job is disabled (`if: false`) pending personal-files interface
approval from Canonical, matching the pattern from confluence-cli
- Uses `ocli-jira` as snap name (following `ocli-confluence` pattern)
with `jtk` alias

## Test Plan

- [x] `goreleaser check` passes
- [x] `make build` succeeds
- [x] `make test` passes
- [x] `make lint` passes
- [ ] After merge: Verify `.deb`/`.rpm` packages appear in GitHub
Release
- [ ] After secrets configured: Verify linux-packages dispatch triggers

Closes #44
Removes the `if: false` condition from the snap job so it will run on
the next release.

The snap will be built and uploaded to the Snapcraft store.
Personal-files interface approval is still pending, but having the snap
in the store is required to request the interface.

Closes #46
## Summary
- Add explicit `dpkg -i` and `rpm -i` install commands to the Binary
download section
- Matches the documentation format used in confluence-cli

Fixes #48

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Add TAG env var to snap job
- Checkout at tag ref so git describe finds the version

Fixes #50
The snap job was not checking out at the tag ref, causing git describe
to fail to find tags. This resulted in snap packages being built with
version 0+git.<hash> instead of the actual release version.

Fixes #97
## Summary

- Replace `--domain` flag with `--url` in config set command for
self-hosted Jira support
- Add `JIRA_URL` environment variable (replaces deprecated
`JIRA_DOMAIN`)
- Maintain backwards compatibility with legacy `domain` config and
`JIRA_DOMAIN` env var

## Changes

**Config (`internal/config/`):**
- Add `URL` field to Config struct
- Add `GetURL()` function with fallback to legacy domain
- Add `NormalizeURL()` helper for scheme/trailing slash handling

**API Client (`api/`):**
- Change `ClientConfig` to use `URL` instead of `Domain`
- Rename `ErrDomainRequired` to `ErrURLRequired`
- Update `IssueURL()` to use base URL directly

**Commands (`internal/cmd/configcmd/`):**
- Replace `--domain` flag with `--url`
- Update help text and examples for both Cloud and self-hosted

**Documentation:**
- Update README.md with new config examples
- Update CLAUDE.md with new environment variables

## Examples

```bash
# Jira Cloud
jtk config set --url https://mycompany.atlassian.net --email user@example.com --token TOKEN

# Self-hosted Jira
jtk config set --url https://jira.internal.corp.com --email user@example.com --token TOKEN
```

## Backwards Compatibility

Existing configs and env vars continue to work:
- `domain` field in config file → constructs URL automatically
- `JIRA_DOMAIN` env var → constructs URL automatically
- Show deprecation indicators in `config show` output

## Test Plan

- [x] Build passes
- [x] All existing tests pass
- [x] New tests for URL normalization and backwards compat
- [x] Lint passes

Closes #52
## Summary

- Add `ATLASSIAN_URL`, `ATLASSIAN_EMAIL`, `ATLASSIAN_API_TOKEN` env var
fallbacks
- Enables shared credentials between jtk (Jira) and cfl (Confluence)
CLIs
- Tool-specific vars (`JIRA_*`) take precedence over shared vars
(`ATLASSIAN_*`)

## Precedence Order

| Setting | Lookup Order |
|---------|-------------|
| URL | `JIRA_URL` → `ATLASSIAN_URL` → config → `JIRA_DOMAIN` (legacy) |
| Email | `JIRA_EMAIL` → `ATLASSIAN_EMAIL` → config |
| Token | `JIRA_API_TOKEN` → `ATLASSIAN_API_TOKEN` → config |

## Usage

**Shared credentials (both tools):**
```bash
export ATLASSIAN_URL=https://mycompany.atlassian.net
export ATLASSIAN_EMAIL=user@example.com
export ATLASSIAN_API_TOKEN=your-token
```

**Per-tool override:**
```bash
export ATLASSIAN_EMAIL=user@example.com
export ATLASSIAN_API_TOKEN=your-token
export JIRA_URL=https://jira.internal.corp.com  # Different URL for Jira only
```

## Changes

- `internal/config/config.go`: Add ATLASSIAN_* checks in Get* functions
- `internal/cmd/configcmd/configcmd.go`: Show ATLASSIAN_* sources in
`config show`
- `internal/config/config_test.go`: Add tests for fallback behavior and
precedence
- `README.md`, `CLAUDE.md`: Document new env vars

## Test Plan

- [x] Build passes
- [x] All tests pass (including new ATLASSIAN_* tests)
- [x] Lint passes

Closes #54
Add support for shared ATLASSIAN_* environment variables that work
across both cfl (Confluence) and jtk (Jira) CLIs.

Precedence order (first match wins):
- URL: CFL_URL → ATLASSIAN_URL → config
- Email: CFL_EMAIL → ATLASSIAN_EMAIL → config
- Token: CFL_API_TOKEN → ATLASSIAN_API_TOKEN → config

This allows users to set credentials once for both tools:
  export ATLASSIAN_URL=https://mycompany.atlassian.net
  export ATLASSIAN_EMAIL=user@example.com
  export ATLASSIAN_API_TOKEN=token

While still allowing per-tool overrides when needed.

Closes #99
git-subtree-dir: tools/cfl
git-subtree-mainline: 7dc18a3
git-subtree-split: 873c329
git-subtree-dir: tools/jtk
git-subtree-mainline: df492ab
git-subtree-split: 03a10b5
- Add confluence-cli as git subtree under tools/cfl
- Add jira-ticket-cli as git subtree under tools/jtk
- Create go.work for Go workspace management
- Add root CLAUDE.md documenting monorepo structure
- Add .gitignore for build artifacts

Closes #1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Phase 1: Create monorepo structure with git history

2 participants