From de97b8726ae2e809b54bc196290eca65ef1bd03c Mon Sep 17 00:00:00 2001 From: WillowDev <216433317+willowdev-code@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:44:45 +0200 Subject: [PATCH 1/2] Icon, Start menu, PATH, uninstall can remove PATs and settings --- CHANGELOG.md | 8 +++ README.md | 12 +++-- README.pl.md | 10 +++- pack.ps1 | 1 + packaging/icon/adolens.ico | Bin 0 -> 19819 bytes packaging/icon/icon.png | Bin 0 -> 14434 bytes packaging/icon/make-icon.ps1 | 91 +++++++++++++++++++++++++++++++++++ packaging/inno/ado-lens.iss | 83 ++++++++++++++++++++++++++++++++ packaging/mcpb/manifest.json | 1 + src/AdoLens/AdoLens.csproj | 2 + src/AdoLens/Cli.cs | 9 +++- src/AdoLens/CommandLine.cs | 2 +- 12 files changed, 212 insertions(+), 7 deletions(-) create mode 100644 packaging/icon/adolens.ico create mode 100644 packaging/icon/icon.png create mode 100644 packaging/icon/make-icon.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2910f4d..76adff6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.5.1 — unreleased + +- An icon: the program, the installer, Settings → Apps, the Start menu and the Claude Desktop extension. +- Start menu folder "ADO Lens": settings (`adolens setup`), status, skills for Claude Desktop, uninstall. +- The installer puts the program folder on the user's PATH: `adolens` works in any new terminal. +- Uninstall asks whether to remove the stored PATs and the settings and cache too (default: keep them); it also takes + the program off the PATH. `adolens logout --all` removes every stored PAT. + ## 0.5.0 — 2026-10-15 Tests, templates, and two more ways to install. diff --git a/README.md b/README.md index c6bb1cd..9a8fb44 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +ADO Lens + # ADO Lens for Azure DevOps — an MCP server for Claude [![CI](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml/badge.svg)](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml) @@ -47,8 +49,12 @@ The install package is not part of the repository (`dist\` is excluded by `.giti administrator rights. It asks for the Azure DevOps link and the PAT (checked before anything is installed), who uses it (Product Owner / developer / everything), installs the skills and registers ADO Lens in Claude; an update skips the questions. Until the program is signed, Windows SmartScreen may show "Windows protected your PC" for a file downloaded -in a browser: *More info → Run anyway* (or use the one-line install above, which avoids it). Uninstall it from -*Settings → Apps*. +in a browser: *More info → Run anyway* (or use the one-line install above, which avoids it). + +After installing, the Start menu has an **ADO Lens** folder: *settings* (mode, environments, another connection — +`adolens setup` in a console), *status* (is everything working) and the skills for Claude Desktop; `adolens` works in +any new terminal. Uninstall from *Settings → Apps → ADO Lens* (or the Start menu): it removes the program, its Claude +registrations and skills, and asks whether to remove the stored PATs and settings too (by default they stay). **Claude Desktop only (extension).** `ado-lens-X.Y.Z.mcpb` from **Releases**: open it with Claude Desktop (or drag it into *Settings → Extensions*) and fill in the project link and the PAT, which Claude Desktop keeps in the system's secure @@ -103,7 +109,7 @@ mentions it once per session; say "update ADO Lens" and `ado_upgrade` downloads installer in its own window. From a terminal: `adolens upgrade` shows what is new, `adolens upgrade --install` installs it (`--pre` includes test releases). Settings, PATs and metadata are kept; Claude may stay open. -Uninstall: `uninstall.ps1` in the installation folder (removes the Claude registrations and skills of this installation, +Uninstall (ZIP and one-line installs): `uninstall.ps1` in the installation folder (removes the Claude registrations and skills of this installation, asks about the stored PATs and the local data). ### The PAT diff --git a/README.pl.md b/README.pl.md index 2f7137a..e00ef9e 100644 --- a/README.pl.md +++ b/README.pl.md @@ -1,3 +1,5 @@ +ADO Lens + # ADO Lens for Azure DevOps — serwer MCP dla Claude'a [![CI](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml/badge.svg)](https://github.com/willowdev-code/ado-lens/actions/workflows/ci.yml) @@ -48,7 +50,11 @@ administratora. Pyta o link do Azure DevOps i PAT (sprawdzane, zanim cokolwiek s Owner / programista / wszystko), instaluje skille i rejestruje ADO Lens w Claudzie; aktualizacja pomija pytania. Dopóki program nie jest podpisany, Windows SmartScreen może przy pliku pobranym przeglądarką pokazać „System Windows ochronił ten komputer”: *Więcej informacji → Uruchom mimo to* (albo użyj instalacji jedną linijką powyżej, która tego unika). -Odinstalowanie: *Ustawienia → Aplikacje*. + +Po instalacji w menu Start jest folder **ADO Lens**: *ustawienia* (tryb, środowiska, kolejne połączenie — `adolens setup` +w konsoli), *status* (czy wszystko działa) i skille dla Claude Desktop; `adolens` działa w każdym nowym terminalu. +Odinstalowanie: *Ustawienia → Aplikacje → ADO Lens* (albo z menu Start) — usuwa program, jego rejestracje w Claudzie +i skille, i pyta, czy usunąć też zapisane PAT-y i ustawienia (domyślnie zostają). **Tylko Claude Desktop (rozszerzenie).** `ado-lens-X.Y.Z.mcpb` z **Releases**: otwórz go w Claude Desktop (albo przeciągnij do *Settings → Extensions*) i wpisz link do projektu oraz PAT, który Claude Desktop trzyma w bezpiecznym @@ -105,7 +111,7 @@ w sesji; wystarczy powiedzieć „zaktualizuj ADO Lens”, a `ado_upgrade` pobie instalator w osobnym oknie. Z terminala: `adolens upgrade` pokazuje, co nowego, `adolens upgrade --install` instaluje (`--pre` uwzględnia wydania testowe). Ustawienia, PAT-y i metadane zostają; Claude może być otwarty. -Deinstalacja: `uninstall.ps1` w folderze instalacji (usuwa rejestracje i skille tej instalacji w Claude, pyta o zapisane +Deinstalacja (instalacja z ZIP-a i jedną linijką): `uninstall.ps1` w folderze instalacji (usuwa rejestracje i skille tej instalacji w Claude, pyta o zapisane PAT-y i dane lokalne). ### PAT diff --git a/pack.ps1 b/pack.ps1 index 9a5471f..7335e7b 100644 --- a/pack.ps1 +++ b/pack.ps1 @@ -92,6 +92,7 @@ if (-not $NoZip) { [IO.File]::WriteAllText((Join-Path $mcpbStage 'manifest.json'), $manifest, (New-Object Text.UTF8Encoding $false)) Copy-Item (Join-Path $stage 'bin') $mcpbStage -Recurse Copy-Item (Join-Path $stage 'LICENSE') $mcpbStage + Copy-Item (Join-Path $PSScriptRoot 'packaging\icon\icon.png') $mcpbStage $mcpb = Join-Path $OutDir "ado-lens-$version.mcpb" New-Zip $mcpbStage $mcpb $false Write-Checksum $mcpb 'mcpb' diff --git a/packaging/icon/adolens.ico b/packaging/icon/adolens.ico new file mode 100644 index 0000000000000000000000000000000000000000..37bf0ebe887079b114848a897561e33a4efd3739 GIT binary patch literal 19819 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 QivR!s07*qoM6N<$g0u-n)&Kwi literal 0 HcmV?d00001 diff --git a/packaging/icon/icon.png b/packaging/icon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ba3d60460d5140dc854c47c76bac144bec5114 GIT binary patch literal 14434 zcmb_@`9IX(_xPQ$W>=brmYM@yZa<{S+GfL>EWMGpWt^auykl+eH3 zr$dL(KbV)Ex)LbqJHG@q$Q=~#DFX00nwDTq0kuzgXqb8d!0_$l2kUUpvjsqEPg6zF z;Hkyhq^1t%VlC;hk3E}_sAP4-y#fEou! zY0KeUgAz~8jq%+2>D;5h`uY$iC2HRPn?C|2PMoEQzdvu;lll<=(Ps1e3NhWQ|5mp| z_Ck*ewW+~-hprdF&TA@fNe*44FC8Qa^8uMz7uz7lmkZe2BR#BiZ&?;r)u<0d zC0HsHFzKsTsd{(msm_45cI+z)Qh!OJ*ObW>Uj~ixa{o-{oXcr{@z=)4G^#R$sB_Lb z_n5}TB-r+L-bPWmZ~H!JUQSJ@v+ke*X4;|=b-}L%YEAgsYKuAz4rL#^bYizOn+tHh z&H%|pc%8F_kL&ne*!wGz`)<% zu)z_vF1^0Lo5~89N-Av{zfydVyQZq4%kQP{(jiOW)OFKdk`)3OXJw9QKg)ReT*yKu z`q@So27?c3B7w=W^bF`!oVXIk#kv0 zJhf`9_+rkL9bcYbuK*~yFClMQ?o*Li%@7y*MMnR|m%1lC(~lto`)n`rn`G+JhYv}> zd=hZ^j$K&23eXAcYcx~iN*W&ZsNS)xrcVGobgZ-Ob)+4HYeqJd7#rbNWT^lTaX|1{ zh>&7zg!`IFq5EN7DgZGipHlDAw%w9=O&IV(Jp;(rd-0om9~10xj&Dh1Uc-zaAzg&p z!4-LzPnhrrAB9&Y16Pg3EIFUtDwG%wx^b~T$XVek06W&VTYeSwUH?$T9H3iZHO#OI=bp3xIVZzT>>S#3R+Lb2gv3K}Le@N9k8r^+KH#=l}@4P#S-c+14;e z^%!zJp`_0Y5|?8$A+DX*qX9q))cF}BueHW2fELL@b=h7aRhrWa1Q-}O=OXcm<t8-I=p_k_WMuXhY*ygux9L~;wH(ke?reQ;QB|8-Yd%!5 z?|VrBTHLn3w>V2A#isCC;vRVO6+bcn!0al^MEeD4d)%v%WJv)4++t}>rXHk6~cWAqfX)L;axFW}msN(yneWf^gXpvI#`u zp5+a3NGAMZ+5qr08I^NcUGS8(9oA5r)BvC@3iY)<1qTF)FC7P^m;ks|>6z8>=EbSr z<-07^L>PEgA+GPP_Kn>Bk49;oE&$<;v7NT^EIhAyhUnn{srRNLQTH0}Df!*s#`4SG zAqtANGIG~UZw!>UkpmE?mhUM4~$u@f$LhteAtQhsXLR8}*00I+b4ZK%h`ofGDMwU3Cps7Z;0r$W$f|e`fzOb$y z414fN3+ZD-cO&_y1m)~9H$aO}Xp^_iuzWQ;CId0aCKD7U*Cy7CC4#~rW%|54-%MLZ zcp5)-4S+J9+zoiq*>wY1iZ&#U`(i^QE~Umlc>SZ;A_0}T zUODJR?2DL=E+EOHYdCHv{~Y>^v7r+V%fV^E@WKInJChkxhf4-mJsfhHaG7r^KJH-H zrdeq9LL6PGn9g)l74+sU>%3>Y@xEx2gVCg9x&3h|-u<_F`+08jI+q0~dXOPU8HFx&SfR1MIZ(NCDZ!HP@Ci*;sln8Qk zrA+VNWuy^Zc3{w_=dFd$+^#1ay_fbVufg1hn^OI(*?MDKr=}%$C`qMrH#q7UH_}L? zfD^Rp6K%h{O!bcvUv>u>;qMu*C+d#O6`gm}=U^0xGmGtt&lhp# zZ;!mof@#&P9nUUJN>M3`p zSz8{``zHJxX~mom#X4FAdE$hs-_>HH)#q=KA>c?}I<2IiBjuRn2)*Dz!As4tNY*Yc zj;;Gs3jHnIgBY8{8z}jFA|7lD=&y~~9au$Lf_-{&RwMja*@wfwN}EP9r%4*TI(vKi z%T0hsU3}Qh{5@mN(091nK^=2xv2VmM;ncn9d1C~;C6nGeQFk;mi_(AhJKxgfG@04T zjoP*r?H9H=O{Z7`oR4VG57-mLKa~icS|Cy7;J)+a&qr8N1}RlQ1V{^6bsNA0ZMXv7 z?~Ue1syw{mD&2ivq4RRNTE_M-U2g?=M$9E&m$-9}QU{R&dc(9f790B&(v@f8%x(Si zaBp8*EIFGl6>U5K_ViDZe~!MuWRh3LYS5Ve61(W3#Cj%?HSf4kP9|@|0l?WM4)4bd zSsmtl=T)?|lj`4odzD}8Oxz6tERnM1qRU2+#`69XP3IPOL|oQfKAq(PKgH`JUMD|N zO5FzRl|#Ey%b(+T!S3v98W97A!4};Ci%*N95rW%9^zw&}p+IJhlHWLcMAX%7ay0g4 zTWm`B;9`?xuDwzOn_reegtluld0cLD`$ z^~<^IjxaMKj?d2Eib86b5>Gp>%NMS9BOB;P5`Nx%A);;kPDEi{3jSDk@Y?#lpsix* z%F}aNbpw`9?TWYGp_|;vwgxR-)P7Sd!I*@L(>=P=YdHPlJ#gLPf*BjXkqucKy^iM< z-{-pQs(lso>`rIgkExl*LLHmQwiID#)jUUzQzc2%uO7^|D`Mpt+tg8C*dzHd-;OH< zqYop|Zwt~CzDgZw77czTl^fT2A}2|(#VfLD;-4Oq`w2|uNz#lI2HL&&nl8XM8Eh;B zXVOLhjNvgy?tToTronu$lAR0H@NbyMC^GB>Z8?#(QMb&{W;9D$@N`@e=1%bCAgN3) zHgq!I6)=z=r+##-)n?$(~c+nkG_6p!a$i=%Lp z`<@tJOaF$DgO#K_uLJ|BP=Eo7<##sr4NGyqX}^L(SM6j&g4<0Ynk=i2JQz_ua*X6) z)x{ZV8qgzX96?8m%yFUrKB%wyRiRi~PF20&2luB6&nVfkO8 zo~_a2Xq0eyNk;9_-LjzP6K8YCX0FnJiEs*(lv>H|ALpAzs{SQ!A0qM0>vU$cv}Ch+ z)U;^3AXr(CJ9$y;VT}5*fHc)AQGlPM=qV#XPMneIvNdTGC@J)g1U; z*qpbzb=NhRV0i0;<|E!865E1DEa#E17)Q^z_rfy*s&0egn{3e&r$6k`3S5~aGag!l zjRnJbKF_zMWPODKQ)2E&6$OoZ6_dum+;o){ zO&HXB#_ua-`}orcYE0RvyPL&xf`5?9b5VJm68VHr3`A-2>j>OH$yjS?ZoNry{1e+W z!1A?^Uftl9)aj#oy#WRM9g_=l@EPW2W}%4f4$6mt-IW0|w4}=}8f&r>KWd1!MQk}$ zfj)|BQcTP==&Trrx4+M_UtP9L);Xfvdsi&awbDVkLX<4QbA$s5M z;(m_@W*d|m>6b_73j!%4-oSa*or!1r{YWEgi^D`ddE48$8$%Tb?Z4kz-9lb2#{@u{Ln~N8-aYivKi0f2sG&u$x?}y+(8H7Hi-F3?H@Y@xVZJamP*_S;iqnzII-o5wg=f&ASv;4mnt$imu%Ev0SfxB$Ud{!7dT)?`&%&x_vO9FNIp=A;ndvn~l+ zBOO`8QA=~#Jm~HkcUeq zit$`W05_K@87D2ab-|}Y?uPf**qB~o73z=F?wSsM+j{;Y6L=W=xio*NmbQy}|CS>{ zu_Vj<-cbpyb2?f_2h=evSu+11tK)B#Y?#bgt z5-owkp@-2LqmGE3@Ss)`f5yt+MQ0RRHKH8cgj5iAtj5FUnw~0^OW}K3ZnS8ZLa1sP zZ+(&WZ-E2lFcBQcs=#LAwnr+wE|zxoH`8N_aSorGNb`?3nj$YYI{5boa73HGRJM?P z()pmyb>QeHx7yHjRZLQK%^v&g%qx&Bh9nAsl)1TKRB!ie`i$L=n0lJUCIZz%tG}(I ziq|~GKY2dTBlUh8@!l=}r92sqAckJfiZwuhK98+s1>9HmO0k1D*j)A`+pr?}`Z&rH zd-Qd%y>{5VYCGXW?SADi{mF1M;1~$oR))>cvEMbnJ+?!f-q9W#r)<)pVrUDSpcfjc zK)bBKYG~0O&`k4jsChfS_KC4xxF0G}VuX^eEgAtUZ&Ds-Y+bD0+`4;KdvkYg?`F%T;wUQ5fCTA3`(^m`*$j7gn>zOahGOs4w^GA{UsNBnH$ zp4J&SGK@tQMaxHq^svzE{vbPsfTO{3SG~1w4|nM-xBAQvSWn@Cb18?8`5t9=Gst@9 z7CZe8!7}ntA%J9I&{S$PQR5@uMcsd+>AmKygY=vjHEeiZvQE-UX#7RojS9@i!!R%k zbT8JoZs%uu(uc5Nd6Ac9$44D`Io zUZ=G8w2**l_ngxFy_ffoo}VDST~c5kE|;BAsX#~CHo4Du+rJZt_4zO0ia zL-HmM(E`i4He4+13yaVV=YJ33;xCLb*Wg_wy5qZum%P!C+J~DPsFcRJBRWIt!Pk}Q z_$sn$B+QD#uc8A_Udnf6&Q;x%4s#!Eduf3d%{m9!hN+mq%F7Bo8EtqOaNMFrzYpee zn{QqIy-=-H;3}3Si}kyR)GIpLFREiy$=(<;{IWQneBn~UyDBnTXpEY;o!|wJDygr- zB>o^=UPbedEb6l|{i*1iv{Qs!0$w-n>o9&dDk#5-(*#hU?_uR{IWRZ`oM|5>;oK|( zhXU+Ks@|LEdVG4r^09`+#bUyO?%Nlmq1B#7a%o26j6K2dmJ3zW&TqDtN%jhkvRo6F z-#=I8(6Lf5{d=+9EO0UJkYikh#&Udc|9b+~$BGL9s)X)vUJLu&7%PjoKkmviNahhX z(fKn-{ekAJ%Taf&4Bof;29jaR!0sbY+qk_a)H-ZvU{91rjZD zE>`%EY3l9_lu4gkrC$LtWRUfY$&w= ztj*r*I+Ops#~+Z^f2S9&QO4zLYt~y1_sW2IG`xkfs-IN9nZT+evOU0={7nYfUTTF~ zEj^Elv*h0N;K{?fM#>!;9F{eI5rVp6@V@Ztu4j$M=_jm~U^M7FLph(G^Hn}MHX9U` zlSsYzQu&8CSy)|^nH~g!hV%GGmPRLj8|fQrxS3VOp&@R{X5*4mLR5B@@F1f>|LtU{ zDxSqFWPAxcm$AI`+qwSvh7M5aUpOG8&58|4l4)KfE9yNZkIk;&*k_~;WbB5w<)>oqj?p-Q{2;6H$z?P@2l1nh@(VmH)(0<-Y@=2OA4 z0edS-3Z(5aQT!o;{!wc@SxoA{^!e-Rk%6(7)QWps=xETG>+We+!}0^I*O@SBy)J%P z$e&m`h+u&F4IeZ?weGSu7P-ux~;%zb*(Oh68$q^j>%TQT@2_`R(o+|!T-E10MpPTWzDpahXiL8B}HuOO7v4X>;uuH7hKw-F)0G>-*<{NUIB#sQ+Fu_fAvwYDQi0W0$I+Gdx~f zE|rbwXgCi|WNGSEXl(f=0V=LvuFT&i#RswtJ*Rsu@q{S6LA>{S*{7pbZ$m4IA5)?O ztY8SBTUHB%0{^11_8f%GC8AZ#0Hs)n!|&KT6ZDwaVhXg1i`dNTaxk{Y295}70@^zZ zkG&kRY{iX|`?G^i?sEfD%jnQe99`i0Bt9lZV0W5KYA)erun@?M@rU+l*ViJRrJ1<6 z4-xHptxE{}Jo;C#8_#Q3n+ivBtJq&b3{yOyMJFC8HTLR0>{E~-9d;<9t#r<8{!D^Ar z)sIiJs0V{M%xt`1I>&dLvGxL7kXB`mM3W#ym{zgkM%{<&3jQlq=|(6HGyP%6qgC;$ z5od~fHRK=-V~{R3bw^@_YmpHm#6d~{#D~bxkFN8Q^~E1SiyWUQ;M(PgMOLu_@f#m2 zr7kNxyIjnmAyo1yH+OiNYSduAy`b2MaCEA&SEC`17Tp-cAJ?%CN4k3<)}K~ca>nR9 z!)^q-+mpV7NCU9qQ5Pab|e**-%MYU zA9TSritk7XhW3N}=IaPNV;d6I%Z;$1{}IJigLinf$a?TIru7c%L+9pG zZUVw5_?mcl{5wGeZrn5cc2B~T6S*1?ZBS^a(6C>rL0ZtdW zsV--|x?>qY!Y}fAAK3)u`)Z$9`d#zmFsua>n)&ekY|Cp^?a>y07q?pAPZtIyrq=T1 zy_0RMi@EMn=-&+7*yQfEl_-pbt7_uRprG@k-b^;CURC z5a83r&FgwS#eNuJyl@h}LmdT|% zP-LP(hrc8Gr=JY#u%`lw(lW`@@Uf=fMOb^DIk;7|C0NCC#NAD#wM}%B#jl46@B@y!n9#HCTH{HcGDC>5^f2f%z+E4WN)H zYU=24Vt&vwWGxz8)zI8>U%$8)EF=*K9A5KdEPmpOE@Dj3XtjEGPGUM+ZFYVodrM>& z*JoeF(uQQDi^RXLeg*yKbMT>OsA4#iX%G6EXq}UvL)+4dd1cNjwUS2_l4La(a8aq; zusDrzr~z^5h)dgVJzszi4Mn#U|7rkbMAA!WW_N->EQuRIb8Gz5Q1;I9vKf>ECo7Z)mFY(E7J<7tm@hr`cRr(RrZP-j9sobA#`>+sGDK;Qk z+>0C-mUGx6pllY)ux>LlkYByMJ-P7iR)evtRE(`;Kk3e8BW|5>db2P%kF%L3SpR&` zXZ}ycGZ!GEl0Al7`f7&?qRl$e8%)TVGEPX~mVQL>Xp9mTY|H zPS=MG{c(B$-4!Z)6VX_2FZX1Hk$kdB!XLD~zhVQm1j=zc&0j7BJdK71a{<~Eim-wB>p9?Hapr+0<`@B3rovfu; zt4hgc+FoRNebjLva!W(2($KXPU^}I+g}x5~$EZJaW!xd1Y$mQef>s=}%WzHmBXgMr zQtT(l>p6p9KUSpRnNOBP-ItfE7j&v5%)`X;T%!j#`_FH^Z@O{rY4Juw_131ULqqxA zgs&@Uc7q}RIGFRY(T0@z^G3}^iIOVLA8X+?U_W%4`dRME4+<}#@#F}@qv0yH!L@F@ zf8liU=F2|qfW?w$931M}mh^|X#xS44W3?yPs&sL6bYs5XdLGsXsSdM>Unn^P4MED2 zZwPB4LSM?z?l#k$xVtfJTc^6D5K&6_**GFbe2b4KI)A_ho%CRl{yD}a{Zm7>63>RM zOVeLQvm1L#A;%enMA=G+f3{SL*IEcdplDFSaZia~6X6T9y*fnMSyPWvR-5D!Vt{}I zE5&k#@nk!nK$+I>Lgj^+DyjA+S{+gsTIS}3_UJSRH>t~49;o$NxVyhle^PrKouUg& z)ER8qN^VAYv&~4N0x)woU9IlY)CvoXD~`(xotI{HMQt<-EPG3Puu!1mAE74mvP^to z>j8l(oQSt->n|L~sX~9ZW}0c@^ur+1w67b$7;j|DJ!i`bQZ_PfWX~=(X)3Jjk=!#y zPNugD@wXg?*MeJxj^mFlkKdAWFY93$ZJ)zij6_qOWkvppUe_Jxez|e0qC2@}w^D}Z zLZsZeJXd~%nwRnS)jvM!BSMaAROQeCz2BDhxOhRdi z>R+FDv2hy)-=i~ftU_Kxw-vU%lTk|c%rkF3dJQg1Dm~R3|K2>~h9RRs3!Bx^^5pyB!?DrN1idfMOxIwAg^be< z((ieVhC|r|Mg%DFSQABVCe7GwC&W#qKbzP)jFHj!9&2{cUF_s4%X3~lp$;LP)0$?X ze3F-Hi)SP2&0+EyRq$UA_kFT`$NR^d*T-j!UpO%qlc?3b$9Z#&j_=eQs$+zJ*&LST zwZJM4%t?|iYpheYxjvq$+BLX3{1L}K3msV-TkK14ln`|RGb`9TqG%yO8OxD*@~eKo zQYr3y$@g0b$EIJMAa1&CMCCG2c>TE}mF^K$@c>I|wA?T_3frue+z@k`nz1|LZ10;1QWZJs&c2 zzm6f*_=pT~=MOe;YFEmw_vj8*UM3$;WrCmqQngRnka5dg`Vhc<({3%XKy0yU#pz2X zH32VQWB`x1g}yL>NEC<85ji5_yjV%2x{ajS@u!nK-SGCvDX$0*F>jPcVIaKqLNIFY z^K1KlFJXP-=0D5ap-}2d^h2rhe3kv?Po8W`WP;3Iszg9)KrF@U`~Rf~i|f`hqz!A> zYU}d-Gqq3hi+Jsey;BPo{u1dBN+k$GQAJffV>B=#TM zmwHNky@Lw601VLxZk~kyie|uZmQ4j>byyaFnpM#?^g@&JQGOg_isrhS3|o z+gBV$FM3&H3(dY5pQLIH_VRwco`{qy$-~hLK^s03r$G0Kl-m>cHlLs^d!QWeb}7qmt6aMm^Ocu0N?fMcWc0?F+=iBq3NLz$V0q5?*p0<6LOtq1aX-=;%7Gj8ZZIb5-;v|HsKKf!n0)tC zEitQGDK^(?tV0({4Sr?~Q~y*FEyvs9HPFdlO_1G7y%C_;pv;V(`v?_6q2nD>+&Q$a+$c+@^L*_0 zS$pgwHS#%h_VOx4#Wv%Om#r%j_cqX(WX*l)?w=bqnyD-Ok`M|2p~w$7$dk@)lU++s zp;?HlbOo{)?7Q71v0gDXHO!`Ipkhfy{Sby9OW36YMd<$M5g)TevTj|DtKbLj><2 zz>m&&F4LRh_jpRrN9il_xF{x#GE(^7N?`DW)Qo{ch%S=BI_0;oKNsP9caf$m2$xuQ z&(-S~-Ty48L5UgtAOp0t+RC7XzY_Syiyf>kCrHM~UM_Fqdn)+3Je4-TM@-H3d9H}_ zJ0FeYeQIrSs0)P-m>IF1$)u*15(nK#5wdNOOI5ZRO;gVW^ZXx)RfnH?d|g7dMGH5k_7FPmA$))`CLgA$Z+aq%UN^|Jr#}Lud>0qty2+Ln_2Uy;&;dM_*}dEW zlj>p#`ZT<4**fHqzFzaGBGostq_dfn%xF}Rt-64RZhN1dx2;i!T;MDPXw_?ULv2c% zD}_J!NUf3QNQ-8Ka$+6s)N`4uU$q-bf){(7LYd}n+ee@+a5ZXoj|s{&Af)u5S8)od z9&Q8mISYl2+qk;Gucsh5Eg|^n5I6`G(1)i6^e5=k^0tLSgjArkJ?fC6r9YcFygsMz z_uW%Wb2=~htP(BBg*qhWUciB>UZoFXDbt0vk2>USoD?7;Z}meuvvh>4t$(`-R$8H z7Rbf;pT5LXdF&*QfE|SK@kj~*tMu*n+QHIhN~{rdGrjI~1xGrPLhx-yRiuaxXo12S z*XH5(=Bv5qmF)R^!{>dP5fRv+x3m#xf->`r97MM?$F+G>;;NmNtU!M3bD5&&B>#WN zTb!8L0BK1Ij)_CS&8hY$JO=oJy`1lS7Y>-Q@ouJ89zGX=es%@{i{4j7mz!HxLYodo z0(^$7nHlL;FtWN$`~1touJYVDzpT=ONEm8nx@4Wo`t5N9A5U`+0+yaX&N7k-(Dm~n zgFgehQeJ47@ddx4BV_OGXOfMM}S3$g+R{%C(_dw9aNmrbUcwL=^Wzsc9nmU zNrCb$`$8n#MGNO{4Uf}&>nb^3FRJ%0H9HynlK@&m2ry|6Ypjs2?6>fFVjf_0yR{}Z9r4H_WuHszg(m`+Vk--`O@xMrsRh*xHcf~h?Yn93ck z^`2#i`53ov8D)?zqZ@h(cAFJ+s)bo! zoj^rHP)}BG=DX>O=v7d()I-~gl4&Lo-dr%;h=BR!9N>bylOHmlbbktU*Y15AFytB` z2Qh?v3^BxZ@YHAt)m-YPKmQy;7XhJbzRJSH2i2m7Q>r4@XGKpYYrrFefYpZ81Ky7S zpihLtx(*K!*oMzIDDnfIp9MzHtGMq9+`85Lo~ONGn^Du$06AR1iGZ2rcZ4+EhzVk<* zLkGPGFX|@$`_7`;LeSK<(5+@KSA%LrB|lOBknlSY_73plFe7 zW(Md7`S)?`sx9~OpE}mp701L=)1pb6CqE7tz}z0b9f4la|2fA7x_p$3AZA+x5wKA` zVmFsJ2k*%cXQ0rM=r~Sk3Kcp7Ho-<}OiFWs8=Gw;Brvo1dA$WgmcF3_JOGKA(_JE$PftA8AK8|tFUQ#~R9Io|9@$<=)}y?3Rsv|jCM zgQZ9^fCv^TSy^hfdO7)*-&b%sZ9KP%#rhZ47V16tL;t>K>GWBE%)(CfCh*>@!#I<= z!m10`l*5A#eJY`nz`n)@7oo~k0Cb%RgI_Tt6i?P=mg0~5>z(VF%3qdB#{im991a9+|2zx&L8*z_5$F{`iX*Q2AvkMXj&P_&sPSDn*3ndyQ4T>J3ZoM5mX_ z9{iTLLcfQ(hwh)y>%RtE)GTQ|``@co#sV}(lb1($yPh%qhO#fQGo}6ns6b zbNXANbB-F6y}8Rc)I7H6{Y-{yqON)P`g5~C-K2{YZ9Q}H#~Z55s)x)xSN7aG^PpV3 zNohsCY)t_h-LB-gxNASWX$snY9~w=X zOtCs=)jgE*oeZD}*B_N!|5Wtnp!2;?B^iXmm^JWt!^mmOp!f;ob@PwB-a>`PuS86A zWFfCB=NBXW(sNTYQs<*(9qNO)D#E<=?#upI*eV9M{lf=QRR8t>XK&ywqTpBPtK|Si zJIS2Yz&%p&Kv}Kk5>&ok!*b9R^(D6J&&A}6!%;AR_Iu>xu{GW6G&WS^3&|-jrRgx8 z-WT!~OyrI+>C3DrG>l)Kn?IWmp!0la2sXzKD6fA2HSuT7kNfQxL|ZBbOrfDa^u;M~ zm=5Q8pM}ciH0qjzCWaT@9FQyw+PxO6J$5m}tE8$qm9~=DYWO zDeh%&y!{ZrRF<_qu7^@j@;m@qE4RmJQJ#@dDn$xvM%5+zkycy%A&Hw^-AGq9fp`ul zTR7gKUV&uUH*Vstb|X&zoaFE!hqfd%oD!#NpV&Kv%boS6%K#W#T8})1>PMNxUcNov z0<{;`@1@%B@_ke(xa11m1+jWvFXi)Pu9+#eV0qn&40`dQUJ`$8pY3wFb#~o=q#We4 zwJtUno`$3%uIiC%#AhEvx+Nyy9B_$Y;&0&CBz-tU}#`SOBQ?>)E}- z4NV6OjXjM=E4G7SpzNlv>&zt4DEDI_G?QN#=4OPJH=Ut>;&9J~`(Iseu(0sld&z|h zBL_SWAgp)JP0a@o`&3z}rdSAQ$jBX)sa_wO^`)BM5WFLK_fR2=kN|+lqt2I0af0rW zNxC67IsJ@wO6VuOf}jgtCDpcM)dU-M)35o*Gth;IZiR(fuRw2|*(C*ez~f|_lwe3a z6){0?QXb^o7jZ{Guf4>CBPm0!&e-jZ`sa}wpK(o`FT~-&SpT~7tm?`pw^K; zizk*sz_&#EV7{ICP>UJ}G1Lm#%v@CMkCR%ty*}}y(;Nnb%4Mfl8MqdI4>t-7V9a5^ zm_HP4Bz}1dhawkVtR^Y=lBrVB>xq|jJNNv0Jq~j?*+5L8RUNLkDh{}lDHdVP^R7#YrUi?2tfWW~3 literal 0 HcmV?d00001 diff --git a/packaging/icon/make-icon.ps1 b/packaging/icon/make-icon.ps1 new file mode 100644 index 0000000..610ae91 --- /dev/null +++ b/packaging/icon/make-icon.ps1 @@ -0,0 +1,91 @@ +<# +.SYNOPSIS + Draws the ADO Lens icon: a lens over three work item bars on an Azure blue tile. + Writes adolens.ico (16-256 px, PNG frames) and icon.png (512 px) next to this script. +#> +$ErrorActionPreference = 'Stop' +Add-Type -AssemblyName System.Drawing + +function New-RoundedRect([float] $x, [float] $y, [float] $w, [float] $h, [float] $r) { + $p = New-Object System.Drawing.Drawing2D.GraphicsPath + $d = 2 * $r + $p.AddArc($x, $y, $d, $d, 180, 90) + $p.AddArc($x + $w - $d, $y, $d, $d, 270, 90) + $p.AddArc($x + $w - $d, $y + $h - $d, $d, $d, 0, 90) + $p.AddArc($x, $y + $h - $d, $d, $d, 90, 90) + $p.CloseFigure() + return $p +} + +function New-IconBitmap([int] $size) { + $bmp = New-Object System.Drawing.Bitmap $size, $size, ([System.Drawing.Imaging.PixelFormat]::Format32bppArgb) + $g = [System.Drawing.Graphics]::FromImage($bmp) + $g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias + $g.PixelOffsetMode = [System.Drawing.Drawing2D.PixelOffsetMode]::HighQuality + $g.Clear([System.Drawing.Color]::Transparent) + $s = [float] $size + + # Tile: Azure blue, lighter at the top. + $margin = [Math]::Max(0.5, $s * 0.03) + $tile = New-RoundedRect $margin $margin ($s - 2 * $margin) ($s - 2 * $margin) ($s * 0.2) + $grad = New-Object System.Drawing.Drawing2D.LinearGradientBrush (New-Object System.Drawing.PointF 0, 0), (New-Object System.Drawing.PointF 0, $s), + ([System.Drawing.Color]::FromArgb(255, 0, 137, 230)), ([System.Drawing.Color]::FromArgb(255, 0, 90, 170)) + $g.FillPath($grad, $tile) + + $white = [System.Drawing.Color]::White + # Lens: a ring, centred a little up and left, with a handle to the bottom right. + $cx = $s * 0.43; $cy = $s * 0.43; $r = $s * 0.24 + $ring = [Math]::Max(1.5, $s * 0.075) + if ($size -ge 32) { + # Three work item bars inside the lens (left out at small sizes, where they would blur). + $bar = New-Object System.Drawing.SolidBrush ([System.Drawing.Color]::FromArgb(235, 255, 255, 255)) + $bh = $s * 0.045 + foreach ($i in 0..2) { + $w = $r * (1.05 - 0.25 * $i) + $y = $cy - $r * 0.42 + $i * $r * 0.42 - $bh / 2 + $path = New-RoundedRect ($cx - $r * 0.55) $y $w $bh ($bh / 2) + $g.FillPath($bar, $path) + } + } + $pen = New-Object System.Drawing.Pen $white, $ring + $g.DrawEllipse($pen, $cx - $r, $cy - $r, 2 * $r, 2 * $r) + $handle = New-Object System.Drawing.Pen $white, ([Math]::Max(2, $s * 0.11)) + $handle.StartCap = [System.Drawing.Drawing2D.LineCap]::Round + $handle.EndCap = [System.Drawing.Drawing2D.LineCap]::Round + $a = 0.7071 * ($r + $ring / 2) + $g.DrawLine($handle, $cx + $a, $cy + $a, $s * 0.76, $s * 0.76) + $g.Dispose() + return $bmp +} + +$dir = $PSScriptRoot +$sizes = 16, 20, 24, 32, 40, 48, 64, 128, 256 +$frames = foreach ($n in $sizes) { + $bmp = New-IconBitmap $n + $ms = New-Object System.IO.MemoryStream + $bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png) + $bmp.Dispose() + , $ms.ToArray() +} + +# ICO: header, one directory entry per size, then the PNG frames. +$out = New-Object System.IO.MemoryStream +$w = New-Object System.IO.BinaryWriter $out +$w.Write([UInt16]0); $w.Write([UInt16]1); $w.Write([UInt16]$sizes.Count) +$offset = 6 + 16 * $sizes.Count +for ($i = 0; $i -lt $sizes.Count; $i++) { + $n = $sizes[$i] + $dim = if ($n -ge 256) { 0 } else { $n } + $w.Write([byte]$dim); $w.Write([byte]$dim); $w.Write([byte]0); $w.Write([byte]0) + $w.Write([UInt16]1); $w.Write([UInt16]32) + $w.Write([UInt32]$frames[$i].Length); $w.Write([UInt32]$offset) + $offset += $frames[$i].Length +} +foreach ($f in $frames) { $w.Write($f) } +$w.Flush() +[IO.File]::WriteAllBytes((Join-Path $dir 'adolens.ico'), $out.ToArray()) + +$big = New-IconBitmap 512 +$big.Save((Join-Path $dir 'icon.png'), [System.Drawing.Imaging.ImageFormat]::Png) +$big.Dispose() +Write-Host "written adolens.ico and icon.png in $dir" diff --git a/packaging/inno/ado-lens.iss b/packaging/inno/ado-lens.iss index 3b0cb7a..e7039f8 100644 --- a/packaging/inno/ado-lens.iss +++ b/packaging/inno/ado-lens.iss @@ -26,7 +26,11 @@ AppSupportURL=https://github.com/willowdev-code/ado-lens/issues DefaultDirName={localappdata}\Programs\ADO Lens DisableDirPage=yes DisableProgramGroupPage=yes +DefaultGroupName=ADO Lens DisableReadyPage=yes +SetupIconFile={#SourcePath}..\icon\adolens.ico +; The program folder goes on the user's PATH, so "adolens" works in any new terminal. +ChangesEnvironment=yes PrivilegesRequired=lowest ArchitecturesAllowed=x64compatible ArchitecturesInstallIn64BitMode=x64compatible @@ -52,6 +56,19 @@ Source: "{#DesktopSkills}\*.zip"; DestDir: "{app}\skills-for-claude-desktop"; Fl ; Claude Code reads skills from %USERPROFILE%\.claude\skills (only when Claude Code is there); removed on uninstall. Source: "{#Source}\skills\*"; DestDir: "{%USERPROFILE}\.claude\skills"; Flags: recursesubdirs ignoreversion; Check: HasClaudeCode +[Icons] +; Start menu: settings and status open in a console that stays open (adolens commands work there too). +Name: "{group}\{cm:IconSettings}"; Filename: "{cmd}"; Parameters: "/k """"{app}\bin\adolens.exe"" setup"""; WorkingDir: "{app}"; IconFilename: "{app}\bin\adolens.exe" +Name: "{group}\{cm:IconStatus}"; Filename: "{cmd}"; Parameters: "/k """"{app}\bin\adolens.exe"" status"""; WorkingDir: "{app}"; IconFilename: "{app}\bin\adolens.exe" +Name: "{group}\{cm:IconSkills}"; Filename: "{app}\skills-for-claude-desktop" +Name: "{group}\{cm:UninstallProgram,ADO Lens}"; Filename: "{uninstallexe}"; IconFilename: "{app}\bin\adolens.exe" + +[Registry] +Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\bin"; Check: NeedsAddPath(ExpandConstant('{app}\bin')) + +[UninstallDelete] +Type: files; Name: "{app}\bin\*.old" + [UninstallRun] Filename: "{app}\bin\adolens.exe"; Parameters: "unregister"; Flags: runhidden waituntilterminated; RunOnceId: "unregister" @@ -60,6 +77,14 @@ Filename: "{app}\skills-for-claude-desktop"; Description: "{cm:OpenSkills}"; Fla Filename: "https://github.com/willowdev-code/ado-lens#readme"; Description: "{cm:OpenReadme}"; Flags: postinstall shellexec skipifsilent unchecked [CustomMessages] +en.IconSettings=ADO Lens - settings +en.IconStatus=ADO Lens - status +en.IconSkills=ADO Lens - skills for Claude Desktop +en.RemoveData=Also remove the stored personal access tokens (Windows Credential Manager) and the settings and cache of ADO Lens?%n%nChoose No to keep them for a later installation. +pl.IconSettings=ADO Lens - ustawienia +pl.IconStatus=ADO Lens - status +pl.IconSkills=ADO Lens - skille dla Claude Desktop +pl.RemoveData=Usunąć też zapisane tokeny dostępu (Menedżer poświadczeń Windows) oraz ustawienia i pamięć podręczną ADO Lens?%n%nWybierz Nie, aby zachować je na potrzeby ponownej instalacji. en.ConnTitle=Azure DevOps en.ConnSub=Where your work items are en.ConnText=Paste a link to your Azure DevOps project from the browser (for example https://dev.azure.com/contoso/Sales), or the organization name. @@ -119,6 +144,64 @@ var function SetEnvironmentVariable(lpName: String; lpValue: String): Boolean; external 'SetEnvironmentVariableW@kernel32.dll stdcall'; +{ Whether a folder is missing from the user's PATH (compared without case and trailing backslash). } +function NeedsAddPath(Dir: String): Boolean; +var + Path: String; +begin + if not RegQueryStringValue(HKCU, 'Environment', 'Path', Path) then + begin + Result := True; + Exit; + end; + Result := Pos(';' + Lowercase(RemoveBackslashUnlessRoot(Dir)) + ';', ';' + Lowercase(Path) + ';') = 0; +end; + +procedure RemoveFromPath(Dir: String); +var + Path, Item, Kept: String; + P: Integer; +begin + if not RegQueryStringValue(HKCU, 'Environment', 'Path', Path) then Exit; + Kept := ''; + Path := Path + ';'; + while Path <> '' do + begin + P := Pos(';', Path); + Item := Copy(Path, 1, P - 1); + Delete(Path, 1, P); + if (Item <> '') and (Lowercase(RemoveBackslashUnlessRoot(Item)) <> Lowercase(RemoveBackslashUnlessRoot(Dir))) then + begin + if Kept <> '' then Kept := Kept + ';'; + Kept := Kept + Item; + end; + end; + RegWriteExpandStringValue(HKCU, 'Environment', 'Path', Kept); +end; + +var + RemoveUserData: Boolean; + +{ Before the files go: ask whether to remove the stored PATs and the local data (default: keep them), and sign out + with the program while it is still there. After: take the program folder off the PATH and delete the data. } +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +var + Code: Integer; +begin + if CurUninstallStep = usUninstall then + begin + RemoveUserData := not UninstallSilent and + (MsgBox(CustomMessage('RemoveData'), mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES); + if RemoveUserData then + Exec(ExpandConstant('{app}\bin\adolens.exe'), 'logout --all', '', SW_HIDE, ewWaitUntilTerminated, Code); + end + else if CurUninstallStep = usPostUninstall then + begin + RemoveFromPath(ExpandConstant('{app}\bin')); + if RemoveUserData then DelTree(ExpandConstant('{localappdata}\ado-lens'), True, True, True); + end; +end; + function HasClaudeCode: Boolean; begin Result := DirExists(ExpandConstant('{%USERPROFILE}\.claude')); diff --git a/packaging/mcpb/manifest.json b/packaging/mcpb/manifest.json index 5c53897..64930b9 100644 --- a/packaging/mcpb/manifest.json +++ b/packaging/mcpb/manifest.json @@ -17,6 +17,7 @@ "documentation": "https://github.com/willowdev-code/ado-lens#readme", "support": "https://github.com/willowdev-code/ado-lens/issues", "license": "MIT", + "icon": "icon.png", "keywords": ["azure devops", "work items", "sprint", "wiki", "tfvc", "git", "pull requests"], "server": { "type": "binary", diff --git a/src/AdoLens/AdoLens.csproj b/src/AdoLens/AdoLens.csproj index f579b8d..dd01bc6 100644 --- a/src/AdoLens/AdoLens.csproj +++ b/src/AdoLens/AdoLens.csproj @@ -12,6 +12,8 @@ true true en + + ..\..\packaging\icon\adolens.ico diff --git a/src/AdoLens/Cli.cs b/src/AdoLens/Cli.cs index e371266..8a819ab 100644 --- a/src/AdoLens/Cli.cs +++ b/src/AdoLens/Cli.cs @@ -22,7 +22,7 @@ public static void PrintUsage() => Console.WriteLine(""" login add or update a connection: organization, default project and PAT --org --project --team --connection --pat-stdin (read the PAT from standard input) --default (make it the default connection) - logout remove the stored PAT of a connection --connection + logout remove the stored PAT of a connection --connection | --all connections list the connections config show or change settings --connection --project --team (defaults of a connection) @@ -184,6 +184,13 @@ public async Task LoginAsync() public int Logout() { var settings = Settings.Load(SettingsPath); + if (cl.Flag("all")) + { + // Uninstall: every stored PAT of the connections in the settings. + foreach (var conn in settings.Connections.Keys) + Console.WriteLine(CredentialStore.Delete(conn) ? $"removed {CredentialStore.TargetFor(conn)}" : $"no stored PAT for '{conn}'"); + return 0; + } var name = cl.Opt("connection") ?? settings.DefaultConnection; if (string.IsNullOrWhiteSpace(name)) { Console.WriteLine("no connection configured - nothing to remove"); return 0; } Console.WriteLine(CredentialStore.Delete(name) diff --git a/src/AdoLens/CommandLine.cs b/src/AdoLens/CommandLine.cs index 1212b13..1c015f7 100644 --- a/src/AdoLens/CommandLine.cs +++ b/src/AdoLens/CommandLine.cs @@ -17,7 +17,7 @@ public sealed partial class CommandLine ["login"] = ["connection=", "org=", "project=", "team=", "pat-stdin", "pat-env=", "default"], ["tests"] = ["connection=", "team=", "detail="], ["test-create"] = ["connection=", "file=", "plan=", "suite="], - ["logout"] = ["connection="], + ["logout"] = ["connection=", "all"], ["connections"] = [], ["trace"] = ["connection=", "detail="], ["pr"] = ["connection=", "project=", "repo=", "list=", "detail="], From 60fcfb2ecb4f5ae4e9edfed1e3cf22ad5bcc6696 Mon Sep 17 00:00:00 2001 From: WillowDev <216433317+willowdev-code@users.noreply.github.com> Date: Thu, 15 Oct 2026 15:45:15 +0200 Subject: [PATCH 2/2] ADO Lens 0.5.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - An icon: the program, the installer, Settings → Apps, the Start menu and the Claude Desktop extension. - Start menu folder "ADO Lens": settings (`adolens setup`), status, skills for Claude Desktop, uninstall. - The installer puts the program folder on the user's PATH: `adolens` works in any new terminal. - Uninstall asks whether to remove the stored PATs and the settings and cache too (default: keep them); it also takes the program off the PATH. `adolens logout --all` removes every stored PAT. --- CHANGELOG.md | 2 +- src/AdoLens/AdoLens.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76adff6..72b2b57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 0.5.1 — unreleased +## 0.5.1 — 2026-10-15 - An icon: the program, the installer, Settings → Apps, the Start menu and the Claude Desktop extension. - Start menu folder "ADO Lens": settings (`adolens setup`), status, skills for Claude Desktop, uninstall. diff --git a/src/AdoLens/AdoLens.csproj b/src/AdoLens/AdoLens.csproj index dd01bc6..d08b4fa 100644 --- a/src/AdoLens/AdoLens.csproj +++ b/src/AdoLens/AdoLens.csproj @@ -23,7 +23,7 @@ ADO Lens for Azure DevOps Azure DevOps (work items, boards, wiki, Git and TFVC, pipelines) served to AI assistants over MCP Copyright © 2026 WillowDev - 0.5.0 + 0.5.1