slopcannon 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +17 -8
  2. package/dist/cli.js +64 -13
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -4,13 +4,15 @@
4
4
  <img src="images/hero.png" width="512" />
5
5
  </p>
6
6
 
7
- Create a git worktree. Launch Claude Code. Ship slop.
7
+ Create a git worktree. Launch Claude Code or Codex. Ship slop.
8
8
 
9
9
  ## What it does
10
10
 
11
11
  ```
12
12
  git worktree add -b <branch> ../repo-branch origin/main
13
- claude --dangerously-skip-permissions
13
+ pick a launcher:
14
+ - claude --dangerously-skip-permissions
15
+ - codex --yolo
14
16
  ```
15
17
 
16
18
  That's it. Run it in any git repo.
@@ -27,12 +29,19 @@ Add to `~/.zshrc` so your shell cds into the worktree:
27
29
 
28
30
  ```bash
29
31
  slopcannon() {
30
- local tmpfile=$(mktemp /tmp/slopcannon.XXXXXX)
31
- bunx slopcannon --path-file "$tmpfile" "$@"
32
- local p=$(cat "$tmpfile" 2>/dev/null)
33
- rm -f "$tmpfile"
32
+ local pathfile=$(mktemp /tmp/slopcannon.path.XXXXXX)
33
+ local launcherfile=$(mktemp /tmp/slopcannon.launcher.XXXXXX)
34
+ bunx slopcannon --path-file "$pathfile" --launcher-file "$launcherfile" "$@"
35
+ local p=$(cat "$pathfile" 2>/dev/null)
36
+ local launcher=$(cat "$launcherfile" 2>/dev/null)
37
+ rm -f "$pathfile" "$launcherfile"
34
38
  if [[ -n "$p" ]] && [[ -d "$p" ]]; then
35
- cd "$p" && claude --dangerously-skip-permissions
39
+ cd "$p" || return
40
+ if [[ "$launcher" == "codex" ]]; then
41
+ codex --yolo
42
+ else
43
+ claude --dangerously-skip-permissions
44
+ fi
36
45
  fi
37
46
  }
38
47
  ```
