[{"data":1,"prerenderedAt":1446},["ShallowReactive",2],{"guide:/guides/claude-code-wsl":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"tag":10,"date":11,"body":12,"_type":1440,"_id":1441,"_source":1442,"_file":1443,"_stem":1444,"_extension":1445},"/guides/claude-code-wsl","guides",false,"","Claude Code in WSL: what breaks and why","Running Claude Code inside WSL on a Windows machine splits your config, your history and your networking in two. Here is every seam, measured on a real setup.","Config","2026-09-13",{"type":13,"children":14,"toc":1431},"root",[15,32,39,53,161,174,180,185,259,312,331,336,342,347,388,409,637,642,860,889,918,924,945,1072,1093,1098,1104,1120,1128,1149,1175,1217,1223,1242,1351,1387,1393,1398,1425],{"type":16,"tag":17,"props":18,"children":19},"element","p",{},[20,23,30],{"type":21,"value":22},"text","Claude Code runs fine inside WSL. What breaks is everything around it, because a Windows machine with WSL is two computers that share a screen: two home directories, two config files, two histories, and a network boundary between them. None of it is documented, and all of it is easy to verify. Everything below was measured on Ubuntu 24.04.2 under WSL2 (kernel 6.18.33.2) with Claude Code 2.1.269. If your hooks are the immediate problem, start with ",{"type":16,"tag":24,"props":25,"children":27},"a",{"href":26},"/guides/claude-code-hook-not-firing",[28],{"type":21,"value":29},"the hook checklist",{"type":21,"value":31},".",{"type":16,"tag":33,"props":34,"children":36},"h2",{"id":35},"you-have-two-claude-code-installs-not-one",[37],{"type":21,"value":38},"You have two Claude Code installs, not one",{"type":16,"tag":17,"props":40,"children":41},{},[42,44,51],{"type":21,"value":43},"This is the root of almost every WSL surprise. Windows and WSL each have their own home directory, so each has its own ",{"type":16,"tag":45,"props":46,"children":48},"code",{"className":47},[],[49],{"type":21,"value":50},"~/.claude",{"type":21,"value":52},", and Claude Code reads whichever one it is launched from.",{"type":16,"tag":54,"props":55,"children":56},"table",{},[57,79],{"type":16,"tag":58,"props":59,"children":60},"thead",{},[61],{"type":16,"tag":62,"props":63,"children":64},"tr",{},[65,69,74],{"type":16,"tag":66,"props":67,"children":68},"th",{},[],{"type":16,"tag":66,"props":70,"children":71},{},[72],{"type":21,"value":73},"Windows",{"type":16,"tag":66,"props":75,"children":76},{},[77],{"type":21,"value":78},"WSL",{"type":16,"tag":80,"props":81,"children":82},"tbody",{},[83,109,135],{"type":16,"tag":62,"props":84,"children":85},{},[86,91,100],{"type":16,"tag":87,"props":88,"children":89},"td",{},[90],{"type":21,"value":10},{"type":16,"tag":87,"props":92,"children":93},{},[94],{"type":16,"tag":45,"props":95,"children":97},{"className":96},[],[98],{"type":21,"value":99},"C:\\Users\\<you>\\.claude\\settings.json",{"type":16,"tag":87,"props":101,"children":102},{},[103],{"type":16,"tag":45,"props":104,"children":106},{"className":105},[],[107],{"type":21,"value":108},"~/.claude/settings.json",{"type":16,"tag":62,"props":110,"children":111},{},[112,117,126],{"type":16,"tag":87,"props":113,"children":114},{},[115],{"type":21,"value":116},"Projects",{"type":16,"tag":87,"props":118,"children":119},{},[120],{"type":16,"tag":45,"props":121,"children":123},{"className":122},[],[124],{"type":21,"value":125},"C:\\Users\\<you>\\.claude\\projects\\",{"type":16,"tag":87,"props":127,"children":128},{},[129],{"type":16,"tag":45,"props":130,"children":132},{"className":131},[],[133],{"type":21,"value":134},"~/.claude/projects/",{"type":16,"tag":62,"props":136,"children":137},{},[138,143,152],{"type":16,"tag":87,"props":139,"children":140},{},[141],{"type":21,"value":142},"Session registry",{"type":16,"tag":87,"props":144,"children":145},{},[146],{"type":16,"tag":45,"props":147,"children":149},{"className":148},[],[150],{"type":21,"value":151},"C:\\Users\\<you>\\.claude\\sessions\\",{"type":16,"tag":87,"props":153,"children":154},{},[155],{"type":16,"tag":45,"props":156,"children":158},{"className":157},[],[159],{"type":21,"value":160},"~/.claude/sessions/",{"type":16,"tag":17,"props":162,"children":163},{},[164,166,172],{"type":21,"value":165},"Measured on a machine that runs both: the Windows ",{"type":16,"tag":45,"props":167,"children":169},{"className":168},[],[170],{"type":21,"value":171},"settings.json",{"type":21,"value":173}," carried two keys, the WSL one carried eleven. They had been configured separately, months apart, and neither knew about the other. If you set up hooks in a terminal and they do nothing in your editor, this is usually why: you configured one install and you are running the other.",{"type":16,"tag":33,"props":175,"children":177},{"id":176},"the-same-repo-gets-two-separate-histories",[178],{"type":21,"value":179},"The same repo gets two separate histories",{"type":16,"tag":17,"props":181,"children":182},{},[183],{"type":21,"value":184},"Claude Code stores a conversation transcript per project, in a folder named after the working directory with every separator replaced by a dash. That encoding is where the two worlds stop being the same place:",{"type":16,"tag":54,"props":186,"children":187},{},[188,210],{"type":16,"tag":58,"props":189,"children":190},{},[191],{"type":16,"tag":62,"props":192,"children":193},{},[194,199],{"type":16,"tag":66,"props":195,"children":196},{},[197],{"type":21,"value":198},"Working directory",{"type":16,"tag":66,"props":200,"children":201},{},[202,204],{"type":21,"value":203},"Folder in ",{"type":16,"tag":45,"props":205,"children":207},{"className":206},[],[208],{"type":21,"value":209},"projects/",{"type":16,"tag":80,"props":211,"children":212},{},[213,236],{"type":16,"tag":62,"props":214,"children":215},{},[216,227],{"type":16,"tag":87,"props":217,"children":218},{},[219,225],{"type":16,"tag":45,"props":220,"children":222},{"className":221},[],[223],{"type":21,"value":224},"/mnt/c/Workspace/my-app",{"type":21,"value":226}," (WSL)",{"type":16,"tag":87,"props":228,"children":229},{},[230],{"type":16,"tag":45,"props":231,"children":233},{"className":232},[],[234],{"type":21,"value":235},"-mnt-c-Workspace-my-app",{"type":16,"tag":62,"props":237,"children":238},{},[239,250],{"type":16,"tag":87,"props":240,"children":241},{},[242,248],{"type":16,"tag":45,"props":243,"children":245},{"className":244},[],[246],{"type":21,"value":247},"C:\\Workspace\\my-app",{"type":21,"value":249}," (Windows)",{"type":16,"tag":87,"props":251,"children":252},{},[253],{"type":16,"tag":45,"props":254,"children":256},{"className":255},[],[257],{"type":21,"value":258},"C--Workspace-my-app",{"type":16,"tag":17,"props":260,"children":261},{},[262,264,270,272,278,280,286,288,294,296,302,304,310],{"type":21,"value":263},"Both point at the same files on the same disk. The leading ",{"type":16,"tag":45,"props":265,"children":267},{"className":266},[],[268],{"type":21,"value":269},"/",{"type":21,"value":271}," becomes a leading dash on one side, while ",{"type":16,"tag":45,"props":273,"children":275},{"className":274},[],[276],{"type":21,"value":277},"C:",{"type":21,"value":279}," becomes ",{"type":16,"tag":45,"props":281,"children":283},{"className":282},[],[284],{"type":21,"value":285},"C--",{"type":21,"value":287}," on the other, so the two never collide. Open the same repo from a Windows terminal and from WSL, and you get two folders, in two different ",{"type":16,"tag":45,"props":289,"children":291},{"className":290},[],[292],{"type":21,"value":293},".claude",{"type":21,"value":295}," trees, holding two unrelated sets of transcripts. Neither ",{"type":16,"tag":45,"props":297,"children":299},{"className":298},[],[300],{"type":21,"value":301},"--continue",{"type":21,"value":303}," nor ",{"type":16,"tag":45,"props":305,"children":307},{"className":306},[],[308],{"type":21,"value":309},"--resume",{"type":21,"value":311}," will show you the other side's work.",{"type":16,"tag":17,"props":313,"children":314},{},[315,317,323,324,330],{"type":21,"value":316},"Spaces are encoded the same way as separators, so ",{"type":16,"tag":45,"props":318,"children":320},{"className":319},[],[321],{"type":21,"value":322},"/mnt/c/Workspace/Animated Characters SVG",{"type":21,"value":279},{"type":16,"tag":45,"props":325,"children":327},{"className":326},[],[328],{"type":21,"value":329},"-mnt-c-Workspace-Animated-Characters-SVG",{"type":21,"value":31},{"type":16,"tag":17,"props":332,"children":333},{},[334],{"type":21,"value":335},"Pick one side per repo and stay there. If you must switch, expect to lose continuity.",{"type":16,"tag":33,"props":337,"children":339},{"id":338},"hooks-localhost-is-not-localhost",[340],{"type":21,"value":341},"Hooks: localhost is not localhost",{"type":16,"tag":17,"props":343,"children":344},{},[345],{"type":21,"value":346},"If a hook posts to a local service, WSL's networking mode decides whether it works, and the default mode is the one that breaks.",{"type":16,"tag":348,"props":349,"children":350},"ul",{},[351,371],{"type":16,"tag":352,"props":353,"children":354},"li",{},[355,361,363,369],{"type":16,"tag":356,"props":357,"children":358},"strong",{},[359],{"type":21,"value":360},"NAT",{"type":21,"value":362}," (the WSL2 default): ",{"type":16,"tag":45,"props":364,"children":366},{"className":365},[],[367],{"type":21,"value":368},"127.0.0.1",{"type":21,"value":370}," inside WSL is WSL's own loopback. A Windows process listening on the Windows loopback is not there. The host is reachable on the default route gateway instead.",{"type":16,"tag":352,"props":372,"children":373},{},[374,379,381,386],{"type":16,"tag":356,"props":375,"children":376},{},[377],{"type":21,"value":378},"Mirrored",{"type":21,"value":380},": ",{"type":16,"tag":45,"props":382,"children":384},{"className":383},[],[385],{"type":21,"value":368},{"type":21,"value":387}," does reach the Windows loopback, and everything just works.",{"type":16,"tag":17,"props":389,"children":390},{},[391,393,399,401,407],{"type":21,"value":392},"Measured from inside WSL against a Windows app listening on port 49217, with no ",{"type":16,"tag":45,"props":394,"children":396},{"className":395},[],[397],{"type":21,"value":398},"networkingMode",{"type":21,"value":400}," set in ",{"type":16,"tag":45,"props":402,"children":404},{"className":403},[],[405],{"type":21,"value":406},".wslconfig",{"type":21,"value":408},":",{"type":16,"tag":410,"props":411,"children":415},"pre",{"code":412,"language":413,"meta":7,"className":414,"style":7},"$ curl -s -m 2 -o /dev/null -w \"%{http_code}\\n\" http://127.0.0.1:49217/event\n000        # connection refused, immediately\n\n$ ip route show default\ndefault via 172.28.176.1 dev eth0 proto kernel\n\n$ curl -s -m 2 -o /dev/null -w \"%{http_code}\\n\" http://172.28.176.1:49217/event\n404        # the Windows process answered\n","bash","language-bash shiki shiki-themes github-light github-dark",[416],{"type":16,"tag":45,"props":417,"children":418},{"__ignoreMap":7},[419,478,493,503,531,570,578,623],{"type":16,"tag":420,"props":421,"children":424},"span",{"class":422,"line":423},"line",1,[425,431,437,443,448,453,458,463,468,473],{"type":16,"tag":420,"props":426,"children":428},{"style":427},"--shiki-default:#6F42C1;--shiki-dark:#B392F0",[429],{"type":21,"value":430},"$",{"type":16,"tag":420,"props":432,"children":434},{"style":433},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[435],{"type":21,"value":436}," curl",{"type":16,"tag":420,"props":438,"children":440},{"style":439},"--shiki-default:#005CC5;--shiki-dark:#79B8FF",[441],{"type":21,"value":442}," -s",{"type":16,"tag":420,"props":444,"children":445},{"style":439},[446],{"type":21,"value":447}," -m",{"type":16,"tag":420,"props":449,"children":450},{"style":439},[451],{"type":21,"value":452}," 2",{"type":16,"tag":420,"props":454,"children":455},{"style":439},[456],{"type":21,"value":457}," -o",{"type":16,"tag":420,"props":459,"children":460},{"style":433},[461],{"type":21,"value":462}," /dev/null",{"type":16,"tag":420,"props":464,"children":465},{"style":439},[466],{"type":21,"value":467}," -w",{"type":16,"tag":420,"props":469,"children":470},{"style":433},[471],{"type":21,"value":472}," \"%{http_code}\\n\"",{"type":16,"tag":420,"props":474,"children":475},{"style":433},[476],{"type":21,"value":477}," http://127.0.0.1:49217/event\n",{"type":16,"tag":420,"props":479,"children":481},{"class":422,"line":480},2,[482,487],{"type":16,"tag":420,"props":483,"children":484},{"style":427},[485],{"type":21,"value":486},"000",{"type":16,"tag":420,"props":488,"children":490},{"style":489},"--shiki-default:#6A737D;--shiki-dark:#6A737D",[491],{"type":21,"value":492},"        # connection refused, immediately\n",{"type":16,"tag":420,"props":494,"children":496},{"class":422,"line":495},3,[497],{"type":16,"tag":420,"props":498,"children":500},{"emptyLinePlaceholder":499},true,[501],{"type":21,"value":502},"\n",{"type":16,"tag":420,"props":504,"children":506},{"class":422,"line":505},4,[507,511,516,521,526],{"type":16,"tag":420,"props":508,"children":509},{"style":427},[510],{"type":21,"value":430},{"type":16,"tag":420,"props":512,"children":513},{"style":433},[514],{"type":21,"value":515}," ip",{"type":16,"tag":420,"props":517,"children":518},{"style":433},[519],{"type":21,"value":520}," route",{"type":16,"tag":420,"props":522,"children":523},{"style":433},[524],{"type":21,"value":525}," show",{"type":16,"tag":420,"props":527,"children":528},{"style":433},[529],{"type":21,"value":530}," default\n",{"type":16,"tag":420,"props":532,"children":534},{"class":422,"line":533},5,[535,540,545,550,555,560,565],{"type":16,"tag":420,"props":536,"children":537},{"style":427},[538],{"type":21,"value":539},"default",{"type":16,"tag":420,"props":541,"children":542},{"style":433},[543],{"type":21,"value":544}," via",{"type":16,"tag":420,"props":546,"children":547},{"style":439},[548],{"type":21,"value":549}," 172.28.176.1",{"type":16,"tag":420,"props":551,"children":552},{"style":433},[553],{"type":21,"value":554}," dev",{"type":16,"tag":420,"props":556,"children":557},{"style":433},[558],{"type":21,"value":559}," eth0",{"type":16,"tag":420,"props":561,"children":562},{"style":433},[563],{"type":21,"value":564}," proto",{"type":16,"tag":420,"props":566,"children":567},{"style":433},[568],{"type":21,"value":569}," kernel\n",{"type":16,"tag":420,"props":571,"children":573},{"class":422,"line":572},6,[574],{"type":16,"tag":420,"props":575,"children":576},{"emptyLinePlaceholder":499},[577],{"type":21,"value":502},{"type":16,"tag":420,"props":579,"children":581},{"class":422,"line":580},7,[582,586,590,594,598,602,606,610,614,618],{"type":16,"tag":420,"props":583,"children":584},{"style":427},[585],{"type":21,"value":430},{"type":16,"tag":420,"props":587,"children":588},{"style":433},[589],{"type":21,"value":436},{"type":16,"tag":420,"props":591,"children":592},{"style":439},[593],{"type":21,"value":442},{"type":16,"tag":420,"props":595,"children":596},{"style":439},[597],{"type":21,"value":447},{"type":16,"tag":420,"props":599,"children":600},{"style":439},[601],{"type":21,"value":452},{"type":16,"tag":420,"props":603,"children":604},{"style":439},[605],{"type":21,"value":457},{"type":16,"tag":420,"props":607,"children":608},{"style":433},[609],{"type":21,"value":462},{"type":16,"tag":420,"props":611,"children":612},{"style":439},[613],{"type":21,"value":467},{"type":16,"tag":420,"props":615,"children":616},{"style":433},[617],{"type":21,"value":472},{"type":16,"tag":420,"props":619,"children":620},{"style":433},[621],{"type":21,"value":622}," http://172.28.176.1:49217/event\n",{"type":16,"tag":420,"props":624,"children":626},{"class":422,"line":625},8,[627,632],{"type":16,"tag":420,"props":628,"children":629},{"style":427},[630],{"type":21,"value":631},"404",{"type":16,"tag":420,"props":633,"children":634},{"style":489},[635],{"type":21,"value":636},"        # the Windows process answered\n",{"type":16,"tag":17,"props":638,"children":639},{},[640],{"type":21,"value":641},"So write the hook to try both. The refusal is instant rather than a timeout, which is what makes the fallback free in the mirrored case:",{"type":16,"tag":410,"props":643,"children":645},{"code":644,"language":413,"meta":7,"className":414,"style":7},"D=$(cat); for H in 127.0.0.1 $(ip route show default 2>/dev/null | awk '{print $3; exit}'); do curl -s -m 2 -X POST \"http://$H:49217/event\" --data-binary \"$D\" >/dev/null 2>&1 && break; done; true\n",[646],{"type":16,"tag":45,"props":647,"children":648},{"__ignoreMap":7},[649],{"type":16,"tag":420,"props":650,"children":651},{"class":422,"line":423},[652,658,664,669,674,679,684,689,694,699,704,709,713,717,722,727,732,737,742,747,751,756,760,764,768,772,777,782,787,792,797,802,807,812,817,822,826,831,836,841,846,851,855],{"type":16,"tag":420,"props":653,"children":655},{"style":654},"--shiki-default:#24292E;--shiki-dark:#E1E4E8",[656],{"type":21,"value":657},"D",{"type":16,"tag":420,"props":659,"children":661},{"style":660},"--shiki-default:#D73A49;--shiki-dark:#F97583",[662],{"type":21,"value":663},"=",{"type":16,"tag":420,"props":665,"children":666},{"style":654},[667],{"type":21,"value":668},"$(",{"type":16,"tag":420,"props":670,"children":671},{"style":427},[672],{"type":21,"value":673},"cat",{"type":16,"tag":420,"props":675,"children":676},{"style":654},[677],{"type":21,"value":678},"); ",{"type":16,"tag":420,"props":680,"children":681},{"style":660},[682],{"type":21,"value":683},"for",{"type":16,"tag":420,"props":685,"children":686},{"style":654},[687],{"type":21,"value":688}," H ",{"type":16,"tag":420,"props":690,"children":691},{"style":660},[692],{"type":21,"value":693},"in",{"type":16,"tag":420,"props":695,"children":696},{"style":433},[697],{"type":21,"value":698}," 127.0.0.1",{"type":16,"tag":420,"props":700,"children":701},{"style":654},[702],{"type":21,"value":703}," $(",{"type":16,"tag":420,"props":705,"children":706},{"style":427},[707],{"type":21,"value":708},"ip",{"type":16,"tag":420,"props":710,"children":711},{"style":433},[712],{"type":21,"value":520},{"type":16,"tag":420,"props":714,"children":715},{"style":433},[716],{"type":21,"value":525},{"type":16,"tag":420,"props":718,"children":719},{"style":433},[720],{"type":21,"value":721}," default",{"type":16,"tag":420,"props":723,"children":724},{"style":660},[725],{"type":21,"value":726}," 2>",{"type":16,"tag":420,"props":728,"children":729},{"style":433},[730],{"type":21,"value":731},"/dev/null",{"type":16,"tag":420,"props":733,"children":734},{"style":660},[735],{"type":21,"value":736}," |",{"type":16,"tag":420,"props":738,"children":739},{"style":427},[740],{"type":21,"value":741}," awk",{"type":16,"tag":420,"props":743,"children":744},{"style":433},[745],{"type":21,"value":746}," '{print $3; exit}'",{"type":16,"tag":420,"props":748,"children":749},{"style":654},[750],{"type":21,"value":678},{"type":16,"tag":420,"props":752,"children":753},{"style":660},[754],{"type":21,"value":755},"do",{"type":16,"tag":420,"props":757,"children":758},{"style":427},[759],{"type":21,"value":436},{"type":16,"tag":420,"props":761,"children":762},{"style":439},[763],{"type":21,"value":442},{"type":16,"tag":420,"props":765,"children":766},{"style":439},[767],{"type":21,"value":447},{"type":16,"tag":420,"props":769,"children":770},{"style":439},[771],{"type":21,"value":452},{"type":16,"tag":420,"props":773,"children":774},{"style":439},[775],{"type":21,"value":776}," -X",{"type":16,"tag":420,"props":778,"children":779},{"style":433},[780],{"type":21,"value":781}," POST",{"type":16,"tag":420,"props":783,"children":784},{"style":433},[785],{"type":21,"value":786}," \"http://",{"type":16,"tag":420,"props":788,"children":789},{"style":654},[790],{"type":21,"value":791},"$H",{"type":16,"tag":420,"props":793,"children":794},{"style":433},[795],{"type":21,"value":796},":49217/event\"",{"type":16,"tag":420,"props":798,"children":799},{"style":439},[800],{"type":21,"value":801}," --data-binary",{"type":16,"tag":420,"props":803,"children":804},{"style":433},[805],{"type":21,"value":806}," \"",{"type":16,"tag":420,"props":808,"children":809},{"style":654},[810],{"type":21,"value":811},"$D",{"type":16,"tag":420,"props":813,"children":814},{"style":433},[815],{"type":21,"value":816},"\"",{"type":16,"tag":420,"props":818,"children":819},{"style":660},[820],{"type":21,"value":821}," >",{"type":16,"tag":420,"props":823,"children":824},{"style":433},[825],{"type":21,"value":731},{"type":16,"tag":420,"props":827,"children":828},{"style":660},[829],{"type":21,"value":830}," 2>&1",{"type":16,"tag":420,"props":832,"children":833},{"style":654},[834],{"type":21,"value":835}," && ",{"type":16,"tag":420,"props":837,"children":838},{"style":660},[839],{"type":21,"value":840},"break",{"type":16,"tag":420,"props":842,"children":843},{"style":654},[844],{"type":21,"value":845},"; ",{"type":16,"tag":420,"props":847,"children":848},{"style":660},[849],{"type":21,"value":850},"done",{"type":16,"tag":420,"props":852,"children":853},{"style":654},[854],{"type":21,"value":845},{"type":16,"tag":420,"props":856,"children":857},{"style":439},[858],{"type":21,"value":859},"true\n",{"type":16,"tag":17,"props":861,"children":862},{},[863,865,871,873,879,881,887],{"type":21,"value":864},"Two details matter in that line. ",{"type":16,"tag":45,"props":866,"children":868},{"className":867},[],[869],{"type":21,"value":870},"D=$(cat)",{"type":21,"value":872}," buffers the payload first, because stdin can only be read once: chaining two ",{"type":16,"tag":45,"props":874,"children":876},{"className":875},[],[877],{"type":21,"value":878},"curl --data-binary @-",{"type":21,"value":880}," calls sends an empty body on the retry. And the ",{"type":16,"tag":45,"props":882,"children":884},{"className":883},[],[885],{"type":21,"value":886},"&& break",{"type":21,"value":888}," stops at the first host that answers.",{"type":16,"tag":17,"props":890,"children":891},{},[892,894,900,902,908,910,916],{"type":21,"value":893},"Note that this is the POSIX form, for the WSL install. The Windows install needs a different one, because Claude Code picks Git Bash or PowerShell depending on what is installed: see ",{"type":16,"tag":24,"props":895,"children":897},{"href":896},"/guides/claude-code-hooks-windows",[898],{"type":21,"value":899},"hooks on Windows",{"type":21,"value":901}," for why an unquoted ",{"type":16,"tag":45,"props":903,"children":905},{"className":904},[],[906],{"type":21,"value":907},"--data-binary @-",{"type":21,"value":909}," is a ",{"type":16,"tag":45,"props":911,"children":913},{"className":912},[],[914],{"type":21,"value":915},"ParserError",{"type":21,"value":917}," under PowerShell.",{"type":16,"tag":33,"props":919,"children":921},{"id":920},"a-wsl-pid-means-nothing-to-windows",[922],{"type":21,"value":923},"A WSL pid means nothing to Windows",{"type":16,"tag":17,"props":925,"children":926},{},[927,929,935,937,943],{"type":21,"value":928},"The ",{"type":16,"tag":24,"props":930,"children":932},{"href":931},"/guides/claude-code-sessions-registry",[933],{"type":21,"value":934},"session registry",{"type":21,"value":936}," writes one JSON file per process, at ",{"type":16,"tag":45,"props":938,"children":940},{"className":939},[],[941],{"type":21,"value":942},"~/.claude/sessions/<pid>.json",{"type":21,"value":944},". Inside WSL, the record qualifies its pid with a Linux namespace:",{"type":16,"tag":410,"props":946,"children":950},{"code":947,"language":948,"meta":7,"className":949,"style":7},"{\n  \"pid\": 2530897,\n  \"cwd\": \"/mnt/c/Workspace/my-app\",\n  \"pidDomain\": \"linux:db5cbacc…:pid:[4026532219]\",\n  \"messagingSocketPath\": \"/run/user/1000/cc-socks/2530897.sock\",\n  \"status\": \"busy\"\n}\n","json","language-json shiki shiki-themes github-light github-dark",[951],{"type":16,"tag":45,"props":952,"children":953},{"__ignoreMap":7},[954,962,984,1005,1026,1047,1064],{"type":16,"tag":420,"props":955,"children":956},{"class":422,"line":423},[957],{"type":16,"tag":420,"props":958,"children":959},{"style":654},[960],{"type":21,"value":961},"{\n",{"type":16,"tag":420,"props":963,"children":964},{"class":422,"line":480},[965,970,974,979],{"type":16,"tag":420,"props":966,"children":967},{"style":439},[968],{"type":21,"value":969},"  \"pid\"",{"type":16,"tag":420,"props":971,"children":972},{"style":654},[973],{"type":21,"value":380},{"type":16,"tag":420,"props":975,"children":976},{"style":439},[977],{"type":21,"value":978},"2530897",{"type":16,"tag":420,"props":980,"children":981},{"style":654},[982],{"type":21,"value":983},",\n",{"type":16,"tag":420,"props":985,"children":986},{"class":422,"line":495},[987,992,996,1001],{"type":16,"tag":420,"props":988,"children":989},{"style":439},[990],{"type":21,"value":991},"  \"cwd\"",{"type":16,"tag":420,"props":993,"children":994},{"style":654},[995],{"type":21,"value":380},{"type":16,"tag":420,"props":997,"children":998},{"style":433},[999],{"type":21,"value":1000},"\"/mnt/c/Workspace/my-app\"",{"type":16,"tag":420,"props":1002,"children":1003},{"style":654},[1004],{"type":21,"value":983},{"type":16,"tag":420,"props":1006,"children":1007},{"class":422,"line":505},[1008,1013,1017,1022],{"type":16,"tag":420,"props":1009,"children":1010},{"style":439},[1011],{"type":21,"value":1012},"  \"pidDomain\"",{"type":16,"tag":420,"props":1014,"children":1015},{"style":654},[1016],{"type":21,"value":380},{"type":16,"tag":420,"props":1018,"children":1019},{"style":433},[1020],{"type":21,"value":1021},"\"linux:db5cbacc…:pid:[4026532219]\"",{"type":16,"tag":420,"props":1023,"children":1024},{"style":654},[1025],{"type":21,"value":983},{"type":16,"tag":420,"props":1027,"children":1028},{"class":422,"line":533},[1029,1034,1038,1043],{"type":16,"tag":420,"props":1030,"children":1031},{"style":439},[1032],{"type":21,"value":1033},"  \"messagingSocketPath\"",{"type":16,"tag":420,"props":1035,"children":1036},{"style":654},[1037],{"type":21,"value":380},{"type":16,"tag":420,"props":1039,"children":1040},{"style":433},[1041],{"type":21,"value":1042},"\"/run/user/1000/cc-socks/2530897.sock\"",{"type":16,"tag":420,"props":1044,"children":1045},{"style":654},[1046],{"type":21,"value":983},{"type":16,"tag":420,"props":1048,"children":1049},{"class":422,"line":572},[1050,1055,1059],{"type":16,"tag":420,"props":1051,"children":1052},{"style":439},[1053],{"type":21,"value":1054},"  \"status\"",{"type":16,"tag":420,"props":1056,"children":1057},{"style":654},[1058],{"type":21,"value":380},{"type":16,"tag":420,"props":1060,"children":1061},{"style":433},[1062],{"type":21,"value":1063},"\"busy\"\n",{"type":16,"tag":420,"props":1065,"children":1066},{"class":422,"line":580},[1067],{"type":16,"tag":420,"props":1068,"children":1069},{"style":654},[1070],{"type":21,"value":1071},"}\n",{"type":16,"tag":17,"props":1073,"children":1074},{},[1075,1077,1083,1085,1091],{"type":21,"value":1076},"That ",{"type":16,"tag":45,"props":1078,"children":1080},{"className":1079},[],[1081],{"type":21,"value":1082},"pidDomain",{"type":21,"value":1084}," is the warning. The pid belongs to the distro's pid namespace, so the same number on the Windows side refers to some unrelated process, or to nothing. The messaging socket is a UNIX socket inside the distro's tmpfs, invisible from Windows entirely. Any tool that wants to see WSL sessions from Windows has to enter the distro and read ",{"type":16,"tag":45,"props":1086,"children":1088},{"className":1087},[],[1089],{"type":21,"value":1090},"/proc",{"type":21,"value":1092}," there, not enumerate Windows processes.",{"type":16,"tag":17,"props":1094,"children":1095},{},[1096],{"type":21,"value":1097},"Nothing prunes these files. The machine measured here had 40 session records for 3 live sessions, the oldest four months old.",{"type":16,"tag":33,"props":1099,"children":1101},{"id":1100},"scripting-wsl-from-windows-three-traps",[1102],{"type":21,"value":1103},"Scripting WSL from Windows: three traps",{"type":16,"tag":17,"props":1105,"children":1106},{},[1107,1118],{"type":16,"tag":356,"props":1108,"children":1109},{},[1110,1116],{"type":16,"tag":45,"props":1111,"children":1113},{"className":1112},[],[1114],{"type":21,"value":1115},"wsl.exe -l -q",{"type":21,"value":1117}," outputs UTF-16LE, with CRLF.",{"type":21,"value":1119}," Every other tool gives you UTF-8, so a naive read gives you a string full of NUL bytes:",{"type":16,"tag":410,"props":1121,"children":1123},{"code":1122},"$ wsl.exe -l -q | od -c | head -2\n0000000   U  \\0   b  \\0   u  \\0   n  \\0   t  \\0   u  \\0  \\r  \\0  \\n  \\0\n0000020   d  \\0   o  \\0   c  \\0   k  \\0   e  \\0   r  \\0   -  \\0   d  \\0\n",[1124],{"type":16,"tag":45,"props":1125,"children":1126},{"__ignoreMap":7},[1127],{"type":21,"value":1122},{"type":16,"tag":17,"props":1129,"children":1130},{},[1131,1133,1139,1141,1147],{"type":21,"value":1132},"Decode as UTF-16LE, then trim ",{"type":16,"tag":45,"props":1134,"children":1136},{"className":1135},[],[1137],{"type":21,"value":1138},"\\r",{"type":21,"value":1140},", NUL, and the ",{"type":16,"tag":45,"props":1142,"children":1144},{"className":1143},[],[1145],{"type":21,"value":1146},"*",{"type":21,"value":1148}," that marks the default distro.",{"type":16,"tag":17,"props":1150,"children":1151},{},[1152,1157,1159,1165,1167,1173],{"type":16,"tag":356,"props":1153,"children":1154},{},[1155],{"type":21,"value":1156},"A registered distro is not a user.",{"type":21,"value":1158}," Docker Desktop and Rancher register their own back-end distros on machines whose owner has never opened a Linux shell. ",{"type":16,"tag":45,"props":1160,"children":1162},{"className":1161},[],[1163],{"type":21,"value":1164},"docker-desktop",{"type":21,"value":1166}," showing up in that list means nothing about whether anyone runs Claude Code there. A better test is whether ",{"type":16,"tag":45,"props":1168,"children":1170},{"className":1169},[],[1171],{"type":21,"value":1172},"~/.claude/projects",{"type":21,"value":1174}," in that distro is non-empty.",{"type":16,"tag":17,"props":1176,"children":1177},{},[1178,1183,1185,1191,1193,1199,1201,1207,1209,1215],{"type":16,"tag":356,"props":1179,"children":1180},{},[1181],{"type":21,"value":1182},"Pass scripts over stdin, not as arguments.",{"type":21,"value":1184}," Quoting is mangled crossing the Win32 to WSL boundary, so ",{"type":16,"tag":45,"props":1186,"children":1188},{"className":1187},[],[1189],{"type":21,"value":1190},"wsl.exe -d <distro> -- sh -c \"…\"",{"type":21,"value":1192}," loses or breaks quotes in anything non-trivial. Feed the script to ",{"type":16,"tag":45,"props":1194,"children":1196},{"className":1195},[],[1197],{"type":21,"value":1198},"sh -s",{"type":21,"value":1200}," on stdin instead, where newlines and quotes are just input. Use ",{"type":16,"tag":45,"props":1202,"children":1204},{"className":1203},[],[1205],{"type":21,"value":1206},"bash -c",{"type":21,"value":1208}," rather than ",{"type":16,"tag":45,"props":1210,"children":1212},{"className":1211},[],[1213],{"type":21,"value":1214},"bash -lc",{"type":21,"value":1216},": a login shell sources the profile and can print a MOTD into whatever you are trying to parse.",{"type":16,"tag":33,"props":1218,"children":1220},{"id":1219},"paths-and-the-permissions-that-are-not-real",[1221],{"type":21,"value":1222},"Paths, and the permissions that are not real",{"type":16,"tag":17,"props":1224,"children":1225},{},[1226,1232,1234,1240],{"type":16,"tag":45,"props":1227,"children":1229},{"className":1228},[],[1230],{"type":21,"value":1231},"wslpath",{"type":21,"value":1233}," translates both ways, and handles the ",{"type":16,"tag":45,"props":1235,"children":1237},{"className":1236},[],[1238],{"type":21,"value":1239},"\\\\wsl.localhost",{"type":21,"value":1241}," form for native Linux paths:",{"type":16,"tag":410,"props":1243,"children":1245},{"code":1244,"language":413,"meta":7,"className":414,"style":7},"$ wslpath -u 'C:\\Workspace\\my-app'      # /mnt/c/Workspace/my-app\n$ wslpath -w /mnt/c/Workspace/my-app    # C:\\Workspace\\my-app\n$ wslpath -w /home/me/.claude           # \\\\wsl.localhost\\Ubuntu\\home\\me\\.claude\n$ wslpath -u 'D:\\nope'                  # fails if the drive is not mounted\n",[1246],{"type":16,"tag":45,"props":1247,"children":1248},{"__ignoreMap":7},[1249,1276,1301,1326],{"type":16,"tag":420,"props":1250,"children":1251},{"class":422,"line":423},[1252,1256,1261,1266,1271],{"type":16,"tag":420,"props":1253,"children":1254},{"style":427},[1255],{"type":21,"value":430},{"type":16,"tag":420,"props":1257,"children":1258},{"style":433},[1259],{"type":21,"value":1260}," wslpath",{"type":16,"tag":420,"props":1262,"children":1263},{"style":439},[1264],{"type":21,"value":1265}," -u",{"type":16,"tag":420,"props":1267,"children":1268},{"style":433},[1269],{"type":21,"value":1270}," 'C:\\Workspace\\my-app'",{"type":16,"tag":420,"props":1272,"children":1273},{"style":489},[1274],{"type":21,"value":1275},"      # /mnt/c/Workspace/my-app\n",{"type":16,"tag":420,"props":1277,"children":1278},{"class":422,"line":480},[1279,1283,1287,1291,1296],{"type":16,"tag":420,"props":1280,"children":1281},{"style":427},[1282],{"type":21,"value":430},{"type":16,"tag":420,"props":1284,"children":1285},{"style":433},[1286],{"type":21,"value":1260},{"type":16,"tag":420,"props":1288,"children":1289},{"style":439},[1290],{"type":21,"value":467},{"type":16,"tag":420,"props":1292,"children":1293},{"style":433},[1294],{"type":21,"value":1295}," /mnt/c/Workspace/my-app",{"type":16,"tag":420,"props":1297,"children":1298},{"style":489},[1299],{"type":21,"value":1300},"    # C:\\Workspace\\my-app\n",{"type":16,"tag":420,"props":1302,"children":1303},{"class":422,"line":495},[1304,1308,1312,1316,1321],{"type":16,"tag":420,"props":1305,"children":1306},{"style":427},[1307],{"type":21,"value":430},{"type":16,"tag":420,"props":1309,"children":1310},{"style":433},[1311],{"type":21,"value":1260},{"type":16,"tag":420,"props":1313,"children":1314},{"style":439},[1315],{"type":21,"value":467},{"type":16,"tag":420,"props":1317,"children":1318},{"style":433},[1319],{"type":21,"value":1320}," /home/me/.claude",{"type":16,"tag":420,"props":1322,"children":1323},{"style":489},[1324],{"type":21,"value":1325},"           # \\\\wsl.localhost\\Ubuntu\\home\\me\\.claude\n",{"type":16,"tag":420,"props":1327,"children":1328},{"class":422,"line":505},[1329,1333,1337,1341,1346],{"type":16,"tag":420,"props":1330,"children":1331},{"style":427},[1332],{"type":21,"value":430},{"type":16,"tag":420,"props":1334,"children":1335},{"style":433},[1336],{"type":21,"value":1260},{"type":16,"tag":420,"props":1338,"children":1339},{"style":439},[1340],{"type":21,"value":1265},{"type":16,"tag":420,"props":1342,"children":1343},{"style":433},[1344],{"type":21,"value":1345}," 'D:\\nope'",{"type":16,"tag":420,"props":1347,"children":1348},{"style":489},[1349],{"type":21,"value":1350},"                  # fails if the drive is not mounted\n",{"type":16,"tag":17,"props":1352,"children":1353},{},[1354,1356,1362,1364,1370,1372,1378,1380,1386],{"type":21,"value":1355},"One more thing that bites hook scripts: everything under ",{"type":16,"tag":45,"props":1357,"children":1359},{"className":1358},[],[1360],{"type":21,"value":1361},"/mnt/c",{"type":21,"value":1363}," is mounted through drvfs and reports mode ",{"type":16,"tag":45,"props":1365,"children":1367},{"className":1366},[],[1368],{"type":21,"value":1369},"0777",{"type":21,"value":1371},". There are no real Unix permissions there, so ",{"type":16,"tag":45,"props":1373,"children":1375},{"className":1374},[],[1376],{"type":21,"value":1377},"chmod +x",{"type":21,"value":1379}," on a script living on the Windows drive does not mean what you think it means. Keep hook scripts in the Linux filesystem, or invoke them explicitly with ",{"type":16,"tag":45,"props":1381,"children":1383},{"className":1382},[],[1384],{"type":21,"value":1385},"bash script.sh",{"type":21,"value":31},{"type":16,"tag":33,"props":1388,"children":1390},{"id":1389},"when-one-machine-is-really-two",[1391],{"type":21,"value":1392},"When one machine is really two",{"type":16,"tag":17,"props":1394,"children":1395},{},[1396],{"type":21,"value":1397},"The practical consequence of all this: a single Windows laptop can run Claude Code in a terminal and inside WSL at the same time, reading two config files, writing two histories, on two sides of a network boundary. Any tool that watches your sessions has to cover both, or it silently covers half your work.",{"type":16,"tag":17,"props":1399,"children":1400},{},[1401,1403,1408,1410,1415,1417,1423],{"type":21,"value":1402},"That is exactly the problem ",{"type":16,"tag":24,"props":1404,"children":1405},{"href":269},[1406],{"type":21,"value":1407},"Blooby",{"type":21,"value":1409}," solves on the desktop side: it installs its hooks into both ",{"type":16,"tag":45,"props":1411,"children":1413},{"className":1412},[],[1414],{"type":21,"value":171},{"type":21,"value":1416}," files, probes each distro as well as Windows itself, and puts one mascot per live session on your taskbar no matter which side it started from. If you run ",{"type":16,"tag":24,"props":1418,"children":1420},{"href":1419},"/guides/multiple-claude-code-sessions",[1421],{"type":21,"value":1422},"several sessions at once",{"type":21,"value":1424},", that is the half of the picture the terminal cannot show you.",{"type":16,"tag":1426,"props":1427,"children":1428},"style",{},[1429],{"type":21,"value":1430},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":480,"depth":480,"links":1432},[1433,1434,1435,1436,1437,1438,1439],{"id":35,"depth":480,"text":38},{"id":176,"depth":480,"text":179},{"id":338,"depth":480,"text":341},{"id":920,"depth":480,"text":923},{"id":1100,"depth":480,"text":1103},{"id":1219,"depth":480,"text":1222},{"id":1389,"depth":480,"text":1392},"markdown","content:guides:claude-code-wsl.md","content","guides/claude-code-wsl.md","guides/claude-code-wsl","md",1]