ccmanager 1.4.1 → 1.4.3

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.
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Box, Text, useInput } from 'ink';
3
- import TextInput from 'ink-text-input';
3
+ import TextInputWrapper from './TextInputWrapper.js';
4
4
  import SelectInput from 'ink-select-input';
5
5
  import { configurationManager } from '../services/configurationManager.js';
6
6
  import { shortcutManager } from '../services/shortcutManager.js';
@@ -294,7 +294,7 @@ const ConfigureCommand = ({ onComplete }) => {
294
294
  errorMessage && (React.createElement(Box, { marginBottom: 1 },
295
295
  React.createElement(Text, { color: "red" }, errorMessage))),
296
296
  React.createElement(Box, null,
297
- React.createElement(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleFieldUpdate, placeholder: editField === 'args' || editField === 'fallbackArgs'
297
+ React.createElement(TextInputWrapper, { value: inputValue, onChange: setInputValue, onSubmit: handleFieldUpdate, placeholder: editField === 'args' || editField === 'fallbackArgs'
298
298
  ? 'e.g., --resume or leave empty'
299
299
  : '' })),
300
300
  React.createElement(Box, { marginTop: 1 },
@@ -339,7 +339,7 @@ const ConfigureCommand = ({ onComplete }) => {
339
339
  errorMessage && (React.createElement(Box, { marginBottom: 1 },
340
340
  React.createElement(Text, { color: "red" }, errorMessage))),
341
341
  React.createElement(Box, null,
342
- React.createElement(TextInput, { value: inputValue, onChange: setInputValue, onSubmit: handleAddPresetInput, placeholder: addStep === 'args' || addStep === 'fallbackArgs'
342
+ React.createElement(TextInputWrapper, { value: inputValue, onChange: setInputValue, onSubmit: handleAddPresetInput, placeholder: addStep === 'args' || addStep === 'fallbackArgs'
343
343
  ? 'e.g., --resume or leave empty'
344
344
  : addStep === 'name'
345
345
  ? 'e.g., Development'
@@ -1,6 +1,6 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { Box, Text, useInput } from 'ink';
3
- import TextInput from 'ink-text-input';
3
+ import TextInputWrapper from './TextInputWrapper.js';
4
4
  import SelectInput from 'ink-select-input';
5
5
  import { configurationManager } from '../services/configurationManager.js';
6
6
  const STATUS_LABELS = {
@@ -108,7 +108,7 @@ const ConfigureHooks = ({ onComplete }) => {
108
108
  STATUS_LABELS[selectedStatus],
109
109
  ":")),
110
110
  React.createElement(Box, { marginBottom: 1 },
111
- React.createElement(TextInput, { value: currentCommand, onChange: setCurrentCommand, onSubmit: handleCommandSubmit, placeholder: "Enter command (e.g., notify-send 'Claude is idle')" })),
111
+ React.createElement(TextInputWrapper, { value: currentCommand, onChange: setCurrentCommand, onSubmit: handleCommandSubmit, placeholder: "Enter command (e.g., notify-send 'Claude is idle')" })),
112
112
  React.createElement(Box, { marginBottom: 1 },
113
113
  React.createElement(Text, null,
114
114
  "Enabled: ",
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Box, Text, useInput } from 'ink';
3
3
  import SelectInput from 'ink-select-input';
4
- import TextInput from 'ink-text-input';
4
+ import TextInputWrapper from './TextInputWrapper.js';
5
5
  import { configurationManager } from '../services/configurationManager.js';
6
6
  import { shortcutManager } from '../services/shortcutManager.js';
7
7
  const ConfigureWorktree = ({ onComplete }) => {
@@ -84,7 +84,7 @@ const ConfigureWorktree = ({ onComplete }) => {
84
84
  " - full branch name")),
85
85
  React.createElement(Box, null,
86
86
  React.createElement(Text, { color: "cyan" }, '> '),
87
- React.createElement(TextInput, { value: tempPattern, onChange: setTempPattern, onSubmit: handlePatternSubmit, placeholder: "../{branch}" })),
87
+ React.createElement(TextInputWrapper, { value: tempPattern, onChange: setTempPattern, onSubmit: handlePatternSubmit, placeholder: "../{branch}" })),
88
88
  React.createElement(Box, { marginTop: 1 },
89
89
  React.createElement(Text, { dimColor: true }, "Press Enter to save or Escape to cancel"))));
90
90
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useState, useMemo } from 'react';
2
2
  import { Box, Text, useInput } from 'ink';
3
- import TextInput from 'ink-text-input';
3
+ import TextInputWrapper from './TextInputWrapper.js';
4
4
  import SelectInput from 'ink-select-input';
5
5
  import { shortcutManager } from '../services/shortcutManager.js';
6
6
  import { configurationManager } from '../services/configurationManager.js';
@@ -84,7 +84,7 @@ const NewWorktree = ({ onComplete, onCancel }) => {
84
84
  React.createElement(Text, null, "Enter worktree path (relative to repository root):")),
85
85
  React.createElement(Box, null,
86
86
  React.createElement(Text, { color: "cyan" }, '> '),
87
- React.createElement(TextInput, { value: path, onChange: setPath, onSubmit: handlePathSubmit, placeholder: "e.g., ../myproject-feature" })))) : step === 'branch' && !isAutoDirectory ? (React.createElement(Box, { flexDirection: "column" },
87
+ React.createElement(TextInputWrapper, { value: path, onChange: setPath, onSubmit: handlePathSubmit, placeholder: "e.g., ../myproject-feature" })))) : step === 'branch' && !isAutoDirectory ? (React.createElement(Box, { flexDirection: "column" },
88
88
  React.createElement(Box, { marginBottom: 1 },
89
89
  React.createElement(Text, null,
90
90
  "Enter branch name for worktree at ",
@@ -92,12 +92,12 @@ const NewWorktree = ({ onComplete, onCancel }) => {
92
92
  ":")),
93
93
  React.createElement(Box, null,
94
94
  React.createElement(Text, { color: "cyan" }, '> '),
95
- React.createElement(TextInput, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })))) : step === 'branch' ? (React.createElement(Box, { flexDirection: "column" },
95
+ React.createElement(TextInputWrapper, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })))) : step === 'branch' ? (React.createElement(Box, { flexDirection: "column" },
96
96
  React.createElement(Box, { marginBottom: 1 },
97
97
  React.createElement(Text, null, "Enter branch name (directory will be auto-generated):")),
98
98
  React.createElement(Box, null,
99
99
  React.createElement(Text, { color: "cyan" }, '> '),
100
- React.createElement(TextInput, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })),
100
+ React.createElement(TextInputWrapper, { value: branch, onChange: setBranch, onSubmit: handleBranchSubmit, placeholder: "e.g., feature/new-feature" })),
101
101
  generatedPath && (React.createElement(Box, { marginTop: 1 },
102
102
  React.createElement(Text, { dimColor: true },
103
103
  "Worktree will be created at:",
@@ -73,10 +73,20 @@ const Session = ({ session, sessionManager, onReturnToMenu, }) => {
73
73
  const handleResize = () => {
74
74
  const cols = process.stdout.columns || 80;
75
75
  const rows = process.stdout.rows || 24;
76
- session.process.resize(cols, rows);
77
- // Also resize the virtual terminal
78
- if (session.terminal) {
79
- session.terminal.resize(cols, rows);
76
+ try {
77
+ session.process.resize(cols, rows);
78
+ // Also resize the virtual terminal
79
+ if (session.terminal) {
80
+ try {
81
+ session.terminal.resize(cols, rows);
82
+ }
83
+ catch {
84
+ // Suppress xterm.js parsing errors
85
+ }
86
+ }
87
+ }
88
+ catch {
89
+ // Suppress PTY resize errors
80
90
  }
81
91
  };
82
92
  stdout.on('resize', handleResize);
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ interface TextInputWrapperProps {
3
+ value: string;
4
+ onChange: (value: string) => void;
5
+ onSubmit?: (value: string) => void;
6
+ placeholder?: string;
7
+ focus?: boolean;
8
+ mask?: string;
9
+ showCursor?: boolean;
10
+ highlightPastedText?: boolean;
11
+ }
12
+ declare const TextInputWrapper: React.FC<TextInputWrapperProps>;
13
+ export default TextInputWrapper;
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import TextInput from 'ink-text-input';
3
+ import stripAnsi from 'strip-ansi';
4
+ const TextInputWrapper = ({ value, onChange, ...props }) => {
5
+ const handleChange = (newValue) => {
6
+ // First strip all ANSI escape sequences
7
+ let cleanedValue = stripAnsi(newValue);
8
+ // Then specifically remove bracketed paste mode markers that might remain
9
+ // These sometimes appear as literal text after ANSI stripping
10
+ cleanedValue = cleanedValue.replace(/\[200~/g, '').replace(/\[201~/g, '');
11
+ onChange(cleanedValue);
12
+ };
13
+ return React.createElement(TextInput, { value: value, onChange: handleChange, ...props });
14
+ };
15
+ export default TextInputWrapper;
@@ -109,8 +109,13 @@ export class SessionManager extends EventEmitter {
109
109
  setupDataHandler(session) {
110
110
  // This handler always runs for all data
111
111
  session.process.onData((data) => {
112
- // Write data to virtual terminal
113
- session.terminal.write(data);
112
+ // Write data to virtual terminal with error suppression
113
+ try {
114
+ session.terminal.write(data);
115
+ }
116
+ catch {
117
+ // Suppress xterm.js parsing errors
118
+ }
114
119
  // Store in output history as Buffer
115
120
  const buffer = Buffer.from(data, 'utf8');
116
121
  session.outputHistory.push(buffer);
@@ -1,11 +1,10 @@
1
1
  import path from 'path';
2
+ import stripAnsi from 'strip-ansi';
2
3
  import { getStatusDisplay } from '../constants/statusIcons.js';
3
4
  import { formatGitFileChanges, formatGitAheadBehind, formatParentBranch, } from './gitStatus.js';
4
5
  // Constants
5
6
  const MAX_BRANCH_NAME_LENGTH = 40; // Maximum characters for branch name display
6
7
  const MIN_COLUMN_PADDING = 2; // Minimum spaces between columns
7
- // Strip ANSI escape codes for length calculation
8
- const stripAnsi = (str) => str.replace(/\x1b\[[0-9;]*m/g, '');
9
8
  // Utility function to truncate strings with ellipsis
10
9
  export function truncateString(str, maxLength) {
11
10
  if (str.length <= maxLength)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccmanager",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "TUI application for managing multiple Claude Code sessions across Git worktrees",
5
5
  "license": "MIT",
6
6
  "author": "Kodai Kabasawa",
@@ -45,7 +45,8 @@
45
45
  "ink-text-input": "^5.0.1",
46
46
  "meow": "^11.0.0",
47
47
  "node-pty": "^1.0.0",
48
- "react": "^18.2.0"
48
+ "react": "^18.2.0",
49
+ "strip-ansi": "^7.1.0"
49
50
  },
50
51
  "devDependencies": {
51
52
  "@eslint/js": "^9.28.0",