#file editing/grepping/etc

1 messages · Page 1 of 1 (latest)

noble scroll
#

🧵 since there are a couple ongoing discussions

#

nice!

#

fwiw I vibe coded an edit implementation that seems to work - instead of sed it does the replacements in Go, by looking for matches for the 'search' and erroring if there are multiple matches, with the error including IDs so the agent can try again with the specific edit ID

tawdry cypress
#

I’m still testing it and want to write some tests

#

Oh interesting. I was heavily inspired by Claude’s tools

noble scroll
#

same - I was using Claude Code a lot over the weekend and noticed it's defensive against multiple matches, so tried to approximate that

vestal flax
#

wait so claude code really has the agent edit files with s/old/new/g instead of by line number?

tawdry cypress
#

Yes. I was surprised. At some point I swear I saw line numbers

#

Maybe it changed

noble scroll
#

yep afaict. i'm not sure how it actually narrows it down if there's ambiguity

vestal flax
#

this explains why claude sonnet 4 uses sed on it's own sometimes

noble scroll
vestal flax
#

i bet you they trained it specifically for this

noble scroll
#

none of these have line numbers

noble scroll
#

but could be wrong if @tawdry cypress saw that

tawdry cypress
#

I thought of doing line number edits in addition to sed. But maybe it gets confused. I’m just hoping that if Claude knows then it must be good

noble scroll
#

it's definitely find-and-replace though

tawdry cypress
#

No it doesn’t use sed. I’m using sed because dagger doesn’t have it

noble scroll
#

my worry with sed would be like...fitting arbitrary code into the replacement pattern

#

i'll push up my edit version so we can compare notes

tawdry cypress
#

And I didn’t want to take all the contents and do it myself but now that I think about it I’m stupid I should just do that

vestal flax
tawdry cypress
noble scroll
tawdry cypress
#

Btw, I'll update the PR description, but Claude's tools doesn't use sed syntax per-se, it's just that since I was using sed, and didnt feel comfortable with the / escaping, i figured i'd let the LLM specify the sed syntax.

noble scroll
#

maybe we could do the replace logic in go, but then generate a precise .patch file that we apply?

tawdry cypress
#

WithNewFile sucks in that case, but what i'm saying is it saves a call to Contents too

noble scroll
#

true

#

how much control do we have over the tools available in the container?

tawdry cypress
#

i use busybox

#

but we can do whatever we want with mounteddirs

noble scroll
#

oh right true

#

so we could run a custom little binary if we wanted

tawdry cypress
#

yes 🙂

#

but the question is the API facing the LLM

#

claude does list of search replace rules

vestal flax
#

subject to caching weirdness potentially though so be thoughtful

tawdry cypress
#

we could add an isRegex bool, and call strings.Replace or regexp.Regexp.Replace in our own binary

noble scroll
#

