1# Tangled CLI – Current Implementation Status
2
3This document provides an overview of the Tangled CLI implementation status for AI agents or developers working on the project.
4
5## Implementation Status
6
7### ✅ Fully Implemented
8
9#### Authentication (`auth`)
10- `login` - Authenticate with AT Protocol using `com.atproto.server.createSession`
11- `status` - Show current authentication status
12- `logout` - Clear stored session from keyring
13
14#### Repositories (`repo`)
15- `list` - List repositories using `com.atproto.repo.listRecords` with `collection=sh.tangled.repo`
16- `create` - Create repositories with two-step flow:
17 1. Create PDS record via `com.atproto.repo.createRecord`
18 2. Initialize bare repo via `sh.tangled.repo.create` with ServiceAuth
19- `clone` - Clone repositories using libgit2 with SSH agent support
20- `info` - Display repository information including stats and languages
21- `delete` - Delete repositories (both PDS record and knot repo)
22- `star` / `unstar` - Star/unstar repositories via `sh.tangled.feed.star`
23
24#### Issues (`issue`)
25- `list` - List issues via `com.atproto.repo.listRecords` with `collection=sh.tangled.repo.issue`
26- `create` - Create issues via `com.atproto.repo.createRecord`
27- `show` - Show issue details and comments
28- `edit` - Edit issue title, body, or state
29- `comment` - Add comments to issues
30
31#### Pull Requests (`pr`)
32- `list` - List PRs via `com.atproto.repo.listRecords` with `collection=sh.tangled.repo.pull`
33- `create` - Create PRs using `git format-patch` for patches
34- `show` - Show PR details and diff
35- `review` - Review PRs with approve/request-changes flags
36- `merge` - Merge PRs via `sh.tangled.repo.merge` with ServiceAuth
37
38#### Knot Management (`knot`)
39- `migrate` - Migrate repositories between knots
40 - Validates working tree is clean and pushed
41 - Creates new repo on target knot with source seeding
42 - Updates PDS record to point to new knot
43
44#### Spindle CI/CD (`spindle`)
45- `config` - Enable/disable or configure spindle URL for a repository
46 - Updates the `spindle` field in `sh.tangled.repo` record
47- `list` - List pipeline runs via `com.atproto.repo.listRecords` with `collection=sh.tangled.pipeline`
48- `logs` - Stream workflow logs via WebSocket (`wss://spindle.tangled.sh/spindle/logs/{knot}/{rkey}/{name}`)
49- `secret list` - List secrets via `sh.tangled.repo.listSecrets` with ServiceAuth
50- `secret add` - Add secrets via `sh.tangled.repo.addSecret` with ServiceAuth
51- `secret remove` - Remove secrets via `sh.tangled.repo.removeSecret` with ServiceAuth
52
53### 🚧 Partially Implemented / Stubs
54
55#### Spindle CI/CD (`spindle`)
56- `run` - Manually trigger a workflow (stub)
57 - **TODO**: Parse `.tangled.yml` to determine workflows
58 - **TODO**: Create pipeline record and trigger spindle ingestion
59 - **TODO**: Support manual trigger inputs
60
61## Architecture Overview
62
63### Workspace Structure
64
65- `crates/tangled-cli` - CLI binary with clap-based argument parsing
66- `crates/tangled-config` - Configuration and keyring-backed session management
67- `crates/tangled-api` - XRPC client wrapper for AT Protocol and Tangled APIs
68- `crates/tangled-git` - Git operation helpers (currently unused)
69
70### Key Patterns
71
72#### ServiceAuth Flow
73Many Tangled API operations require ServiceAuth tokens:
741. Obtain token via `com.atproto.server.getServiceAuth` from PDS
75 - `aud` parameter must be `did:web:<target-host>`
76 - `exp` parameter should be Unix timestamp + 600 seconds
772. Use token as `Authorization: Bearer <serviceAuth>` for Tangled API calls
78
79#### Repository Creation Flow
80Two-step process:
811. **PDS**: Create `sh.tangled.repo` record via `com.atproto.repo.createRecord`
822. **Tangled API**: Initialize bare repo via `sh.tangled.repo.create` with ServiceAuth
83
84#### Repository Listing
85Done entirely via PDS (not Tangled API):
861. Resolve handle → DID if needed via `com.atproto.identity.resolveHandle`
872. List records via `com.atproto.repo.listRecords` with `collection=sh.tangled.repo`
883. Filter client-side (e.g., by knot)
89
90#### Pull Request Merging
911. Fetch PR record to get patch and target branch
922. Obtain ServiceAuth token
933. Call `sh.tangled.repo.merge` with `{did, name, patch, branch, commitMessage, commitBody}`
94
95### Base URLs and Defaults
96
97- **PDS Base** (auth + record operations): Default `https://bsky.social`, stored in session
98- **Tangled API Base** (server operations): Default `https://tngl.sh`, can override via `TANGLED_API_BASE`
99- **Spindle Base** (CI/CD): Default `wss://spindle.tangled.sh` for WebSocket logs, can override via `TANGLED_SPINDLE_BASE`
100
101### Session Management
102
103Sessions are stored in the system keyring:
104- Linux: GNOME Keyring / KWallet via Secret Service API
105- macOS: macOS Keychain
106- Windows: Windows Credential Manager
107
108Session includes:
109```rust
110struct Session {
111 access_jwt: String,
112 refresh_jwt: String,
113 did: String,
114 handle: String,
115 pds: Option<String>, // PDS base URL
116}
117```
118
119## Working with tangled-core
120
121The `../tangled-core` repository contains the server implementation and lexicon definitions.
122
123### Key Files to Check
124
125- **Lexicons**: `../tangled-core/lexicons/**/*.json`
126 - Defines XRPC method schemas (NSIDs, parameters, responses)
127 - Example: `sh.tangled.repo.create`, `sh.tangled.repo.merge`
128
129- **XRPC Routes**: `../tangled-core/knotserver/xrpc/xrpc.go`
130 - Shows which endpoints require ServiceAuth
131 - Maps NSIDs to handler functions
132
133- **API Handlers**: `../tangled-core/knotserver/xrpc/*.go`
134 - Implementation details for server-side operations
135 - Example: `create_repo.go`, `merge.go`
136
137### Useful Search Commands
138
139```bash
140# Find a specific NSID
141rg -n "sh\.tangled\.repo\.create" ../tangled-core
142
143# List all lexicons
144ls ../tangled-core/lexicons/repo
145
146# Check ServiceAuth usage
147rg -n "ServiceAuth|VerifyServiceAuth" ../tangled-core
148```
149
150## Next Steps for Contributors
151
152### Priority: Implement `spindle run`
153
154The only remaining stub is `spindle run` for manually triggering workflows. Implementation plan:
155
1561. **Parse `.tangled.yml`** in the current repository to extract workflow definitions
157 - Look for workflow names, triggers, and manual trigger inputs
158
1592. **Create pipeline record** on PDS via `com.atproto.repo.createRecord`:
160 ```rust
161 collection: "sh.tangled.pipeline"
162 record: {
163 triggerMetadata: {
164 kind: "manual",
165 repo: { knot, did, repo, defaultBranch },
166 manual: { inputs: [...] }
167 },
168 workflows: [{ name, engine, clone, raw }]
169 }
170 ```
171
1723. **Notify spindle** (if needed) or let the ingester pick up the new record
173
1744. **Support workflow selection** when multiple workflows exist:
175 - `--workflow <name>` flag to select specific workflow
176 - Default to first workflow if not specified
177
1785. **Support manual inputs** (if workflow defines them):
179 - Prompt for input values or accept via flags
180
181### Code Quality Tasks
182
183- Add more comprehensive error messages for common failure cases
184- Improve table formatting for list commands (consider using `tabled` crate features)
185- Add shell completion generation (bash, zsh, fish)
186- Add more unit tests with `mockito` for API client methods
187- Add integration tests with `assert_cmd` for CLI commands
188
189### Documentation Tasks
190
191- Add man pages for all commands
192- Create video tutorials for common workflows
193- Add troubleshooting guide for common issues
194
195## Development Workflow
196
197### Building
198
199```sh
200cargo build # Debug build
201cargo build --release # Release build
202```
203
204### Running
205
206```sh
207cargo run -p tangled-cli -- <command>
208```
209
210### Testing
211
212```sh
213cargo test # Run all tests
214cargo test -- --nocapture # Show println output
215```
216
217### Code Quality
218
219```sh
220cargo fmt # Format code
221cargo clippy # Run linter
222cargo clippy -- -W clippy::all # Strict linting
223```
224
225## Troubleshooting Common Issues
226
227### Keyring Errors on Linux
228
229Ensure a secret service is running:
230```sh
231systemctl --user enable --now gnome-keyring-daemon
232```
233
234### Invalid Token Errors
235
236- For record operations: Use PDS client, not Tangled API client
237- For server operations: Ensure ServiceAuth audience DID matches target host
238
239### Repository Not Found
240
241- Verify repo exists: `tangled repo info owner/name`
242- Check you're using the correct owner (handle or DID)
243- Ensure you have access permissions
244
245### WebSocket Connection Failures
246
247- Check spindle base URL is correct (default: `wss://spindle.tangled.sh`)
248- Verify the job_id format: `knot:rkey:name`
249- Ensure the workflow has actually run and has logs
250
251## Additional Resources
252
253- Main README: `README.md` - User-facing documentation
254- Getting Started Guide: `docs/getting-started.md` - Tutorial for new users
255- Lexicons: `../tangled-core/lexicons/` - XRPC method definitions
256- Server Implementation: `../tangled-core/knotserver/` - Server-side code
257
258---
259
260Last updated: 2025-10-14