Skip to content

Add croc-transfer extension#27304

Closed
Mrkinpa wants to merge 15 commits intoraycast:mainfrom
Mrkinpa:ext/croc-transfer
Closed

Add croc-transfer extension#27304
Mrkinpa wants to merge 15 commits intoraycast:mainfrom
Mrkinpa:ext/croc-transfer

Conversation

@Mrkinpa
Copy link
Copy Markdown

@Mrkinpa Mrkinpa commented Apr 20, 2026

A Raycast extension for peer-to-peer file transfer using croc. Supports Send, Receive, Quick Send, and Transfer History commands with end-to-end encryption.

Co-Authored-By: Oz oz-agent@warp.dev

wilton added 9 commits April 9, 2026 04:02
- Remove file renaming on receive (preserve original filenames)
- Async croc binary detection in useCrocCheck (non-blocking)
- clearCrocPathCache() + resolveCrocPathAsync() in croc.ts
- buildCrocArgs overloads: receive takes no extra args
- computeFileSize() in process.ts (recursive, sync)
- formatFileSize() in history.ts
- TransferStatus gains 'in_progress' + sessionId field
- cleanStaleInProgressRecords() for session-based cleanup
- useTransfer hook: covers form/zipping states, cancel writes record
- InstallGuide: Refresh + Install with Homebrew actions
- receive-file: Form input (autoFocus, clipboard pre-fill), Finder reveal, cancel writes record, no /Share subdir
- send-file: uses useTransfer hook, showHUD on complete, computeFileSize stored in record
- transfer-history: date groups (Today/Yesterday/Earlier), accessories (date + file count tag), keywords (basenames), size in metadata
- quick-send: no-view command with write-ahead history pattern
- package.json: quick-send command entry, updated downloadDirectory description
…to clipboard

- Wrap spawnCrocSend in Promise so no-view command doesn't exit prematurely
- Auto-copy code phrase to clipboard on Quick Send for easy sharing
- Change default download directory to ~/Downloads/Share
- fix: reSend() now records status as in_progress on phrase, updates to
  success/failed on completion (matches quick-send lifecycle)
- feat: add CHANGELOG.md required for new extensions
- feat: add metadata/ directory with screenshots (send, receive, history)
- chore: migrate ESLint config from legacy .eslintrc.json to v9 flat
  config (eslint.config.mjs), upgrade eslint ^8→^9 and
  @raycast/eslint-config ^1→^2
@raycastbot raycastbot added the new extension Label for PRs with new extensions label Apr 20, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

Congratulations on your new Raycast extension! 🚀

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

