<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Mehdi Chaid</title>
    <subtitle>Personal portfolio and blog.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://chaid.me/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://chaid.me"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-01-01T00:00:00+00:00</updated>
    <id>https://chaid.me/atom.xml</id>
    <entry xml:lang="en">
        <title>Mira</title>
        <published>2026-01-01T00:00:00+00:00</published>
        <updated>2026-01-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/projects/mira/"/>
        <id>https://chaid.me/projects/mira/</id>
        
        <content type="html" xml:base="https://chaid.me/projects/mira/"></content>
        
    </entry>
    <entry xml:lang="en">
        <title>gatekeeper</title>
        <published>2025-07-11T00:00:00+00:00</published>
        <updated>2025-07-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/projects/api-gateway/"/>
        <id>https://chaid.me/projects/api-gateway/</id>
        
        <content type="html" xml:base="https://chaid.me/projects/api-gateway/"></content>
        
    </entry>
    <entry xml:lang="en">
        <title>chartlab</title>
        <published>2025-04-30T00:00:00+00:00</published>
        <updated>2025-04-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/projects/data-viz/"/>
        <id>https://chaid.me/projects/data-viz/</id>
        
        <content type="html" xml:base="https://chaid.me/projects/data-viz/"></content>
        
    </entry>
    <entry xml:lang="en">
        <title>devtool</title>
        <published>2025-02-14T00:00:00+00:00</published>
        <updated>2025-02-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/projects/cli-tool/"/>
        <id>https://chaid.me/projects/cli-tool/</id>
        
        <content type="html" xml:base="https://chaid.me/projects/cli-tool/"></content>
        
    </entry>
    <entry xml:lang="en">
        <title>Some more convenient tools for W11</title>
        <published>2024-12-13T00:00:00+00:00</published>
        <updated>2024-12-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/notes/winconv/"/>
        <id>https://chaid.me/notes/winconv/</id>
        
        <content type="html" xml:base="https://chaid.me/notes/winconv/">&lt;p&gt;There&#x27;s quite a lot of very convenient features on most Linux DEs that
are just not in Windows by default, so I&#x27;m showing here some of the useful
ones I&#x27;ve found on W11.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wincompose&quot;&gt;WinCompose&lt;&#x2F;h2&gt;
&lt;p&gt;For writing code, I prefer using the classic US keyboard layout, but I also often need
french letters and symbols for writing messages. Unfortunately, I&#x27;m not a fan of the french layout
for writing code, as some of the very useful symbols like &#x2F; and {} are a pain to type. I&#x27;m also not
very fond of swapping keyboard layouts all the time.&lt;&#x2F;p&gt;
&lt;p&gt;Most Linux distributions ship with
something called &lt;code&gt;ComposeKey&lt;&#x2F;code&gt; by default that lets you type accent letters and much more, by composing
them together. For example, &lt;code&gt;é&lt;&#x2F;code&gt; can be written by pressing a compose key (that you set in your settings)
followed by &lt;code&gt;e&lt;&#x2F;code&gt; and &lt;code&gt;&#x27;&lt;&#x2F;code&gt;. It&#x27;s quite intuitive and you don&#x27;t have to remember where each of the letters is
on a french layout, which isn&#x27;t always obvious.&lt;&#x2F;p&gt;
&lt;p&gt;Well, Windows does not have Compose Key by default, but there&#x27;s a really nice software on
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;samhocevar&#x2F;wincompose&quot;&gt;GitHub&lt;&#x2F;a&gt; that brings back that functionality. I&#x27;ve been using it for
over 7 years, it&#x27;s great.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;windhawk&quot;&gt;Windhawk&lt;&#x2F;h2&gt;
&lt;p&gt;Continuing the Microsoft tradition of making new Windows releases shittier than the previous ones, they removed
some useful features from W10 when W11 shipped.&lt;&#x2F;p&gt;
&lt;p&gt;The right click contextual menu was dumbed down a lot for
&quot;clarity&quot;, the taskbar is not locked to the bottom, can&#x27;t be put as a topbar anymore, and it&#x27;s always stuck on
your main monitor. Personally, I prefer having it on the top of my secondary monitor, to make it easy to watch the
time and the open apps.&lt;&#x2F;p&gt;
&lt;p&gt;Recently, I found a new marketplace for Windows utilities called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ramensoftware&#x2F;windhawk&quot;&gt;WindHawk&lt;&#x2F;a&gt;.
You can develop mods (basically dlls) that can be loaded to bring new features or restore old ones. It&#x27;s a use at your
own risk kind of software though, because although Windhawk itself is opensource, I&#x27;m not sure how vested each of the
marketplace modules are, although the source code for them is available for them. The ones I&#x27;ve been using are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Classic context menu on Windows 11&lt;&#x2F;li&gt;
&lt;li&gt;Primary taskbar on secondary monitor&lt;&#x2F;li&gt;
&lt;li&gt;Taskbar on top for Windows 11&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;more-ahk-scripts&quot;&gt;More AHK scripts&lt;&#x2F;h2&gt;
&lt;p&gt;I mentioned AHK scripts in the &lt;a href=&quot;&#x2F;notes&#x2F;winsetup&quot;&gt;linux workspaces in W11 note&lt;&#x2F;a&gt;, where I use it to swap desktops.
It can do a lot more, like launching apps with shorcuts, so here&#x27;s a few examples I use. You can also use it to
launch a terminal at a specific File Explorer location, I&#x27;m leaving an example here.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ahk2&quot; class=&quot;language-ahk2 &quot;&gt;&lt;code class=&quot;language-ahk2&quot; data-lang=&quot;ahk2&quot;&gt;#b:: ; Win + B =&amp;gt; Firefox
{
  Run &amp;quot;firefox.exe&amp;quot;
}