oh fun, does claude code do regex replacements too? (i see it grepping all the time but havent seen it edit like that i don't think)

tawdry cypress
#

ah my bad, you are right

#

it's just strings.Replace

noble scroll
#

i do see MultiEdit too yeah, wonder if it's been using that and i haven't noticed

tawdry cypress
#

yeah i wasn't sure whether both were needed

#

i implemented MultiEdit and called it FileEdit

noble scroll
#

i feel like it just does a bunch of edits one at a time pretty often

tawdry cypress
#

i dont want to depend on the golang image though. But that means need to set up pipelines to push a new replace image

noble scroll
#

there's always the option of improving the Dagger API

#

if we're hesitant to read a whole file into memory, other clients might be too

#

that being said, maybe it's fine? these are just text files, and i think folks know to not have absurdly large code files with vibecoding

#

cc @civic basin - vaguely remember us considering making the file operation APIs more fluent so people don't have to keep implementing filesystem Workspaces

vestal flax
noble scroll
#

how huge is huge 😛

tawdry cypress
#

Agreed on improving dagger api

vestal flax
#

idk bigger than i like as a human, i like that i can load a phat amount of context in with a single file

noble scroll
#

our longest file in dagger/dagger is module_test.go at 6153 (next is ~5k and then a drop off to ~2k)

#

which is 156k

noble scroll
civic basin
tawdry cypress
#

It’s not entirely clear to me what the patch logic would be

tawdry cypress
tawdry cypress
noble scroll
#

does busybox have patch?

tawdry cypress
#

Ah you mean not do search replace and do patch instead?

noble scroll
#

i mean do the search and replace logic in Go, but then generate a .patch file from that and apply that in the environment, since that'd be more minimal than WithNewFile with the whole content

tawdry cypress
#

ahhh right

noble scroll
noble scroll
#

is it cheating too much to just use the patch executable from in the environment? it feels about the same as depending on sh. patch is used as part of a bunch of clunky linux distro packaging systems so I'd expect this core functionality to be pretty universal

here's how it looks (trace)

#

(sorry if I'm stepping on your toes here @tawdry cypress - I'm still toying with my own impl so I can dogfood container-use more for side stuff)

tawdry cypress
#

No worries at all! It's a great idea! I'll blatantly steal your commit. I just prefer to rely on busybox patch instead of the user's environment.

brazen jay
tawdry cypress
#

Same!

#

I'm upgrading my PR to use a custom efficient binary that does search replace, no Contents()

noble scroll
#

I'll be using it from now on with this change salute

#

funny story: I told Claude to trim trailing whitespace the other day, and it happily ran a find . -type f -exec sed -i -e 's/ $//g' {} \; and corrupted my git repo

#

so...plenty motivated

tawdry cypress
#

wow

#

lol

noble scroll
#

btw - has anyone asked Claude to dump its tool schemas yet? seems like it's willing to. or is there a public repo with all that?

#

here's Edit:

{
  "description": "Performs exact string replacements in files. \n\nUsage:\n- You must use your `Read` tool at least once in the conversation before editing. This tool will error if you attempt an edit without reading the file. \n- When editing text from Read tool output, ensure you preserve the exact
indentation (tabs/spaces) as it appears AFTER the line number prefix. The line number prefix format is: spaces + line number + tab. Everything after that tab is the actual file content to match. Never include any part of the line number prefix in the old_string or new_string.\n- ALWAYS prefer editing existing
files in the codebase. NEVER write new files unless explicitly required.\n- Only use emojis if the user explicitly requests it. Avoid adding emojis to files unless asked.\n- The edit will FAIL if `old_string` is not unique in the file. Either provide a larger string with more surrounding context to make it
unique or use `replace_all` to change every instance of `old_string`. \n- Use `replace_all` for replacing and renaming strings across the file. This parameter is useful if you want to rename a variable for instance.",
  "name": "Edit",
  "parameters": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "additionalProperties": false,
    "properties": {
      "file_path": {
        "description": "The absolute path to the file to modify",
        "type": "string"
      },
      "new_string": {
        "description": "The text to replace it with (must be different from old_string)",
        "type": "string"
      },
      "old_string": {
        "description": "The text to replace",
        "type": "string"
      },
      "replace_all": {
        "default": false,
        "description": "Replace all occurences of old_string (default false)",
        "type": "boolean"
      }
    },
    "required": ["file_path", "old_string", "new_string"],
    "type": "object"
  }
}
tawdry cypress
#

yeah i have it all

noble scroll
#

nice

tawdry cypress
#

i'm working on a proxy so i know EVERYTHING 😄

#

The descriptions are quite long and detailed

noble scroll
#

yeah

noble scroll
#

those are different from Claude Code, i think, but strong parallels for sure

tawdry cypress
#

As of yesterday. Could change

tawdry cypress
#

i updated my PR @noble scroll not sure if you're still testing it

noble scroll
#

sweet, i'll give it a try

tawdry cypress
#

something's not working i'm debugging

#

or is it the usual claude issue with:
tool_use ids were found without tool_result blocks immediately after: toolu_0116Ls3UTdr89LEm6rNhXnHV. Each tool_use block must have a corresponding tool_result block in the next message.

noble scroll
#

Strange to see that in Claude code, I haven't when using it directly

tawdry cypress
#

coz i'm in goose

#

i will try it with claude code too

noble scroll
#

Proxy could help, in the past that's been a sign that the client is doing something wrong (eg dropping error responses)

#

So maybe goose bug

tawdry cypress
#

i'll figure it out eventually 🙂 but right now i wanna make sure the fstools pr works

#

i dont trust the code i changed it too many times

brazen jay
noble scroll
noble scroll
#

$3.08 and 13 minutes later, seems like success. wonder how much it would have cost without the patch tool. time to find out

#

oh, oops, that was with MY branch facepalm

noble scroll
#

hit a couple issues with the real pr, left comments

noble scroll
#

btw looks like Claude just revised the Grep tool, started it just now and saw:

• Redesigned Search (Grep) tool with new tool input parameters and features