Once the PR is approved and merged, the extension will be available on our Store.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This commit addresses four prior review findings: the CHANGELOG now uses the correct [Initial Release] title with {PR_MERGE_DATE}, the unused @raycast/utils dependency is removed, getCrocVersion is hardened against shell injection via execFileSync, and Python 3 is now located dynamically through a candidate-path probe with a which python3 fallback instead of a hardcoded path.

  • CHANGELOG + package.json: Both cleanly corrected — correct date placeholder and no stale dependency.
  • croc.ts shell injection fix: execFileSync(crocPath, [\"--version\"]) safely replaces the execSync(\\"${crocPath}" --version\) shell form.
  • process.ts Python path: findPython3Path() tries four well-known locations then falls back to which python3, throwing a user-readable error if nothing is found. The code === 0 || phrase false-success condition in spawnCrocSend (flagged in a prior review) remains unchanged and still reports transfer success whenever a code phrase was emitted, even if the transfer subsequently fails.

Confidence Score: 4/5

The four targeted fixes are correct, but the false-success path in spawnCrocSend still reports successful transfers when croc exits non-zero after emitting a code phrase.

The code === 0 || phrase condition in spawnCrocSend (line 318 of process.ts) was flagged in a previous review and is still present. A network drop, relay timeout, or receiver abort that occurs after the code phrase is printed will cause onComplete({ success: true }) to fire even though no data was delivered, silently misleading the user about the transfer outcome.

croc-transfer/src/utils/process.ts — the spawnCrocSend exit callback

Important Files Changed

Filename Overview
croc-transfer/CHANGELOG.md Fixed: title changed to [Initial Release] and date replaced with {PR_MERGE_DATE} placeholder per Raycast convention.
croc-transfer/package.json Removed unused @raycast/utils dependency; @raycast/api remains as the only dependency.
croc-transfer/src/utils/croc.ts Shell injection fixed: getCrocVersion now uses execFileSync instead of execSync with shell interpolation.
croc-transfer/src/utils/process.ts Added findPython3Path() to probe candidate paths and fall back to which python3; hardcoded /usr/bin/python3 eliminated. However, the `code === 0

Reviews (3): Last reviewed commit: "fix: address all code review issues" | Re-trigger Greptile

Comment thread extensions/croc-transfer/CHANGELOG.md Outdated
@@ -0,0 +1,13 @@
# Croc Transfer Changelog

## [Initial Version] - 2026-04-09
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 CHANGELOG uses hardcoded date and wrong title

The entry uses a literal date (2026-04-09) instead of the required {PR_MERGE_DATE} placeholder, and the section title should be [Initial Release] not [Initial Version].

Suggested change
## [Initial Version] - 2026-04-09
## [Initial Release] - {PR_MERGE_DATE}

Rule Used: What: In Raycast extension changelogs, `{PR_MERGE_... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/croc-transfer/CHANGELOG.md
Line: 3

Comment:
**CHANGELOG uses hardcoded date and wrong title**

The entry uses a literal date (`2026-04-09`) instead of the required `{PR_MERGE_DATE}` placeholder, and the section title should be `[Initial Release]` not `[Initial Version]`.

```suggestion
## [Initial Release] - {PR_MERGE_DATE}
```

**Rule Used:** What: In Raycast extension changelogs, `{PR_MERGE_... ([source](https://app.greptile.com/review/custom-context?memory=799af734-ebd9-4b40-9ffd-97a70fc71c8a))

How can I resolve this? If you propose a fix, please make it concise.

Comment thread extensions/croc-transfer/package.json Outdated
Comment on lines +116 to +117
"@raycast/utils": "^1.16.0"
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 @raycast/utils is listed but never imported

@raycast/utils appears in dependencies but is not imported in any file under src/. Unused dependencies bloat the bundle and create confusion about what the extension actually requires.

Suggested change
"@raycast/utils": "^1.16.0"
},
"@raycast/api": "^1.72.0"

Rule Used: What: Every dependency listed in package.json must... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/croc-transfer/package.json
Line: 116-117

Comment:
**`@raycast/utils` is listed but never imported**

`@raycast/utils` appears in `dependencies` but is not imported in any file under `src/`. Unused dependencies bloat the bundle and create confusion about what the extension actually requires.

```suggestion
    "@raycast/api": "^1.72.0"
```

**Rule Used:** What: Every dependency listed in package.json must... ([source](https://app.greptile.com/review/custom-context?memory=bffc60eb-f9f2-4219-b804-76e29e267d43))

How can I resolve this? If you propose a fix, please make it concise.

};

try {
proc = spawn("/usr/bin/python3", [wrapperPath, crocPath, ...args], {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Hardcoded /usr/bin/python3 will silently break transfers if Python 3 isn't installed

/usr/bin/python3 is only present on macOS when Xcode Command Line Tools are installed; on minimal or managed systems it may be absent, causing spawn to fail with ENOENT and every transfer to immediately error. There is no fallback to /opt/homebrew/bin/python3, /usr/local/bin/python3, or a which python3 lookup.

Consider resolving the python3 path with the same candidate-list pattern already used for croc, or checking existence before spawning and surfacing an actionable error message if Python 3 cannot be found.

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/croc-transfer/src/utils/process.ts
Line: 157

Comment:
**Hardcoded `/usr/bin/python3` will silently break transfers if Python 3 isn't installed**

`/usr/bin/python3` is only present on macOS when Xcode Command Line Tools are installed; on minimal or managed systems it may be absent, causing `spawn` to fail with `ENOENT` and every transfer to immediately error. There is no fallback to `/opt/homebrew/bin/python3`, `/usr/local/bin/python3`, or a `which python3` lookup.

Consider resolving the python3 path with the same candidate-list pattern already used for croc, or checking existence before spawning and surfacing an actionable error message if Python 3 cannot be found.

How can I resolve this? If you propose a fix, please make it concise.


export function getCrocVersion(crocPath: string): string | null {
try {
const output = execSync(`"${crocPath}" --version`, {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 security execSync with shell interpolation; prefer execFileSync

execSync(\"${crocPath}" --version`)passes the command to/bin/sh, so a crocPathcontaining shell metacharacters (e.g. a custom path set in preferences like/tmp/croc"; echo pwned; echo ") can execute arbitrary commands. The async sibling getCrocVersionAsyncalready uses the saferexecFileAPI —getCrocVersion` should do the same.

Replace with execFileSync(crocPath, ["--version"], { encoding: "utf8", timeout: 3000 }).

Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/croc-transfer/src/utils/croc.ts
Line: 70

Comment:
**`execSync` with shell interpolation; prefer `execFileSync`**

`execSync(\`"${crocPath}" --version\`)` passes the command to `/bin/sh`, so a `crocPath` containing shell metacharacters (e.g. a custom path set in preferences like `/tmp/croc"; echo pwned; echo "`) can execute arbitrary commands. The async sibling `getCrocVersionAsync` already uses the safer `execFile` API — `getCrocVersion` should do the same.

Replace with `execFileSync(crocPath, ["--version"], { encoding: "utf8", timeout: 3000 })`.

How can I resolve this? If you propose a fix, please make it concise.

wilton added 5 commits April 22, 2026 12:19
…g polling

- add runState.ts: STATE_FILE / LIVE_LOG_FILE constants, RunState interface,
  read/write helpers, isProcessAlive util
- rewrite runScript.ts: spawn a temp wrapper.sh with stdio:ignore+detached so
  the child survives parent exit; wrapper redirects all output to LIVE_LOG_FILE
  and writes final state back via python3; RunHandle now exposes {pid, kill}
  instead of {promise, kill}
- add LivePollView.tsx: polls LIVE_LOG_FILE (500ms) and STATE_FILE (1500ms);
  works after Raycast restart; reads result.json / *.summary.txt on completion
- update release-testflight.tsx: call runScript → writeRunState → push LivePollView;
  remove the old in-process ExecutionView (~350 lines of streaming/state logic)
…ing releases

reads STATE_FILE written by the detached wrapper and renders LivePollView;
works for both in-progress and completed runs, shows "no record" when state
file is absent; registered in package.json with type declarations in raycast-env.d.ts
@raycastbot
Copy link
Copy Markdown
Collaborator

This pull request has been automatically marked as stale because it did not have any recent activity.

It will be closed if no further activity occurs in the next 7 days to keep our backlog clean 😊

@raycastbot raycastbot added the status: stalled Stalled due inactivity label May 4, 2026
- Fix CHANGELOG.md to use {PR_MERGE_DATE} placeholder and correct title
- Remove unused @raycast/utils dependency from package.json
- Fix hardcoded Python3 path with findPython3Path() function
- Fix shell injection vulnerability in getCrocVersion()
@Mrkinpa Mrkinpa closed this May 6, 2026
@Mrkinpa Mrkinpa force-pushed the ext/croc-transfer branch from abba561 to 9b919de Compare May 6, 2026 07:13
@Mrkinpa
Copy link
Copy Markdown
Author

Mrkinpa commented May 6, 2026

@greptile-apps @raycastbot

I have reopened this PR because all review issues have now been fixed:

✅ Fixed issues:

  1. CHANGELOG.md - Updated to [Initial Release] - {PR_MERGE_DATE}
  2. package.json - Removed the unused @raycast/utils dependency
  3. Python3 path - Added a findPython3Path() function to support multiple candidate paths
  4. Security vulnerability - Fixed the shell injection issue in execSync

@Mrkinpa
Copy link
Copy Markdown
Author

Mrkinpa commented May 6, 2026

🔧 Verification:

  • Build successful: npm run build
  • Lint check: npm run lint

The PR is now ready for review again. Thank you for your patience!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new extension Label for PRs with new extensions status: stalled Stalled due inactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants