Quick Fix: Claude Code Image Paste in Linux Terminal

Can't paste images to Claude Code in your Linux terminal? Here's a one-minute fix for Kitty users.

The Fix

1. Create the script (~/bin/clip2path):

#!/usr/bin/env bash
set -e

if [ -n "$WAYLAND_DISPLAY" ]; then
    types=$(wl-paste --list-types)
    if grep -q '^image/' <<<"$types"; then
        ext=$(grep -m1 '^image/' <<<"$types" | cut -d/ -f2 | cut -d';' -f1)
        file="/tmp/clip_$(date +%s).${ext}"
        wl-paste > "$file"
        printf '%q' "$file" | kitty @ send-text --stdin
    else
        wl-paste --no-newline | kitty @ send-text --stdin
    fi
elif [ -n "$DISPLAY" ]; then
    types=$(xclip -selection clipboard -t TARGETS -o)
    if grep -q '^image/' <<<"$types"; then
        ext=$(grep -m1 '^image/' <<<"$types" | cut -d/ -f2 | cut -d';' -f1)
        file="/tmp/clip_$(date +%s).${ext}"
        xclip -selection clipboard -t "image/${ext}" -o > "$file"
        printf '%q' "$file" | kitty @ send-text --stdin
    else
        xclip -selection clipboard -o | kitty @ send-text --stdin
    fi
fi

2. Make executable:

chmod +x ~/bin/clip2path

3. Add to ~/.config/kitty/kitty.conf:

allow_remote_control yes
listen_on unix:/tmp/kitty-socket
map ctrl+v launch --type=background --allow-remote-control --keep-focus ~/bin/clip2path

4. Install dependencies:

# X11 users only
sudo apt install xclip

5. Restart Kitty

6. Setup automatic cleanup (optional):

# Add to crontab to clean old screenshots daily
(crontab -l 2>/dev/null; echo "0 3 * * * find /tmp -name 'clip_*' -type f -mtime +1 -delete") | crontab -

Now Ctrl+V automatically saves clipboard images as temp files and pastes their paths. Works on both Wayland and X11.

网友语录 - 第38期 - 为了做自己,爱情当然可以不要

这里记录我的一周分享,通常在周六发布。


赞声与骂声,都不要在意,而要在乎自己能不能做好。把自己做好,就没有问题。


一位印度程序员2023年评论道: "有时我对 ChatGPT 的理解能力感到惊讶,但是更多时候,我不得不拼命推动它,朝着我想要的方向前进。它有时会产生意料之外的结果,让我感到非常沮丧。"

"它像一个吸收了所有人类知识、但需要别人帮忙才能把这些知识串起来的应届毕业生。"

"看来我今年的工作是安全的。但是,我需要好好学习 ChatGPT,精通它的使用,让我明年也是安全的。"

(Claude 比 ChatGPT 厉害得多,但其200k的上下文还是有点小)

…more

网友语录 - 第37期 - 人们会忘记你说过的话,会忘记你做过的事,但永远不会忘记你带给他们的感受

这里记录我的一周分享,通常在周六发布。


西瓦 “更令人担心的是,还有很多人没有看清问题的本质。实际上,教育的目的与升学率和考试分数无关,教育的目的是帮助人们收获人生的果实,教育的责任是挖掘人的潜力,教育的使命是提升人的尊严。”


heepst @heepst.bsky.social

Uh-oh.

There's a saying in the Baltic region - it's one of those dark jokes with at least a kernel of truth - that you don't need to start worrying until the Kremlin denies it.

(扶额.

波罗的海地区有句老话——既是黑色幽默又颇真实:“不用太早担心,除非克里姆林宫开始否认这件事”)


Shi De Sheng 人在疲惫的时候,什么事都做不成。精神和身体保持健康状态,才是一切的开始。

生命是一次又一次的循环。好好吃饭,好好睡觉,认真记录,就是对生命最隆重的赞美

归根结底人生有两条路:要么销售,要么创造。

不被爱只是不走运,而不会爱是种不幸。–阿尔贝·加缪《局外人》

生命的意义不在于发现自我,而在于塑造自我。这的确是两回事。

人们会忘记你说过的话,会忘记你做过的事,但永远不会忘记你带给他们的感受

“爱是这样一种状态:另一个人的幸福对你自己的幸福至关重要。” ― Robert A. Heinlein。

https://shidesheng.wordpress.com/2025/06/08/2025年5月/

…more

Running Claude Code on Windows Without WSL

