···11+`goat`: Go AT protocol CLI tool
22+===============================
33+44+This is a re-implementation of [adenosine-cli](https://gitlab.com/bnewbold/adenosine/-/tree/main/adenosine-cli?ref_type=heads) in golang.
55+66+77+## Install
88+99+If you have the Go toolchain installed and configured correctly, you can directly build and install the tool for your local account:
1010+1111+```bash
1212+go install github.com/bluesky-social/indigo/cmd/goat@latest
1313+```
1414+1515+A more manual way to install is:
1616+1717+```bash
1818+git clone https://github.com/bluesky-social/indigo
1919+go build ./cmd/goat
2020+sudo cp goat /usr/local/bin
2121+```
2222+2323+The intention is to also provide a Homebrew "cask" and Debian/Ubuntu packages.
2424+2525+2626+## Usage
2727+2828+`goat` is relatively self-documenting via help pages:
2929+3030+```bash
3131+goat --help
3232+goat bsky -h
3333+goat help bsky
3434+# etc
3535+```
3636+3737+Most 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>`.
3838+3939+WARNING: `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.
4040+4141+Some commands output JSON, and you can use tools like `jq` to process them.
4242+4343+## Examples
4444+4545+Resolve an account's identity in the network:
4646+4747+```bash
4848+$ goat resolve wyden.senate.gov
4949+{
5050+ "id": "did:plc:ydtsvzzsl6nlfkmnuooeqcmc",
5151+ "alsoKnownAs": [
5252+ "at://wyden.senate.gov"
5353+ ],
5454+ "verificationMethod": [
5555+ {
5656+ "id": "did:plc:ydtsvzzsl6nlfkmnuooeqcmc#atproto",
5757+ "type": "Multikey",
5858+ "controller": "did:plc:ydtsvzzsl6nlfkmnuooeqcmc",
5959+ "publicKeyMultibase": "zQ3shuMW7q4KBdsFcdvebGi2EVv8KcqS24tF9Pg7Wh5NLB2NM"
6060+ }
6161+ ],
6262+ "service": [
6363+ {
6464+ "id": "#atproto_pds",
6565+ "type": "AtprotoPersonalDataServer",
6666+ "serviceEndpoint": "https://shimeji.us-east.host.bsky.network"
6767+ }
6868+ ]
6969+}
7070+```
7171+7272+List record collection types for an account:
7373+7474+```bash
7575+$ goat ls -c dril.bsky.social
7676+app.bsky.actor.profile
7777+app.bsky.feed.post
7878+app.bsky.feed.repost
7979+app.bsky.graph.follow
8080+chat.bsky.actor.declaration
8181+```
8282+8383+Fetch a record from the network as JSON:
8484+8585+```bash
8686+$ goat get at://dril.bsky.social/app.bsky.feed.post/3kkreaz3amd27
8787+{
8888+ "$type": "app.bsky.feed.post",
8989+ "createdAt": "2024-02-06T18:15:19.802Z",
9090+ "langs": [
9191+ "en"
9292+ ],
9393+ "text": "I do not Fucking recall them asking the blue sky elders permission to open registration to commoners ."
9494+}
9595+```
9696+9797+Make a public snapshot of your account:
9898+9999+```bash
100100+$ goat repo export jay.bsky.team
101101+downloading from https://morel.us-east.host.bsky.network to: jay.bsky.team.20240811183155.car
102102+103103+$ downloading blobs to: jay.bsky.team_blobs
104104+jay.bsky.team_blobs/bafkreia2x4faux5y7v7v54yl5ebkbaek7z7nhmsd4cooubz3yj4zox34cq downloaded
105105+jay.bsky.team_blobs/bafkreia3qgbww7odprmysd6jcyxoh5sczkwoxinnmzpsp73gs623fqfm3a downloaded
106106+jay.bsky.team_blobs/bafkreia3rgnywdrysy65vid42ulyno2cybxhxrn3ragm7cw3smmsxzvbs4 downloaded
107107+[...]
108108+```
109109+110110+Show PLC history for a single account, or make a snapshot of all PLC records (this takes a while), or monitor new ops:
111111+112112+```bash
113113+$ goat plc history atproto.com
114114+[...]
115115+116116+$ goat plc dump | pv -l | gzip > plc_snapshot.json.gz
117117+[...]
118118+119119+$ goat plc dump --cursor now --tail
120120+[...]
121121+```
122122+123123+Verify syntax and generate TIDs:
124124+125125+```bash
126126+$ goat syntax handle check xn--fiqa61au8b7zsevnm8ak20mc4a87e.xn--fiqs8s
127127+valid
128128+129129+$ goat syntax rkey check dHJ1ZQ==
130130+error: recordkey syntax didn't validate via regex
131131+132132+$ goat syntax tid inspect 3kzifvcppte22
133133+Timestamp (UTC): 2024-08-12T02:08:03.29Z
134134+Timestamp (Local): 2024-08-11T19:08:03-07:00
135135+ClockID: 0
136136+uint64: 0x187dcbda2b5ca800
137137+```
138138+139139+The `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:
140140+141141+```bash
142142+# possible handle updates
143143+$ goat firehose --account-events | jq .payload.handle
144144+[...]
145145+146146+# text of posts (empty lines for post-deletions)
147147+$ goat firehose - app.bsky.feed.post --ops | jq .record.text
148148+[...]
149149+150150+# sample ratio of languages in current posts
151151+$ goat firehose --ops -c app.bsky.feed.post | head -n100 | jq .record.langs[0] -c | sort | uniq -c | sort -nr
152152+ 51 "en"
153153+ 33 "ja"
154154+ 7 null
155155+ 3 "pt"
156156+ 2 "ko"
157157+ 1 "th"
158158+ 1 "id"
159159+ 1 "es"
160160+ 1 "am"
161161+```
162162+163163+A minimal bsky posting interface, requires account login:
164164+165165+```bash
166166+$ goat bsky post "hello from goat"
167167+```