@@ -41,4 +50,4 @@ slopcannon() {
41
50
 
42
51
  - [bun](https://bun.sh)
43
52
  - [git](https://git-scm.com)
44
- - [claude CLI](https://docs.anthropic.com/en/docs/claude-code)
53
+ - [claude CLI](https://docs.anthropic.com/en/docs/claude-code) or `codex`
package/dist/cli.js CHANGED
@@ -1735,7 +1735,7 @@ async function typewriterActivation() {
1735
1735
  process.stdout.write(`
1736
1736
  `);
1737
1737
  }
1738
- async function runTui() {
1738
+ async function runTui(deps) {
1739
1739
  We("slopcannon");
1740
1740
  let info;
1741
1741
  try {
@@ -1763,6 +1763,25 @@ async function runTui() {
1763
1763
  return null;
1764
1764
  }
1765
1765
  const baseBranch = baseBranchEntry;
1766
+ const launcherOptions = [
1767
+ deps.claude ? {
1768
+ value: "claude",
1769
+ label: "claude --dangerously-skip-permissions"
1770
+ } : null,
1771
+ deps.codex ? {
1772
+ value: "codex",
1773
+ label: "codex --yolo"
1774
+ } : null
1775
+ ].filter((option) => Boolean(option));
1776
+ const launcher = await Je({
1777
+ message: "Launcher",
1778
+ options: launcherOptions,
1779
+ initialValue: deps.claude ? "claude" : "codex"
1780
+ });
1781
+ if (Ct(launcher)) {
1782
+ Le("Cancelled.");
1783
+ return null;
1784
+ }
1766
1785
  const defaultName = randomBranchName();
1767
1786
  const newBranch = await Ze({
1768
1787
  message: "New branch name",
@@ -1799,10 +1818,24 @@ async function runTui() {
1799
1818
  return null;
1800
1819
  }
1801
1820
  try {
1802
- const envFiles = fs.readdirSync(info.root).filter((f) => f.startsWith(".env"));
1821
+ let walkForEnv = function(dir) {
1822
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1823
+ if (entry.isDirectory()) {
1824
+ if (!SKIP_DIRS.has(entry.name))
1825
+ walkForEnv(path3.join(dir, entry.name));
1826
+ } else if (entry.name.startsWith(".env")) {
1827
+ envFiles.push(path3.relative(info.root, path3.join(dir, entry.name)));
1828
+ }
1829
+ }
1830
+ };
1831
+ const SKIP_DIRS = new Set(["node_modules", ".git", ".claude"]);
1832
+ const envFiles = [];
1833
+ walkForEnv(info.root);
1803
1834
  if (envFiles.length > 0) {
1804
- for (const f of envFiles) {
1805
- fs.copyFileSync(path3.join(info.root, f), path3.join(worktreePath, f));
1835
+ for (const rel of envFiles) {
1836
+ const destDir = path3.join(worktreePath, path3.dirname(rel));
1837
+ fs.mkdirSync(destDir, { recursive: true });
1838
+ fs.copyFileSync(path3.join(info.root, rel), path3.join(worktreePath, rel));
1806
1839
  }
1807
1840
  R2.info(`Copied ${envFiles.join(", ")}`);
1808
1841
  }
@@ -1813,7 +1846,10 @@ async function runTui() {
1813
1846
  else if (style === "typewriter")
1814
1847
  await typewriterActivation();
1815
1848
  Le(worktreePath);
1816
- return worktreePath;
1849
+ return {
1850
+ worktreePath,
1851
+ launcher
1852
+ };
1817
1853
  }
1818
1854
 
1819
1855
  // src/cleanup.ts
@@ -1951,18 +1987,19 @@ Then run: bunx slopcannon`);
1951
1987
  process.exit(1);
1952
1988
  }
1953
1989
  var HELP = `
1954
- slopcannon - Create a git worktree. Launch Claude Code. Ship slop.
1990
+ slopcannon - Create a git worktree. Launch Claude Code or Codex. Ship slop.
1955
1991
 
1956
1992
  Usage:
1957
1993
  slopcannon Interactive TUI
1958
1994
  slopcannon cleanup|clean Clean up merged/stale worktrees
1959
1995
  slopcannon config Configure settings
1960
1996
  slopcannon --path-file <path> Write worktree path to file (for shell function)
1997
+ slopcannon --launcher-file <path> Write selected launcher to file
1961
1998
  slopcannon --help Show this help
1962
1999
 
1963
2000
  What it does:
1964
2001
  git worktree add -b <branch> ../repo-branch origin/main
1965
- claude --dangerously-skip-permissions
2002
+ then launches your selected CLI
1966
2003
  `.trim();
1967
2004
  function parseArgs() {
1968
2005
  const args = process.argv.slice(2);
@@ -1974,6 +2011,8 @@ function parseArgs() {
1974
2011
  result.version = true;
1975
2012
  } else if (args[i] === "--path-file" && i + 1 < args.length) {
1976
2013
  result.pathFile = args[++i];
2014
+ } else if (args[i] === "--launcher-file" && i + 1 < args.length) {
2015
+ result.launcherFile = args[++i];
1977
2016
  } else if (args[i] === "config") {
1978
2017
  result.config = true;
1979
2018
  } else if (args[i] === "cleanup" || args[i] === "clean") {
@@ -1990,6 +2029,7 @@ function checkDeps() {
1990
2029
  return {
1991
2030
  git: Bun.which("git"),
1992
2031
  claude: Bun.which("claude"),
2032
+ codex: Bun.which("codex"),
1993
2033
  gh: Bun.which("gh"),
1994
2034
  bun: Bun.which("bun")
1995
2035
  };
@@ -2022,23 +2062,34 @@ async function main() {
2022
2062
  process.exit(0);
2023
2063
  }
2024
2064
  requireGit(deps);
2025
- if (!deps.claude) {
2026
- console.error(`Error: claude CLI is not installed.
2027
- Install: https://docs.anthropic.com/en/docs/claude-code`);
2065
+ if (!deps.claude && !deps.codex) {
2066
+ console.error(`Error: neither claude nor codex CLI is installed.
2067
+ Install one of them before running slopcannon.`);
2028
2068
  process.exit(1);
2029
2069
  }
2030
2070
  if (!deps.gh) {
2031
2071
  console.warn("Warning: gh CLI not found. Remote detection may be limited.");
2032
2072
  }
2033
- const worktreePath = await runTui();
2034
- if (!worktreePath) {
2073
+ const tuiResult = await runTui({
2074
+ claude: deps.claude,
2075
+ codex: deps.codex
2076
+ });
2077
+ if (!tuiResult) {
2035
2078
  process.exit(0);
2036
2079
  }
2080
+ const { worktreePath, launcher } = tuiResult;
2037
2081
  if (args.pathFile) {
2038
2082
  await Bun.write(args.pathFile, worktreePath);
2083
+ }
2084
+ if (args.launcherFile) {
2085
+ await Bun.write(args.launcherFile, launcher + `
2086
+ `);
2087
+ }
2088
+ if (args.pathFile || args.launcherFile) {
2039
2089
  process.exit(0);
2040
2090
  }
2041
- const proc = Bun.spawn(["claude", "--dangerously-skip-permissions"], {
2091
+ const launchCommand = launcher === "codex" ? ["codex", "--yolo"] : ["claude", "--dangerously-skip-permissions"];
2092
+ const proc = Bun.spawn(launchCommand, {
2042
2093
  cwd: worktreePath,
2043
2094
  stdin: "inherit",
2044
2095
  stdout: "inherit",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "slopcannon",
3
- "version": "0.1.6",
4
- "description": "Create a git worktree. Launch Claude Code. Ship slop.",
3
+ "version": "0.1.8",
4
+ "description": "Create a git worktree. Launch Claude Code or Codex. Ship slop.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "slopcannon": "dist/cli.js"