#q:: ; Win + Q =&amp;gt; Wezterm
{
  OpenAndFocusWindow(&amp;quot;C:\Program Files\WezTerm\wezterm-gui.exe&amp;quot;)
}

#+q:: ; Win + Shift + Q =&amp;gt; Wezterm open at location
{
  path := GetExplorerPath()
  if path {
    ; Always launch a new instance with the specific path
    Run(&amp;#x27;&amp;quot;C:\Program Files\WezTerm\wezterm-gui.exe&amp;quot; start --cwd &amp;quot;&amp;#x27; path &amp;#x27;&amp;quot;&amp;#x27;)
    ; Wait for the new window and activate it
    if WinWait(&amp;quot;ahk_exe wezterm-gui.exe&amp;quot;, , 2) {  ; Wait up to 2 seconds
      WinActivate(&amp;quot;ahk_exe wezterm-gui.exe&amp;quot;)
    }
  } else {
    OpenAndFocusWindow(&amp;quot;C:\Program Files\WezTerm\wezterm-gui.exe&amp;quot;)
  }
}

; ==================
; UTILITY FUNCTIONS
; ==================

OpenAndFocusWindow(cmd, winTitle := &amp;quot;&amp;quot;, timeout := 500) {
    ; If no specific title provided, use the executable name
    if (winTitle = &amp;quot;&amp;quot;)
        winTitle := &amp;quot;ahk_exe &amp;quot; . StrSplit(cmd, &amp;quot;\&amp;quot;)[-1]

    if WinExist(winTitle) {
        ToggleWindow(winTitle)
    } else {
      Run(cmd)
      if WinWait(winTitle, , timeout) {
        ToggleWindow(winTitle)
      }
    }
}

ToggleWindow(winTitle) {
  if WinActive(winTitle) &amp;amp;&amp;amp; WinGetMinMax(winTitle) != -1 {
      WinMinimize(winTitle)
  } else {
    WinActivate(winTitle)
  } 
}

GetExplorerPath() {
    hwnd := GetActiveExplorerHWND()
    if !hwnd {
        return
    }

    ; Retrieve the file path from the active Explorer window
    shellWindows := ComObject(&amp;quot;Shell.Application&amp;quot;).Windows
    for window in shellWindows {
        try {
            if window.hwnd == hwnd
                return window.Document.Folder.Self.Path
        } catch {
            continue
        }
    }
    return &amp;quot;&amp;quot;
}

GetActiveExplorerHWND() {
    ; Check for active Explorer window and return its hwnd
    activeWindow := WinActive(&amp;quot;ahk_class CabinetWClass&amp;quot;) 
                 || WinActive(&amp;quot;ahk_class ExploreWClass&amp;quot;)
    return activeWindow ? WinExist(&amp;quot;A&amp;quot;) : &amp;quot;&amp;quot;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;winget&quot;&gt;Winget&lt;&#x2F;h2&gt;
&lt;p&gt;Although not as widespread as &lt;code&gt;apt&lt;&#x2F;code&gt;, &lt;code&gt;pacman&lt;&#x2F;code&gt;, &lt;code&gt;yum&lt;&#x2F;code&gt;, etc, Windows have had package managers
for a while, such as &lt;code&gt;Chocolatey&lt;&#x2F;code&gt; and &lt;code&gt;Scoop&lt;&#x2F;code&gt;. Well, they also have an official one called
&lt;code&gt;winget&lt;&#x2F;code&gt; now. It doesn&#x27;t have all the packages the popular ones have but being the official manager,
it&#x27;s catching up fast.&lt;&#x2F;p&gt;
&lt;p&gt;I prefer managing my apps through a terminal personally, so winget is convenient
and it ships by default with W11.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Linux workspaces in W11</title>
        <published>2023-05-07T00:00:00+00:00</published>
        <updated>2023-05-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/notes/winsetup/"/>
        <id>https://chaid.me/notes/winsetup/</id>
        
        <content type="html" xml:base="https://chaid.me/notes/winsetup/">&lt;h2 id=&quot;the-issue&quot;&gt;The issue&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;ve been using a bunch of different Linux desktop environments and windows managers
over the past few years, from Gnome, KDE to bspwm and i3. However, I often have to
develop on Windows as well for game development or work, and one thing that&#x27;s been
icking me is its attrocious multi-desktop support.&lt;&#x2F;p&gt;
&lt;p&gt;In any of the different DEs and WMs I&#x27;ve used, it&#x27;s been pretty easy to create multiple
workspaces and assign keybinds in a config files for swapping between workspaces,
sending apps to a different workspace, and assigning apps to a default workspace.&lt;&#x2F;p&gt;
&lt;p&gt;On Windows, it&#x27;s a different story. Workspaces are static, and switching between them
is done with the &lt;code&gt;Ctrl&lt;&#x2F;code&gt; + &lt;code&gt;Win&lt;&#x2F;code&gt; + &lt;code&gt;←&lt;&#x2F;code&gt; or &lt;code&gt;→&lt;&#x2F;code&gt; keybinds (and there&#x27;s this slow transition
animation between workspace).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;basic-solution&quot;&gt;Basic solution&lt;&#x2F;h2&gt;
&lt;p&gt;As far as I&#x27;m aware, there&#x27;s no easy way to override the default keybinds for changing
workspaces, and I&#x27;m not aware of any keybind to send apps to different workspaces other
than &lt;code&gt;Win&lt;&#x2F;code&gt; + &lt;code&gt;Tab&lt;&#x2F;code&gt; and manually dragging them there.&lt;&#x2F;p&gt;
&lt;p&gt;A convenient tool for scripting solutions like that for Windows is
&lt;a href=&quot;https:&#x2F;&#x2F;www.autohotkey.com&#x2F;&quot;&gt;Autohotkey&lt;&#x2F;a&gt;, which I&#x27;ve been using for a while for all
my scripting needs on Windows. It&#x27;s well documented and easy to use. I used to have
an old fashioned way of doing things for workspace management, where I&#x27;d have a counter
for which desktop I&#x27;m in, and when I press &lt;code&gt;Win&lt;&#x2F;code&gt; + &lt;code&gt;Num&lt;&#x2F;code&gt; it would activate the default
windows shortcuts a number of times to reach the desired desktop. Something like that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ahk2&quot; class=&quot;language-ahk2 &quot;&gt;&lt;code class=&quot;language-ahk2&quot; data-lang=&quot;ahk2&quot;&gt;#Requires AutoHotkey v2.0

currentDesktop := 1
totalDesktops := 4  ; Adjust to however many desktops you have

#1:: SwitchToDesktop(1)
#2:: SwitchToDesktop(2)
#3:: SwitchToDesktop(3)
#4:: SwitchToDesktop(4)

SwitchToDesktop(target) {
    global currentDesktop
    if (target = currentDesktop || target &amp;gt; totalDesktops)
        return

    if (target &amp;gt; currentDesktop) {
        loop (target - currentDesktop)
            Send &amp;quot;^#{Right}&amp;quot;
    } else {
        loop (currentDesktop - target)
            Send &amp;quot;^#{Left}&amp;quot;
    }

    currentDesktop := target
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The issue is that it&#x27;s kind of hacky. AHK does not have a direct way of accessing virtual
desktops, and the API for them on Windows is... There&#x27;s also no easy way to send apps to
virtual desktops with shortcuts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-better-way&quot;&gt;A better way&lt;&#x2F;h2&gt;
&lt;p&gt;Recently, I came across this &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Ciantic&#x2F;VirtualDesktopAccessor&quot;&gt;repository&lt;&#x2F;a&gt;.
It&#x27;s a DLL for accessing the virtual desktops API easily in AHK (and there&#x27;s binding for Rust as well!).
With this, I was able to update my scripts to directly go to the right desktop, skip the pesky slow animation
and even add keybinds to send apps to a desktop of my choice:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;ahk2&quot; class=&quot;language-ahk2 &quot;&gt;&lt;code class=&quot;language-ahk2&quot; data-lang=&quot;ahk2&quot;&gt;#Requires AutoHotkey v2.0
SetWorkingDir(A_ScriptDir)

; =================
; VIRTUAL DESKTOPS
; =================

VDA_PATH := A_ScriptDir . &amp;quot;\virtual_desktop_accessor.dll&amp;quot;
hVirtualDesktopAccessor := DllCall(&amp;quot;LoadLibrary&amp;quot;, &amp;quot;Str&amp;quot;, VDA_PATH, &amp;quot;Ptr&amp;quot;)

if (hVirtualDesktopAccessor = 0) {
  MsgBox(&amp;quot;Failed to load virtual_desktop_accessor.dll&amp;quot;)
  ExitApp
}

GetDesktopCountProc := DllCall(&amp;quot;GetProcAddress&amp;quot;, &amp;quot;Ptr&amp;quot;, hVirtualDesktopAccessor, 
                               &amp;quot;AStr&amp;quot;, &amp;quot;GetDesktopCount&amp;quot;, &amp;quot;Ptr&amp;quot;)
GoToDesktopNumberProc := DllCall(&amp;quot;GetProcAddress&amp;quot;, &amp;quot;Ptr&amp;quot;, hVirtualDesktopAccessor, 
                                 &amp;quot;AStr&amp;quot;, &amp;quot;GoToDesktopNumber&amp;quot;, &amp;quot;Ptr&amp;quot;)
GetCurrentDesktopNumberProc := DllCall(&amp;quot;GetProcAddress&amp;quot;, &amp;quot;Ptr&amp;quot;, hVirtualDesktopAccessor, 
                                       &amp;quot;AStr&amp;quot;, &amp;quot;GetCurrentDesktopNumber&amp;quot;, &amp;quot;Ptr&amp;quot;)
MoveWindowToDesktopNumberProc := DllCall(&amp;quot;GetProcAddress&amp;quot;, &amp;quot;Ptr&amp;quot;, hVirtualDesktopAccessor, 
                                         &amp;quot;AStr&amp;quot;, &amp;quot;MoveWindowToDesktopNumber&amp;quot;, &amp;quot;Ptr&amp;quot;)

ActivateWindowUnderMouse() {
  MouseGetPos ,, &amp;amp;winID
  if winID {
    WinActivate(winID)
  }
}

GetDesktopCount() {
    global GetDesktopCountProc
    count := DllCall(GetDesktopCountProc, &amp;quot;Int&amp;quot;)
    return count
}

GoToDesktopNumber(num) {
    global GoToDesktopNumberProc
    DllCall(GoToDesktopNumberProc, &amp;quot;Int&amp;quot;, num, &amp;quot;Int&amp;quot;)
    Sleep(50)
    ActivateWindowUnderMouse()
    return 
}

MoveCurrentWindowToDesktop(number) {
    global MoveWindowToDesktopNumberProc, GoToDesktopNumberProc
    activeHwnd := WinGetID(&amp;quot;A&amp;quot;)
    DllCall(MoveWindowToDesktopNumberProc, &amp;quot;Ptr&amp;quot;, activeHwnd, &amp;quot;Int&amp;quot;, number, &amp;quot;Int&amp;quot;)
    DllCall(GoToDesktopNumberProc, &amp;quot;Int&amp;quot;, number, &amp;quot;Int&amp;quot;)
}

MoveOrGotoDesktopNumber(num) {
    ; If user is holding down Mouse left button, move the current window also
    if (GetKeyState(&amp;quot;LButton&amp;quot;)) {
        MoveCurrentWindowToDesktop(num)
    } else {
        GoToDesktopNumber(num)
    }
    return
}

; ========================
; VIRTUAL DESKTOP BINDINGS
; ========================

Loop 5 { ; Win + 1-5, can go up to 9 if needed
    n := A_Index - 1
    Hotkey(&amp;quot;#&amp;quot; . A_Index, (*) =&amp;gt; MoveOrGotoDesktopNumber(n))
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&amp;amp; voilà, Linux WMs shorcuts are now restored on Windows 11!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>On the fly access to PassGen</title>
        <published>2016-09-17T00:00:00+00:00</published>
        <updated>2016-09-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/notes/pypassapp/"/>
        <id>https://chaid.me/notes/pypassapp/</id>
        
        <content type="html" xml:base="https://chaid.me/notes/pypassapp/">&lt;p&gt;In &lt;a href=&quot;&#x2F;notes&#x2F;pypass&#x2F;&quot;&gt;the previous article&lt;&#x2F;a&gt;, we made a small python script to generate a custom password with a given algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;The problem is, having to manually &lt;code&gt;cd&lt;&#x2F;code&gt; into the script directory, run it and copy the output can be painful. Running the algorithm in your head or a piece of paper would be even more troublesome, although it is a good fallback scenario and one of the main strength of this approach: You don&#x27;t have to remember the password, just the salt and the algorithm. The brain is better at recalling patterns than unreadable strings anyway.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;&#x2F;h2&gt;
&lt;p&gt;The idea here is that we need a small application, accessible anywhere in your device, that will take your salt and domain name as input and paste the password in the correct field for you, while keeping the previous status of your clipboard. After all, hoarding your password in your clipboard could be dangerous: Imagine you paste it in a chatbox later on!&lt;&#x2F;p&gt;
&lt;p&gt;The app we&#x27;ll build will look somehow like this:&lt;&#x2F;p&gt;
&lt;img src=&quot;assets&#x2F;example.gif&quot; width=&quot;100%&quot;&gt;
&lt;h2 id=&quot;ui&quot;&gt;UI&lt;&#x2F;h2&gt;
&lt;p&gt;For the UI, let&#x27;s keep things simple: We&#x27;ll use a library called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;poulp&#x2F;zenipy&quot;&gt;zenipy&lt;&#x2F;a&gt;, a gtk-based dialog generator for python.&lt;&#x2F;p&gt;
&lt;p&gt;First, let&#x27;s install it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip install zenipy
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I personally prefer keeping things contained withing virtual environnements, so I&#x27;ll install it as follow:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;python -m venv env
source env&amp;#x2F;bin&amp;#x2F;activate
pip install zenipy
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll also need &lt;code&gt;python3-gi&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip install python3-gi
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, let&#x27;s import zenipy at the top of our script. Since we&#x27;re dealing with password, we&#x27;ll use the password module instead of the regular text input.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;from zenipy import password
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, replace the &lt;code&gt;input()&lt;&#x2F;code&gt; with zenipy&#x27;s &lt;code&gt;password()&lt;&#x2F;code&gt; method to prompt the password field to the user (a.k.a yours truly).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;service = password(&amp;quot;Service&amp;quot;)
salt = password(&amp;quot;Salt&amp;quot;)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Run that, you get:&lt;&#x2F;p&gt;
&lt;img src=&quot;assets&#x2F;sofar.gif&quot; width=&quot;100%&quot;&gt;
&lt;h2 id=&quot;prompt-from-anywhere&quot;&gt;Prompt from anywhere&lt;&#x2F;h2&gt;
&lt;p&gt;The last step would be to make a shell script to run that python script, get the output, put it into the clipboard, paste the later in the password field and finally, restore the previous state of the clipboard.&lt;&#x2F;p&gt;
&lt;p&gt;All of it could technically be done within our little python script with a library called &lt;a href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;pyperclip&#x2F;&quot;&gt;pyperclip&lt;&#x2F;a&gt;, but I&#x27;m experienting issues related to the latest version of Ubuntu with this library.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll cover both the python approach and the shell one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;python-way&quot;&gt;Python way&lt;&#x2F;h2&gt;
&lt;p&gt;Install pyperclip:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;pip install pyperclip
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then add the following code at the end of our PassGen script:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;old_clip = pyperclip.paste()

pyperclip.copy(password)

pyperclip.paste()

pyperclip.copy(old_clip)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We save the previous state of the clipboard, copy the generated password, paste it and restore the old content of the clipboard.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shell-way&quot;&gt;Shell way&lt;&#x2F;h2&gt;
&lt;p&gt;Using shell, we can achieve the same result just as easily with xclip and xdotool, covered in &lt;a href=&quot;&#x2F;notes&#x2F;pass&#x2F;&quot;&gt;a previous tutorial&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;oldclip=`xclip -sel c -o`
temp=`&amp;#x2F;path&amp;#x2F;to&amp;#x2F;python &amp;#x2F;path&amp;#x2F;to&amp;#x2F;example.py`
echo $temp | xclip -sel c
sleep 0.5
xdotool key ctrl+shift+v
echo $oldclip | xclip -sel c 
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code saves the previous clipboard state, run the PassGen script and paste the result where our cursor is. Then it restores the CTRL+C CTRL+V machine to its old glory, saving us the troubles of pasting passwords where undesired :)&lt;&#x2F;p&gt;
&lt;p&gt;Now make this script runnable and you&#x27;re ready to rock!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;shell&quot; class=&quot;language-shell &quot;&gt;&lt;code class=&quot;language-shell&quot; data-lang=&quot;shell&quot;&gt;chmod +x example.sh
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;accessing-the-script&quot;&gt;Accessing the script&lt;&#x2F;h2&gt;
&lt;p&gt;Follow the guide at the end of the &lt;a href=&quot;&#x2F;notes&#x2F;pass&#x2F;&quot;&gt;Bash Script for Token Pasting&lt;&#x2F;a&gt; tutorial to assign a keyboard shortcut to your script, and you&#x27;ll be rocking this:&lt;&#x2F;p&gt;
&lt;img src=&quot;assets&#x2F;final.gif&quot; width=&quot;100%&quot;&gt;
&lt;h2 id=&quot;end-words&quot;&gt;End words&lt;&#x2F;h2&gt;
&lt;p&gt;This concludes our little password generation adventure. We covered how to run a python script on demand from a custom keyboard shortcut, how to make a password generation script and how to make a small GUI to access it from anywhere, anytime you need it on your machine.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Password generator with Python</title>
        <published>2016-09-16T00:00:00+00:00</published>
        <updated>2016-09-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/notes/pypass/"/>
        <id>https://chaid.me/notes/pypass/</id>
        
        <content type="html" xml:base="https://chaid.me/notes/pypass/">&lt;p&gt;In the &lt;a href=&quot;&#x2F;notes&#x2F;pass&#x2F;&quot;&gt;last article&lt;&#x2F;a&gt;, we covered the basics of bash scripting for pasting a 2FA token on demand. We&#x27;ll now take this process a few steps further by adding support for password generation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-will-we-build&quot;&gt;What will we build?&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll build today a prompt that, when called, will take as input a salt as well as a domain name, and output a unique password that works for you.&lt;&#x2F;p&gt;
&lt;img src=&quot;assets&#x2F;passgen.gif&quot; width=&quot;100%&quot;&gt;
&lt;h2 id=&quot;how-is-it-useful&quot;&gt;How is it useful?&lt;&#x2F;h2&gt;
&lt;p&gt;Consider this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You have a weak and meaningful password, that will be quite easy to bypass, but at least you can remember it.&lt;&#x2F;li&gt;
&lt;li&gt;You have a long and strong password, that might prove harder to guess, but good luck remembering it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Either way, any password can be hacked and it&#x27;s always much safer to activate 2FA on your accounts.&lt;&#x2F;p&gt;
&lt;p&gt;Now let&#x27;s say you go with the second option and have a password with all the recommended criterias. Mixture of upper&#x2F;lower cases, numbers, symbols, etc... You name it. Truth is, it might end up not as safe as expected, since you&#x27;ll likely end up forgetting it and saving your password in some sort of safekeep. Maybe a text file, a password manager or some other form of way to have it under your hand when necessary.&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;re now at risk of exposing it, rendering the whole &quot;stronger&#x2F;longer password&quot; process virtually worthless if it leaks.&lt;&#x2F;p&gt;
&lt;p&gt;I was kind of thinking about that a few years ago and came up with another solution: A strong password that can still be remembered.&lt;&#x2F;p&gt;
&lt;p&gt;The trick is, our brain is much better at keeping patterns in mind than unreadable strings. Instead of trying to recall a sentence, come up with an algorithm that will map an input to a password, given a set of rules that you define.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;password-generation&quot;&gt;Password generation&lt;&#x2F;h2&gt;
&lt;p&gt;So how are we generating such password with an algorithm? That&#x27;s pretty much up to you to decide how to encode your safe code, I&#x27;ll give an example of one way of doing it. This process will take two inputs: A salt that&#x27;s unique to you and a domain name, unique to the application you&#x27;re login in to. You could choose to change that to a username, a special thing about each app, etc. We&#x27;ll keep things simple for now.&lt;&#x2F;p&gt;
&lt;p&gt;The salt will be composed of 4 numbers that you&#x27;ll choose. Like a pin, it&#x27;s the part you&#x27;ll keep in mind and help making your password safe even if someone find your algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;The domain name will be a lowercase string with max length of 8. It will be responsible of providing a unique password for each website, while still making it easy for you to fetch it in case you forget the password.&lt;&#x2F;p&gt;
&lt;p&gt;All you have to do is to remember the salt and the process, then you input your domain name and it will give you the unique password. With that in mind, I recommend you to use more than one salt for every app :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-algorithm&quot;&gt;The algorithm&lt;&#x2F;h2&gt;
&lt;p&gt;As I said, we&#x27;ll keep the algorithm easy since it&#x27;s only for demo purposes. I encourage you to come up with your own for personal use.&lt;&#x2F;p&gt;
&lt;p&gt;The process will consist on four steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Every vowel will be replaced by a given symbol:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;vowels = {
    &amp;#x27;a&amp;#x27; : &amp;#x27;!&amp;#x27;,
    &amp;#x27;e&amp;#x27; : &amp;#x27;@&amp;#x27;,
    &amp;#x27;i&amp;#x27; : &amp;#x27;#&amp;#x27;,
    &amp;#x27;o&amp;#x27; : &amp;#x27;$&amp;#x27;,
    &amp;#x27;u&amp;#x27; : &amp;#x27;%&amp;#x27;
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I simply sorted the vowels alphabetically and mapped each one to the symbols in the US keymap, in order.&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Every recurring consonnant up to five times will be replaced by a given symbol:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;recurring = {
    2 : &amp;#x27;^&amp;#x27;,
    3 : &amp;#x27;&amp;amp;&amp;#x27;,
    4 : &amp;#x27;*&amp;#x27;,
    5 : &amp;#x27;(&amp;#x27;,
}
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, US keymapping from where we stopped at the first step.&lt;&#x2F;p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;
&lt;p&gt;We&#x27;ll put a figure of the salt every three characters, and append the remaining ones at the end.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Finally, every first character after a second number will be upper-cased, the rest will be lower-cased.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;from collections import defaultdict 

# Your hashmaps here
[...]

def hash_word(input_word, salt_part):
    generated_word = &amp;quot;&amp;quot;
    appearance = defaultdict(int)
    figure = 0
    next_upper = 0

    for idx, c in enumerate(input_word.lower()):
        if idx % 3 == 0:
            generated_word += salt_part[figure]
            figure += 1
            next_upper += 1

        appearance[c] += 1

        if c in vowels:
            generated_word += vowels[c]
            continue
        
        if appearance[c] &amp;gt; 1 and appearance[c] &amp;lt; 6:
            generated_word += recurring[appearance[c]]
            continue
        
        if next_upper == 2:
            generated_word += c.upper()
            next_upper = 0
            continue

        generated_word += c
    
    if figure &amp;lt; len(salt_part):
        generated_word += salt_part[figure :]

    return generated_word
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All that&#x27;s left is to call the function with the right input and the password is yours.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;if __name__ == &amp;quot;__main__&amp;quot;:
    service = input(&amp;quot;Service\n&amp;quot;)
    salt = input(&amp;quot;Salt\n&amp;quot;)

    password = hash_word(service[:8], salt[:4])

    print(password)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Result:&lt;&#x2F;p&gt;
&lt;img src=&quot;assets&#x2F;passgen.gif&quot; width=&quot;100%&quot;&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;&#x2F;h2&gt;
&lt;p&gt;Feel free to adapt that example to your liking and use it for personal use. Tune it your way the best way you think, as long as you can remember it :)&lt;&#x2F;p&gt;
&lt;p&gt;The next step in this little adventure will be to make a small desktop app that triggers on a certain key combo to fetch the password on demand — covered in the &lt;a href=&quot;&#x2F;notes&#x2F;pypassapp&#x2F;&quot;&gt;next article&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Bash script for token pasting</title>
        <published>2016-08-27T00:00:00+00:00</published>
        <updated>2016-08-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://chaid.me/notes/pass/"/>
        <id>https://chaid.me/notes/pass/</id>
        
        <content type="html" xml:base="https://chaid.me/notes/pass/">&lt;p&gt;Do you have two factor authentification activated on GitHub yet? You most definitely should. 2FA really helps making your account secure and you will regret not having it on your account the day someone get a hold of your password.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;problem-with-2fa&quot;&gt;Problem with 2FA&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s assume you have taken a moment to setup 2FA on your account. You&#x27;re now on your terminal trying to push some changes. You do a &lt;code&gt;git push&lt;&#x2F;code&gt; and are asked to enter your username and password. Problem is: There&#x27;s no field for your 2FA code.&lt;&#x2F;p&gt;
&lt;p&gt;A possible solution is to go in your developer settings, select the &lt;em&gt;Personal Access Token&lt;&#x2F;em&gt; tab and generate a new token.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;personal-access-token&quot;&gt;Personal access token&lt;&#x2F;h2&gt;
&lt;p&gt;This token is a long hash that you can use in place of your password, which you can also restrain the level of freedom with your account. It acts like an OAuth token and can be used instead of your password over HTTPS. Such token can be restricted to pull a private repo, push, invite people to a repository, etc.&lt;&#x2F;p&gt;
&lt;p&gt;The thing is, once one is generated, you have to save it and use it everytime you need to login, it won&#x27;t be visible on your developer settings anymore for you to copy over from an other computer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;accessing-the-token&quot;&gt;Accessing the token&lt;&#x2F;h2&gt;
&lt;p&gt;So now, you have the token saved in a text file for example, and everytime you try to login in your github account from a terminal or over HTTPS, you will need to open that text file, copy the token and then paste it on the password field in place of your password.&lt;&#x2F;p&gt;
&lt;p&gt;Surely there is a way to make this whole process faster? That was the question haunting my mind when I was faced with this situation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;&#x2F;h2&gt;
&lt;p&gt;I have been exploring various solutions, including messing Compose keys and other keyboard based options, and I knew what I wanted: A custom keyboard shortcut that will fetch the personal access token and paste it into the field when prompted.&lt;&#x2F;p&gt;
&lt;p&gt;Being on ubuntu right now, I will use linux tools to achieve that goal. Note that a very similar process to what I&#x27;m about to describe is also available on OSX.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-process&quot;&gt;The process&lt;&#x2F;h2&gt;
&lt;p&gt;The solution is composed of many steps:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Have the token saved on a text file.&lt;&#x2F;li&gt;
&lt;li&gt;A special shortcut will fetch that token.&lt;&#x2F;li&gt;
&lt;li&gt;The token is copied to the clipboard.&lt;&#x2F;li&gt;
&lt;li&gt;It is then pasted into the password prompt.&lt;&#x2F;li&gt;
&lt;li&gt;The old content of the clipboard is restored.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Step 1 is pretty straight forward. You get your token, save it into a file and close the file.&lt;&#x2F;p&gt;
&lt;p&gt;Next, you&#x27;d want a script that will read that file and save its content in your clipboard. For linux, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;astrand&#x2F;xclip&quot;&gt;xclip&lt;&#x2F;a&gt;, a command line interface to the X11 clipboard, will do just fine.&lt;&#x2F;p&gt;
&lt;p&gt;Create a &lt;code&gt;token_accessor.sh&lt;&#x2F;code&gt; script and paste the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;xclip -sel c &amp;lt; &amp;#x2F;path&amp;#x2F;to&amp;#x2F;script&amp;#x2F;token_accessor.txt
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;-sel&lt;&#x2F;code&gt; will tell xclip which X selection to use, in this case the &lt;code&gt;c&lt;&#x2F;code&gt; clipboard option. Other options are &lt;code&gt;p&lt;&#x2F;code&gt; for primary and &lt;code&gt;s&lt;&#x2F;code&gt; for secondary. The &lt;code&gt;&amp;lt;&lt;&#x2F;code&gt; will get the content of the &lt;code&gt;token_accessor.sh&lt;&#x2F;code&gt; and write it in the selection.&lt;&#x2F;p&gt;
&lt;p&gt;You now have the token saved on your clipboard. The next step is to paste it into the password field. We could do it manually by pressing &lt;code&gt;ctrl&lt;&#x2F;code&gt; + &lt;code&gt;shift&lt;&#x2F;code&gt; + &lt;code&gt;v&lt;&#x2F;code&gt; but we might as well have the script do it for us.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;auto-pasting&quot;&gt;Auto-pasting&lt;&#x2F;h2&gt;
&lt;p&gt;To get that, we&#x27;ll need the script to be able to execute keyboard commands. &lt;a href=&quot;https:&#x2F;&#x2F;www.semicomplete.com&#x2F;projects&#x2F;xdotool&#x2F;&quot;&gt;xdotool&lt;&#x2F;a&gt; is perfect for that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo apt install xdotool
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now use it in our shell script as follow:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sleep 0.5
xdotool key ctrl+shift+v
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;sleep 0.5&lt;&#x2F;code&gt; is needed to let xclip finish executing. Then, we tell &lt;code&gt;xdotool&lt;&#x2F;code&gt; to input the key combo &lt;code&gt;ctrl&lt;&#x2F;code&gt;+&lt;code&gt;shift&lt;&#x2F;code&gt;+&lt;code&gt;v&lt;&#x2F;code&gt; for us.&lt;&#x2F;p&gt;
&lt;p&gt;Here we go, you no longer have to open the file holding your token everytime you want to connect to GitHub over HTTPS.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;restore-the-previous-clipboard&quot;&gt;Restore the previous clipboard&lt;&#x2F;h2&gt;
&lt;p&gt;We want to do that for two reasons:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You usually don&#x27;t want your token (aka password) on your clipboard and paste it in the wrong field, thus exposing it.&lt;&#x2F;li&gt;
&lt;li&gt;You don&#x27;t need the token on your clipboard at all time since the shortcut is pasting it anyway and chances are, it&#x27;s overwritting what you had before that might be more useful for you.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s change the script to that:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;oldpw=`xclip -sel c -o`
xclip -sel c &amp;lt; &amp;#x2F;path&amp;#x2F;to&amp;#x2F;script&amp;#x2F;token_accessor.txt
sleep 0.5
xdotool key ctrl+shift+v
echo $oldpw | xclip -sel c 
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first line saves the content of your current clipboard into &lt;code&gt;oldpw&lt;&#x2F;code&gt;. Then at the end, we restore our clipboard from the same variable.&lt;&#x2F;p&gt;
&lt;p&gt;Mac&#x27;s OSX also have &lt;code&gt;pbcopy&lt;&#x2F;code&gt; and &lt;code&gt;pbpaste&lt;&#x2F;code&gt; to achieve a very similar result.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;setup-the-keyboard-shortcut&quot;&gt;Setup the keyboard shortcut&lt;&#x2F;h2&gt;
&lt;p&gt;Now, the only thing left is to actually have a shortcut to execute that script.&lt;&#x2F;p&gt;
&lt;p&gt;First, make it executable:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;chmod +x token_accessor.sh
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, depending on your system, you want to set a shortcut to execute the script. Navigate to &lt;code&gt;Settings&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Devices&lt;&#x2F;code&gt; -&amp;gt; &lt;code&gt;Keyboard&lt;&#x2F;code&gt; and add a new shortcut with the following command:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;bash &amp;#x2F;path&amp;#x2F;to&amp;#x2F;script&amp;#x2F;token_accessor.sh
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here we go, you can now enjoy a quick access to your token when needed!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;&#x2F;h2&gt;
&lt;p&gt;Looking forward, we could use a similar script to paste a password of your choice into a field and keep the same behavior. Obviously, we don&#x27;t want an actual password to be saved as is in a non secure text file. For that reason, we&#x27;ll cover in the &lt;a href=&quot;&#x2F;notes&#x2F;pypass&#x2F;&quot;&gt;next article&lt;&#x2F;a&gt; how to generate passwords on the fly when using the script.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