This post is out-dated. Claude code has now officially supported GitBash, see https://docs.anthropic.com/en/docs/claude-code/setup for detail.

Got a Windows dev VM where you can't install WSL? Here's how to get Claude Code working with just Git Bash.

The Fix

Add these to your .bashrc:

export NPM_CONFIG_IGNORE_SCRIPTS=true
export SHELL=/c/Program\ Files/Git/bin/bash.exe

Then:

source ~/.bashrc
npm install -g @anthropic-ai/claude-code

Done.

Why It Works

Git Bash provides enough Unix-like environment for Claude Code. The SHELL export tells it where to find bash, and NPM_CONFIG_IGNORE_SCRIPTS prevents install script issues.

Caveats

This is a workaround, not official support. Works fine in my vm, let me know if it also works on your machine!

Tested on Windows Server 2022 with Git for Windows 2.50.0.windows.1

Solving Flutter Web Image Rendering Issues: A Cross-Platform Approach

If you've ever tried to display images in a Flutter app that needs to work seamlessly across web and mobile platforms, you've probably run into some frustrating limitations. Recently, I tackled this exact problem when our markdown image renderer started choking on web deployments due to CORS restrictions and lack of proper zoom functionality.

The Problem

Our original implementation was painfully simple - just Image.network(src) wrapped in a GestureDetector. This worked fine on mobile, or on web with --web-renderer html. However, the HTML web renderer is obsolete and will be removed shortly. We needed a more reliable solution.

The Solution: Platform-Specific Implementations

The key insight was to leverage Flutter's conditional imports to create platform-specific implementations while maintaining a clean, unified API.

Setting Up Conditional Imports

// Conditional imports for web
import 'web_image_stub.dart'
    if (dart.library.html) 'web_image_impl.dart';

This pattern lets you have different implementations for web vs mobile while keeping your main code clean. The stub file handles non-web platforms, while the implementation file contains the web-specific logic.

Web Implementation: HTML Elements to the Rescue

For web, I ditched Flutter's built-in image widgets entirely and went straight to HTML elements using HtmlElementView. This bypasses CORS issues since the browser handles the image loading directly.

final imgElement = html.ImageElement()
  ..src = src
  ..style.width = '100%'
  ..style.objectFit = 'contain'
  ..style.cursor = 'pointer';

The magic happens when you register this as a platform view. Flutter treats it like any other widget, but under the hood, it's pure HTML - which means it plays nicely with browser security policies.

Adding Zoom Functionality

The fullscreen implementation includes both mouse wheel and touch gesture zoom:

// Mouse wheel zoom
imgElement.onWheel.listen((event) {
  event.preventDefault();
  scale += event.deltaY > 0 ? -0.1 : 0.1;
  scale = scale.clamp(0.5, 3.0);
  imgElement.style.transform = 'scale($scale)';
});

For touch devices, I implemented pinch-to-zoom by tracking multiple touch points and calculating the distance between them. It's more complex than the mouse wheel version, but it gives web users the same intuitive zoom experience they expect.

Mobile Implementation: Keep It Simple

For mobile platforms, I stuck with the tried-and-true approach but improved the UX:

Dialog.fullscreen(
  backgroundColor: Colors.black,
  child: Stack(
    children: [
      Center(
        child: PhotoView(
          imageProvider: NetworkImage(url),
          minScale: PhotoViewComputedScale.contained,
          maxScale: PhotoViewComputedScale.covered * 4,
        ),
      ),
      // Close button positioned in top-right
    ],
  ),
)

The key improvements were switching to Dialog.fullscreen instead of a regular dialog and adding a proper close button with consistent styling.

Key Takeaways

  1. Conditional imports are your friend - They let you maintain clean separation between platform-specific code without cluttering your main logic.

  2. HTML elements can solve web-specific problems - When Flutter widgets don't cut it on web, dropping down to HTML often provides better browser compatibility.

  3. Consistent UX matters - Users expect zoom functionality on images, especially in fullscreen mode. Don't skimp on these details.

  4. Don't fight the platform - Web and mobile have different strengths. Embrace them instead of trying to force a one-size-fits-all solution.

The Result

After implementing these changes, our image handling works consistently across platforms. Web users get smooth zoom functionality without CORS headaches, mobile users get the native experience they expect, and the codebase remains maintainable with clear separation of concerns.

Sometimes the best solution isn't the most elegant one - it's the one that actually works for your users across all the platforms they're using.