commits
Add src/lexicon to biome ignore list since these files are
auto-generated by @atproto/lex-cli and should not be linted
or formatted.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add the base issue command structure with create subcommand:
- Command accepts title argument and optional body via --body or --body-file
- Validates authentication and repository context
- Builds AT-URI and creates issue record via AT Protocol
- Displays success message with issue number (rkey) and URI
- Comprehensive tests covering all input methods and error cases
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This pipeline runs on every push to any branch and ensures:
- Code follows linting standards (Biome)
- TypeScript compilation succeeds
- All tests pass
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements comprehensive issue management via AT Protocol:
- createIssue(): Create new issues with title and optional body
- listIssues(): List and filter issues by repository
- getIssue(): Retrieve specific issue details
- updateIssue(): Update issue title and/or body with atomic CID swap
- closeIssue(): Mark issue as closed via state record
- deleteIssue(): Permanently delete an issue
Features:
- Uses generated lexicon types (IssueRecord) for type safety
- Uses requireAuth() helper for authentication validation
- Uses parseIssueUri() internal helper to eliminate duplication
- Clear error messages with context
- Repository filtering in list operations
- Ownership verification for update/delete
Includes comprehensive test coverage (23 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added src/lexicon/**/* to exclude list in tsconfig.json to skip
type checking generated code. The generated code has compatibility
issues but we only need to import type definitions from it.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extracts duplicated auth validation logic into reusable utility:
- requireAuth(): Validates client is authenticated and has active session
- Throws clear error messages if not authenticated
- Returns session with DID and handle
This helper will be used across all API operations that require
authentication, ensuring consistent error messages and reducing
code duplication.
Includes test coverage (3 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Supports multiple input methods following GitHub CLI patterns:
- Direct string input via --body flag
- File input via --body-file <path>
- Stdin input via --body-file - (tested via integration tests)
Features:
- Validates that only one input method is used
- Handles empty strings correctly
- Clear error messages for file not found, permission denied, etc.
Includes comprehensive test coverage (12 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
New utilities:
- parseAtUri(): Parse AT-URI into components (did, collection, rkey)
- resolveHandleToDid(): Resolve handle to DID via AT Protocol
- buildRepoAtUri(): Construct repository AT-URI from owner and repo name
New validation schemas:
- issueTitleSchema: 1-256 characters
- issueBodySchema: Optional, max 50,000 characters
- atUriSchema: Validate AT-URI format
Includes comprehensive test coverage (45 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Generated type-safe client code from vendored lexicons using @atproto/lex-cli.
Includes type definitions for:
- Issue management (sh.tangled.repo.issue)
- Pull requests (sh.tangled.repo.pull)
- Repository operations
- All Tangled-specific record types
Note: Generated code committed to version control for:
- Reviewability in PRs
- No build step required for type checking
- Offline development support
We'll use the type definitions (interfaces) for type safety while calling
AT Protocol APIs directly via @atproto/api to avoid module resolution issues
with the generated client methods.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Install @atproto/lex-cli for generating TypeScript types from lexicons
- Add npm scripts:
- codegen: Generate TS client API from lexicons
- update-lexicons: Update vendored lexicons from tangled.org
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Downloaded AT Protocol lexicon definitions for Tangled.org service:
- Issue management (issue, comment, state)
- Pull requests (pull, comment, state)
- Repository operations (repo, branch, tag, blob, tree, etc.)
- Labels, pipelines, and other Tangled-specific types
Source: https://tangled.org/tangled.org/core/raw/master/lexicons/
Last updated: 2026-02-09
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add scripts/update-lexicons.sh for downloading lexicons from tangled.org
- Add lexicons/README.md documenting source, structure, and update process
- Script downloads all Tangled lexicons over HTTPS from official repo
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add mandatory coding guidelines section to prevent common mistakes:
- ALL validation functions must go in src/utils/validation.ts
- ALL code requires comprehensive test coverage
- Include examples and PR checklist
This ensures consistency and prevents validation functions from
being scattered across the codebase.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add the new config and context commands to the main CLI program:
- tangled config: Manage CLI configuration
- tangled context: Debug repository context resolution
These commands are now accessible through the CLI.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement context debug command to help users understand repository
context resolution:
- Shows if current directory is a Tangled repository
- Displays owner (DID or handle), repository name, protocol
- Shows which Git remote is being used
- Provides helpful error messages when not in a Tangled repo
This is a debug/diagnostic tool that helps users verify their
context resolution is working correctly.
Includes comprehensive test coverage (4 tests) for success and
error cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement generic config management command:
- tangled config list: List all available config keys with descriptions
- tangled config get [key]: View current configuration (all or specific)
- tangled config set <key> <value> [--global]: Set any config value
- tangled config unset <key> [--global]: Clear any config value
The --global flag switches between local (.tangledrc in repo) and
user (~/.tangledrc) config storage. Generic set/unset allows for
future config keys without code changes. The list command helps
users discover available configuration options.
Includes comprehensive test coverage (15 tests) for all operations
and edge cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extend prompts module with:
- promptForRemoteSelection(): Interactive picker for Git remotes
with default to "origin" if present
- promptToSaveRemote(): Confirmation prompt to persist remote choice
to .tangledrc config file
These prompts are used by context resolution when multiple tangled.org
remotes exist and user input is needed.
Includes comprehensive test coverage (10 tests total, 5 new tests).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add context resolver to automatically detect tangled.org repositories:
- getCurrentRepoContext(): Get repository context from current directory
- getTangledRemotes(): Find all tangled.org remotes
- promptForRemote(): Interactive selection for multiple remotes
- Smart selection logic: prefer "origin", use config, or prompt
- Offers to save selection to config for future use
This enables commands to automatically determine which repository
they're operating on without requiring explicit flags.
Includes comprehensive test coverage (19 tests) for all resolution
scenarios including config handling and user prompts.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add config system for persisting user preferences:
- Load config with precedence: TANGLED_REMOTE env var > local
.tangledrc > user ~/.tangledrc > system /etc/tangledrc
- Uses cosmiconfig for flexible config file support
- setLocalRemote/setUserRemote: Save remote selection
- clearLocalRemote/clearUserRemote: Clear saved remote
- Integrates with Git to save local config in repository root
This allows users to configure their preferred remote once and have
it automatically selected for ambiguous cases.
Includes comprehensive test coverage (16 tests) for all precedence
scenarios and error cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add utilities to parse and validate tangled.org Git remote URLs:
- isTangledRemote(): Check if URL points to tangled.org
- parseTangledRemote(): Extract owner, repo name, protocol from URL
- Support both SSH (git@tangled.org:owner/repo.git) and HTTPS
(https://tangled.org/owner/repo) formats
- Parse owner as DID (did:plc:...) or AT Protocol handle
- Extract repository name and protocol information
Uses validation helpers from validation.ts for DID and handle checking.
Includes comprehensive test coverage (17 tests) for all URL formats
and edge cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add boolean validation functions to check DID and handle formats:
- isValidHandle(): Check if string is valid AT Protocol handle
- isValidTangledDid(): Check if string is valid Tangled DID (did:plc: format)
These helpers return true/false without throwing, useful for parsing
operations. Includes comprehensive test coverage.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add simple-git for Git operations and cosmiconfig for configuration
management with proper precedence handling.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Defer importing ssh keys automatically as it's too large in scope right now.
- Change from 'tsx' to 'npx tsx' in integration tests
- Ensures tests use project's local tsx installation
- Fixes VS Code test runner compatibility
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add tangled auth login command with credential prompts
- Add tangled auth logout command with session cleanup
- Add tangled auth status command to check authentication state
- Prevent duplicate logins when already authenticated
- Wire up auth commands to main CLI (src/index.ts)
- Add 9 comprehensive tests for all auth command scenarios
- Mock process.exit to properly test early returns
All 56 tests passing.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add promptForIdentifier() with validation
- Add promptForPassword() with masking
- Add promptForLogin() combining both prompts
- Use @inquirer/prompts for user-friendly CLI interaction
- Add 5 tests covering all prompt functions and validation
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create TangledApiClient wrapper around AtpAgent
- Support login with identifier and password
- Implement logout with session cleanup
- Add session resumption from OS keychain
- Handle authentication state and errors
- Add 12 comprehensive tests for all API client functionality
- All tests properly typed using vi.mocked() without suppressions
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add validation schemas for handles, DIDs, identifiers, and passwords
- Support custom domain handles (e.g., markbennett.ca)
- Provide both throwing and safe validation functions
- Add 17 comprehensive validation tests covering all edge cases
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create tests/helpers/mock-data.ts with reusable mock session data
- Refactor session tests to use shared mock data
- Move mock keyring storage to module scope for cleaner access
- Remove biome-ignore suppressions by using proper types
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Save/load/delete session data from keychain
- Use @napi-rs/keyring for cross-platform support
- Track current session metadata
- Error handling for keychain operations
- Comprehensive unit tests with mocked keychain
- Fix AtpSessionData type compliance (add required 'active' field)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- @atproto/api for AT Protocol client
- @inquirer/prompts for interactive CLI prompts
- @napi-rs/keyring for secure OS keychain access (replaces archived keytar)
- zod for input validation
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add the base issue command structure with create subcommand:
- Command accepts title argument and optional body via --body or --body-file
- Validates authentication and repository context
- Builds AT-URI and creates issue record via AT Protocol
- Displays success message with issue number (rkey) and URI
- Comprehensive tests covering all input methods and error cases
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implements comprehensive issue management via AT Protocol:
- createIssue(): Create new issues with title and optional body
- listIssues(): List and filter issues by repository
- getIssue(): Retrieve specific issue details
- updateIssue(): Update issue title and/or body with atomic CID swap
- closeIssue(): Mark issue as closed via state record
- deleteIssue(): Permanently delete an issue
Features:
- Uses generated lexicon types (IssueRecord) for type safety
- Uses requireAuth() helper for authentication validation
- Uses parseIssueUri() internal helper to eliminate duplication
- Clear error messages with context
- Repository filtering in list operations
- Ownership verification for update/delete
Includes comprehensive test coverage (23 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extracts duplicated auth validation logic into reusable utility:
- requireAuth(): Validates client is authenticated and has active session
- Throws clear error messages if not authenticated
- Returns session with DID and handle
This helper will be used across all API operations that require
authentication, ensuring consistent error messages and reducing
code duplication.
Includes test coverage (3 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Supports multiple input methods following GitHub CLI patterns:
- Direct string input via --body flag
- File input via --body-file <path>
- Stdin input via --body-file - (tested via integration tests)
Features:
- Validates that only one input method is used
- Handles empty strings correctly
- Clear error messages for file not found, permission denied, etc.
Includes comprehensive test coverage (12 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
New utilities:
- parseAtUri(): Parse AT-URI into components (did, collection, rkey)
- resolveHandleToDid(): Resolve handle to DID via AT Protocol
- buildRepoAtUri(): Construct repository AT-URI from owner and repo name
New validation schemas:
- issueTitleSchema: 1-256 characters
- issueBodySchema: Optional, max 50,000 characters
- atUriSchema: Validate AT-URI format
Includes comprehensive test coverage (45 tests passing)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Generated type-safe client code from vendored lexicons using @atproto/lex-cli.
Includes type definitions for:
- Issue management (sh.tangled.repo.issue)
- Pull requests (sh.tangled.repo.pull)
- Repository operations
- All Tangled-specific record types
Note: Generated code committed to version control for:
- Reviewability in PRs
- No build step required for type checking
- Offline development support
We'll use the type definitions (interfaces) for type safety while calling
AT Protocol APIs directly via @atproto/api to avoid module resolution issues
with the generated client methods.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Downloaded AT Protocol lexicon definitions for Tangled.org service:
- Issue management (issue, comment, state)
- Pull requests (pull, comment, state)
- Repository operations (repo, branch, tag, blob, tree, etc.)
- Labels, pipelines, and other Tangled-specific types
Source: https://tangled.org/tangled.org/core/raw/master/lexicons/
Last updated: 2026-02-09
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add mandatory coding guidelines section to prevent common mistakes:
- ALL validation functions must go in src/utils/validation.ts
- ALL code requires comprehensive test coverage
- Include examples and PR checklist
This ensures consistency and prevents validation functions from
being scattered across the codebase.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement context debug command to help users understand repository
context resolution:
- Shows if current directory is a Tangled repository
- Displays owner (DID or handle), repository name, protocol
- Shows which Git remote is being used
- Provides helpful error messages when not in a Tangled repo
This is a debug/diagnostic tool that helps users verify their
context resolution is working correctly.
Includes comprehensive test coverage (4 tests) for success and
error cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement generic config management command:
- tangled config list: List all available config keys with descriptions
- tangled config get [key]: View current configuration (all or specific)
- tangled config set <key> <value> [--global]: Set any config value
- tangled config unset <key> [--global]: Clear any config value
The --global flag switches between local (.tangledrc in repo) and
user (~/.tangledrc) config storage. Generic set/unset allows for
future config keys without code changes. The list command helps
users discover available configuration options.
Includes comprehensive test coverage (15 tests) for all operations
and edge cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extend prompts module with:
- promptForRemoteSelection(): Interactive picker for Git remotes
with default to "origin" if present
- promptToSaveRemote(): Confirmation prompt to persist remote choice
to .tangledrc config file
These prompts are used by context resolution when multiple tangled.org
remotes exist and user input is needed.
Includes comprehensive test coverage (10 tests total, 5 new tests).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add context resolver to automatically detect tangled.org repositories:
- getCurrentRepoContext(): Get repository context from current directory
- getTangledRemotes(): Find all tangled.org remotes
- promptForRemote(): Interactive selection for multiple remotes
- Smart selection logic: prefer "origin", use config, or prompt
- Offers to save selection to config for future use
This enables commands to automatically determine which repository
they're operating on without requiring explicit flags.
Includes comprehensive test coverage (19 tests) for all resolution
scenarios including config handling and user prompts.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add config system for persisting user preferences:
- Load config with precedence: TANGLED_REMOTE env var > local
.tangledrc > user ~/.tangledrc > system /etc/tangledrc
- Uses cosmiconfig for flexible config file support
- setLocalRemote/setUserRemote: Save remote selection
- clearLocalRemote/clearUserRemote: Clear saved remote
- Integrates with Git to save local config in repository root
This allows users to configure their preferred remote once and have
it automatically selected for ambiguous cases.
Includes comprehensive test coverage (16 tests) for all precedence
scenarios and error cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add utilities to parse and validate tangled.org Git remote URLs:
- isTangledRemote(): Check if URL points to tangled.org
- parseTangledRemote(): Extract owner, repo name, protocol from URL
- Support both SSH (git@tangled.org:owner/repo.git) and HTTPS
(https://tangled.org/owner/repo) formats
- Parse owner as DID (did:plc:...) or AT Protocol handle
- Extract repository name and protocol information
Uses validation helpers from validation.ts for DID and handle checking.
Includes comprehensive test coverage (17 tests) for all URL formats
and edge cases.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add boolean validation functions to check DID and handle formats:
- isValidHandle(): Check if string is valid AT Protocol handle
- isValidTangledDid(): Check if string is valid Tangled DID (did:plc: format)
These helpers return true/false without throwing, useful for parsing
operations. Includes comprehensive test coverage.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add tangled auth login command with credential prompts
- Add tangled auth logout command with session cleanup
- Add tangled auth status command to check authentication state
- Prevent duplicate logins when already authenticated
- Wire up auth commands to main CLI (src/index.ts)
- Add 9 comprehensive tests for all auth command scenarios
- Mock process.exit to properly test early returns
All 56 tests passing.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Create TangledApiClient wrapper around AtpAgent
- Support login with identifier and password
- Implement logout with session cleanup
- Add session resumption from OS keychain
- Handle authentication state and errors
- Add 12 comprehensive tests for all API client functionality
- All tests properly typed using vi.mocked() without suppressions
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Save/load/delete session data from keychain
- Use @napi-rs/keyring for cross-platform support
- Track current session metadata
- Error handling for keychain operations
- Comprehensive unit tests with mocked keychain
- Fix AtpSessionData type compliance (add required 'active' field)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>