-
Notifications
You must be signed in to change notification settings - Fork 378
Description
Checks
- I have searched github.com/aws/amazon-q-developer-cli/issues and there are no duplicates of my issue
- I have run
q doctorin the affected terminal session - I have run
q restartand replicated the issue again
Operating system
macOS 15.3.2
Expected behaviour
Amazon Q CLI not to slow down terminal initialisation or impact runtime performance.
Actual behaviour
Q CLI Analysis
The Amazon Q CLI significantly slows down the loading of new terminal sessions on macOS when integrated with zsh. Profiling and analysis reveal that the primary causes are double initialisation and a slow pre-command hook.
Environment:
- Shell:
zsh - Operating System: macOS 15.3.2
- Amazon Q CLI Installation Method: The latest official Amazon Q installer
Problem Summary:
After Amazon Q CLI makes changes to add itself into both ~/.zshrc and ~/.zprofile, the startup time of new terminal sessions increased dramatically. Furthermore, the shell felt generally sluggish, with a noticeable delay before each prompt appeared.
Detailed Findings:
-
Double Initialisation: The Amazon Q CLI initialisation script (
q init zsh pre) is executed twice during shell startup: once from~/.zprofileand again from~/.zshrc. The scripts generated forpreare identical for both files. This leads to redundant operations and significantly increases the initial load time.- Evidence:
zshprofiling (zprof) and tracing (set -x) clearly show the repeated execution of the initialisation logic.
- Evidence:
-
Slow
q _ pre-cmd: Theq _ pre-cmdcommand, which is executed before every prompt via aprecmdhook, introduces a significant delay. This delay is the primary cause of the perceived sluggishness of the shell after the initial load.-
Evidence: Timing measurements using the
timecommand show thatq _ pre-cmdtakes approximately 11ms to complete:time $HOME/.local/bin/q _ pre-cmd --alias "$(\alias)"
Output:
$HOME/.local/bin/q _ pre-cmd --alias "$(\alias)" 0.00s user 0.00s system 85% cpu 0.011 total
This 11ms delay is added to every command execution, making the shell feel unresponsive.
-
-
q _ should-figterm-launchContributes to Startup Delay: Theq _ should-figterm-launchcommand, executed during initialisation, also contributes to the initial startup delay.-
Evidence: Timing measurements:
time $HOME/.local/bin/q _ should-figterm-launch
Output:
❌ zsh (qterm) | (46360) <- ✅ zsh (46368) 🟡 Falling back to old mechanism since on macOS $HOME/.local/bin/q _ should-figterm-launch 0.01s user 0.01s system 93% cpu 0.013 total
This adds 13ms to the startup time.
-
-
qtermis not being launched: The output fromq _ should-figterm-launchindicates it is falling back to an "old mechanism".
Steps to Reproduce:
- Profile zsh without Q
- Install the Amazon Q CLI.
- Integrate the CLI into
zshby adding the recommended lines to~/.zshrcand~/.zprofile. - Profile zsh with Q
- Open a new terminal session and observe the slow startup time.
- Type commands and observe the delay before each prompt.
Proposed Solutions/Workarounds
-
Prevent Double Initialisation: Modified
.zprofileto include a guard variable, preventing the initialisation block from running in.zshrc:# In ~/.zprofile: if [[ -z "$AMAZON_Q_INITIALIZED" ]]; then if [[ -f '$HOME/Library/Application Support/amazon-q/shell/zprofile.pre.zsh' ]]; then source '$HOME/Library/Application Support/amazon-q/shell/zprofile.pre.zsh' fi if [[ -f '$HOME/Library/Application Support/amazon-q/shell/zprofile.post.zsh' ]]; then source '$HOME/Library/Application Support/amazon-q/shell/zprofile.post.zsh' fi export AMAZON_Q_INITIALIZED=1 fi
Removed the entire Amazon Q block from
~/.zshrc. This significantly reduced the initial startup time. -
Disable
q _ pre-cmd: Commented out the call toq _ pre-cmdwithin thefig_precmdfunction and also the call outside the function definition, in$HOME/Library/Application Support/amazon-q/shell/zprofile.post.zsh. This dramatically improved the responsiveness of the shell after startup, eliminating the per-prompt delay.fig_precmd() { # ... (other code) ... # if command -v q >/dev/null 2>&1; then # (command q _ pre-cmd --alias "$(\alias)" > /dev/null 2>&1 &) >/dev/null 2>&1 # fi } fig_reset_hooks if [[ -n "${PROCESS_LAUNCHED_BY_Q:-}" ]]; then fig_osc DoneSourcing fi # fi # <- this was already commented out #(command q _ pre-cmd --alias "$(\alias)" > /dev/null 2>&1 &) >/dev/null 2>&1 # comment this out.
Quantitative Performance Impact
The following table summarizes the relevant key differences in execution times of zsh functions during startup, as measured by zprof, with and without Amazon Q CLI integration.
Note: These timings only reflect the initial shell startup, and do not include the ongoing overhead of the precmd hook (which adds ~11ms to every command, as detailed separately).
| Function | Without Q (ms) | With Q (ms) | Difference (ms) | Notes |
|---|---|---|---|---|
| Amazon Q Initialisation | 0 | ~1860 | +~1860 | This is a significant difference. This represents the time spent in the Amazon Q initialisation blocks (running q init and evaling the result), derived from earlier set -x tracing. |
| TOTAL (Approximate) | ~125 | ~1940 | +~1815 | Total is estimated based on zprof times and tracing, showing a difference close to the 2 seconds noted in the earlier set -x tracing. This highlights the massive impact of the Amazon Q initialisation. |
Key Observations
- Overall Startup Increase: The total startup time increases by approximately 1.8 seconds with the Amazon Q CLI enabled, before considering the
precmdhook overhead (~11ms per command). - Amazon Q Initialisation Dominates: The vast majority of the increased startup time is directly attributable to the Amazon Q initialisation process. The other functions are comparatively minor.
This table clearly demonstrates the significant negative impact of the Amazon Q CLI on shell startup time, providing quantitative evidence to support the qualitative observation of a slower terminal. The dominant factor is the Amazon Q initialisation itself.
Methodology
I performed analysis of the scripts that Amazon Q CLI injects into the shell, and used zsh's profiling (zprof) and tracing (set -x) to identify the key performance bottlenecks.
The scripts are generated from the following four commands that I exported to files for analysis:
${HOME}/.local/bin/q init zsh pre --rcfile zprofile > q_init_pre_zprofile.zsh
${HOME}/.local/bin/q init zsh pre --rcfile zshrc > q_init_pre_zshrc.zsh
${HOME}/.local/bin/q init zsh post --rcfile zprofile > q_init_post_zprofile.zsh
${HOME}/.local/bin/q init zsh post --rcfile zshrc > q_init_post_zshrc.zshDetailed Q Scripts Analysis
q_init_pre_zprofile.zshandq_init_pre_zshrc.zsh(Identical): These two files are identical, which immediately confirms the double-initialisation problem. This is the primary cause of the initial slowdown. The script does the following:- Sets up
PATH: Adds~/.local/binto thePATHif it exists and isn't already there. This is generally good practice, but not a major performance concern. Q_NEW_SESSIONHandling: Unsets someQTERMrelated variables ifQ_NEW_SESSIONis set. This suggests some session management, but it's unlikely to be a significant slowdown on its own.Q_SET_PARENT_CHECKHandling: Deals with parent process IDs. Again, not likely to be a major performance bottleneck.SHOULD_QTERM_LAUNCHCheck: This is a crucial part. It callsq _ should-figterm-launchand stores the exit code. This is a likely source of slowdown, as it's an external call to theqcommand. We'll need to investigateq _ should-figterm-launch.- The
qtermLaunch Logic: The largeifblock checks several conditions before potentially launchingqterm:[[ -t 1 ]]: Checks if standard output is connected to a terminal (i.e., it's an interactive shell).[[ -z "${PROCESS_LAUNCHED_BY_Q:-}" ]]: Checks if the process was launched by Q. This prevents nested invocations.command -v qterm 1>/dev/null 2>&1: Checks if theqtermcommand exists. This is a repeated check (it also happens insideq _ should-figterm-launch, very likely).- The complex
SHOULD_QTERM_LAUNCHandQ_TERM,Q_TERM_TMUX,TMUXchecks. - If all conditions are met, it determines the
Q_TERM_NAMEandQ_TERM_PATH, and then usesexec -a "${Q_TERM_NAME}" "${Q_TERM_PATH}"to replace the current shell process withqterm. The-aoption sets the name thatqtermsees as its own process name (argv[0]).
- Reading Initial Text: The
while read -rt 0loop attempts to read initial text from standard input. This is likely related to howqterminteracts with the terminal, but it's only executed ifqtermis launched. The timeout (-t 0) means it won't block, but it's still a bit of extra work.
- Sets up
q_init_post_zprofile.zshandq_init_post_zshrc.zsh(Identical): These files are also identical, and they are responsible for setting up thepreexecandprecmdhooks.fig_oscFunction: Defines a function to send OSC (Operating System Command) escape sequences to the terminal. This is used for communication between Q and the terminal emulator. The function itself is fast.fig_preexecandfig_precmd: These are the hook functions. They are called before every command (preexec) and before every prompt (precmd).- Prompt Restoration (in
fig_preexec): Restores the user's original prompt settings. This is important because Q modifies the prompt. - OSC Messages (in both): Sends a series of
fig_osccalls to communicate withqterm. This includes sending the current directory, shell, PID, exit code, etc. This is the ongoing overhead that will affect every command. - Prompt Modification (in
fig_precmd): This is the core of how Q integrates. It saves the user's prompt settings (PS1, PS2, etc.) and then wraps them withSTART_PROMPTandEND_PROMPTmarkers. These markers are OSC escape sequences (\033]697;...). This allowsqtermto identify the prompt and inject its own output. q _ pre-cmdCall: At the end offig_precmd, it calls(command q _ pre-cmd --alias "$(\alias)" > /dev/null 2>&1 &) >/dev/null 2>&1. This runsq _ pre-cmdin the background before every prompt. This is another likely source of ongoing slowdown, and we need to investigate whatq _ pre-cmddoes. The--alias "$(\alias)"part is passing a list of defined aliases to the command.
- Prompt Restoration (in
Key Findings and Confirmed Problems
- Double Initialisation (Confirmed): The
prescripts are identical and run twice, causing unnecessary work and likely doubling the startup time. q _ should-figterm-launch(Likely Slowdown): This external call is made in theprescript and is a prime suspect.qtermLaunch (Potential Slowdown): The conditions for launchingqtermare complex, andqtermitself is an unknown quantity.preexec/precmdHooks (Ongoing Overhead): These hooks add overhead to every command and prompt, making the terminal feel sluggish. Thefig_osccalls and theq _ pre-cmdcall are the main contributors to this overhead.q _ pre-cmdcalled before every prompt: (Likely Slowdown).
Requests for Amazon Q CLI Developers
- Address Double Initialisation: Modify the installation/integration process to prevent the initialisation script from running multiple times. A simple check for an environment variable (like the
AMAZON_Q_INITIALIZEDexample above) would suffice. - Optimise or Eliminate
q _ pre-cmd: The 11ms delay introduced byq _ pre-cmdis unacceptable for a pre-command hook. This command needs to be significantly optimised, or its functionality should be achieved through a different mechanism that doesn't impact prompt responsiveness. Ideally, provide an option to disable this hook if the user doesn't require its functionality. - Investigate
q _ should-figterm-launch: While less critical thanq _ pre-cmd, the 13ms delay ofq _ should-figterm-launchstill contributes to startup time. - Consider a Shell Script for
q(Optional): If feasible, consider providing at least parts of theqfunctionality as a shell script (rather than a compiled binary). This would allow users to more easily debug performance issues and potentially contribute improvements. - Provide Clear Documentation: The documentation should clearly state which parts are run at start-up and which are run before every prompt.
The current implementation significantly degrades the user experience, making the shell feel sluggish and unresponsive.
The workarounds described above improve the situation, but they require manual intervention and may disable some Amazon Q functionality.
A proper fix within the Amazon Q CLI is needed and indicates the need for more robust testing and optimisation of the CLI's shell integration.
Steps to reproduce
No response
Environment
q diagnostic
[q-details]
version = "1.7.1"
hash = "7d766a2d0580db62fae5a4bc2e6eb63946d4d08e"
date = "2025-03-14T22:08:03.470338Z (3d ago)"
variant = "full"
[system-info]
os = "macOS 15.3.2 (24D81)"
chip = "Apple M2 Max"
total-cores = 12
memory = "96.00 GB"
[environment]
cwd = "/Users/USER/Downloads/q-cli-slow"
cli-path = "/Users/USER/Downloads/q-cli-slow"
os = "Mac"
shell-path = "/opt/homebrew/Cellar/zsh/5.9/bin/zsh"
shell-version = "5.9"
terminal = "iTerm 2"
install-method = "unknown"
[env-vars]
QTERM_SESSION_ID = "afa917ee9dcf47bda9d32585f8425880"
Q_SET_PARENT_CHECK = "1"
Q_TERM = "1.7.1"
SHELL = "/opt/homebrew/bin/zsh"
TERM = "xterm-256color"
__CFBundleIdentifier = "com.googlecode.iterm2"