1`goat`: Go AT protocol CLI tool
2===============================
3
4This is a re-implementation of [adenosine-cli](https://gitlab.com/bnewbold/adenosine/-/tree/main/adenosine-cli?ref_type=heads) in golang.
5
6
7## Install
8
9If you have the Go toolchain installed and configured correctly, you can directly build and install the tool for your local account:
10
11```bash
12go install github.com/bluesky-social/indigo/cmd/goat@latest
13```
14
15A more manual way to install is:
16
17```bash
18git clone https://github.com/bluesky-social/indigo
19go build ./cmd/goat
20sudo cp goat /usr/local/bin
21```
22
23The intention is to also provide a Homebrew "cask" and Debian/Ubuntu packages.
24
25
26## Usage
27
28`goat` is relatively self-documenting via help pages:
29
30```bash
31goat --help
32goat bsky -h
33goat help bsky
34# etc
35```
36
37Most commands use public APIs are don't require authentication. Some commands, like creating records, require an atproto account. You can log in using an "app password" with `goat account login -u <handle> -p <app-password>`.
38
39WARNING: `goat` will store both the app password and authentication tokens in the current users home directory, in cleartext. `goat logout` will wipe the file. Intention is to eventually support configuration via environment variables to keep sensitive state in a password manager or otherwise not-cleartext-on-disk.
40
41Some commands output JSON, and you can use tools like `jq` to process them.
42
43## Examples
44
45Resolve an account's identity in the network:
46
47```bash
48$ goat resolve wyden.senate.gov
49{
50 "id": "did:plc:ydtsvzzsl6nlfkmnuooeqcmc",
51 "alsoKnownAs": [
52 "at://wyden.senate.gov"
53 ],
54 "verificationMethod": [
55 {
56 "id": "did:plc:ydtsvzzsl6nlfkmnuooeqcmc#atproto",
57 "type": "Multikey",
58 "controller": "did:plc:ydtsvzzsl6nlfkmnuooeqcmc",
59 "publicKeyMultibase": "zQ3shuMW7q4KBdsFcdvebGi2EVv8KcqS24tF9Pg7Wh5NLB2NM"
60 }
61 ],
62 "service": [
63 {
64 "id": "#atproto_pds",
65 "type": "AtprotoPersonalDataServer",
66 "serviceEndpoint": "https://shimeji.us-east.host.bsky.network"
67 }
68 ]
69}
70```
71
72List record collection types for an account:
73
74```bash
75$ goat ls -c dril.bsky.social
76app.bsky.actor.profile
77app.bsky.feed.post
78app.bsky.feed.repost
79app.bsky.graph.follow
80chat.bsky.actor.declaration
81```
82
83Fetch a record from the network as JSON:
84
85```bash
86$ goat get at://dril.bsky.social/app.bsky.feed.post/3kkreaz3amd27
87{
88 "$type": "app.bsky.feed.post",
89 "createdAt": "2024-02-06T18:15:19.802Z",
90 "langs": [
91 "en"
92 ],
93 "text": "I do not Fucking recall them asking the blue sky elders permission to open registration to commoners ."
94}
95```
96
97Make a public snapshot of your account:
98
99```bash
100$ goat repo export jay.bsky.team
101downloading from https://morel.us-east.host.bsky.network to: jay.bsky.team.20240811183155.car
102
103$ downloading blobs to: jay.bsky.team_blobs
104jay.bsky.team_blobs/bafkreia2x4faux5y7v7v54yl5ebkbaek7z7nhmsd4cooubz3yj4zox34cq downloaded
105jay.bsky.team_blobs/bafkreia3qgbww7odprmysd6jcyxoh5sczkwoxinnmzpsp73gs623fqfm3a downloaded
106jay.bsky.team_blobs/bafkreia3rgnywdrysy65vid42ulyno2cybxhxrn3ragm7cw3smmsxzvbs4 downloaded
107[...]
108```
109
110Show PLC history for a single account, or make a snapshot of all PLC records (this takes a while), or monitor new ops:
111
112```bash
113$ goat plc history atproto.com
114[...]
115
116$ goat plc dump | pv -l | gzip > plc_snapshot.json.gz
117[...]
118
119$ goat plc dump --cursor now --tail
120[...]
121```
122
123Verify syntax and generate TIDs:
124
125```bash
126$ goat syntax handle check xn--fiqa61au8b7zsevnm8ak20mc4a87e.xn--fiqs8s
127valid
128
129$ goat syntax rkey check dHJ1ZQ==
130error: recordkey syntax didn't validate via regex
131
132$ goat syntax tid inspect 3kzifvcppte22
133Timestamp (UTC): 2024-08-12T02:08:03.29Z
134Timestamp (Local): 2024-08-11T19:08:03-07:00
135ClockID: 0
136uint64: 0x187dcbda2b5ca800
137```
138
139The `firehose` commands subscribes to the repo commit stream from a Relay. The default stream outputs event metadata, but doesn't include record blocks (bytes). The `--ops` variant will unpack records and output one line per record operation (instead of one line per commit event), and includes the record values themselves. Some example invocations:
140
141```bash
142# possible handle updates
143$ goat firehose --account-events | jq .payload.handle
144[...]
145
146# text of posts (empty lines for post-deletions)
147$ goat firehose - app.bsky.feed.post --ops | jq .record.text
148[...]
149
150# sample ratio of languages in current posts
151$ goat firehose --ops -c app.bsky.feed.post | head -n100 | jq .record.langs[0] -c | sort | uniq -c | sort -nr
152 51 "en"
153 33 "ja"
154 7 null
155 3 "pt"
156 2 "ko"
157 1 "th"
158 1 "id"
159 1 "es"
160 1 "am"
161```
162
163A minimal bsky posting interface, requires account login:
164
165```bash
166$ goat bsky post "hello from goat"
167```