johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
{
"views": {
"home": "/",
"search": "/search?q=t",
"start": "/start",
"terms": "/terms",
"privacy": "/privacy",
"guidelines": "/guidelines",
"stats": "/stats",
"profile": "/alice.test",
"profile-fork": "/bob.test",
"profile-repos": "/alice.test?tab=repos",
"profile-activity": "/alice.test?tab=activity",
"org": "/textkit.test",
"org-members": "/textkit.test?tab=members",
"repository": "/alice.test/tally",
"repository-watch": "/alice.test/tally",
"directory": "/alice.test/tally/tree/main/src",
"file": "/alice.test/tally/blob/main/src/lib.rs",
"blame": "/alice.test/tally/blame/main/src/lib.rs",
"markdown": "/alice.test/tally/blob/main/README.md",
"markdown-plain": "/alice.test/tally/blob/main/README.md?plain=1",
"diagram": "/alice.test/tally/blob/main/docs/DESIGN.md",
"image": "/alice.test/tally/blob/main/assets/logo.svg",
"commits": "/alice.test/tally/commits/main",
"commit": "/alice.test/tally/commit/052e48d313c5ebeb08f596cd683ba1eade3fb1ac",
"commit-merged": "/alice.test/tally/commit/1be297a440088f5808a7cdcf5254ac71c024458f",
"pulls": "/alice.test/tally/pulls",
"pulls-closed": "/alice.test/tally/pulls?state=closed",
"pull": "/alice.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7my3ltr",
"pull-open": "/alice.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhahturhe",
"pull-files": "/alice.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7my3ltr/files",
"issues": "/alice.test/tally/issues",
"issues-closed": "/alice.test/tally/issues?state=closed",
"issue": "/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhak63fo4",
"issue-subscribe": "/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhak63fo4",
"issue-closed": "/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhaqw6os3",
"issue-fixed": "/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru",
"fork": "/bob.test/tally",
"empty": "/alice.test/scratch",
"missing": "/alice.test/tally/blob/main/nowhere",
"check": "/bob.test/tally/check/did:plc:55j6e4wxzlzndxm4nov2lz7x/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test",
"queue": "/bob.test/tally/queue",
"checks": "/bob.test/tally/checks",
"pull-queued": "/bob.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhbuzv5n3",
"pull-ejected": "/bob.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhcnn4cic",
"settings": "/alice.test/tally/settings",
"settings-branches": "/alice.test/tally/settings/branches",
"settings-labels": "/alice.test/tally/settings/labels",
"settings-access": "/alice.test/tally/settings/access",
"settings-actions": "/alice.test/tally/settings/actions",
"releases": "/alice.test/tally/releases",
"releases-image": "/alice.test/tally/releases?package=tally-server",
"releases-empty": "/bob.test/tally/releases",
"notifications": "/notifications",
"code": "/search?type=code&q=count",
"code-repo": "/search?type=code&q=count+repo:alice.test/tally"
},
"answers": {
"/alice.test/tally/raw/main/assets/logo.svg": {
"status": 200,
"headers": {
"content-type": "image/svg+xml",
"cache-control": "no-cache",
"content-security-policy": "sandbox; default-src 'none'; style-src 'unsafe-inline'"
},
"body": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 120 120\" width=\"120\" height=\"120\"><rect width=\"120\" height=\"120\" rx=\"28\" fill=\"#1c1d20\"/><g stroke=\"#fff\" stroke-width=\"8\" stroke-linecap=\"round\"><path d=\"M36 34v52M52 34v52M68 34v52M84 34v52\"/><path d=\"M28 72l64-24\"/></g></svg>\n"
},
"/bob.test/tally/raw/main/assets/logo.svg": {
"status": 200,
"headers": {
"content-type": "image/svg+xml",
"cache-control": "no-cache",
"content-security-policy": "sandbox; default-src 'none'; style-src 'unsafe-inline'"
},
"body": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 120 120\" width=\"120\" height=\"120\"><rect width=\"120\" height=\"120\" rx=\"28\" fill=\"#1c1d20\"/><g stroke=\"#fff\" stroke-width=\"8\" stroke-linecap=\"round\"><path d=\"M36 34v52M52 34v52M68 34v52M84 34v52\"/><path d=\"M28 72l64-24\"/></g></svg>\n"
},
"/xrpc/dev.knotless.getActorActivity?actor=did%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x&since=2025-10-21T00%3A00%3A00.000Z&tz=America%2FNew_York": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"days\":[{\"day\":\"2026-10-09\",\"repos\":1,\"pushes\":3,\"pulls\":2,\"issues\":1,\"comments\":1},{\"day\":\"2026-10-10\",\"repos\":0,\"pushes\":8,\"pulls\":5,\"issues\":2,\"comments\":0}],\"repos\":[{\"name\":\"tally\",\"pushedAt\":\"2026-10-10T21:09:00.000Z\",\"days\":[{\"day\":\"2026-10-09\",\"pushes\":3},{\"day\":\"2026-10-10\",\"pushes\":8}]}]}"
},
"/xrpc/dev.knotless.getActorActivity?actor=did%3Aplc%3Aabe24xewga4qdbzjcxmuzdt3&since=2025-10-21T00%3A00%3A00.000Z&tz=America%2FNew_York": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"days\":[{\"day\":\"2026-10-09\",\"repos\":3,\"pushes\":5,\"pulls\":0,\"issues\":0,\"comments\":2},{\"day\":\"2026-10-10\",\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":1}],\"repos\":[{\"name\":\"notes\",\"pushedAt\":\"2026-10-09T15:33:00.000Z\",\"days\":[{\"day\":\"2026-10-09\",\"pushes\":3}]},{\"name\":\"tally\",\"pushedAt\":\"2026-10-10T01:25:00.000Z\",\"days\":[{\"day\":\"2026-10-09\",\"pushes\":2}]}]}"
},
"/xrpc/dev.knotless.getActorRepos?actor=alice.test": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"repos\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/scratch\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"name\":\"scratch\",\"createdAt\":\"2026-10-09T14:56:00.000Z\"},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/notes\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"name\":\"notes\",\"description\":\"Scratch notes ๐\",\"createdAt\":\"2026-10-09T11:51:00.000Z\"},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"name\":\"tally\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"language\":{\"name\":\"Rust\",\"color\":\"#dea584\",\"bytes\":1785,\"permille\":1000}}]}"
},
"/xrpc/dev.knotless.getActorRepos?actor=bob.test": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"repos\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.repo/tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"name\":\"tally\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"forkOf\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"createdAt\":\"2026-10-09T18:38:00.000Z\",\"language\":{\"name\":\"Rust\",\"color\":\"#dea584\",\"bytes\":1595,\"permille\":1000}}]}"
},
"/xrpc/dev.knotless.getBlame?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2Fsrc%2Flib.rs": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"src/lib.rs\",\"lines\":37,\"text\":\"//! Counting, kept apart from reading so it can be tested.\\n\\nmod parse;\\n\\n/// What a text holds.\\n#[derive(Debug, Default, PartialEq)]\\npub struct Counts {\\n pub lines: usize,\\n pub words: usize,\\n pub bytes: usize,\\n}\\n\\n/// Counts `text` in one pass.\\npub fn count(text: &str) -> Counts {\\n let mut counts = Counts { bytes: text.len(), ..Counts::default() };\\n for line in parse::lines(text) {\\n counts.lines += 1;\\n counts.words += parse::words(line);\\n }\\n counts\\n}\\n\\n#[cfg(test)]\\nmod tests {\\n use super::*;\\n\\n #[test]\\n fn counts() {\\n let c = count(\\\"one two\\\\nthree\\\\n\\\");\\n assert_eq!(c, Counts { lines: 2, words: 3, bytes: 14 });\\n }\\n\\n #[test]\\n fn a_last_line_without_a_newline() {\\n assert_eq!(count(\\\"a\\\\nb\\\").lines, 2);\\n }\\n}\\n\",\"ranges\":\"comment:0,59,13,23,126,31;string:585,18,153,6;keyword:60,3,69,3,1,6,14,3,19,3,19,3,49,3,1,2,35,3,1,3,65,3,6,2,126,3,13,3,1,5,22,2,20,3,120,2;number:422,1,221,1,9,1,9,2,105,1;function:259,5,67,3,14,7,29,5,67,5,91,6,21,5,30,10,73,29,13,10;type:104,5,2,7,2,9,14,6,18,5,17,5,17,5,56,3,5,6,24,6,24,6,282,6;attr:95,9,5,2,7,2,9,2,358,12,36,7,138,7\",\"hunks\":[{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"start\":1,\"count\":2},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"start\":3,\"count\":2,\"previous\":{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"path\":\"src/lib.rs\"}},{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"start\":5,\"count\":11},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"start\":16,\"count\":1,\"previous\":{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"path\":\"src/lib.rs\"}},{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"start\":17,\"count\":1},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"start\":18,\"count\":1,\"previous\":{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"path\":\"src/lib.rs\"}},{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"start\":19,\"count\":13},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"start\":32,\"count\":5,\"previous\":{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"path\":\"src/lib.rs\"}},{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"start\":37,\"count\":1}],\"commits\":[{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"parents\":[{\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-02T14:40:00+00:00\",\"committedAt\":\"2026-10-02T14:40:00+00:00\",\"message\":\"Count words, lines and bytes\"},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"parents\":[{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-08T11:47:00+00:00\",\"committedAt\":\"2026-10-08T11:47:00+00:00\",\"message\":\"Split parsing into its own module\"}]}"
},
"/xrpc/dev.knotless.getCheck?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"failure\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"finishedAt\":\"2026-10-10T16:13:45.500Z\",\"images\":[{\"alt\":\"pull-desktop-light 1 before\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreifhzh7dl36rji3rpd3yf5v76ktdultbqrwsaczwwaggigald7ooui\"},{\"alt\":\"pull-desktop-light 2 after\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreia22sofk3n6ehep4qsfhd6bhvbysz4f4tazkigduv3xl5r7a6zm4m\"},{\"alt\":\"pull-desktop-light 3 difference\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreidgy7vnqjmsemzlt5ah4fo3v3vn2q7uaj3bgq2jcaovfqr3lo2rq4\"}]},\"ref\":\"refs/heads/json\",\"runner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"steps\":[{\"name\":\"build\",\"status\":\"success\",\"exitCode\":0,\"durationMs\":41200},{\"name\":\"test\",\"status\":\"failure\",\"exitCode\":101,\"durationMs\":3300}],\"log\":\"==> build\\n Compiling tally v0.1.0 (/work)\\n Finished `test` profile [unoptimized + debuginfo] target(s) in 41.17s\\n==> test\\n Running unittests src/lib.rs (target/debug/deps/tally-3f9c2a1b)\\n\\nrunning 4 tests\\ntest tests::counts_bytes ... ok\\ntest tests::counts_lines ... ok\\ntest tests::counts_words ... ok\\ntest tests::prints_json ... FAILED\\n\\nfailures:\\n\\n---- tests::prints_json stdout ----\\nthread 'tests::prints_json' panicked at src/lib.rs:41:9:\\nassertion `left == right` failed\\n left: \\\"{\\\"lines\\\":2,\\\"words\\\":3,\\\"bytes\\\":14}\\\"\\n right: \\\"{\\\"lines\\\":2,\\\"words\\\":3,\\\"bytes\\\":14,\\\"name\\\":\\\"-\\\"}\\\"\\n\\ntest result: FAILED. 3 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s\\n\"}"
},
"/xrpc/dev.knotless.getCommit?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&sha=052e48d313c5ebeb08f596cd683ba1eade3fb1ac&firstRows=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"commit\":{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"parents\":[{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-08T11:47:00+00:00\",\"committedAt\":\"2026-10-08T11:47:00+00:00\",\"message\":\"Split parsing into its own module\"},\"files\":[{\"old\":\"docs/design.md\",\"new\":\"docs/DESIGN.md\",\"status\":\"renamed\",\"added\":0,\"removed\":0,\"note\":\"Moved without changes.\",\"rows\":[]},{\"old\":\"src/lib.rs\",\"new\":\"src/lib.rs\",\"status\":\"modified\",\"added\":9,\"removed\":2,\"ranges\":\"comment:0,58,14,22,58,30;string:529,18,153,6;keyword:60,3,69,3,1,6,41,3,1,2,35,3,1,3,65,3,6,2,20,3,6,2,177,3,120,2;number:384,1,203,1,9,1,9,2,105,1;function:190,5,67,3,14,7,27,5,28,5,65,16,3,5,35,5,43,5,30,10,73,29,13,10;type:104,5,2,7,2,9,14,6,54,3,5,6,24,6,24,6,295,6;attr:95,9,5,2,7,2,9,2,495,7;xins:339,17,112,17;xdel:308,11,92,30\",\"rows\":[{\"kind\":\"h\",\"line\":false,\"text\":\"@@ -1,5 +1,7 @@\"},{\"kind\":\"\",\"line\":true,\"old\":1,\"new\":1,\"text\":\"//! Counting, kept apart from reading so it can be tested.\"},{\"kind\":\"\",\"line\":true,\"old\":2,\"new\":2,\"text\":\"\"},{\"kind\":\"a\",\"line\":true,\"new\":3,\"text\":\"mod parse;\"},{\"kind\":\"a\",\"line\":true,\"new\":4,\"text\":\"\"},{\"kind\":\"\",\"line\":true,\"old\":3,\"new\":5,\"text\":\"/// What a text holds.\"},{\"kind\":\"\",\"line\":true,\"old\":4,\"new\":6,\"text\":\"#[derive(Debug, Default, PartialEq)]\"},{\"kind\":\"\",\"line\":true,\"old\":5,\"new\":7,\"text\":\"pub struct Counts {\"},{\"kind\":\"h\",\"line\":false,\"text\":\"@@ -11,9 +13,9 @@ pub struct Counts {\"},{\"kind\":\"\",\"line\":true,\"old\":11,\"new\":13,\"text\":\"/// Counts `text` in one pass.\"},{\"kind\":\"\",\"line\":true,\"old\":12,\"new\":14,\"text\":\"pub fn count(text: &str) -> Counts {\"},{\"kind\":\"\",\"line\":true,\"old\":13,\"new\":15,\"text\":\" let mut counts = Counts { bytes: text.len(), ..Counts::default() };\"},{\"kind\":\"d\",\"line\":true,\"old\":14,\"text\":\" for line in text.lines() {\"},{\"kind\":\"a\",\"line\":true,\"new\":16,\"text\":\" for line in parse::lines(text) {\"},{\"kind\":\"\",\"line\":true,\"old\":15,\"new\":17,\"text\":\" counts.lines += 1;\"},{\"kind\":\"d\",\"line\":true,\"old\":16,\"text\":\" counts.words += line.split_whitespace().count();\"},{\"kind\":\"a\",\"line\":true,\"new\":18,\"text\":\" counts.words += parse::words(line);\"},{\"kind\":\"\",\"line\":true,\"old\":17,\"new\":19,\"text\":\" }\"},{\"kind\":\"\",\"line\":true,\"old\":18,\"new\":20,\"text\":\" counts\"},{\"kind\":\"\",\"line\":true,\"old\":19,\"new\":21,\"text\":\"}\"},{\"kind\":\"h\",\"line\":false,\"text\":\"@@ -27,4 +29,9 @@ mod tests {\"},{\"kind\":\"\",\"line\":true,\"old\":27,\"new\":29,\"text\":\" let c = count(\\\"one two\\\\nthree\\\\n\\\");\"},{\"kind\":\"\",\"line\":true,\"old\":28,\"new\":30,\"text\":\" assert_eq!(c, Counts { lines: 2, words: 3, bytes: 14 });\"},{\"kind\":\"\",\"line\":true,\"old\":29,\"new\":31,\"text\":\" }\"},{\"kind\":\"a\",\"line\":true,\"new\":32,\"text\":\"\"},{\"kind\":\"a\",\"line\":true,\"new\":33,\"text\":\" #[test]\"},{\"kind\":\"a\",\"line\":true,\"new\":34,\"text\":\" fn a_last_line_without_a_newline() {\"},{\"kind\":\"a\",\"line\":true,\"new\":35,\"text\":\" assert_eq!(count(\\\"a\\\\nb\\\").lines, 2);\"},{\"kind\":\"a\",\"line\":true,\"new\":36,\"text\":\" }\"},{\"kind\":\"\",\"line\":true,\"old\":30,\"new\":37,\"text\":\"}\"}]},{\"old\":\"src/parse.rs\",\"new\":\"src/parse.rs\",\"status\":\"added\",\"added\":11,\"removed\":0,\"ranges\":\"comment:0,48,2,57,76,68;keyword:108,3,1,2,138,3,1,2,22,4;function:115,5,33,16,3,5,82,5,54,5;type:128,3,5,5,131,3,10,8,1,4,4,3\",\"rows\":[{\"kind\":\"h\",\"line\":false,\"text\":\"@@ -0,0 +1,11 @@\"},{\"kind\":\"a\",\"line\":true,\"new\":1,\"text\":\"//! Splitting text into the things tally counts.\"},{\"kind\":\"a\",\"line\":true,\"new\":2,\"text\":\"\"},{\"kind\":\"a\",\"line\":true,\"new\":3,\"text\":\"/// The words of `line`: runs of anything but whitespace.\"},{\"kind\":\"a\",\"line\":true,\"new\":4,\"text\":\"pub fn words(line: &str) -> usize {\"},{\"kind\":\"a\",\"line\":true,\"new\":5,\"text\":\" line.split_whitespace().count()\"},{\"kind\":\"a\",\"line\":true,\"new\":6,\"text\":\"}\"},{\"kind\":\"a\",\"line\":true,\"new\":7,\"text\":\"\"},{\"kind\":\"a\",\"line\":true,\"new\":8,\"text\":\"/// The lines of `text`. A last line without a newline still counts.\"},{\"kind\":\"a\",\"line\":true,\"new\":9,\"text\":\"pub fn lines(text: &str) -> impl Iterator<Item = &str> {\"},{\"kind\":\"a\",\"line\":true,\"new\":10,\"text\":\" text.lines()\"},{\"kind\":\"a\",\"line\":true,\"new\":11,\"text\":\"}\"}]}]}"
},
"/xrpc/dev.knotless.getCommit?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&sha=1be297a440088f5808a7cdcf5254ac71c024458f&firstRows=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"commit\":{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00+00:00\",\"committedAt\":\"2026-10-09T15:00:00+00:00\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}},\"files\":[{\"old\":\"src/parse.rs\",\"new\":\"src/parse.rs\",\"status\":\"modified\",\"added\":11,\"removed\":2,\"ranges\":\"comment:39,68,1,72,1,25;string:435,2;keyword:207,3,1,2,22,4,104,3,25,2,49,5;number:448,1;function:9,16,3,5,181,5,54,5,12,5,3,6,11,8,51,24,13,10;type:227,3,10,8,1,4,4,3;attr:330,12,17,7;xins:175,5,117,29;xdel:106,1\",\"rows\":[{\"kind\":\"h\",\"line\":false,\"text\":\"@@ -5,7 +5,16 @@ pub fn words(line: &str) -> usize {\"},{\"kind\":\"\",\"line\":true,\"old\":5,\"new\":5,\"text\":\" line.split_whitespace().count()\"},{\"kind\":\"\",\"line\":true,\"old\":6,\"new\":6,\"text\":\"}\"},{\"kind\":\"\",\"line\":true,\"old\":7,\"new\":7,\"text\":\"\"},{\"kind\":\"d\",\"line\":true,\"old\":8,\"text\":\"/// The lines of `text`. A last line without a newline still counts.\"},{\"kind\":\"a\",\"line\":true,\"new\":8,\"text\":\"/// The lines of `text`. A last line without a newline still counts, and\"},{\"kind\":\"a\",\"line\":true,\"new\":9,\"text\":\"/// empty input has none.\"},{\"kind\":\"\",\"line\":true,\"old\":9,\"new\":10,\"text\":\"pub fn lines(text: &str) -> impl Iterator<Item = &str> {\"},{\"kind\":\"d\",\"line\":true,\"old\":10,\"text\":\" text.lines()\"},{\"kind\":\"a\",\"line\":true,\"new\":11,\"text\":\" text.lines().filter(|_| !text.is_empty())\"},{\"kind\":\"a\",\"line\":true,\"new\":12,\"text\":\"}\"},{\"kind\":\"a\",\"line\":true,\"new\":13,\"text\":\"\"},{\"kind\":\"a\",\"line\":true,\"new\":14,\"text\":\"#[cfg(test)]\"},{\"kind\":\"a\",\"line\":true,\"new\":15,\"text\":\"mod tests {\"},{\"kind\":\"a\",\"line\":true,\"new\":16,\"text\":\" #[test]\"},{\"kind\":\"a\",\"line\":true,\"new\":17,\"text\":\" fn empty_input_has_no_lines() {\"},{\"kind\":\"a\",\"line\":true,\"new\":18,\"text\":\" assert_eq!(super::lines(\\\"\\\").count(), 0);\"},{\"kind\":\"a\",\"line\":true,\"new\":19,\"text\":\" }\"},{\"kind\":\"\",\"line\":true,\"old\":11,\"new\":20,\"text\":\"}\"}]}]}"
},
"/xrpc/dev.knotless.getFeed": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"events\":[{\"createdAt\":\"2026-10-10T21:09:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":false,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"message\":\"Release from tags when asked\"}]}},{\"createdAt\":\"2026-10-10T18:04:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhcnn4cic\",\"title\":\"Print a total for many files\"}},{\"createdAt\":\"2026-10-10T16:50:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/totals\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"6f89484c63a36649168e3d77a1e631f695469b74\",\"message\":\"Print a total for many files\"}]}},{\"createdAt\":\"2026-10-10T16:13:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhcffbj7l\",\"title\":\"Count words in any script\"}},{\"createdAt\":\"2026-10-10T14:59:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/words\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"f834a66404f8eb1f5ccf94b3ef31e47246fd30ab\",\"message\":\"Count words in any script\"}]}},{\"createdAt\":\"2026-10-10T14:22:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhc5eopws\",\"title\":\"Line the columns up with tabs\"}},{\"createdAt\":\"2026-10-10T13:08:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/tabs\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"message\":\"Line the columns up with tabs\"}]}},{\"createdAt\":\"2026-10-10T12:31:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhbuzv5n3\",\"title\":\"Count bytes in files that are not UTF-8\"}},{\"createdAt\":\"2026-10-10T11:17:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/bytes\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"87a3fcfe0a12c9f038fa4e5a5d276a96b19e03ca\",\"message\":\"Count bytes in files that are not UTF-8\"}]}},{\"createdAt\":\"2026-10-10T10:40:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#changed\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhbacgmx6\",\"title\":\"Show usage on --help\",\"state\":\"merged\"}},{\"createdAt\":\"2026-10-10T10:03:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#deleted\",\"ref\":\"refs/heads/usage\"}},{\"createdAt\":\"2026-10-10T09:26:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":false,\"count\":1,\"new\":0,\"commits\":[]}},{\"createdAt\":\"2026-10-10T08:49:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhbacgmx6\",\"title\":\"Show usage on --help\"}},{\"createdAt\":\"2026-10-10T07:35:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/usage\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"226488be4afaf037c2331c7480d4a48790f20eba\",\"message\":\"Show usage on --help\"}]}},{\"createdAt\":\"2026-10-10T06:58:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#changed\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhaqw6os3\",\"title\":\"Typo in the README โ๏ธ\",\"state\":\"closed\"}},{\"createdAt\":\"2026-10-10T06:21:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhaqw6os3\",\"title\":\"Typo in the README โ๏ธ\"}},{\"createdAt\":\"2026-10-10T05:07:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhak63fo4\",\"title\":\"Fails on files that are not UTF-8\"}},{\"createdAt\":\"2026-10-10T04:30:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#commented\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhak63fo4\",\"title\":\"Fails on files that are not UTF-8\",\"text\":\"Confirmed. Reading bytes and counting words lossily would fix it.\"}},{\"createdAt\":\"2026-10-10T03:53:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhahturhe\",\"title\":\"Print counts as JSON with --json\"}},{\"createdAt\":\"2026-10-10T03:16:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#changed\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwh7kezpru\",\"title\":\"Counts one line for an empty file\",\"state\":\"closed\"}},{\"createdAt\":\"2026-10-10T02:39:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#changed\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\",\"state\":\"merged\"}},{\"createdAt\":\"2026-10-10T01:25:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":false,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\\n\\nat://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\"}]}},{\"createdAt\":\"2026-10-10T00:48:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}},{\"createdAt\":\"2026-10-10T00:11:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#commented\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\",\"text\":\"It only runs per line, so the cost is one comparison each. Happy to change it if you prefer.\"}},{\"createdAt\":\"2026-10-09T23:34:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#commented\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\",\"text\":\"Fair enough. Thanks!\",\"verdict\":\"approve\"}},{\"createdAt\":\"2026-10-09T22:57:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#commented\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\",\"text\":\"Could `lines` check for emptiness once, rather than in the filter?\",\"verdict\":\"changes\"}},{\"createdAt\":\"2026-10-09T22:20:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#opened\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwh7kezpru\",\"title\":\"Counts one line for an empty file\"}},{\"createdAt\":\"2026-10-09T21:06:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/json\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"message\":\"Print counts as JSON with --json\"}]}},{\"createdAt\":\"2026-10-09T19:52:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/empty-input\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"d1f87fe9540ab153762a7caf292887855d3e1a90\",\"message\":\"Count no lines in empty input\"}]}},{\"createdAt\":\"2026-10-09T18:38:00.000Z\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#created\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"forkOf\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"}}},{\"createdAt\":\"2026-10-09T15:33:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":false,\"count\":2,\"new\":1,\"commits\":[{\"sha\":\"661c67a96bf920012bc578c6c6895e4103128dfe\",\"message\":\"Add Working in Public\"}]}},{\"createdAt\":\"2026-10-09T14:56:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"scratch\"},\"action\":{\"$type\":\"dev.knotless.getFeed#created\"}},{\"createdAt\":\"2026-10-09T13:42:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/reading\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"7b66c6ffd4369e246fc00c2bcb3e16d0ed1846d1\",\"message\":\"Start a reading list\"}]}},{\"createdAt\":\"2026-10-09T12:28:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"e78543abf0f799b7eb5713ccdf8d88b84d0f8ec0\",\"message\":\"Begin\"}]}},{\"createdAt\":\"2026-10-09T11:51:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#created\",\"description\":\"Scratch notes ๐\"}},{\"createdAt\":\"2026-10-09T10:37:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":true,\"count\":6,\"new\":6,\"commits\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"message\":\"Split parsing into its own module\"},{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"message\":\"Document usage and output\"},{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\",\"message\":\"Add a logo\"},{\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\",\"message\":\"Read from stdin when no file is given\\n\\nSo tally works at the end of a pipe, as wc does. The name shown\\nfor stdin is \\\"-\\\".\"},{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"message\":\"Count words, lines and bytes\"},{\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\",\"message\":\"Start tally\"}]}},{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#created\",\"description\":\"Counts lines, words and bytes, with output that lines up\"}}]}"
},
"/xrpc/dev.knotless.getFeed?actor=did%3Aplc%3Aabe24xewga4qdbzjcxmuzdt3&limit=40": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"events\":[{\"createdAt\":\"2026-10-10T06:58:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#changed\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhaqw6os3\",\"title\":\"Typo in the README โ๏ธ\",\"state\":\"closed\"}},{\"createdAt\":\"2026-10-10T04:30:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#commented\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhak63fo4\",\"title\":\"Fails on files that are not UTF-8\",\"text\":\"Confirmed. Reading bytes and counting words lossily would fix it.\"}},{\"createdAt\":\"2026-10-10T03:16:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#changed\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwh7kezpru\",\"title\":\"Counts one line for an empty file\",\"state\":\"closed\"}},{\"createdAt\":\"2026-10-10T02:39:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#changed\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\",\"state\":\"merged\"}},{\"createdAt\":\"2026-10-10T01:25:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":false,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\\n\\nat://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\"}]}},{\"createdAt\":\"2026-10-09T23:34:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#commented\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\",\"text\":\"Fair enough. Thanks!\",\"verdict\":\"approve\"}},{\"createdAt\":\"2026-10-09T22:57:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#commented\",\"subject\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\",\"text\":\"Could `lines` check for emptiness once, rather than in the filter?\",\"verdict\":\"changes\"}},{\"createdAt\":\"2026-10-09T15:33:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":false,\"count\":2,\"new\":1,\"commits\":[{\"sha\":\"661c67a96bf920012bc578c6c6895e4103128dfe\",\"message\":\"Add Working in Public\"}]}},{\"createdAt\":\"2026-10-09T14:56:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"scratch\"},\"action\":{\"$type\":\"dev.knotless.getFeed#created\"}},{\"createdAt\":\"2026-10-09T13:42:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/reading\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"7b66c6ffd4369e246fc00c2bcb3e16d0ed1846d1\",\"message\":\"Start a reading list\"}]}},{\"createdAt\":\"2026-10-09T12:28:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":true,\"count\":1,\"new\":1,\"commits\":[{\"sha\":\"e78543abf0f799b7eb5713ccdf8d88b84d0f8ec0\",\"message\":\"Begin\"}]}},{\"createdAt\":\"2026-10-09T11:51:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"notes\"},\"action\":{\"$type\":\"dev.knotless.getFeed#created\",\"description\":\"Scratch notes ๐\"}},{\"createdAt\":\"2026-10-09T10:37:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#pushed\",\"ref\":\"refs/heads/main\",\"created\":true,\"count\":6,\"new\":6,\"commits\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"message\":\"Split parsing into its own module\"},{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"message\":\"Document usage and output\"},{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\",\"message\":\"Add a logo\"},{\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\",\"message\":\"Read from stdin when no file is given\\n\\nSo tally works at the end of a pipe, as wc does. The name shown\\nfor stdin is \\\"-\\\".\"},{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"message\":\"Count words, lines and bytes\"},{\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\",\"message\":\"Start tally\"}]}},{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"action\":{\"$type\":\"dev.knotless.getFeed#created\",\"description\":\"Counts lines, words and bytes, with output that lines up\"}}]}"
},
"/xrpc/dev.knotless.getFile?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2FREADME.md": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"README.md\",\"kind\":\"text\",\"size\":388,\"lines\":27,\"text\":\"# tally\\n\\nCounts lines, words and bytes, like `wc`, with output that lines up.\\n\\n\\n\\n## Usage\\n\\n```sh\\ncargo install --path .\\ntally notes.txt\\necho \\\"one two\\\" | tally\\n```\\n\\n## Output\\n\\n| Column | Meaning |\\n| --- | --- |\\n| 1 | lines |\\n| 2 | words, split on whitespace |\\n| 3 | bytes |\\n\\nSee [the design notes](docs/design.md) for why it reads the whole file.\\n\\n## License\\n\\nMIT\\n\",\"ranges\":\"comment:116,3,65,3;string:45,4,39,15,63,9,147,14;number:136,6;function:0,8,98,9,7,5,18,5,11,4,13,5,6,10,173,11;attr:81,5,33,2,183,16\",\"html\":\"<h1>tally</h1>\\n<p>Counts lines, words and bytes, like <code>wc</code>, with output that lines up.</p>\\n<p><img src=\\\"/alice.test/tally/raw/main/assets/logo.svg\\\" alt=\\\"tally\\\" /></p>\\n<h2>Usage</h2>\\n<pre><code class=\\\"language-sh\\\">cargo install --path .\\ntally notes.txt\\necho \\\"one two\\\" | tally\\n</code></pre>\\n<h2>Output</h2>\\n<table><thead><tr><th>Column</th><th>Meaning</th></tr></thead><tbody>\\n<tr><td>1</td><td>lines</td></tr>\\n<tr><td>2</td><td>words, split on whitespace</td></tr>\\n<tr><td>3</td><td>bytes</td></tr>\\n</tbody></table>\\n<p>See <a href=\\\"/alice.test/tally/blob/main/docs/design.md\\\">the design notes</a> for why it reads the whole file.</p>\\n<h2>License</h2>\\n<p>MIT</p>\\n\"}"
},
"/xrpc/dev.knotless.getFile?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2Fassets%2Flogo.svg": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"assets/logo.svg\",\"kind\":\"image\",\"size\":282,\"lines\":1}"
},
"/xrpc/dev.knotless.getFile?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2Fdocs%2FDESIGN.md": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"docs/DESIGN.md\",\"kind\":\"text\",\"size\":341,\"lines\":14,\"text\":\"# Design\\n\\ntally reads the whole input before counting. Inputs are small, and one\\npass over a string is simpler than a streaming reader.\\n\\n```mermaid\\nflowchart LR\\n input[File or stdin] --> read[Read it whole]\\n read --> count{Count}\\n count --> lines\\n count --> words\\n count --> bytes\\n lines & words & bytes --> row[One row, lined up]\\n```\\n\",\"ranges\":\"comment:137,3,197,3;function:0,9;attr:140,7\",\"html\":\"<h1>Design</h1>\\n<p>tally reads the whole input before counting. Inputs are small, and one\\npass over a string is simpler than a streaming reader.</p>\\n<pre><code class=\\\"language-mermaid\\\">flowchart LR\\n input[File or stdin] --> read[Read it whole]\\n read --> count{Count}\\n count --> lines\\n count --> words\\n count --> bytes\\n lines & words & bytes --> row[One row, lined up]\\n</code></pre>\\n\"}"
},
"/xrpc/dev.knotless.getFile?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2Fnowhere": {
"status": 404,
"headers": {
"content-type": "application/json",
"cache-control": "no-store"
},
"body": "{\"error\":\"NotFound\",\"message\":\"no nowhere at main\"}"
},
"/xrpc/dev.knotless.getFile?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2Fsrc%2Flib.rs": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"src/lib.rs\",\"kind\":\"text\",\"size\":783,\"lines\":37,\"text\":\"//! Counting, kept apart from reading so it can be tested.\\n\\nmod parse;\\n\\n/// What a text holds.\\n#[derive(Debug, Default, PartialEq)]\\npub struct Counts {\\n pub lines: usize,\\n pub words: usize,\\n pub bytes: usize,\\n}\\n\\n/// Counts `text` in one pass.\\npub fn count(text: &str) -> Counts {\\n let mut counts = Counts { bytes: text.len(), ..Counts::default() };\\n for line in parse::lines(text) {\\n counts.lines += 1;\\n counts.words += parse::words(line);\\n }\\n counts\\n}\\n\\n#[cfg(test)]\\nmod tests {\\n use super::*;\\n\\n #[test]\\n fn counts() {\\n let c = count(\\\"one two\\\\nthree\\\\n\\\");\\n assert_eq!(c, Counts { lines: 2, words: 3, bytes: 14 });\\n }\\n\\n #[test]\\n fn a_last_line_without_a_newline() {\\n assert_eq!(count(\\\"a\\\\nb\\\").lines, 2);\\n }\\n}\\n\",\"ranges\":\"comment:0,59,13,23,126,31;string:585,18,153,6;keyword:60,3,69,3,1,6,14,3,19,3,19,3,49,3,1,2,35,3,1,3,65,3,6,2,126,3,13,3,1,5,22,2,20,3,120,2;number:422,1,221,1,9,1,9,2,105,1;function:259,5,67,3,14,7,29,5,67,5,91,6,21,5,30,10,73,29,13,10;type:104,5,2,7,2,9,14,6,18,5,17,5,17,5,56,3,5,6,24,6,24,6,282,6;attr:95,9,5,2,7,2,9,2,358,12,36,7,138,7\"}"
},
"/xrpc/dev.knotless.getLastCommits?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Fscratch": {
"status": 404,
"headers": {
"content-type": "application/json",
"cache-control": "no-store"
},
"body": "{\"error\":\"NotFound\",\"message\":\"no revision main: couldn't parse revision, input=\\\"main\\\": Reference \\\"main\\\" could not be found: NotFound\"}"
},
"/xrpc/dev.knotless.getLastCommits?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"\",\"entries\":[{\"name\":\".gitignore\",\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\"},{\"name\":\"Cargo.toml\",\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\"},{\"name\":\"README.md\",\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"},{\"name\":\"assets\",\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\"},{\"name\":\"docs\",\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"},{\"name\":\"src\",\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\"}],\"commits\":[{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00+00:00\",\"committedAt\":\"2026-10-09T15:00:00+00:00\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"parents\":[{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-08T11:47:00+00:00\",\"committedAt\":\"2026-10-08T11:47:00+00:00\",\"message\":\"Split parsing into its own module\"},{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"parents\":[{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-06T10:02:00+00:00\",\"committedAt\":\"2026-10-06T10:02:00+00:00\",\"message\":\"Document usage and output\"},{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\",\"parents\":[{\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-02T11:30:00+00:00\",\"committedAt\":\"2026-10-05T17:21:00+00:00\",\"message\":\"Add a logo\"},{\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\",\"parents\":[],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-01T09:12:00+00:00\",\"committedAt\":\"2026-10-01T09:12:00+00:00\",\"message\":\"Start tally\"}],\"commitCount\":7}"
},
"/xrpc/dev.knotless.getLastCommits?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2Fsrc": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"src\",\"entries\":[{\"name\":\"lib.rs\",\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"},{\"name\":\"main.rs\",\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\"},{\"name\":\"parse.rs\",\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\"}],\"commits\":[{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00+00:00\",\"committedAt\":\"2026-10-09T15:00:00+00:00\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"parents\":[{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-08T11:47:00+00:00\",\"committedAt\":\"2026-10-08T11:47:00+00:00\",\"message\":\"Split parsing into its own module\"},{\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\",\"parents\":[{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-03T08:05:00+00:00\",\"committedAt\":\"2026-10-03T08:05:00+00:00\",\"message\":\"Read from stdin when no file is given\\n\\nSo tally works at the end of a pipe, as wc does. The name shown\\nfor stdin is \\\"-\\\".\"}]}"
},
"/xrpc/dev.knotless.getLastCommits?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"\",\"entries\":[{\"name\":\".gitignore\",\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\"},{\"name\":\".knotless\",\"sha\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\"},{\"name\":\"Cargo.toml\",\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\"},{\"name\":\"README.md\",\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"},{\"name\":\"assets\",\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\"},{\"name\":\"docs\",\"sha\":\"226488be4afaf037c2331c7480d4a48790f20eba\"},{\"name\":\"src\",\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"commits\":[{\"sha\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"parents\":[{\"sha\":\"226488be4afaf037c2331c7480d4a48790f20eba\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"date\":\"2026-10-20T12:00:00+00:00\",\"committedAt\":\"2026-10-20T12:00:00+00:00\",\"message\":\"Release from tags when asked\"},{\"sha\":\"226488be4afaf037c2331c7480d4a48790f20eba\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"date\":\"2026-10-11T08:00:00+00:00\",\"committedAt\":\"2026-10-11T08:00:00+00:00\",\"message\":\"Show usage on --help\"},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"parents\":[{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"}],\"author\":{\"name\":\"Alice Moreau\"},\"coauthors\":[],\"date\":\"2026-10-08T11:47:00+00:00\",\"committedAt\":\"2026-10-08T11:47:00+00:00\",\"message\":\"Split parsing into its own module\"},{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"parents\":[{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\"}],\"author\":{\"name\":\"Alice Moreau\"},\"coauthors\":[],\"date\":\"2026-10-06T10:02:00+00:00\",\"committedAt\":\"2026-10-06T10:02:00+00:00\",\"message\":\"Document usage and output\"},{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\",\"parents\":[{\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\"}],\"author\":{\"name\":\"Alice Moreau\"},\"coauthors\":[],\"date\":\"2026-10-02T11:30:00+00:00\",\"committedAt\":\"2026-10-05T17:21:00+00:00\",\"message\":\"Add a logo\"},{\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\",\"parents\":[],\"author\":{\"name\":\"Alice Moreau\"},\"coauthors\":[],\"date\":\"2026-10-01T09:12:00+00:00\",\"committedAt\":\"2026-10-01T09:12:00+00:00\",\"message\":\"Start tally\"}],\"commitCount\":8}"
},
"/xrpc/dev.knotless.getProfile?actor=alice.test": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"displayName\":\"Alice Moreau\",\"description\":\"Small tools for text. Writes tally.\",\"followersCount\":1,\"followsCount\":0,\"badges\":[{\"kind\":\"forked-and-fixed\",\"tier\":1,\"count\":1},{\"kind\":\"shipped\",\"tier\":1,\"count\":4,\"next\":10},{\"kind\":\"carry-your-own\",\"tier\":1,\"count\":1},{\"kind\":\"first-light\",\"tier\":1,\"count\":1}]}"
},
"/xrpc/dev.knotless.getProfile?actor=bob.test": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"followersCount\":0,\"followsCount\":1,\"orgs\":[{\"actor\":{\"did\":\"did:plc:2ejydq2mzgqz2tzdtgk3figi\",\"handle\":\"textkit.test\"}}],\"badges\":[{\"kind\":\"carry-your-own\",\"tier\":1,\"count\":1},{\"kind\":\"first-light\",\"tier\":1,\"count\":1}]}"
},
"/xrpc/dev.knotless.getQueue?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"branches\":[{\"branch\":\"main\",\"pulls\":[{\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhbuzv5n3\",\"kind\":\"pull\",\"title\":\"Count bytes in files that are not UTF-8\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T12:31:00.000Z\",\"comments\":0},\"queuedAt\":\"2026-10-15T09:30:00.000Z\",\"said\":\"In a batch of 2 being checked\",\"stage\":\"checking\",\"checks\":[],\"batch\":0},{\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhc5eopws\",\"kind\":\"pull\",\"title\":\"Line the columns up with tabs\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T14:22:00.000Z\",\"comments\":0},\"queuedAt\":\"2026-10-16T09:30:00.000Z\",\"said\":\"In a batch of 2 being checked\",\"stage\":\"checking\",\"checks\":[],\"batch\":0},{\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhcffbj7l\",\"kind\":\"pull\",\"title\":\"Count words in any script\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T16:13:00.000Z\",\"comments\":0},\"queuedAt\":\"2026-10-17T09:30:00.000Z\",\"said\":\"Queued, 3rd of 3, running its checks\",\"stage\":\"preflight\",\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.x7xwerv7qozd33kq5cq5j54zdt.f834a66404f8eb1f5ccf94b3ef31e47246fd30ab.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"running\",\"commit\":\"f834a66404f8eb1f5ccf94b3ef31e47246fd30ab\",\"startedAt\":\"2026-10-20T13:57:00Z\",\"images\":[]}]}],\"batches\":[{\"commit\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"state\":\"checking\",\"size\":2,\"startedAt\":\"2026-10-20T10:00:00Z\",\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6.226488be4afaf037c2331c7480d4a48790f20eba.build\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"build\",\"status\":\"success\",\"commit\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"startedAt\":\"2026-10-20T10:00:00Z\",\"finishedAt\":\"2026-10-20T10:01:35.000Z\",\"images\":[]},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"running\",\"commit\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"startedAt\":\"2026-10-20T10:00:00Z\",\"images\":[]}]}]}],\"ejected\":[{\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhcnn4cic\",\"kind\":\"pull\",\"title\":\"Print a total for many files\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T18:04:00.000Z\",\"comments\":0},\"ejectedAt\":\"2026-10-19T15:02:00.000Z\",\"reason\":\"its batch failed its checks at 6f89484c63a3, on main at 226488be4afa: test (failure)\",\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.6f89484c63a36649168e3d77a1e631f695469b74.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"failure\",\"commit\":\"6f89484c63a36649168e3d77a1e631f695469b74\",\"startedAt\":\"2026-10-19T15:00:00Z\",\"finishedAt\":\"2026-10-19T15:01:35.000Z\",\"images\":[]}]}],\"landed\":[{\"branch\":\"main\",\"commit\":\"226488be4afaf037c2331c7480d4a48790f20eba\",\"landedAt\":\"2026-10-19T09:01:35.000Z\",\"pulls\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhbacgmx6\",\"kind\":\"pull\",\"title\":\"Show usage on --help\",\"state\":\"merged\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T08:49:00.000Z\",\"comments\":0}]}],\"typical\":{\"batchSeconds\":95,\"preflightSeconds\":360}}"
},
"/xrpc/dev.knotless.getRepo?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Fscratch": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/scratch\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"name\":\"scratch\",\"key\":\"3mz2z2irwxiwv\",\"defaultBranch\":\"main\",\"openPulls\":0,\"openIssues\":0,\"card\":\"/alice.test/scratch/card.png?v=8d5b3f136b93e209\",\"starCount\":0,\"forkCount\":0}"
},
"/xrpc/dev.knotless.getRepo?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"name\":\"tally\",\"key\":\"3mz2z2gkqpvhk\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"links\":[{\"url\":\"https://tally.dev\"},{\"url\":\"https://docs.tally.dev\",\"title\":\"Docs\"}],\"defaultBranch\":\"main\",\"openPulls\":1,\"openIssues\":1,\"card\":\"/alice.test/tally/card.png?v=8da376836ab23847\",\"starCount\":1,\"forkCount\":1,\"releases\":{\"count\":4,\"release\":{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.release/3myvwh5dhhixv.wapcnu7vuujqxhmnqiofvhlb47.chxchoh4f7dbtvxkwytxvw22kj\",\"package\":\"tally\",\"version\":\"0.1.1\",\"latest\":true,\"createdAt\":\"2026-10-10T19:18:00.000Z\"},\"packages\":[{\"name\":\"tally\",\"latest\":\"0.1.1\",\"releaseCount\":3},{\"name\":\"tally-server\",\"latest\":\"0.1.0\",\"image\":true,\"releaseCount\":1}]}}"
},
"/xrpc/dev.knotless.getRepo?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.repo/tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"name\":\"tally\",\"key\":\"3mz2z2jedyqxn\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"forkOf\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"defaultBranch\":\"main\",\"openPulls\":4,\"openIssues\":0,\"mergeQueue\":true,\"card\":\"/bob.test/tally/card.png?v=68776149d6ea2b31\",\"starCount\":0,\"forkCount\":0}"
},
"/xrpc/dev.knotless.getRepoSettings?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"links\":[{\"url\":\"https://tally.dev\"},{\"url\":\"https://docs.tally.dev\",\"title\":\"Docs\"}],\"defaultBranch\":\"main\",\"rules\":[{\"branch\":\"main\",\"history\":\"linear\"}],\"runners\":true,\"labels\":[{\"name\":\"kind/bug\",\"description\":\"Something is broken\",\"color\":\"#d73a4a\"},{\"name\":\"priority/high\",\"color\":\"#fbca04\",\"exclusive\":true},{\"name\":\"priority/low\",\"exclusive\":true}],\"collaborators\":[],\"triagers\":[]}"
},
"/xrpc/dev.knotless.getRepoStorage?repo=at%3A%2F%2Fdid%3Aplc%3Aabe24xewga4qdbzjcxmuzdt3%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"packs\":2,\"objects\":35,\"bytes\":5031,\"blobBytes\":0}"
},
"/xrpc/dev.knotless.getStats": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "public, max-age=300"
},
"body": "{\"days\":[{\"day\":\"2026-09-29\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-09-30\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-01\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-02\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-03\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-04\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-05\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-06\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-07\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-08\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-09\",\"visitors\":0,\"views\":0,\"repos\":4,\"pushes\":7,\"pulls\":0,\"issues\":1,\"comments\":2,\"checks\":1,\"authors\":2},{\"day\":\"2026-10-10\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":9,\"pulls\":7,\"issues\":2,\"comments\":2,\"checks\":4,\"authors\":2},{\"day\":\"2026-10-11\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":2,\"authors\":0},{\"day\":\"2026-10-12\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-13\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-14\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-15\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":1},{\"day\":\"2026-10-16\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":1},{\"day\":\"2026-10-17\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":1},{\"day\":\"2026-10-18\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":1},{\"day\":\"2026-10-19\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":4,\"authors\":1},{\"day\":\"2026-10-20\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":2,\"authors\":0},{\"day\":\"2026-10-21\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-22\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-23\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-24\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-25\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-26\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-27\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0},{\"day\":\"2026-10-28\",\"visitors\":0,\"views\":0,\"repos\":0,\"pushes\":0,\"pulls\":0,\"issues\":0,\"comments\":0,\"checks\":0,\"authors\":0}],\"network\":{\"accounts\":2,\"repos\":4,\"authorsWeek\":0,\"authorsMonth\":2}}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.issue%2F3myvwh7kezpru&filesOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwh7kezpru\",\"kind\":\"issue\",\"title\":\"Counts one line for an empty file\",\"state\":\"closed\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-09T22:20:00.000Z\",\"comments\":0},\"comments\":[],\"closes\":[],\"closedBy\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"},\"checks\":[],\"card\":\"/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru/card.png?v=46a09b63af6fcadf\"}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.issue%2F3myvwhak63fo4&filesOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhak63fo4\",\"kind\":\"issue\",\"title\":\"Fails on files that are not UTF-8\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T05:07:00.000Z\",\"comments\":1,\"labels\":[{\"name\":\"kind/bug\",\"description\":\"Something is broken\",\"color\":\"#d73a4a\"},{\"name\":\"priority/high\",\"color\":\"#fbca04\",\"exclusive\":true}]},\"body\":\"Running `tally image.png` panics:\\n\\n```\\nthread 'main' panicked at src/main.rs:8:56:\\nstream did not contain valid UTF-8\\n```\\n\\nwc counts bytes for any file.\",\"html\":\"<p>Running <code>tally image.png</code> panics:</p>\\n<pre><code>thread 'main' panicked at src/main.rs:8:56:\\nstream did not contain valid UTF-8\\n</code></pre>\\n<p>wc counts bytes for any file.</p>\\n\",\"comments\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.comment/3myvwhakyq3pz\",\"author\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"createdAt\":\"2026-10-10T04:30:00.000Z\",\"updatedAt\":\"2026-10-10T04:42:00.000Z\",\"body\":\"Confirmed. Reading bytes and counting words lossily would fix it.\",\"html\":\"<p>Confirmed. Reading bytes and counting words lossily would fix it.</p>\\n\"}],\"closes\":[],\"checks\":[],\"card\":\"/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhak63fo4/card.png?v=d70e31b0efe160a5\"}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.issue%2F3myvwhaqw6os3&filesOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhaqw6os3\",\"kind\":\"issue\",\"title\":\"Typo in the README โ๏ธ\",\"state\":\"closed\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T06:21:00.000Z\",\"comments\":0},\"comments\":[],\"closes\":[],\"checks\":[],\"card\":\"/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhaqw6os3/card.png?v=88e0042fce25624d\"}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.pull%2F3myvwh7my3ltr&filesOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"kind\":\"pull\",\"title\":\"Count no lines in empty input\",\"state\":\"merged\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T00:48:00.000Z\",\"comments\":3},\"body\":\"`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"html\":\"<p><code>tally</code> printed one line for an empty file. <code>lines</code> now yields nothing when the text is empty, and a test covers it.</p>\\n<p>Fixes <a href=\\\"https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru\\\">the empty file's count</a>.</p>\\n\",\"base\":\"main\",\"head\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"branch\":\"empty-input\"},\"merged\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"comments\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.comment/3myvwh7ohg4vo\",\"author\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"createdAt\":\"2026-10-09T22:57:00.000Z\",\"body\":\"Could `lines` check for emptiness once, rather than in the filter?\",\"html\":\"<p>Could <code>lines</code> check for emptiness once, rather than in the filter?</p>\\n\",\"verdict\":\"changes\"},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.comment/3myvwh7p3spvq\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T00:11:00.000Z\",\"body\":\"It only runs per line, so the cost is one comparison each. Happy to change it if you prefer.\",\"html\":\"<p>It only runs per line, so the cost is one comparison each. Happy to change it if you prefer.</p>\\n\"},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.comment/3myvwh7pws4vr\",\"author\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"createdAt\":\"2026-10-09T23:34:00.000Z\",\"body\":\"Fair enough. Thanks!\",\"html\":\"<p>Fair enough. Thanks!</p>\\n\",\"verdict\":\"approve\"}],\"closes\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwh7kezpru\",\"kind\":\"issue\",\"title\":\"Counts one line for an empty file\",\"state\":\"closed\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-09T22:20:00.000Z\",\"comments\":0}],\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.eyz4we3pck2i4z63rw5caruhiv.d1f87fe9540ab153762a7caf292887855d3e1a90.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"d1f87fe9540ab153762a7caf292887855d3e1a90\",\"startedAt\":\"2026-10-09T09:32:00Z\",\"finishedAt\":\"2026-10-09T09:32:41.500Z\",\"images\":[]}],\"minutes\":[{\"runner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"minutes\":1640,\"allowance\":2000,\"freeing\":[{\"at\":\"2026-11-02T00:00:00Z\",\"minutes\":310}],\"updatedAt\":\"2026-10-25T17:52:00Z\"}],\"changes\":{\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"commits\":[{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00Z\",\"committedAt\":\"2026-10-09T15:00:00Z\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}}],\"files\":[{\"old\":\"src/parse.rs\",\"new\":\"src/parse.rs\",\"status\":\"modified\",\"added\":11,\"removed\":2,\"rows\":[],\"rowCount\":19,\"hunkCount\":1}]},\"card\":\"/alice.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7my3ltr/card.png?v=6530fbcb6cb5067c\"}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.pull%2F3myvwh7my3ltr&filesOnly=true&firstRows=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"kind\":\"pull\",\"title\":\"Count no lines in empty input\",\"state\":\"merged\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T00:48:00.000Z\",\"comments\":3},\"body\":\"`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"html\":\"<p><code>tally</code> printed one line for an empty file. <code>lines</code> now yields nothing when the text is empty, and a test covers it.</p>\\n<p>Fixes <a href=\\\"https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru\\\">the empty file's count</a>.</p>\\n\",\"base\":\"main\",\"head\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"branch\":\"empty-input\"},\"merged\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"comments\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.comment/3myvwh7ohg4vo\",\"author\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"createdAt\":\"2026-10-09T22:57:00.000Z\",\"body\":\"Could `lines` check for emptiness once, rather than in the filter?\",\"html\":\"<p>Could <code>lines</code> check for emptiness once, rather than in the filter?</p>\\n\",\"verdict\":\"changes\"},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.comment/3myvwh7p3spvq\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T00:11:00.000Z\",\"body\":\"It only runs per line, so the cost is one comparison each. Happy to change it if you prefer.\",\"html\":\"<p>It only runs per line, so the cost is one comparison each. Happy to change it if you prefer.</p>\\n\"},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.comment/3myvwh7pws4vr\",\"author\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"createdAt\":\"2026-10-09T23:34:00.000Z\",\"body\":\"Fair enough. Thanks!\",\"html\":\"<p>Fair enough. Thanks!</p>\\n\",\"verdict\":\"approve\"}],\"closes\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwh7kezpru\",\"kind\":\"issue\",\"title\":\"Counts one line for an empty file\",\"state\":\"closed\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-09T22:20:00.000Z\",\"comments\":0}],\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.eyz4we3pck2i4z63rw5caruhiv.d1f87fe9540ab153762a7caf292887855d3e1a90.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"d1f87fe9540ab153762a7caf292887855d3e1a90\",\"startedAt\":\"2026-10-09T09:32:00Z\",\"finishedAt\":\"2026-10-09T09:32:41.500Z\",\"images\":[]}],\"minutes\":[{\"runner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"minutes\":1640,\"allowance\":2000,\"freeing\":[{\"at\":\"2026-11-02T00:00:00Z\",\"minutes\":310}],\"updatedAt\":\"2026-10-25T17:52:00Z\"}],\"changes\":{\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"commits\":[{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00Z\",\"committedAt\":\"2026-10-09T15:00:00Z\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}}],\"files\":[{\"old\":\"src/parse.rs\",\"new\":\"src/parse.rs\",\"status\":\"modified\",\"added\":11,\"removed\":2,\"ranges\":\"comment:39,68,1,72,1,25;string:435,2;keyword:207,3,1,2,22,4,104,3,25,2,49,5;number:448,1;function:9,16,3,5,181,5,54,5,12,5,3,6,11,8,51,24,13,10;type:227,3,10,8,1,4,4,3;attr:330,12,17,7;xins:175,5,117,29;xdel:106,1\",\"rows\":[{\"kind\":\"h\",\"line\":false,\"text\":\"@@ -5,7 +5,16 @@ pub fn words(line: &str) -> usize {\"},{\"kind\":\"\",\"line\":true,\"old\":5,\"new\":5,\"text\":\" line.split_whitespace().count()\"},{\"kind\":\"\",\"line\":true,\"old\":6,\"new\":6,\"text\":\"}\"},{\"kind\":\"\",\"line\":true,\"old\":7,\"new\":7,\"text\":\"\"},{\"kind\":\"d\",\"line\":true,\"old\":8,\"text\":\"/// The lines of `text`. A last line without a newline still counts.\"},{\"kind\":\"a\",\"line\":true,\"new\":8,\"text\":\"/// The lines of `text`. A last line without a newline still counts, and\"},{\"kind\":\"a\",\"line\":true,\"new\":9,\"text\":\"/// empty input has none.\"},{\"kind\":\"\",\"line\":true,\"old\":9,\"new\":10,\"text\":\"pub fn lines(text: &str) -> impl Iterator<Item = &str> {\"},{\"kind\":\"d\",\"line\":true,\"old\":10,\"text\":\" text.lines()\"},{\"kind\":\"a\",\"line\":true,\"new\":11,\"text\":\" text.lines().filter(|_| !text.is_empty())\"},{\"kind\":\"a\",\"line\":true,\"new\":12,\"text\":\"}\"},{\"kind\":\"a\",\"line\":true,\"new\":13,\"text\":\"\"},{\"kind\":\"a\",\"line\":true,\"new\":14,\"text\":\"#[cfg(test)]\"},{\"kind\":\"a\",\"line\":true,\"new\":15,\"text\":\"mod tests {\"},{\"kind\":\"a\",\"line\":true,\"new\":16,\"text\":\" #[test]\"},{\"kind\":\"a\",\"line\":true,\"new\":17,\"text\":\" fn empty_input_has_no_lines() {\"},{\"kind\":\"a\",\"line\":true,\"new\":18,\"text\":\" assert_eq!(super::lines(\\\"\\\").count(), 0);\"},{\"kind\":\"a\",\"line\":true,\"new\":19,\"text\":\" }\"},{\"kind\":\"\",\"line\":true,\"old\":11,\"new\":20,\"text\":\"}\"}]}]},\"card\":\"/alice.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7my3ltr/card.png?v=6530fbcb6cb5067c\"}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.pull%2F3myvwhahturhe&filesOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhahturhe\",\"kind\":\"pull\",\"title\":\"Print counts as JSON with --json\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T03:53:00.000Z\",\"comments\":0},\"body\":\"For scripts. The object has `lines`, `words`, `bytes` and `name`.\",\"html\":\"<p>For scripts. The object has <code>lines</code>, <code>words</code>, <code>bytes</code> and <code>name</code>.</p>\\n\",\"base\":\"main\",\"head\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"branch\":\"json\"},\"comments\":[],\"closes\":[],\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.build\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"build\",\"status\":\"success\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"finishedAt\":\"2026-10-10T16:13:41.500Z\",\"images\":[]},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.docs\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"docs\",\"status\":\"success\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"finishedAt\":\"2026-10-10T16:13:00.000Z\",\"skipped\":\"skipped: nothing changed in docs/**, assets/**, .knotless/workflows/docs.yml\",\"images\":[]},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.lint\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"lint\",\"status\":\"running\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"images\":[]},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"failure\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"finishedAt\":\"2026-10-10T16:13:45.500Z\",\"images\":[{\"alt\":\"pull-desktop-light 1 before\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreifhzh7dl36rji3rpd3yf5v76ktdultbqrwsaczwwaggigald7ooui\"},{\"alt\":\"pull-desktop-light 2 after\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreia22sofk3n6ehep4qsfhd6bhvbysz4f4tazkigduv3xl5r7a6zm4m\"},{\"alt\":\"pull-desktop-light 3 difference\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreidgy7vnqjmsemzlt5ah4fo3v3vn2q7uaj3bgq2jcaovfqr3lo2rq4\"}]}],\"minutes\":[{\"runner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"minutes\":1640,\"allowance\":2000,\"freeing\":[{\"at\":\"2026-11-02T00:00:00Z\",\"minutes\":310}],\"updatedAt\":\"2026-10-25T17:52:00Z\"}],\"changes\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"commits\":[{\"sha\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\"},\"coauthors\":[],\"date\":\"2026-10-10T16:12:00Z\",\"committedAt\":\"2026-10-10T16:12:00Z\",\"message\":\"Print counts as JSON with --json\"}],\"files\":[{\"old\":\"src/main.rs\",\"new\":\"src/main.rs\",\"status\":\"modified\",\"added\":10,\"removed\":4,\"rows\":[],\"rowCount\":26,\"hunkCount\":2}]},\"card\":\"/alice.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhahturhe/card.png?v=5eefedaa620f788d\"}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.pull%2F3myvwhbuzv5n3&filesOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhbuzv5n3\",\"kind\":\"pull\",\"title\":\"Count bytes in files that are not UTF-8\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T12:31:00.000Z\",\"comments\":0},\"base\":\"main\",\"head\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"branch\":\"bytes\"},\"comments\":[],\"closes\":[],\"queue\":{\"state\":\"queued\",\"createdAt\":\"2026-10-15T09:30:00.000Z\",\"said\":\"In a batch of 2 being checked\",\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6.226488be4afaf037c2331c7480d4a48790f20eba.build\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"build\",\"status\":\"success\",\"commit\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"startedAt\":\"2026-10-20T10:00:00Z\",\"finishedAt\":\"2026-10-20T10:01:35.000Z\",\"images\":[]},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"running\",\"commit\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"startedAt\":\"2026-10-20T10:00:00Z\",\"images\":[]}],\"stage\":\"checking\",\"typical\":{\"batchSeconds\":95,\"preflightSeconds\":360},\"batchStartedAt\":\"2026-10-20T10:00:00Z\"},\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.qlmgye4xm2squgtqbxmey3k6wo.87a3fcfe0a12c9f038fa4e5a5d276a96b19e03ca.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"87a3fcfe0a12c9f038fa4e5a5d276a96b19e03ca\",\"startedAt\":\"2026-10-20T09:40:00Z\",\"finishedAt\":\"2026-10-20T09:46:00.000Z\",\"images\":[]}],\"minutes\":[{\"runner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"minutes\":2140,\"allowance\":2000,\"freeing\":[{\"at\":\"2026-11-02T00:00:00Z\",\"minutes\":400}],\"updatedAt\":\"2026-10-25T17:52:00Z\"}],\"changes\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"commits\":[{\"sha\":\"87a3fcfe0a12c9f038fa4e5a5d276a96b19e03ca\",\"parents\":[{\"sha\":\"226488be4afaf037c2331c7480d4a48790f20eba\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"date\":\"2026-10-11T09:00:00Z\",\"committedAt\":\"2026-10-11T09:00:00Z\",\"message\":\"Count bytes in files that are not UTF-8\"}],\"files\":[{\"old\":\"docs/bytes.md\",\"new\":\"docs/bytes.md\",\"status\":\"added\",\"added\":1,\"removed\":0,\"rows\":[],\"rowCount\":2,\"hunkCount\":1}]},\"card\":\"/bob.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhbuzv5n3/card.png?v=4db36ffc788a66bb\"}"
},
"/xrpc/dev.knotless.getThread?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.pull%2F3myvwhcnn4cic&filesOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"item\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhcnn4cic\",\"kind\":\"pull\",\"title\":\"Print a total for many files\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T18:04:00.000Z\",\"comments\":0},\"base\":\"main\",\"head\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"branch\":\"totals\"},\"comments\":[],\"closes\":[],\"queue\":{\"state\":\"ejected\",\"reason\":\"its batch failed its checks at 6f89484c63a3, on main at 226488be4afa: test (failure)\",\"createdAt\":\"2026-10-19T15:02:00.000Z\",\"said\":\"Ejected: its batch failed its checks at 6f89484c63a3, on main at 226488be4afa: test (failure). Failed: test (failure)\",\"checks\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.6f89484c63a36649168e3d77a1e631f695469b74.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"failure\",\"commit\":\"6f89484c63a36649168e3d77a1e631f695469b74\",\"startedAt\":\"2026-10-19T15:00:00Z\",\"finishedAt\":\"2026-10-19T15:01:35.000Z\",\"images\":[]}]},\"checks\":[],\"minutes\":[{\"runner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"minutes\":2140,\"allowance\":2000,\"freeing\":[{\"at\":\"2026-11-02T00:00:00Z\",\"minutes\":400}],\"updatedAt\":\"2026-10-25T17:52:00Z\"}],\"changes\":{\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"commits\":[{\"sha\":\"6f89484c63a36649168e3d77a1e631f695469b74\",\"parents\":[{\"sha\":\"226488be4afaf037c2331c7480d4a48790f20eba\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"date\":\"2026-10-11T12:00:00Z\",\"committedAt\":\"2026-10-11T12:00:00Z\",\"message\":\"Print a total for many files\"}],\"files\":[{\"old\":\"docs/totals.md\",\"new\":\"docs/totals.md\",\"status\":\"added\",\"added\":1,\"removed\":0,\"rows\":[],\"rowCount\":2,\"hunkCount\":1}]},\"card\":\"/bob.test/tally/pull/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwhcnn4cic/card.png?v=0bde049a81b5f11e\"}"
},
"/xrpc/dev.knotless.getTree?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Fscratch": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"\",\"empty\":true,\"entries\":[],\"checks\":[],\"languages\":[]}"
},
"/xrpc/dev.knotless.getTree?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"\",\"lastCommit\":{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00+00:00\",\"committedAt\":\"2026-10-09T15:00:00+00:00\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}},\"entries\":[{\"name\":\"assets\",\"kind\":\"tree\"},{\"name\":\"docs\",\"kind\":\"tree\"},{\"name\":\"src\",\"kind\":\"tree\"},{\"name\":\".gitignore\",\"kind\":\"blob\",\"size\":8},{\"name\":\"Cargo.toml\",\"kind\":\"blob\",\"size\":122},{\"name\":\"README.md\",\"kind\":\"blob\",\"size\":388}],\"readme\":{\"name\":\"README.md\",\"html\":\"<h1>tally</h1>\\n<p>Counts lines, words and bytes, like <code>wc</code>, with output that lines up.</p>\\n<p><img src=\\\"/alice.test/tally/raw/main/assets/logo.svg\\\" alt=\\\"tally\\\" /></p>\\n<h2>Usage</h2>\\n<pre><code class=\\\"language-sh\\\">cargo install --path .\\ntally notes.txt\\necho \\\"one two\\\" | tally\\n</code></pre>\\n<h2>Output</h2>\\n<table><thead><tr><th>Column</th><th>Meaning</th></tr></thead><tbody>\\n<tr><td>1</td><td>lines</td></tr>\\n<tr><td>2</td><td>words, split on whitespace</td></tr>\\n<tr><td>3</td><td>bytes</td></tr>\\n</tbody></table>\\n<p>See <a href=\\\"/alice.test/tally/blob/main/docs/design.md\\\">the design notes</a> for why it reads the whole file.</p>\\n<h2>License</h2>\\n<p>MIT</p>\\n\"},\"checks\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.check/ppk3ktprvyuf4xa3s63c2nt3kd.3myvwh5dhhixv.7eq32bpgrmbxidcfbzlf4dtbop.1be297a440088f5808a7cdcf5254ac71c024458f.lint\",\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"workflow\":\"lint\",\"status\":\"success\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"startedAt\":\"2026-10-11T09:00:00Z\",\"finishedAt\":\"2026-10-11T09:00:41.500Z\",\"images\":[]},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.check/ppk3ktprvyuf4xa3s63c2nt3kd.3myvwh5dhhixv.7eq32bpgrmbxidcfbzlf4dtbop.1be297a440088f5808a7cdcf5254ac71c024458f.test\",\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"startedAt\":\"2026-10-11T09:00:00Z\",\"finishedAt\":\"2026-10-11T09:00:41.500Z\",\"images\":[]}],\"languages\":[{\"name\":\"Rust\",\"color\":\"#dea584\",\"bytes\":1785,\"permille\":1000}]}"
},
"/xrpc/dev.knotless.getTree?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main%2Fsrc": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"src\",\"lastCommit\":{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00+00:00\",\"committedAt\":\"2026-10-09T15:00:00+00:00\",\"message\":\"Count no lines in empty input\\n\\n`tally` printed one line for an empty file. `lines` now yields nothing when the text is empty, and a test covers it.\\n\\nFixes [the empty file's count](https://knotless.dev/alice.test/tally/issue/did:plc:55j6e4wxzlzndxm4nov2lz7x/3myvwh7kezpru).\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}},\"entries\":[{\"name\":\"lib.rs\",\"kind\":\"blob\",\"size\":783},{\"name\":\"main.rs\",\"kind\":\"blob\",\"size\":484},{\"name\":\"parse.rs\",\"kind\":\"blob\",\"size\":518}],\"checks\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.check/ppk3ktprvyuf4xa3s63c2nt3kd.3myvwh5dhhixv.7eq32bpgrmbxidcfbzlf4dtbop.1be297a440088f5808a7cdcf5254ac71c024458f.lint\",\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"workflow\":\"lint\",\"status\":\"success\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"startedAt\":\"2026-10-11T09:00:00Z\",\"finishedAt\":\"2026-10-11T09:00:41.500Z\",\"images\":[]},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.check/ppk3ktprvyuf4xa3s63c2nt3kd.3myvwh5dhhixv.7eq32bpgrmbxidcfbzlf4dtbop.1be297a440088f5808a7cdcf5254ac71c024458f.test\",\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"startedAt\":\"2026-10-11T09:00:00Z\",\"finishedAt\":\"2026-10-11T09:00:41.500Z\",\"images\":[]}],\"languages\":[]}"
},
"/xrpc/dev.knotless.getTree?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"\",\"lastCommit\":{\"sha\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"parents\":[{\"sha\":\"226488be4afaf037c2331c7480d4a48790f20eba\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"date\":\"2026-10-20T12:00:00+00:00\",\"committedAt\":\"2026-10-20T12:00:00+00:00\",\"message\":\"Release from tags when asked\"},\"entries\":[{\"name\":\".knotless\",\"kind\":\"tree\"},{\"name\":\"assets\",\"kind\":\"tree\"},{\"name\":\"docs\",\"kind\":\"tree\"},{\"name\":\"src\",\"kind\":\"tree\"},{\"name\":\".gitignore\",\"kind\":\"blob\",\"size\":8},{\"name\":\"Cargo.toml\",\"kind\":\"blob\",\"size\":122},{\"name\":\"README.md\",\"kind\":\"blob\",\"size\":388}],\"readme\":{\"name\":\"README.md\",\"html\":\"<h1>tally</h1>\\n<p>Counts lines, words and bytes, like <code>wc</code>, with output that lines up.</p>\\n<p><img src=\\\"/bob.test/tally/raw/main/assets/logo.svg\\\" alt=\\\"tally\\\" /></p>\\n<h2>Usage</h2>\\n<pre><code class=\\\"language-sh\\\">cargo install --path .\\ntally notes.txt\\necho \\\"one two\\\" | tally\\n</code></pre>\\n<h2>Output</h2>\\n<table><thead><tr><th>Column</th><th>Meaning</th></tr></thead><tbody>\\n<tr><td>1</td><td>lines</td></tr>\\n<tr><td>2</td><td>words, split on whitespace</td></tr>\\n<tr><td>3</td><td>bytes</td></tr>\\n</tbody></table>\\n<p>See <a href=\\\"/bob.test/tally/blob/main/docs/design.md\\\">the design notes</a> for why it reads the whole file.</p>\\n<h2>License</h2>\\n<p>MIT</p>\\n\"},\"checks\":[],\"languages\":[{\"name\":\"Rust\",\"color\":\"#dea584\",\"bytes\":1595,\"permille\":1000}]}"
},
"/xrpc/dev.knotless.getViewer": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"login\":false}"
},
"/xrpc/dev.knotless.listBranches?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Fscratch&limit=1000": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"branches\":[]}"
},
"/xrpc/dev.knotless.listBranches?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&limit=1000": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"branches\":[{\"name\":\"main\"}]}"
},
"/xrpc/dev.knotless.listBranches?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally&limit=1000": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"branches\":[{\"name\":\"main\"},{\"name\":\"bytes\"},{\"name\":\"empty-input\"},{\"name\":\"json\"},{\"name\":\"tabs\"},{\"name\":\"totals\"},{\"name\":\"words\"}]}"
},
"/xrpc/dev.knotless.listCommits?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&ref=main&subjectOnly=true": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"ref\":\"main\",\"path\":\"\",\"commits\":[{\"sha\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"parents\":[{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\"}],\"author\":{\"name\":\"Bob Tanaka\",\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},\"coauthors\":[],\"committer\":{\"name\":\"alice.test\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"date\":\"2026-10-09T09:31:00+00:00\",\"committedAt\":\"2026-10-09T15:00:00+00:00\",\"message\":\"Count no lines in empty input\",\"pull\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"title\":\"Count no lines in empty input\"}},{\"sha\":\"052e48d313c5ebeb08f596cd683ba1eade3fb1ac\",\"parents\":[{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-08T11:47:00+00:00\",\"committedAt\":\"2026-10-08T11:47:00+00:00\",\"message\":\"Split parsing into its own module\"},{\"sha\":\"4abc93fa7cb85e41149e17f70dfcc4d3830ba0f2\",\"parents\":[{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-06T10:02:00+00:00\",\"committedAt\":\"2026-10-06T10:02:00+00:00\",\"message\":\"Document usage and output\"},{\"sha\":\"4b29199f359ce31aa300ec409cdbdfa44d347ad5\",\"parents\":[{\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-02T11:30:00+00:00\",\"committedAt\":\"2026-10-05T17:21:00+00:00\",\"message\":\"Add a logo\"},{\"sha\":\"7818a5bc1bef9184ad313cf79175da3d87d4b9cf\",\"parents\":[{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-03T08:05:00+00:00\",\"committedAt\":\"2026-10-03T08:05:00+00:00\",\"message\":\"Read from stdin when no file is given\"},{\"sha\":\"a7e467c6f9acd7b1be0603afdec0b8cfdcf3cf49\",\"parents\":[{\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\"}],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-02T14:40:00+00:00\",\"committedAt\":\"2026-10-02T14:40:00+00:00\",\"message\":\"Count words, lines and bytes\"},{\"sha\":\"cac02c464843db4d55fecfa69d327ef7b12702c0\",\"parents\":[],\"author\":{\"name\":\"Alice Moreau\",\"actor\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},\"coauthors\":[],\"date\":\"2026-10-01T09:12:00+00:00\",\"committedAt\":\"2026-10-01T09:12:00+00:00\",\"message\":\"Start tally\"}],\"checks\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.check/ppk3ktprvyuf4xa3s63c2nt3kd.3myvwh5dhhixv.7eq32bpgrmbxidcfbzlf4dtbop.1be297a440088f5808a7cdcf5254ac71c024458f.lint\",\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"workflow\":\"lint\",\"status\":\"success\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"startedAt\":\"2026-10-11T09:00:00Z\",\"finishedAt\":\"2026-10-11T09:00:41.500Z\",\"images\":[]},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.check/ppk3ktprvyuf4xa3s63c2nt3kd.3myvwh5dhhixv.7eq32bpgrmbxidcfbzlf4dtbop.1be297a440088f5808a7cdcf5254ac71c024458f.test\",\"repo\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"startedAt\":\"2026-10-11T09:00:00Z\",\"finishedAt\":\"2026-10-11T09:00:41.500Z\",\"images\":[]}]}"
},
"/xrpc/dev.knotless.listItems?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&kind=issue": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"items\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhak63fo4\",\"kind\":\"issue\",\"title\":\"Fails on files that are not UTF-8\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T05:07:00.000Z\",\"comments\":1,\"labels\":[{\"name\":\"kind/bug\",\"description\":\"Something is broken\",\"color\":\"#d73a4a\"},{\"name\":\"priority/high\",\"color\":\"#fbca04\",\"exclusive\":true}]}],\"openCount\":1,\"closedCount\":2,\"labels\":[{\"name\":\"kind/bug\",\"description\":\"Something is broken\",\"color\":\"#d73a4a\"},{\"name\":\"priority/high\",\"color\":\"#fbca04\",\"exclusive\":true},{\"name\":\"priority/low\",\"exclusive\":true}],\"authors\":[{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}]}"
},
"/xrpc/dev.knotless.listItems?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&kind=issue&state=closed": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"items\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwhaqw6os3\",\"kind\":\"issue\",\"title\":\"Typo in the README โ๏ธ\",\"state\":\"closed\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T06:21:00.000Z\",\"comments\":0},{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.issue/3myvwh7kezpru\",\"kind\":\"issue\",\"title\":\"Counts one line for an empty file\",\"state\":\"closed\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-09T22:20:00.000Z\",\"comments\":0}],\"openCount\":1,\"closedCount\":2,\"labels\":[{\"name\":\"kind/bug\",\"description\":\"Something is broken\",\"color\":\"#d73a4a\"},{\"name\":\"priority/high\",\"color\":\"#fbca04\",\"exclusive\":true},{\"name\":\"priority/low\",\"exclusive\":true}],\"authors\":[{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}]}"
},
"/xrpc/dev.knotless.listItems?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&kind=pull": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"items\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwhahturhe\",\"kind\":\"pull\",\"title\":\"Print counts as JSON with --json\",\"state\":\"open\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T03:53:00.000Z\",\"comments\":0}],\"openCount\":1,\"closedCount\":1,\"labels\":[{\"name\":\"kind/bug\",\"description\":\"Something is broken\",\"color\":\"#d73a4a\"},{\"name\":\"priority/high\",\"color\":\"#fbca04\",\"exclusive\":true},{\"name\":\"priority/low\",\"exclusive\":true}],\"authors\":[{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}]}"
},
"/xrpc/dev.knotless.listItems?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&kind=pull&state=closed": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"items\":[{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.pull/3myvwh7my3ltr\",\"kind\":\"pull\",\"title\":\"Count no lines in empty input\",\"state\":\"merged\",\"author\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"createdAt\":\"2026-10-10T00:48:00.000Z\",\"comments\":3}],\"openCount\":1,\"closedCount\":1,\"labels\":[{\"name\":\"kind/bug\",\"description\":\"Something is broken\",\"color\":\"#d73a4a\"},{\"name\":\"priority/high\",\"color\":\"#fbca04\",\"exclusive\":true},{\"name\":\"priority/low\",\"exclusive\":true}],\"authors\":[{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}]}"
},
"/xrpc/dev.knotless.listReleases?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"releases\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.release/3myvwh5dhhixv.wapcnu7vuujqxhmnqiofvhlb47.4iqtjhkd5xtc6nvxjtcplav3mh\",\"package\":\"tally\",\"version\":\"0.2.0-rc.1\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"notes\":\"A first look at 0.2.0: try it before it is the latest.\\n\\n- `tally --json` prints the counts as JSON.\",\"html\":\"<p>A first look at 0.2.0: try it before it is the latest.</p>\\n<ul>\\n<li><code>tally --json</code> prints the counts as JSON.</li>\\n</ul>\\n\",\"files\":[{\"name\":\"tally-0.2.0-rc.1-aarch64-apple-darwin.tar.gz\",\"size\":172032,\"sha256\":\"da6e38124ca1bb9efa43eb35d5148ab3d437b49da67f258efd19d98bd46fb860\"},{\"name\":\"tally-0.2.0-rc.1-x86_64-unknown-linux-musl.tar.gz\",\"size\":192512,\"sha256\":\"9c0a748f61f0f6f1f1f5518393e02abdb79ec862dfd753907dc1bcdcfa74832f\"}],\"createdAt\":\"2026-10-10T20:32:00.000Z\"},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.release/3myvwh5dhhixv.sajgnrdpok3qjqfai5tphxfymk.nlmwcosfk6mnnwjol5ptscvuxk\",\"package\":\"tally-server\",\"version\":\"0.1.0\",\"latest\":true,\"image\":true,\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"notes\":\"Serves counts over HTTP: `POST /count` with the text, and the counts come back as JSON.\",\"html\":\"<p>Serves counts over HTTP: <code>POST /count</code> with the text, and the counts come back as JSON.</p>\\n\",\"files\":[{\"name\":\"index.json\",\"size\":240,\"sha256\":\"a53c265aef5680b3af6e7cff738c2b74ed168fd9b0a9e52cf95341c99e28fd37\"},{\"name\":\"sha256-0a65ccdfafd0466251f34e09646cb6b61b3efc5ffad195fd93e197e7813dee7c\",\"size\":38912,\"sha256\":\"0a65ccdfafd0466251f34e09646cb6b61b3efc5ffad195fd93e197e7813dee7c\"},{\"name\":\"sha256-a766366ea00c16715e1482c28134d519c69b9b9800b96fc88c8e6d25d3d782a8\",\"size\":151,\"sha256\":\"a766366ea00c16715e1482c28134d519c69b9b9800b96fc88c8e6d25d3d782a8\"},{\"name\":\"sha256-d5fcb60ba73f2450429ca13d79353b065b58ec5750b1ec7f996e86b0b200cb3d\",\"size\":403,\"sha256\":\"d5fcb60ba73f2450429ca13d79353b065b58ec5750b1ec7f996e86b0b200cb3d\"}],\"createdAt\":\"2026-10-10T19:55:00.000Z\"},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.release/3myvwh5dhhixv.wapcnu7vuujqxhmnqiofvhlb47.chxchoh4f7dbtvxkwytxvw22kj\",\"package\":\"tally\",\"version\":\"0.1.1\",\"latest\":true,\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"notes\":\"### Fixed\\n\\n- An empty file counts no lines.\\n- Input that is not UTF-8 is counted as bytes rather than failing.\",\"html\":\"<h3>Fixed</h3>\\n<ul>\\n<li>An empty file counts no lines.</li>\\n<li>Input that is not UTF-8 is counted as bytes rather than failing.</li>\\n</ul>\\n\",\"files\":[{\"name\":\"tally-0.1.1-aarch64-apple-darwin.tar.gz\",\"size\":151552,\"sha256\":\"49cb04d7a48d024d74e374957d3fa877e38f609441647e396313224e03524120\"},{\"name\":\"tally-0.1.1-x86_64-unknown-linux-musl.tar.gz\",\"size\":172032,\"sha256\":\"a51f44205754a7c796f4e978fc4a262ffd6fb552fe47cca174b2f64105b56391\"}],\"createdAt\":\"2026-10-10T19:18:00.000Z\"},{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.release/3myvwh5dhhixv.wapcnu7vuujqxhmnqiofvhlb47.nlmwcosfk6mnnwjol5ptscvuxk\",\"package\":\"tally\",\"version\":\"0.1.0\",\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"notes\":\"The first release: `tally` counts lines, words and bytes, as `wc` does.\",\"html\":\"<p>The first release: <code>tally</code> counts lines, words and bytes, as <code>wc</code> does.</p>\\n\",\"files\":[{\"name\":\"tally-0.1.0-aarch64-apple-darwin.tar.gz\",\"size\":151552,\"sha256\":\"e5cd98302910fdf1958bff52b1396c13ef7e0931804763bcd2bcafbce1608652\"},{\"name\":\"tally-0.1.0-x86_64-unknown-linux-musl.tar.gz\",\"size\":172032,\"sha256\":\"b1a1dc96954e2d9f74d938aa55828a0cc265a285d4fa741e9bc271649609a338\"}],\"createdAt\":\"2026-10-10T18:41:00.000Z\"}],\"packages\":[{\"name\":\"tally\",\"latest\":\"0.1.1\",\"releaseCount\":3},{\"name\":\"tally-server\",\"latest\":\"0.1.0\",\"image\":true,\"releaseCount\":1}]}"
},
"/xrpc/dev.knotless.listReleases?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&package=tally-server": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"releases\":[{\"uri\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.release/3myvwh5dhhixv.sajgnrdpok3qjqfai5tphxfymk.nlmwcosfk6mnnwjol5ptscvuxk\",\"package\":\"tally-server\",\"version\":\"0.1.0\",\"latest\":true,\"image\":true,\"commit\":\"1be297a440088f5808a7cdcf5254ac71c024458f\",\"notes\":\"Serves counts over HTTP: `POST /count` with the text, and the counts come back as JSON.\",\"html\":\"<p>Serves counts over HTTP: <code>POST /count</code> with the text, and the counts come back as JSON.</p>\\n\",\"files\":[{\"name\":\"index.json\",\"size\":240,\"sha256\":\"a53c265aef5680b3af6e7cff738c2b74ed168fd9b0a9e52cf95341c99e28fd37\"},{\"name\":\"sha256-0a65ccdfafd0466251f34e09646cb6b61b3efc5ffad195fd93e197e7813dee7c\",\"size\":38912,\"sha256\":\"0a65ccdfafd0466251f34e09646cb6b61b3efc5ffad195fd93e197e7813dee7c\"},{\"name\":\"sha256-a766366ea00c16715e1482c28134d519c69b9b9800b96fc88c8e6d25d3d782a8\",\"size\":151,\"sha256\":\"a766366ea00c16715e1482c28134d519c69b9b9800b96fc88c8e6d25d3d782a8\"},{\"name\":\"sha256-d5fcb60ba73f2450429ca13d79353b065b58ec5750b1ec7f996e86b0b200cb3d\",\"size\":403,\"sha256\":\"d5fcb60ba73f2450429ca13d79353b065b58ec5750b1ec7f996e86b0b200cb3d\"}],\"createdAt\":\"2026-10-10T19:55:00.000Z\"}],\"packages\":[{\"name\":\"tally\",\"latest\":\"0.1.1\",\"releaseCount\":3},{\"name\":\"tally-server\",\"latest\":\"0.1.0\",\"image\":true,\"releaseCount\":1}]}"
},
"/xrpc/dev.knotless.listReleases?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"releases\":[]}"
},
"/xrpc/dev.knotless.listRepos?q=t": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"repos\":[{\"createdAt\":\"2026-10-09T18:38:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},{\"createdAt\":\"2026-10-09T14:56:00.000Z\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"scratch\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},{\"createdAt\":\"2026-10-09T11:51:00.000Z\",\"description\":\"Scratch notes ๐\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"notes\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}},{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}]}"
},
"/xrpc/dev.knotless.listRunners?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"runners\":[{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}],\"minutes\":[{\"runner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"minutes\":1640,\"allowance\":2000,\"freeing\":[{\"at\":\"2026-11-02T00:00:00Z\",\"minutes\":310}],\"updatedAt\":\"2026-10-25T17:52:00Z\"}],\"keys\":[{\"runner\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"key\":\"did:key:zDnaepwQjCS7ayRrLp2j3oFd8kfJ97mehqYTGFBNA3QqSsvNV\"}]}"
},
"/xrpc/dev.knotless.listRuns?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"runs\":[{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"running\",\"commit\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"startedAt\":\"2026-10-20T10:00:00Z\",\"images\":[]},\"ref\":\"refs/heads/main\",\"batch\":2},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6.226488be4afaf037c2331c7480d4a48790f20eba.build\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"build\",\"status\":\"success\",\"commit\":\"ee347cbe693bbc8c7f70dbb7b30bc329f34dcfa6\",\"startedAt\":\"2026-10-20T10:00:00Z\",\"finishedAt\":\"2026-10-20T10:01:35.000Z\",\"images\":[]},\"ref\":\"refs/heads/main\",\"batch\":2},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.6f89484c63a36649168e3d77a1e631f695469b74.226488be4afaf037c2331c7480d4a48790f20eba.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"failure\",\"commit\":\"6f89484c63a36649168e3d77a1e631f695469b74\",\"startedAt\":\"2026-10-19T15:00:00Z\",\"finishedAt\":\"2026-10-19T15:01:35.000Z\",\"images\":[]},\"ref\":\"refs/heads/main\",\"batch\":1},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.6f89484c63a36649168e3d77a1e631f695469b74.226488be4afaf037c2331c7480d4a48790f20eba.build\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"build\",\"status\":\"success\",\"commit\":\"6f89484c63a36649168e3d77a1e631f695469b74\",\"startedAt\":\"2026-10-19T15:00:00Z\",\"finishedAt\":\"2026-10-19T15:01:35.000Z\",\"images\":[]},\"ref\":\"refs/heads/main\",\"batch\":1},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.226488be4afaf037c2331c7480d4a48790f20eba.052e48d313c5ebeb08f596cd683ba1eade3fb1ac.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"226488be4afaf037c2331c7480d4a48790f20eba\",\"startedAt\":\"2026-10-19T09:00:00Z\",\"finishedAt\":\"2026-10-19T09:01:35.000Z\",\"images\":[]},\"ref\":\"refs/heads/main\",\"batch\":1},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.gkn5el4746pzeyvms3btnm2gqt.226488be4afaf037c2331c7480d4a48790f20eba.052e48d313c5ebeb08f596cd683ba1eade3fb1ac.build\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"build\",\"status\":\"success\",\"commit\":\"226488be4afaf037c2331c7480d4a48790f20eba\",\"startedAt\":\"2026-10-19T09:00:00Z\",\"finishedAt\":\"2026-10-19T09:01:35.000Z\",\"images\":[]},\"ref\":\"refs/heads/main\",\"batch\":1},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"failure\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"finishedAt\":\"2026-10-10T16:13:45.500Z\",\"images\":[{\"alt\":\"pull-desktop-light 1 before\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreifhzh7dl36rji3rpd3yf5v76ktdultbqrwsaczwwaggigald7ooui\"},{\"alt\":\"pull-desktop-light 2 after\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreia22sofk3n6ehep4qsfhd6bhvbysz4f4tazkigduv3xl5r7a6zm4m\"},{\"alt\":\"pull-desktop-light 3 difference\",\"url\":\"/xrpc/dev.knotless.getCheckImage?repo=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.repo%2Ftally&uri=at%3A%2F%2Fdid%3Aplc%3A55j6e4wxzlzndxm4nov2lz7x%2Fdev.knotless.check%2Fqdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.test&cid=bafkreidgy7vnqjmsemzlt5ah4fo3v3vn2q7uaj3bgq2jcaovfqr3lo2rq4\"}]},\"ref\":\"refs/heads/json\",\"subject\":\"Print counts as JSON with --json\"},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.lint\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"lint\",\"status\":\"running\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"images\":[]},\"ref\":\"refs/heads/json\",\"subject\":\"Print counts as JSON with --json\"},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.docs\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"docs\",\"status\":\"success\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"finishedAt\":\"2026-10-10T16:13:00.000Z\",\"skipped\":\"skipped: nothing changed in docs/**, assets/**, .knotless/workflows/docs.yml\",\"images\":[]},\"ref\":\"refs/heads/json\",\"subject\":\"Print counts as JSON with --json\"},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.uuiududme6qwohxvshbn32i4nw.bea82d97f7448b5d6d93b6a8a108ccb9d86277ad.build\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"build\",\"status\":\"success\",\"commit\":\"bea82d97f7448b5d6d93b6a8a108ccb9d86277ad\",\"startedAt\":\"2026-10-10T16:13:00Z\",\"finishedAt\":\"2026-10-10T16:13:41.500Z\",\"images\":[]},\"ref\":\"refs/heads/json\",\"subject\":\"Print counts as JSON with --json\"},{\"check\":{\"uri\":\"at://did:plc:55j6e4wxzlzndxm4nov2lz7x/dev.knotless.check/qdjbmvovu2tnodagwluxk6jxmq.3myvwh72yvtgz.eyz4we3pck2i4z63rw5caruhiv.d1f87fe9540ab153762a7caf292887855d3e1a90.test\",\"repo\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\",\"name\":\"tally\"},\"workflow\":\"test\",\"status\":\"success\",\"commit\":\"d1f87fe9540ab153762a7caf292887855d3e1a90\",\"startedAt\":\"2026-10-09T09:32:00Z\",\"finishedAt\":\"2026-10-09T09:32:41.500Z\",\"images\":[]},\"ref\":\"refs/heads/empty-input\",\"subject\":\"Count no lines in empty input\"}],\"workflows\":[{\"name\":\"release\",\"asked\":true,\"about\":\"Builds the release binaries for a tag and attaches them to it.\"}],\"minutes\":[{\"runner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"minutes\":2140,\"allowance\":2000,\"freeing\":[{\"at\":\"2026-11-02T00:00:00Z\",\"minutes\":400}],\"updatedAt\":\"2026-10-25T17:52:00Z\"}]}"
},
"/xrpc/dev.knotless.listTags?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Fscratch&limit=1000": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"tags\":[]}"
},
"/xrpc/dev.knotless.listTags?repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally&limit=1000": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"tags\":[]}"
},
"/xrpc/dev.knotless.listTags?repo=at%3A%2F%2Fbob.test%2Fdev.knotless.repo%2Ftally&limit=1000": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"tags\":[]}"
},
"/xrpc/dev.knotless.searchOwners?q=t": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"owners\":[{\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"repoCount\":1},{\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"},\"repoCount\":3}]}"
},
"/xrpc/dev.knotless.getActorActivity?actor=did%3Aplc%3A2ejydq2mzgqz2tzdtgk3figi&since=2025-10-21T00%3A00%3A00.000Z&tz=America%2FNew_York": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"days\":[],\"repos\":[]}"
},
"/xrpc/dev.knotless.getActorRepos?actor=textkit.test": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"repos\":[]}"
},
"/xrpc/dev.knotless.getOrg?actor=did%3Aplc%3A2ejydq2mzgqz2tzdtgk3figi": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"org\":{\"did\":\"did:plc:2ejydq2mzgqz2tzdtgk3figi\",\"handle\":\"textkit.test\"},\"organization\":true,\"inside\":false,\"members\":[{\"actor\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"},\"role\":\"admin\",\"standing\":\"public\",\"invitedAt\":\"2026-10-12T09:00:00.000Z\",\"joinedAt\":\"2026-10-12T11:00:00.000Z\"}]}"
},
"/xrpc/dev.knotless.getProfile?actor=textkit.test": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"did\":\"did:plc:2ejydq2mzgqz2tzdtgk3figi\",\"handle\":\"textkit.test\",\"displayName\":\"Textkit\",\"description\":\"Tools for text, made together.\",\"followersCount\":0,\"followsCount\":0,\"organization\":true,\"badges\":[{\"kind\":\"carry-your-own\",\"tier\":1,\"count\":1}]}"
},
"/xrpc/dev.knotless.listRepos?q=count": {
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": "{\"repos\":[{\"createdAt\":\"2026-10-09T16:47:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}},{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}]}"
},
"/xrpc/dev.knotless.searchCode?q=count": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"fileCount\":12,\"files\":[{\"chunks\":[{\"content\":\"//! Counting, kept apart from reading so it can be tested.\\n\",\"highlights\":\"comment:0,59\",\"ranges\":[{\"byteEnd\":9,\"byteStart\":4,\"line\":1}],\"startLine\":1},{\"content\":\"#[derive(Debug, Default, PartialEq)]\\npub struct Counts {\\n pub lines: usize,\",\"highlights\":\"keyword:37,3,1,6,14,3;type:9,5,2,7,2,9,14,6,18,5;attr:0,9,5,2,7,2,9,2\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":7}],\"startLine\":6},{\"content\":\"\\n/// Counts `text` in one pass.\\npub fn count(text: &str) -> Counts {\\n let mut counts = Counts { bytes: text.len(), ..Counts::default() };\\n for line in parse::lines(text) {\\n counts.lines += 1;\\n counts.words += parse::words(line);\\n }\\n counts\\n}\",\"highlights\":\"comment:1,31;keyword:32,3,1,2,35,3,1,3,65,3,6,2;number:202,1;function:39,5,67,3,14,7,29,5,67,5;type:52,3,5,6,24,6,24,6\",\"ranges\":[{\"byteEnd\":9,\"byteStart\":4,\"line\":13},{\"byteEnd\":12,\"byteStart\":7,\"line\":14},{\"byteEnd\":33,\"byteStart\":28,\"line\":14},{\"byteEnd\":17,\"byteStart\":12,\"line\":15},{\"byteEnd\":26,\"byteStart\":21,\"line\":15},{\"byteEnd\":56,\"byteStart\":51,\"line\":15},{\"byteEnd\":13,\"byteStart\":8,\"line\":17},{\"byteEnd\":13,\"byteStart\":8,\"line\":18},{\"byteEnd\":9,\"byteStart\":4,\"line\":20}],\"startLine\":12},{\"content\":\" #[test]\\n fn counts() {\\n let c = count(\\\"one two\\\\nthree\\\\n\\\");\\n assert_eq!(c, Counts { lines: 2, words: 3, bytes: 14 });\\n }\",\"highlights\":\"string:52,18;keyword:16,2,20,3;number:111,1,9,1,9,2;function:19,6,21,5,30,10;type:95,6;attr:4,7\",\"ranges\":[{\"byteEnd\":12,\"byteStart\":7,\"line\":28},{\"byteEnd\":21,\"byteStart\":16,\"line\":29},{\"byteEnd\":27,\"byteStart\":22,\"line\":30}],\"startLine\":27},{\"content\":\" fn a_last_line_without_a_newline() {\\n assert_eq!(count(\\\"a\\\\nb\\\").lines, 2);\\n }\",\"highlights\":\"string:66,6;keyword:4,2;number:81,1;function:7,29,13,10\",\"ranges\":[{\"byteEnd\":24,\"byteStart\":19,\"line\":35}],\"startLine\":34}],\"commit\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"language\":\"Rust\",\"path\":\"src/lib.rs\",\"repo\":{\"createdAt\":\"2026-10-09T16:47:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}}},{\"chunks\":[{\"content\":\"//! Counting, kept apart from reading so it can be tested.\\n\",\"highlights\":\"comment:0,59\",\"ranges\":[{\"byteEnd\":9,\"byteStart\":4,\"line\":1}],\"startLine\":1},{\"content\":\"#[derive(Debug, Default, PartialEq)]\\npub struct Counts {\\n pub lines: usize,\",\"highlights\":\"keyword:37,3,1,6,14,3;type:9,5,2,7,2,9,14,6,18,5;attr:0,9,5,2,7,2,9,2\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":7}],\"startLine\":6},{\"content\":\"\\n/// Counts `text` in one pass.\\npub fn count(text: &str) -> Counts {\\n let mut counts = Counts { bytes: text.len(), ..Counts::default() };\\n for line in parse::lines(text) {\\n counts.lines += 1;\\n counts.words += parse::words(line);\\n }\\n counts\\n}\",\"highlights\":\"comment:1,31;keyword:32,3,1,2,35,3,1,3,65,3,6,2;number:202,1;function:39,5,67,3,14,7,29,5,67,5;type:52,3,5,6,24,6,24,6\",\"ranges\":[{\"byteEnd\":9,\"byteStart\":4,\"line\":13},{\"byteEnd\":12,\"byteStart\":7,\"line\":14},{\"byteEnd\":33,\"byteStart\":28,\"line\":14},{\"byteEnd\":17,\"byteStart\":12,\"line\":15},{\"byteEnd\":26,\"byteStart\":21,\"line\":15},{\"byteEnd\":56,\"byteStart\":51,\"line\":15},{\"byteEnd\":13,\"byteStart\":8,\"line\":17},{\"byteEnd\":13,\"byteStart\":8,\"line\":18},{\"byteEnd\":9,\"byteStart\":4,\"line\":20}],\"startLine\":12},{\"content\":\" #[test]\\n fn counts() {\\n let c = count(\\\"one two\\\\nthree\\\\n\\\");\\n assert_eq!(c, Counts { lines: 2, words: 3, bytes: 14 });\\n }\",\"highlights\":\"string:52,18;keyword:16,2,20,3;number:111,1,9,1,9,2;function:19,6,21,5,30,10;type:95,6;attr:4,7\",\"ranges\":[{\"byteEnd\":12,\"byteStart\":7,\"line\":28},{\"byteEnd\":21,\"byteStart\":16,\"line\":29},{\"byteEnd\":27,\"byteStart\":22,\"line\":30}],\"startLine\":27},{\"content\":\" fn a_last_line_without_a_newline() {\\n assert_eq!(count(\\\"a\\\\nb\\\").lines, 2);\\n }\",\"highlights\":\"string:66,6;keyword:4,2;number:81,1;function:7,29,13,10\",\"ranges\":[{\"byteEnd\":24,\"byteStart\":19,\"line\":35}],\"startLine\":34}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Rust\",\"path\":\"src/lib.rs\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"\\ntally reads the whole input before counting. Inputs are small, and one\\npass over a string is simpler than a streaming reader.\",\"highlights\":\"\",\"ranges\":[{\"byteEnd\":40,\"byteStart\":35,\"line\":3}],\"startLine\":2},{\"content\":\" input[File or stdin] --> read[Read it whole]\\n read --> count{Count}\\n count --> lines\\n count --> words\\n count --> bytes\\n lines & words & bytes --> row[One row, lined up]\",\"highlights\":\"attr:8,13,11,13,112,17\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":9},{\"byteEnd\":22,\"byteStart\":17,\"line\":9},{\"byteEnd\":7,\"byteStart\":2,\"line\":10},{\"byteEnd\":7,\"byteStart\":2,\"line\":11},{\"byteEnd\":7,\"byteStart\":2,\"line\":12}],\"startLine\":8}],\"commit\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"language\":\"Markdown\",\"path\":\"docs/DESIGN.md\",\"repo\":{\"createdAt\":\"2026-10-09T16:47:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}}},{\"chunks\":[{\"content\":\"use std::io::Read;\\nuse tally::count;\\n\",\"highlights\":\"keyword:0,3,16,3;type:13,4\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":2}],\"startLine\":1},{\"content\":\" };\\n let c = count(&text);\\n let name = path.as_deref().unwrap_or(\\\"-\\\");\",\"highlights\":\"string:74,3;keyword:11,3,23,3;function:19,5,29,8,3,9\",\"ranges\":[{\"byteEnd\":17,\"byteStart\":12,\"line\":14}],\"startLine\":13}],\"commit\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"language\":\"Rust\",\"path\":\"src/main.rs\",\"repo\":{\"createdAt\":\"2026-10-09T16:47:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}}},{\"chunks\":[{\"content\":\"use std::io::Read;\\nuse tally::count;\\n\",\"highlights\":\"keyword:0,3,16,3;type:13,4\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":2}],\"startLine\":1},{\"content\":\" };\\n let c = count(&text);\\n let name = path.as_deref().unwrap_or(\\\"-\\\");\",\"highlights\":\"string:74,3;keyword:11,3,23,3;function:19,5,29,8,3,9\",\"ranges\":[{\"byteEnd\":17,\"byteStart\":12,\"line\":14}],\"startLine\":13}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Rust\",\"path\":\"src/main.rs\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"//! Splitting text into the things tally counts.\\n\",\"highlights\":\"comment:0,49\",\"ranges\":[{\"byteEnd\":46,\"byteStart\":41,\"line\":1}],\"startLine\":1},{\"content\":\"pub fn words(line: &str) -> usize {\\n line.split_whitespace().count()\\n}\",\"highlights\":\"keyword:0,3,1,2;function:7,5,33,16,3,5;type:20,3,5,5\",\"ranges\":[{\"byteEnd\":33,\"byteStart\":28,\"line\":5}],\"startLine\":4},{\"content\":\"\\n/// The lines of `text`. A last line without a newline still counts.\\npub fn lines(text: &str) -> impl Iterator<Item = &str> {\",\"highlights\":\"comment:1,69;keyword:70,3,1,2,22,4;type:90,3,10,8,1,4,4,3\",\"ranges\":[{\"byteEnd\":66,\"byteStart\":61,\"line\":8}],\"startLine\":7}],\"commit\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"language\":\"Rust\",\"path\":\"src/parse.rs\",\"repo\":{\"createdAt\":\"2026-10-09T16:47:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}}},{\"chunks\":[{\"content\":\"//! Splitting text into the things tally counts.\\n\",\"highlights\":\"comment:0,49\",\"ranges\":[{\"byteEnd\":46,\"byteStart\":41,\"line\":1}],\"startLine\":1},{\"content\":\"pub fn words(line: &str) -> usize {\\n line.split_whitespace().count()\\n}\",\"highlights\":\"keyword:0,3,1,2;function:7,5,33,16,3,5;type:20,3,5,5\",\"ranges\":[{\"byteEnd\":33,\"byteStart\":28,\"line\":5}],\"startLine\":4},{\"content\":\"\\n/// The lines of `text`. A last line without a newline still counts, and\\n/// empty input has none.\",\"highlights\":\"comment:1,98\",\"ranges\":[{\"byteEnd\":66,\"byteStart\":61,\"line\":8}],\"startLine\":7},{\"content\":\" fn empty_input_has_no_lines() {\\n assert_eq!(super::lines(\\\"\\\").count(), 0);\\n }\",\"highlights\":\"string:68,2;keyword:4,2,49,5;number:81,1;function:7,24,13,10\",\"ranges\":[{\"byteEnd\":41,\"byteStart\":36,\"line\":18}],\"startLine\":17}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Rust\",\"path\":\"src/parse.rs\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"\\ntally reads the whole input before counting. Inputs are small, and one\\npass over a string is simpler than a streaming reader.\",\"highlights\":\"\",\"ranges\":[{\"byteEnd\":40,\"byteStart\":35,\"line\":3}],\"startLine\":2},{\"content\":\" input[File or stdin] --> read[Read it whole]\\n read --> count{Count}\\n count --> lines\\n count --> words\\n count --> bytes\\n lines & words & bytes --> row[One row, lined up]\",\"highlights\":\"attr:8,13,11,13,112,17\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":9},{\"byteEnd\":22,\"byteStart\":17,\"line\":9},{\"byteEnd\":7,\"byteStart\":2,\"line\":10},{\"byteEnd\":7,\"byteStart\":2,\"line\":11},{\"byteEnd\":7,\"byteStart\":2,\"line\":12}],\"startLine\":8}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Markdown\",\"path\":\"docs/DESIGN.md\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"\\nCounts lines, words and bytes, like `wc`, with output that lines up.\\n\",\"highlights\":\"string:37,4\",\"ranges\":[{\"byteEnd\":5,\"byteStart\":0,\"line\":3}],\"startLine\":2}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Markdown\",\"path\":\"README.md\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"\\nCounts lines, words and bytes, like `wc`, with output that lines up.\\n\",\"highlights\":\"string:37,4\",\"ranges\":[{\"byteEnd\":5,\"byteStart\":0,\"line\":3}],\"startLine\":2}],\"commit\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"language\":\"Markdown\",\"path\":\"README.md\",\"repo\":{\"createdAt\":\"2026-10-09T16:47:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}}},{\"chunks\":[{\"content\":\"edition = \\\"2024\\\"\\ndescription = \\\"Counts lines, words and bytes\\\"\\nlicense = \\\"MIT\\\"\",\"highlights\":\"string:10,6,15,31,11,5;type:0,7,10,11,35,7\",\"ranges\":[{\"byteEnd\":20,\"byteStart\":15,\"line\":5}],\"startLine\":4}],\"commit\":\"4c4f3483836ee19f1f64f7976d1bc44ebc9db642\",\"language\":\"TOML\",\"path\":\"Cargo.toml\",\"repo\":{\"createdAt\":\"2026-10-09T16:47:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"forkOf\":\"at://did:plc:abe24xewga4qdbzjcxmuzdt3/dev.knotless.repo/tally\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:55j6e4wxzlzndxm4nov2lz7x\",\"handle\":\"bob.test\"}}},{\"chunks\":[{\"content\":\"edition = \\\"2024\\\"\\ndescription = \\\"Counts lines, words and bytes\\\"\\nlicense = \\\"MIT\\\"\",\"highlights\":\"string:10,6,15,31,11,5;type:0,7,10,11,35,7\",\"ranges\":[{\"byteEnd\":20,\"byteStart\":15,\"line\":5}],\"startLine\":4}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"TOML\",\"path\":\"Cargo.toml\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}}],\"languages\":[{\"name\":\"Rust\",\"color\":\"#dea584\",\"files\":6},{\"name\":\"Markdown\",\"color\":\"#083fa1\",\"files\":4},{\"name\":\"TOML\",\"color\":\"#9c4221\",\"files\":2}],\"matchCount\":57}"
},
"/xrpc/dev.knotless.searchCode?q=count&repo=at%3A%2F%2Falice.test%2Fdev.knotless.repo%2Ftally": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"fileCount\":6,\"files\":[{\"chunks\":[{\"content\":\"//! Counting, kept apart from reading so it can be tested.\\n\",\"highlights\":\"comment:0,59\",\"ranges\":[{\"byteEnd\":9,\"byteStart\":4,\"line\":1}],\"startLine\":1},{\"content\":\"#[derive(Debug, Default, PartialEq)]\\npub struct Counts {\\n pub lines: usize,\",\"highlights\":\"keyword:37,3,1,6,14,3;type:9,5,2,7,2,9,14,6,18,5;attr:0,9,5,2,7,2,9,2\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":7}],\"startLine\":6},{\"content\":\"\\n/// Counts `text` in one pass.\\npub fn count(text: &str) -> Counts {\\n let mut counts = Counts { bytes: text.len(), ..Counts::default() };\\n for line in parse::lines(text) {\\n counts.lines += 1;\\n counts.words += parse::words(line);\\n }\\n counts\\n}\",\"highlights\":\"comment:1,31;keyword:32,3,1,2,35,3,1,3,65,3,6,2;number:202,1;function:39,5,67,3,14,7,29,5,67,5;type:52,3,5,6,24,6,24,6\",\"ranges\":[{\"byteEnd\":9,\"byteStart\":4,\"line\":13},{\"byteEnd\":12,\"byteStart\":7,\"line\":14},{\"byteEnd\":33,\"byteStart\":28,\"line\":14},{\"byteEnd\":17,\"byteStart\":12,\"line\":15},{\"byteEnd\":26,\"byteStart\":21,\"line\":15},{\"byteEnd\":56,\"byteStart\":51,\"line\":15},{\"byteEnd\":13,\"byteStart\":8,\"line\":17},{\"byteEnd\":13,\"byteStart\":8,\"line\":18},{\"byteEnd\":9,\"byteStart\":4,\"line\":20}],\"startLine\":12},{\"content\":\" #[test]\\n fn counts() {\\n let c = count(\\\"one two\\\\nthree\\\\n\\\");\\n assert_eq!(c, Counts { lines: 2, words: 3, bytes: 14 });\\n }\",\"highlights\":\"string:52,18;keyword:16,2,20,3;number:111,1,9,1,9,2;function:19,6,21,5,30,10;type:95,6;attr:4,7\",\"ranges\":[{\"byteEnd\":12,\"byteStart\":7,\"line\":28},{\"byteEnd\":21,\"byteStart\":16,\"line\":29},{\"byteEnd\":27,\"byteStart\":22,\"line\":30}],\"startLine\":27},{\"content\":\" fn a_last_line_without_a_newline() {\\n assert_eq!(count(\\\"a\\\\nb\\\").lines, 2);\\n }\",\"highlights\":\"string:66,6;keyword:4,2;number:81,1;function:7,29,13,10\",\"ranges\":[{\"byteEnd\":24,\"byteStart\":19,\"line\":35}],\"startLine\":34}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Rust\",\"path\":\"src/lib.rs\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"use std::io::Read;\\nuse tally::count;\\n\",\"highlights\":\"keyword:0,3,16,3;type:13,4\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":2}],\"startLine\":1},{\"content\":\" };\\n let c = count(&text);\\n let name = path.as_deref().unwrap_or(\\\"-\\\");\",\"highlights\":\"string:74,3;keyword:11,3,23,3;function:19,5,29,8,3,9\",\"ranges\":[{\"byteEnd\":17,\"byteStart\":12,\"line\":14}],\"startLine\":13}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Rust\",\"path\":\"src/main.rs\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"\\ntally reads the whole input before counting. Inputs are small, and one\\npass over a string is simpler than a streaming reader.\",\"highlights\":\"\",\"ranges\":[{\"byteEnd\":40,\"byteStart\":35,\"line\":3}],\"startLine\":2},{\"content\":\" input[File or stdin] --> read[Read it whole]\\n read --> count{Count}\\n count --> lines\\n count --> words\\n count --> bytes\\n lines & words & bytes --> row[One row, lined up]\",\"highlights\":\"attr:8,13,11,13,112,17\",\"ranges\":[{\"byteEnd\":16,\"byteStart\":11,\"line\":9},{\"byteEnd\":22,\"byteStart\":17,\"line\":9},{\"byteEnd\":7,\"byteStart\":2,\"line\":10},{\"byteEnd\":7,\"byteStart\":2,\"line\":11},{\"byteEnd\":7,\"byteStart\":2,\"line\":12}],\"startLine\":8}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Markdown\",\"path\":\"docs/DESIGN.md\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"//! Splitting text into the things tally counts.\\n\",\"highlights\":\"comment:0,49\",\"ranges\":[{\"byteEnd\":46,\"byteStart\":41,\"line\":1}],\"startLine\":1},{\"content\":\"pub fn words(line: &str) -> usize {\\n line.split_whitespace().count()\\n}\",\"highlights\":\"keyword:0,3,1,2;function:7,5,33,16,3,5;type:20,3,5,5\",\"ranges\":[{\"byteEnd\":33,\"byteStart\":28,\"line\":5}],\"startLine\":4},{\"content\":\"\\n/// The lines of `text`. A last line without a newline still counts, and\\n/// empty input has none.\",\"highlights\":\"comment:1,98\",\"ranges\":[{\"byteEnd\":66,\"byteStart\":61,\"line\":8}],\"startLine\":7},{\"content\":\" fn empty_input_has_no_lines() {\\n assert_eq!(super::lines(\\\"\\\").count(), 0);\\n }\",\"highlights\":\"string:68,2;keyword:4,2,49,5;number:81,1;function:7,24,13,10\",\"ranges\":[{\"byteEnd\":41,\"byteStart\":36,\"line\":18}],\"startLine\":17}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Rust\",\"path\":\"src/parse.rs\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"\\nCounts lines, words and bytes, like `wc`, with output that lines up.\\n\",\"highlights\":\"string:37,4\",\"ranges\":[{\"byteEnd\":5,\"byteStart\":0,\"line\":3}],\"startLine\":2}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"Markdown\",\"path\":\"README.md\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}},{\"chunks\":[{\"content\":\"edition = \\\"2024\\\"\\ndescription = \\\"Counts lines, words and bytes\\\"\\nlicense = \\\"MIT\\\"\",\"highlights\":\"string:10,6,15,31,11,5;type:0,7,10,11,35,7\",\"ranges\":[{\"byteEnd\":20,\"byteStart\":15,\"line\":5}],\"startLine\":4}],\"commit\":\"aae0fe0316b38d65d0c88c17c026786348223d7d\",\"language\":\"TOML\",\"path\":\"Cargo.toml\",\"repo\":{\"createdAt\":\"2026-10-09T10:00:00.000Z\",\"description\":\"Counts lines, words and bytes, with output that lines up\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"tally\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}}],\"languages\":[{\"name\":\"Rust\",\"color\":\"#dea584\",\"files\":3},{\"name\":\"Markdown\",\"color\":\"#083fa1\",\"files\":2},{\"name\":\"TOML\",\"color\":\"#9c4221\",\"files\":1}],\"matchCount\":29}"
},
"/xrpc/dev.knotless.searchCode?q=t&limit=1": {
"status": 200,
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"body": "{\"fileCount\":10,\"files\":[{\"chunks\":[{\"content\":\"# notes\\n\\nThings worth remembering.\",\"highlights\":\"function:0,8\",\"ranges\":[{\"byteEnd\":5,\"byteStart\":4,\"line\":1},{\"byteEnd\":1,\"byteStart\":0,\"line\":3},{\"byteEnd\":11,\"byteStart\":10,\"line\":3}],\"startLine\":1}],\"commit\":\"661c67a96bf920012bc578c6c6895e4103128dfe\",\"language\":\"Markdown\",\"path\":\"README.md\",\"repo\":{\"createdAt\":\"2026-10-09T11:51:00.000Z\",\"description\":\"Scratch notes ๐\",\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"name\":\"notes\",\"owner\":{\"did\":\"did:plc:abe24xewga4qdbzjcxmuzdt3\",\"handle\":\"alice.test\"}}}],\"matchCount\":271}"
}
}
}