workon 2.1.3 → 3.0.0

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 (66) hide show
  1. package/README.md +19 -4
  2. package/bin/workon +1 -11
  3. package/dist/cli.js +2227 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/index.cjs +1216 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +280 -0
  8. package/dist/index.d.ts +280 -0
  9. package/dist/index.js +1173 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +68 -21
  12. package/.claude/settings.local.json +0 -11
  13. package/.cursorindexingignore +0 -3
  14. package/.history/.gitignore_20250806202718 +0 -30
  15. package/.history/.gitignore_20250806231444 +0 -32
  16. package/.history/.gitignore_20250806231450 +0 -32
  17. package/.history/lib/tmux_20250806233103.js +0 -109
  18. package/.history/lib/tmux_20250806233219.js +0 -109
  19. package/.history/lib/tmux_20250806233223.js +0 -109
  20. package/.history/lib/tmux_20250806233230.js +0 -109
  21. package/.history/lib/tmux_20250806233231.js +0 -109
  22. package/.history/lib/tmux_20250807120751.js +0 -190
  23. package/.history/lib/tmux_20250807120757.js +0 -190
  24. package/.history/lib/tmux_20250807120802.js +0 -190
  25. package/.history/lib/tmux_20250807120808.js +0 -190
  26. package/.history/package_20250807114243.json +0 -43
  27. package/.history/package_20250807114257.json +0 -43
  28. package/.history/package_20250807114404.json +0 -43
  29. package/.history/package_20250807114409.json +0 -43
  30. package/.history/package_20250807114510.json +0 -43
  31. package/.history/package_20250807114637.json +0 -43
  32. package/.vscode/launch.json +0 -20
  33. package/.vscode/terminals.json +0 -11
  34. package/CHANGELOG.md +0 -110
  35. package/CLAUDE.md +0 -100
  36. package/cli/base.js +0 -16
  37. package/cli/config/index.js +0 -19
  38. package/cli/config/list.js +0 -26
  39. package/cli/config/set.js +0 -19
  40. package/cli/config/unset.js +0 -26
  41. package/cli/index.js +0 -184
  42. package/cli/interactive.js +0 -290
  43. package/cli/manage.js +0 -413
  44. package/cli/open.js +0 -414
  45. package/commands/base.js +0 -105
  46. package/commands/core/cwd/index.js +0 -86
  47. package/commands/core/ide/index.js +0 -84
  48. package/commands/core/web/index.js +0 -109
  49. package/commands/extensions/claude/index.js +0 -211
  50. package/commands/extensions/docker/index.js +0 -167
  51. package/commands/extensions/npm/index.js +0 -208
  52. package/commands/registry.js +0 -196
  53. package/demo-colon-syntax.js +0 -57
  54. package/docs/adr/001-command-centric-architecture.md +0 -304
  55. package/docs/adr/002-positional-command-arguments.md +0 -402
  56. package/docs/ideas.md +0 -93
  57. package/lib/config.js +0 -51
  58. package/lib/environment/base.js +0 -12
  59. package/lib/environment/index.js +0 -108
  60. package/lib/environment/project.js +0 -26
  61. package/lib/project.js +0 -68
  62. package/lib/tmux.js +0 -223
  63. package/lib/validation.js +0 -120
  64. package/test-architecture.js +0 -145
  65. package/test-colon-syntax.js +0 -85
  66. package/test-registry.js +0 -57
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/config.ts","../src/lib/project.ts","../src/lib/tmux.ts","../src/lib/environment.ts","../src/events/core/cwd.ts","../src/events/core/ide.ts","../src/events/core/web.ts","../src/events/extensions/claude.ts","../src/events/extensions/docker.ts","../src/events/extensions/npm.ts","../src/events/registry.ts"],"sourcesContent":["import Conf from 'conf';\nimport type { AppConfig, ProjectConfig, ProjectDefaults } from '../types/index.js';\n\nconst TRANSIENT_PROPS = ['pkg', 'work'] as const;\n\nexport class Config {\n private _transient: Record<string, unknown> = {};\n private _store: Conf<AppConfig>;\n\n constructor() {\n this._store = new Conf<AppConfig>({\n projectName: 'workon',\n });\n }\n\n get<T = unknown>(key: string, defaultValue?: T): T | undefined {\n const rootKey = key.split('.')[0];\n if (TRANSIENT_PROPS.includes(rootKey as (typeof TRANSIENT_PROPS)[number])) {\n return (this._transient[key] as T) ?? defaultValue;\n }\n return this._store.get(key as keyof AppConfig, defaultValue as AppConfig[keyof AppConfig]) as\n | T\n | undefined;\n }\n\n set(key: string, value?: unknown): void {\n const rootKey = key.split('.')[0];\n if (TRANSIENT_PROPS.includes(rootKey as (typeof TRANSIENT_PROPS)[number])) {\n this._transient[key] = value;\n } else {\n if (value === undefined) {\n // Setting entire object\n this._store.set(key as keyof AppConfig, value as never);\n } else {\n this._store.set(key as keyof AppConfig, value as never);\n }\n }\n }\n\n has(key: string): boolean {\n const rootKey = key.split('.')[0];\n if (TRANSIENT_PROPS.includes(rootKey as (typeof TRANSIENT_PROPS)[number])) {\n return Object.prototype.hasOwnProperty.call(this._transient, key);\n }\n return this._store.has(key as keyof AppConfig);\n }\n\n delete(key: string): void {\n const rootKey = key.split('.')[0];\n if (TRANSIENT_PROPS.includes(rootKey as (typeof TRANSIENT_PROPS)[number])) {\n delete this._transient[key];\n } else {\n this._store.delete(key as keyof AppConfig);\n }\n }\n\n getProjects(): Record<string, ProjectConfig> {\n return this.get<Record<string, ProjectConfig>>('projects') ?? {};\n }\n\n getProject(name: string): ProjectConfig | undefined {\n const projects = this.getProjects();\n return projects[name];\n }\n\n setProject(name: string, config: ProjectConfig): void {\n const projects = this.getProjects();\n projects[name] = config;\n this.set('projects', projects);\n }\n\n deleteProject(name: string): void {\n const projects = this.getProjects();\n delete projects[name];\n this.set('projects', projects);\n }\n\n getDefaults(): ProjectDefaults | undefined {\n return this.get<ProjectDefaults>('project_defaults');\n }\n\n setDefaults(defaults: ProjectDefaults): void {\n this.set('project_defaults', defaults);\n }\n\n get path(): string {\n return this._store.path;\n }\n\n get store(): AppConfig {\n return this._store.store;\n }\n}\n","import File from 'phylo';\nimport deepAssign from 'deep-assign';\nimport type { ProjectConfig, EventsConfig, IdeType, ProjectDefaults } from '../types/index.js';\n\nexport class Project {\n name: string;\n private _base?: ReturnType<typeof File.from>;\n private _path?: ReturnType<typeof File.from>;\n private _ide?: IdeType;\n private _events: EventsConfig = {};\n private _branch?: string;\n private _homepage?: string;\n private _defaults: ProjectDefaults;\n private _initialCfg: ProjectConfig;\n\n constructor(name: string, cfg?: Partial<ProjectConfig>, defaults?: ProjectDefaults) {\n this._defaults = defaults ?? { base: '' };\n this._initialCfg = { path: name, events: {}, ...cfg };\n\n this.name = cfg?.name ?? name;\n\n // Apply defaults first, then config\n const merged = deepAssign({}, this._defaults, this._initialCfg) as ProjectConfig & {\n base?: string;\n };\n\n if (merged.base) {\n this.base = merged.base;\n }\n if (merged.path) {\n this.path = merged.path;\n }\n if (merged.ide) {\n this._ide = merged.ide;\n }\n if (merged.events) {\n this._events = merged.events;\n }\n if (merged.branch) {\n this._branch = merged.branch;\n }\n if (merged.homepage) {\n this._homepage = merged.homepage;\n }\n }\n\n set base(path: string) {\n this._base = File.from(path).absolutify();\n }\n\n get base(): ReturnType<typeof File.from> | undefined {\n return this._base;\n }\n\n set ide(cmd: IdeType | undefined) {\n this._ide = cmd;\n }\n\n get ide(): IdeType | undefined {\n return this._ide;\n }\n\n set events(eventCfg: EventsConfig) {\n this._events = eventCfg;\n }\n\n get events(): EventsConfig {\n return this._events;\n }\n\n set path(path: string) {\n if (this._base) {\n this._path = this._base.join(path);\n } else {\n this._path = File.from(path);\n }\n this._path = this._path.absolutify();\n }\n\n get path(): ReturnType<typeof File.from> {\n if (!this._path) {\n throw new Error('Project path not set');\n }\n return this._path;\n }\n\n set branch(branch: string | undefined) {\n this._branch = branch;\n }\n\n get branch(): string | undefined {\n return this._branch;\n }\n\n set homepage(url: string | undefined) {\n this._homepage = url;\n }\n\n get homepage(): string | undefined {\n return this._homepage;\n }\n\n static $isProject = true;\n $isProject = true;\n}\n","import { exec as execCallback, spawn } from 'child_process';\nimport { promisify } from 'util';\n\nconst exec = promisify(execCallback);\n\nexport class TmuxManager {\n private sessionPrefix = 'workon-';\n\n async isTmuxAvailable(): Promise<boolean> {\n try {\n await exec('which tmux');\n return true;\n } catch {\n return false;\n }\n }\n\n async sessionExists(sessionName: string): Promise<boolean> {\n try {\n await exec(`tmux has-session -t \"${sessionName}\"`);\n return true;\n } catch {\n return false;\n }\n }\n\n getSessionName(projectName: string): string {\n return `${this.sessionPrefix}${projectName}`;\n }\n\n async killSession(sessionName: string): Promise<boolean> {\n try {\n await exec(`tmux kill-session -t \"${sessionName}\"`);\n return true;\n } catch {\n return false;\n }\n }\n\n async createSplitSession(\n projectName: string,\n projectPath: string,\n claudeArgs: string[] = []\n ): Promise<string> {\n const sessionName = this.getSessionName(projectName);\n\n // Kill existing session if it exists\n if (await this.sessionExists(sessionName)) {\n await this.killSession(sessionName);\n }\n\n const claudeCommand = claudeArgs.length > 0 ? `claude ${claudeArgs.join(' ')}` : 'claude';\n\n // Create new tmux session with claude in the first pane\n await exec(`tmux new-session -d -s \"${sessionName}\" -c \"${projectPath}\" '${claudeCommand}'`);\n\n // Split window horizontally and run shell in second pane\n await exec(`tmux split-window -h -t \"${sessionName}\" -c \"${projectPath}\"`);\n\n // Set focus on claude pane (left pane)\n await exec(`tmux select-pane -t \"${sessionName}:0.0\"`);\n\n return sessionName;\n }\n\n async createThreePaneSession(\n projectName: string,\n projectPath: string,\n claudeArgs: string[] = [],\n npmCommand = 'npm run dev'\n ): Promise<string> {\n const sessionName = this.getSessionName(projectName);\n\n // Kill existing session if it exists\n if (await this.sessionExists(sessionName)) {\n await this.killSession(sessionName);\n }\n\n const claudeCommand = claudeArgs.length > 0 ? `claude ${claudeArgs.join(' ')}` : 'claude';\n\n // Create new tmux session with claude in the first pane (left side)\n await exec(`tmux new-session -d -s \"${sessionName}\" -c \"${projectPath}\" '${claudeCommand}'`);\n\n // Split window vertically - creates right side (50/50 split)\n await exec(`tmux split-window -h -t \"${sessionName}\" -c \"${projectPath}\"`);\n\n // Split the right pane horizontally - creates top-right and bottom-right (50/50 split)\n await exec(`tmux split-window -v -t \"${sessionName}:0.1\" -c \"${projectPath}\" '${npmCommand}'`);\n\n // Set remain-on-exit to keep pane open if command fails\n await exec(`tmux set-option -t \"${sessionName}:0.2\" remain-on-exit on`);\n\n // Resize panes to ensure npm pane is visible (give it at least 10 lines)\n await exec(`tmux resize-pane -t \"${sessionName}:0.2\" -y 10`);\n\n // Set focus on claude pane (left pane)\n await exec(`tmux select-pane -t \"${sessionName}:0.0\"`);\n\n return sessionName;\n }\n\n async createTwoPaneNpmSession(\n projectName: string,\n projectPath: string,\n npmCommand = 'npm run dev'\n ): Promise<string> {\n const sessionName = this.getSessionName(projectName);\n\n // Kill existing session if it exists\n if (await this.sessionExists(sessionName)) {\n await this.killSession(sessionName);\n }\n\n // Create new tmux session with shell in the first pane (left side)\n await exec(`tmux new-session -d -s \"${sessionName}\" -c \"${projectPath}\"`);\n\n // Split window vertically and run npm command in right pane\n await exec(`tmux split-window -h -t \"${sessionName}\" -c \"${projectPath}\" '${npmCommand}'`);\n\n // Set remain-on-exit to keep pane open if command fails\n await exec(`tmux set-option -t \"${sessionName}:0.1\" remain-on-exit on`);\n\n // Set focus on terminal pane (left pane)\n await exec(`tmux select-pane -t \"${sessionName}:0.0\"`);\n\n return sessionName;\n }\n\n async attachToSession(sessionName: string): Promise<void> {\n // Check if we're already in a tmux session\n if (process.env.TMUX) {\n // If we're already in tmux, switch to the session\n await exec(`tmux switch-client -t \"${sessionName}\"`);\n } else {\n // Check if iTerm2 integration is available\n const isITerm =\n process.env.TERM_PROGRAM === 'iTerm.app' ||\n process.env.LC_TERMINAL === 'iTerm2' ||\n !!process.env.ITERM_SESSION_ID;\n const useiTermIntegration = isITerm && !process.env.TMUX_CC_NOT_SUPPORTED;\n\n if (useiTermIntegration) {\n // Use iTerm2 tmux integration - spawn detached to avoid blocking\n spawn('tmux', ['-CC', 'attach-session', '-t', sessionName], {\n stdio: 'inherit',\n detached: true,\n });\n } else {\n // Use regular tmux - spawn detached to avoid blocking\n spawn('tmux', ['attach-session', '-t', sessionName], {\n stdio: 'inherit',\n detached: true,\n });\n }\n }\n }\n\n buildShellCommands(\n projectName: string,\n projectPath: string,\n claudeArgs: string[] = []\n ): string[] {\n const sessionName = this.getSessionName(projectName);\n const claudeCommand = claudeArgs.length > 0 ? `claude ${claudeArgs.join(' ')}` : 'claude';\n\n return [\n `# Create tmux split session for ${projectName}`,\n `tmux has-session -t \"${sessionName}\" 2>/dev/null && tmux kill-session -t \"${sessionName}\"`,\n `tmux new-session -d -s \"${sessionName}\" -c \"${projectPath}\" '${claudeCommand}'`,\n `tmux split-window -h -t \"${sessionName}\" -c \"${projectPath}\"`,\n `tmux select-pane -t \"${sessionName}:0.0\"`,\n this.getAttachCommand(sessionName),\n ];\n }\n\n buildThreePaneShellCommands(\n projectName: string,\n projectPath: string,\n claudeArgs: string[] = [],\n npmCommand = 'npm run dev'\n ): string[] {\n const sessionName = this.getSessionName(projectName);\n const claudeCommand = claudeArgs.length > 0 ? `claude ${claudeArgs.join(' ')}` : 'claude';\n\n return [\n `# Create tmux three-pane session for ${projectName}`,\n `tmux has-session -t \"${sessionName}\" 2>/dev/null && tmux kill-session -t \"${sessionName}\"`,\n `tmux new-session -d -s \"${sessionName}\" -c \"${projectPath}\" '${claudeCommand}'`,\n `tmux split-window -h -t \"${sessionName}\" -c \"${projectPath}\"`,\n `tmux split-window -v -t \"${sessionName}:0.1\" -c \"${projectPath}\" '${npmCommand}'`,\n `tmux set-option -t \"${sessionName}:0.2\" remain-on-exit on`,\n `tmux resize-pane -t \"${sessionName}:0.2\" -y 10`,\n `tmux select-pane -t \"${sessionName}:0.0\"`,\n this.getAttachCommand(sessionName),\n ];\n }\n\n buildTwoPaneNpmShellCommands(\n projectName: string,\n projectPath: string,\n npmCommand = 'npm run dev'\n ): string[] {\n const sessionName = this.getSessionName(projectName);\n\n return [\n `# Create tmux two-pane session with npm for ${projectName}`,\n `tmux has-session -t \"${sessionName}\" 2>/dev/null && tmux kill-session -t \"${sessionName}\"`,\n `tmux new-session -d -s \"${sessionName}\" -c \"${projectPath}\"`,\n `tmux split-window -h -t \"${sessionName}\" -c \"${projectPath}\" '${npmCommand}'`,\n `tmux set-option -t \"${sessionName}:0.1\" remain-on-exit on`,\n `tmux select-pane -t \"${sessionName}:0.0\"`,\n this.getAttachCommand(sessionName),\n ];\n }\n\n private getAttachCommand(sessionName: string): string {\n if (process.env.TMUX) {\n return `tmux switch-client -t \"${sessionName}\"`;\n }\n\n const isITerm =\n process.env.TERM_PROGRAM === 'iTerm.app' ||\n process.env.LC_TERMINAL === 'iTerm2' ||\n process.env.ITERM_SESSION_ID;\n const useiTermIntegration = isITerm && !process.env.TMUX_CC_NOT_SUPPORTED;\n\n if (useiTermIntegration) {\n return `tmux -CC attach-session -t \"${sessionName}\"`;\n }\n return `tmux attach-session -t \"${sessionName}\"`;\n }\n\n async listWorkonSessions(): Promise<string[]> {\n try {\n const { stdout } = await exec('tmux list-sessions -F \"#{session_name}\"');\n return stdout\n .trim()\n .split('\\n')\n .filter((session) => session.startsWith(this.sessionPrefix))\n .map((session) => session.replace(this.sessionPrefix, ''));\n } catch {\n return [];\n }\n }\n}\n","import File from 'phylo';\nimport { simpleGit } from 'simple-git';\nimport { Config } from './config.js';\nimport { Project } from './project.js';\nimport type { Logger, ProjectConfig, ProjectDefaults } from '../types/index.js';\n\nexport class BaseEnvironment {\n $isProjectEnvironment = false as const;\n}\n\nexport class ProjectEnvironment {\n $isProjectEnvironment = true as const;\n project: Project;\n\n constructor(projectCfg: ProjectConfig & { name: string; exactName?: string }) {\n this.project = new Project(projectCfg.name, projectCfg);\n }\n\n static load(\n cfg: ProjectConfig & { name: string },\n defaults?: ProjectDefaults\n ): ProjectEnvironment {\n const project = new Project(cfg.name, cfg, defaults);\n return new ProjectEnvironment({ ...cfg, name: project.name });\n }\n}\n\nexport type Environment = BaseEnvironment | ProjectEnvironment;\n\ninterface ProjectWithPath {\n name: string;\n path: ReturnType<typeof File.from>;\n ide?: ProjectConfig['ide'];\n homepage?: string;\n events: ProjectConfig['events'];\n branch?: string;\n}\n\nexport class EnvironmentRecognizer {\n private static config: Config;\n private static log: Logger;\n private static projects: ProjectWithPath[] = [];\n private static configured = false;\n\n static configure(config: Config, log: Logger): void {\n if (this.configured) {\n return;\n }\n this.config = config;\n this.log = log;\n this.configured = true;\n }\n\n static async recognize(dir: string | ReturnType<typeof File.from>): Promise<Environment> {\n this.ensureConfigured();\n\n const theDir = File.from(dir).canonicalize();\n this.log.debug('Directory to recognize is: ' + theDir.canonicalPath());\n\n const allProjects = this.getAllProjects();\n const matching = allProjects.filter((p) => p.path.canonicalPath() === theDir.path);\n\n if (matching.length === 0) {\n return new BaseEnvironment();\n }\n\n this.log.debug(`Found ${matching.length} matching projects`);\n\n // Find base project (without branch suffix)\n const base = matching.find((p) => !p.name.includes('#')) ?? matching[0];\n this.log.debug('Base project is: ' + base.name);\n\n // Try to detect git branch\n const gitDir = base.path.up('.git');\n if (gitDir) {\n try {\n const git = simpleGit(gitDir.path);\n const branchSummary = await git.branchLocal();\n (base as ProjectWithPath & { branch?: string }).branch = branchSummary.current;\n } catch {\n // Git not available or not a git repo\n }\n }\n\n return this.getProjectEnvironment(base, matching);\n }\n\n private static getAllProjects(refresh = false): ProjectWithPath[] {\n if (this.projects.length > 0 && !refresh) {\n return this.projects;\n }\n\n const defaults = this.config.getDefaults();\n if (!defaults?.base) {\n this.projects = [];\n return this.projects;\n }\n\n const baseDir = File.from(defaults.base);\n const projectsMap = this.config.getProjects();\n\n this.projects = Object.entries(projectsMap).map(([name, project]) => ({\n ...project,\n name,\n path: baseDir.join(project.path),\n }));\n\n return this.projects;\n }\n\n private static getProjectEnvironment(\n base: ProjectWithPath & { branch?: string },\n _matching: ProjectWithPath[]\n ): ProjectEnvironment {\n const exactName = `${base.name}#${base.branch}`;\n\n // Check if there's an exact branch-specific config\n const exactProj = this.projects.find((p) => p.name === exactName);\n\n // Convert ProjectWithPath to ProjectConfig format (path as string)\n const toProjectConfig = (\n p: ProjectWithPath\n ): ProjectConfig & { name: string; exactName?: string } => ({\n name: p.name,\n path: p.path.path, // Convert PhyloFile to string path\n ide: p.ide,\n homepage: p.homepage,\n events: p.events,\n branch: p.branch,\n exactName,\n });\n\n if (exactProj) {\n return new ProjectEnvironment({ ...toProjectConfig(exactProj), branch: base.branch });\n }\n\n return new ProjectEnvironment(toProjectConfig(base));\n }\n\n private static ensureConfigured(): void {\n if (!this.configured) {\n this.config = new Config();\n // Create a no-op logger if not configured\n this.log = {\n debug: () => {},\n info: () => {},\n log: () => {},\n warn: () => {},\n error: () => {},\n setLogLevel: () => {},\n };\n this.configured = true;\n }\n }\n}\n","import { spawn } from 'child_process';\nimport type {\n EventMetadata,\n EventValidation,\n EventConfiguration,\n EventProcessing,\n EventHelp,\n EventProcessingContext,\n} from '../../types/index.js';\n\nexport class CwdEvent {\n static get metadata(): EventMetadata {\n return {\n name: 'cwd',\n displayName: 'Change directory (cwd)',\n description: 'Change current working directory to project path',\n category: 'core',\n requiresTmux: false,\n dependencies: [],\n };\n }\n\n static get validation(): EventValidation {\n return {\n validateConfig(config: unknown): true | string {\n if (typeof config === 'boolean' || config === 'true' || config === 'false') {\n return true;\n }\n return 'cwd config must be a boolean (true/false)';\n },\n };\n }\n\n static get configuration(): EventConfiguration {\n return {\n async configureInteractive(): Promise<boolean> {\n return true;\n },\n getDefaultConfig(): boolean {\n return true;\n },\n };\n }\n\n static get processing(): EventProcessing {\n return {\n async processEvent(context: EventProcessingContext): Promise<void> {\n const { project, isShellMode, shellCommands } = context;\n const projectPath = project.path.path;\n\n if (isShellMode) {\n shellCommands.push(`cd \"${projectPath}\"`);\n } else {\n // Spawn a new shell in the project directory\n const shell = process.env.SHELL || '/bin/bash';\n spawn(shell, [], {\n cwd: projectPath,\n stdio: 'inherit',\n });\n }\n },\n generateShellCommand(context: EventProcessingContext): string[] {\n const projectPath = context.project.path.path;\n return [`cd \"${projectPath}\"`];\n },\n };\n }\n\n static get tmux() {\n return null;\n }\n\n static get help(): EventHelp {\n return {\n usage: 'cwd: true | false',\n description: 'Change the current working directory to the project path',\n examples: [\n { config: true, description: 'Enable directory change' },\n { config: false, description: 'Disable directory change' },\n ],\n };\n }\n}\n\nexport default CwdEvent;\n","import { spawn } from 'child_process';\nimport type {\n EventMetadata,\n EventValidation,\n EventConfiguration,\n EventProcessing,\n EventHelp,\n EventProcessingContext,\n} from '../../types/index.js';\n\nexport class IdeEvent {\n static get metadata(): EventMetadata {\n return {\n name: 'ide',\n displayName: 'Open in IDE',\n description: 'Open project in configured IDE/editor',\n category: 'core',\n requiresTmux: false,\n dependencies: [],\n };\n }\n\n static get validation(): EventValidation {\n return {\n validateConfig(config: unknown): true | string {\n if (typeof config === 'boolean' || config === 'true' || config === 'false') {\n return true;\n }\n return 'ide config must be a boolean (true/false)';\n },\n };\n }\n\n static get configuration(): EventConfiguration {\n return {\n async configureInteractive(): Promise<boolean> {\n return true;\n },\n getDefaultConfig(): boolean {\n return true;\n },\n };\n }\n\n static get processing(): EventProcessing {\n return {\n async processEvent(context: EventProcessingContext): Promise<void> {\n const { project, isShellMode, shellCommands } = context;\n const projectPath = project.path.path;\n const ide = project.ide || 'code';\n\n if (isShellMode) {\n shellCommands.push(`${ide} \"${projectPath}\" &`);\n } else {\n spawn(ide, [projectPath], {\n detached: true,\n stdio: 'ignore',\n }).unref();\n }\n },\n generateShellCommand(context: EventProcessingContext): string[] {\n const projectPath = context.project.path.path;\n const ide = context.project.ide || 'code';\n return [`${ide} \"${projectPath}\" &`];\n },\n };\n }\n\n static get tmux() {\n return null;\n }\n\n static get help(): EventHelp {\n return {\n usage: 'ide: true | false',\n description: 'Open the project in the configured IDE',\n examples: [\n { config: true, description: 'Enable IDE opening' },\n { config: false, description: 'Disable IDE opening' },\n ],\n };\n }\n}\n\nexport default IdeEvent;\n","import { spawn } from 'child_process';\nimport { platform } from 'os';\nimport type {\n EventMetadata,\n EventValidation,\n EventConfiguration,\n EventProcessing,\n EventHelp,\n EventProcessingContext,\n} from '../../types/index.js';\n\nexport class WebEvent {\n static get metadata(): EventMetadata {\n return {\n name: 'web',\n displayName: 'Open homepage in browser',\n description: 'Open project homepage in web browser',\n category: 'core',\n requiresTmux: false,\n dependencies: [],\n };\n }\n\n static get validation(): EventValidation {\n return {\n validateConfig(config: unknown): true | string {\n if (typeof config === 'boolean' || config === 'true' || config === 'false') {\n return true;\n }\n return 'web config must be a boolean (true/false)';\n },\n };\n }\n\n static get configuration(): EventConfiguration {\n return {\n async configureInteractive(): Promise<boolean> {\n return true;\n },\n getDefaultConfig(): boolean {\n return true;\n },\n };\n }\n\n static getOpenCommand(): string {\n const os = platform();\n switch (os) {\n case 'darwin':\n return 'open';\n case 'win32':\n return 'start';\n default:\n return 'xdg-open';\n }\n }\n\n static get processing(): EventProcessing {\n return {\n async processEvent(context: EventProcessingContext): Promise<void> {\n const { project, isShellMode, shellCommands } = context;\n const homepage = project.homepage;\n\n if (!homepage) {\n console.warn('No homepage configured for project');\n return;\n }\n\n const openCmd = WebEvent.getOpenCommand();\n\n if (isShellMode) {\n shellCommands.push(`${openCmd} \"${homepage}\" &`);\n } else {\n spawn(openCmd, [homepage], {\n detached: true,\n stdio: 'ignore',\n }).unref();\n }\n },\n generateShellCommand(context: EventProcessingContext): string[] {\n const homepage = context.project.homepage;\n if (!homepage) return [];\n\n const openCmd = WebEvent.getOpenCommand();\n return [`${openCmd} \"${homepage}\" &`];\n },\n };\n }\n\n static get tmux() {\n return null;\n }\n\n static get help(): EventHelp {\n return {\n usage: 'web: true | false',\n description: 'Open the project homepage in the default browser',\n examples: [\n { config: true, description: 'Enable browser opening' },\n { config: false, description: 'Disable browser opening' },\n ],\n };\n }\n}\n\nexport default WebEvent;\n","import { spawn } from 'child_process';\nimport { input, confirm } from '@inquirer/prompts';\nimport type {\n EventMetadata,\n EventValidation,\n EventConfiguration,\n EventProcessing,\n EventTmux,\n EventHelp,\n EventProcessingContext,\n ClaudeConfig,\n} from '../../types/index.js';\n\nexport class ClaudeEvent {\n static get metadata(): EventMetadata {\n return {\n name: 'claude',\n displayName: 'Launch Claude Code',\n description: 'Launch Claude Code with optional flags and configuration',\n category: 'development',\n requiresTmux: true,\n dependencies: ['claude'],\n };\n }\n\n static get validation(): EventValidation {\n return {\n validateConfig(config: unknown): true | string {\n if (typeof config === 'boolean' || config === 'true' || config === 'false') {\n return true;\n }\n\n if (typeof config === 'object' && config !== null) {\n const cfg = config as ClaudeConfig;\n\n if (cfg.flags !== undefined) {\n if (!Array.isArray(cfg.flags)) {\n return 'claude.flags must be an array of strings';\n }\n for (const flag of cfg.flags) {\n if (typeof flag !== 'string') {\n return 'claude.flags must contain only strings';\n }\n if (!flag.startsWith('-')) {\n return `Invalid flag \"${flag}\": flags must start with - or --`;\n }\n }\n }\n\n if (cfg.split_terminal !== undefined && typeof cfg.split_terminal !== 'boolean') {\n return 'claude.split_terminal must be a boolean';\n }\n\n return true;\n }\n\n return 'claude config must be a boolean or object with flags/split_terminal';\n },\n };\n }\n\n static get configuration(): EventConfiguration {\n return {\n async configureInteractive(): Promise<boolean | ClaudeConfig> {\n const useAdvanced = await confirm({\n message: 'Configure advanced Claude options?',\n default: false,\n });\n\n if (!useAdvanced) {\n return true;\n }\n\n const flagsInput = await input({\n message: 'Enter Claude flags (comma-separated, e.g., --resume, --debug):',\n default: '',\n });\n\n const flags = flagsInput\n .split(',')\n .map((f) => f.trim())\n .filter((f) => f.length > 0 && f.startsWith('-'));\n\n const splitTerminal = await confirm({\n message: 'Use split terminal layout (Claude + shell)?',\n default: true,\n });\n\n if (flags.length === 0 && !splitTerminal) {\n return true;\n }\n\n const config: ClaudeConfig = {};\n if (flags.length > 0) config.flags = flags;\n if (splitTerminal) config.split_terminal = splitTerminal;\n\n return config;\n },\n getDefaultConfig(): boolean {\n return true;\n },\n };\n }\n\n static getClaudeCommand(config: boolean | ClaudeConfig | undefined): string {\n if (typeof config === 'boolean' || config === undefined) {\n return 'claude';\n }\n\n const flags = config.flags || [];\n return flags.length > 0 ? `claude ${flags.join(' ')}` : 'claude';\n }\n\n static get processing(): EventProcessing {\n return {\n async processEvent(context: EventProcessingContext): Promise<void> {\n const { project, isShellMode, shellCommands } = context;\n const claudeConfig = project.events.claude;\n const claudeCommand = ClaudeEvent.getClaudeCommand(claudeConfig as boolean | ClaudeConfig);\n\n if (isShellMode) {\n shellCommands.push(claudeCommand);\n } else {\n const args = claudeCommand.split(' ').slice(1);\n spawn('claude', args, {\n cwd: project.path.path,\n stdio: 'inherit',\n });\n }\n },\n generateShellCommand(context: EventProcessingContext): string[] {\n const claudeConfig = context.project.events.claude;\n return [ClaudeEvent.getClaudeCommand(claudeConfig as boolean | ClaudeConfig)];\n },\n };\n }\n\n static get tmux(): EventTmux {\n return {\n getLayoutPriority(): number {\n return 100; // High priority for Claude\n },\n contributeToLayout(enabledCommands: string[]): string {\n if (enabledCommands.includes('npm')) {\n return 'three-pane';\n }\n return 'split';\n },\n };\n }\n\n static get help(): EventHelp {\n return {\n usage: 'claude: true | { flags: string[], split_terminal: boolean }',\n description: 'Launch Claude Code in the project directory',\n examples: [\n { config: true, description: 'Launch Claude with defaults' },\n { config: { flags: ['--resume'] }, description: 'Resume previous session' },\n {\n config: { flags: ['--model', 'opus'], split_terminal: true },\n description: 'Use Opus model with split terminal',\n },\n ],\n };\n }\n}\n\nexport default ClaudeEvent;\n","import { spawn } from 'child_process';\nimport { input } from '@inquirer/prompts';\nimport type {\n EventMetadata,\n EventValidation,\n EventConfiguration,\n EventProcessing,\n EventHelp,\n EventProcessingContext,\n DockerConfig,\n} from '../../types/index.js';\n\nexport class DockerEvent {\n static get metadata(): EventMetadata {\n return {\n name: 'docker',\n displayName: 'Docker container management',\n description: 'Start/stop Docker containers for the project',\n category: 'development',\n requiresTmux: false,\n dependencies: ['docker'],\n };\n }\n\n static get validation(): EventValidation {\n return {\n validateConfig(config: unknown): true | string {\n if (typeof config === 'boolean' || config === 'true' || config === 'false') {\n return true;\n }\n\n if (typeof config === 'string') {\n // Assume it's a compose file path\n return true;\n }\n\n if (typeof config === 'object' && config !== null) {\n const cfg = config as DockerConfig;\n\n if (cfg.compose_file !== undefined && typeof cfg.compose_file !== 'string') {\n return 'docker.compose_file must be a string';\n }\n\n if (cfg.services !== undefined) {\n if (!Array.isArray(cfg.services)) {\n return 'docker.services must be an array';\n }\n for (const service of cfg.services) {\n if (typeof service !== 'string') {\n return 'docker.services must contain only strings';\n }\n }\n }\n\n return true;\n }\n\n return 'docker config must be a boolean, string (compose file), or object';\n },\n };\n }\n\n static get configuration(): EventConfiguration {\n return {\n async configureInteractive(): Promise<string | DockerConfig> {\n const composeFile = await input({\n message: 'Enter docker-compose file path:',\n default: 'docker-compose.yml',\n });\n\n const servicesInput = await input({\n message: 'Enter services to start (comma-separated, leave empty for all):',\n default: '',\n });\n\n const services = servicesInput\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n\n if (composeFile === 'docker-compose.yml' && services.length === 0) {\n return { compose_file: 'docker-compose.yml' };\n }\n\n if (services.length === 0) {\n return composeFile;\n }\n\n return {\n compose_file: composeFile,\n services,\n };\n },\n getDefaultConfig(): DockerConfig {\n return { compose_file: 'docker-compose.yml' };\n },\n };\n }\n\n static getDockerCommand(config: boolean | string | DockerConfig | undefined): string {\n if (typeof config === 'boolean' || config === undefined) {\n return 'docker-compose up -d';\n }\n\n if (typeof config === 'string') {\n return `docker-compose -f ${config} up -d`;\n }\n\n const composeFile = config.compose_file || 'docker-compose.yml';\n const services = config.services?.join(' ') || '';\n\n return `docker-compose -f ${composeFile} up -d ${services}`.trim();\n }\n\n static get processing(): EventProcessing {\n return {\n async processEvent(context: EventProcessingContext): Promise<void> {\n const { project, isShellMode, shellCommands } = context;\n const dockerConfig = project.events.docker;\n const dockerCommand = DockerEvent.getDockerCommand(\n dockerConfig as boolean | string | DockerConfig\n );\n\n if (isShellMode) {\n shellCommands.push(dockerCommand);\n } else {\n const [cmd, ...args] = dockerCommand.split(' ');\n spawn(cmd, args, {\n cwd: project.path.path,\n stdio: 'inherit',\n });\n }\n },\n generateShellCommand(context: EventProcessingContext): string[] {\n const dockerConfig = context.project.events.docker;\n return [DockerEvent.getDockerCommand(dockerConfig as boolean | string | DockerConfig)];\n },\n };\n }\n\n static get tmux() {\n return null;\n }\n\n static get help(): EventHelp {\n return {\n usage: 'docker: true | \"compose-file.yml\" | { compose_file: string, services?: string[] }',\n description: 'Start Docker containers for the project',\n examples: [\n { config: true, description: 'Use default docker-compose.yml' },\n { config: 'docker-compose.dev.yml', description: 'Use custom compose file' },\n {\n config: { compose_file: 'docker-compose.yml', services: ['web', 'db'] },\n description: 'Start specific services',\n },\n ],\n };\n }\n}\n\nexport default DockerEvent;\n","import { spawn } from 'child_process';\nimport { input, confirm } from '@inquirer/prompts';\nimport type {\n EventMetadata,\n EventValidation,\n EventConfiguration,\n EventProcessing,\n EventTmux,\n EventHelp,\n EventProcessingContext,\n NpmConfig,\n} from '../../types/index.js';\n\nexport class NpmEvent {\n static get metadata(): EventMetadata {\n return {\n name: 'npm',\n displayName: 'Run NPM command',\n description: 'Execute NPM scripts in project directory',\n category: 'development',\n requiresTmux: true,\n dependencies: ['npm'],\n };\n }\n\n static get validation(): EventValidation {\n return {\n validateConfig(config: unknown): true | string {\n if (typeof config === 'boolean' || config === 'true' || config === 'false') {\n return true;\n }\n\n if (typeof config === 'string') {\n if (config.trim().length === 0) {\n return 'npm script name cannot be empty';\n }\n return true;\n }\n\n if (typeof config === 'object' && config !== null) {\n const cfg = config as NpmConfig;\n\n if (typeof cfg.command !== 'string' || cfg.command.trim().length === 0) {\n return 'npm.command must be a non-empty string';\n }\n\n if (cfg.watch !== undefined && typeof cfg.watch !== 'boolean') {\n return 'npm.watch must be a boolean';\n }\n\n if (cfg.auto_restart !== undefined && typeof cfg.auto_restart !== 'boolean') {\n return 'npm.auto_restart must be a boolean';\n }\n\n return true;\n }\n\n return 'npm config must be a boolean, string (script name), or object';\n },\n };\n }\n\n static get configuration(): EventConfiguration {\n return {\n async configureInteractive(): Promise<string | NpmConfig> {\n const scriptName = await input({\n message: 'Enter NPM script to run:',\n default: 'dev',\n });\n\n const useAdvanced = await confirm({\n message: 'Configure advanced NPM options?',\n default: false,\n });\n\n if (!useAdvanced) {\n return scriptName;\n }\n\n const watch = await confirm({\n message: 'Enable watch mode?',\n default: false,\n });\n\n const autoRestart = await confirm({\n message: 'Auto-restart on crash?',\n default: false,\n });\n\n if (!watch && !autoRestart) {\n return scriptName;\n }\n\n return {\n command: scriptName,\n watch,\n auto_restart: autoRestart,\n };\n },\n getDefaultConfig(): string {\n return 'dev';\n },\n };\n }\n\n static getNpmCommand(config: boolean | string | NpmConfig | undefined): string {\n if (typeof config === 'boolean' || config === undefined) {\n return 'npm run dev';\n }\n\n if (typeof config === 'string') {\n return `npm run ${config}`;\n }\n\n return `npm run ${config.command}`;\n }\n\n static get processing(): EventProcessing {\n return {\n async processEvent(context: EventProcessingContext): Promise<void> {\n const { project, isShellMode, shellCommands } = context;\n const npmConfig = project.events.npm;\n const npmCommand = NpmEvent.getNpmCommand(npmConfig as boolean | string | NpmConfig);\n\n if (isShellMode) {\n shellCommands.push(npmCommand);\n } else {\n const [cmd, ...args] = npmCommand.split(' ');\n spawn(cmd, args, {\n cwd: project.path.path,\n stdio: 'inherit',\n });\n }\n },\n generateShellCommand(context: EventProcessingContext): string[] {\n const npmConfig = context.project.events.npm;\n return [NpmEvent.getNpmCommand(npmConfig as boolean | string | NpmConfig)];\n },\n };\n }\n\n static get tmux(): EventTmux {\n return {\n getLayoutPriority(): number {\n return 50; // Medium priority\n },\n contributeToLayout(enabledCommands: string[]): string {\n if (enabledCommands.includes('claude')) {\n return 'three-pane';\n }\n return 'two-pane-npm';\n },\n };\n }\n\n static get help(): EventHelp {\n return {\n usage: 'npm: true | \"script\" | { command: string, watch?: boolean, auto_restart?: boolean }',\n description: 'Run an NPM script in the project directory',\n examples: [\n { config: true, description: 'Run npm run dev' },\n { config: 'test', description: 'Run npm run test' },\n { config: { command: 'dev', watch: true }, description: 'Run dev with watch mode' },\n ],\n };\n }\n}\n\nexport default NpmEvent;\n","import type { EventHandler, EventMetadata } from '../types/index.js';\n\n// Explicit imports for all events (works with bundled builds)\nimport { CwdEvent } from './core/cwd.js';\nimport { IdeEvent } from './core/ide.js';\nimport { WebEvent } from './core/web.js';\nimport { ClaudeEvent } from './extensions/claude.js';\nimport { DockerEvent } from './extensions/docker.js';\nimport { NpmEvent } from './extensions/npm.js';\n\n// All available event classes\nconst ALL_EVENTS = [CwdEvent, IdeEvent, WebEvent, ClaudeEvent, DockerEvent, NpmEvent] as const;\n\n/**\n * Event Registry for management of events\n * Uses explicit imports to work with bundled builds\n */\nclass EventRegistryClass {\n private _events = new Map<string, EventHandler>();\n private _initialized = false;\n\n /**\n * Initialize the registry by registering all events\n */\n async initialize(): Promise<void> {\n if (this._initialized) return;\n\n this.registerEvents();\n this._initialized = true;\n }\n\n /**\n * Register all event classes\n */\n private registerEvents(): void {\n for (const EventClass of ALL_EVENTS) {\n if (this.isValidEvent(EventClass)) {\n const metadata = (EventClass as unknown as { metadata: EventMetadata }).metadata;\n this._events.set(metadata.name, EventClass as unknown as EventHandler);\n }\n }\n }\n\n /**\n * Validate if a class is a proper event\n */\n private isValidEvent(EventClass: unknown): boolean {\n try {\n if (typeof EventClass !== 'function') return false;\n\n const metadata = (EventClass as { metadata?: EventMetadata }).metadata;\n return (\n metadata !== undefined &&\n typeof metadata.name === 'string' &&\n typeof metadata.displayName === 'string' &&\n typeof (EventClass as { validation?: object }).validation === 'object' &&\n typeof (EventClass as { configuration?: object }).configuration === 'object' &&\n typeof (EventClass as { processing?: object }).processing === 'object'\n );\n } catch {\n return false;\n }\n }\n\n /**\n * Get all valid event names from registered events\n */\n getValidEventNames(): string[] {\n this.ensureInitialized();\n return Array.from(this._events.keys());\n }\n\n /**\n * Get event by name\n */\n getEventByName(name: string): EventHandler | null {\n this.ensureInitialized();\n return this._events.get(name) ?? null;\n }\n\n /**\n * Get all events for management UI\n */\n getEventsForManageUI(): Array<{ name: string; value: string; description: string }> {\n this.ensureInitialized();\n\n const events: Array<{ name: string; value: string; description: string }> = [];\n for (const [name, EventClass] of this._events) {\n const metadata = (EventClass as { metadata: EventMetadata }).metadata;\n events.push({\n name: metadata.displayName,\n value: name,\n description: metadata.description,\n });\n }\n\n return events.sort((a, b) => a.name.localeCompare(b.name));\n }\n\n /**\n * Get events that support tmux integration\n */\n getTmuxEnabledEvents(): Array<{ name: string; event: EventHandler; priority: number }> {\n this.ensureInitialized();\n\n const tmuxEvents: Array<{ name: string; event: EventHandler; priority: number }> = [];\n for (const [name, EventClass] of this._events) {\n const tmux = (EventClass as { tmux?: { getLayoutPriority?: () => number } }).tmux;\n if (tmux) {\n tmuxEvents.push({\n name,\n event: EventClass,\n priority: tmux.getLayoutPriority ? tmux.getLayoutPriority() : 0,\n });\n }\n }\n\n return tmuxEvents.sort((a, b) => b.priority - a.priority);\n }\n\n /**\n * Get all available events with their metadata\n */\n getAllEvents(): Array<{\n name: string;\n metadata: EventMetadata;\n hasValidation: boolean;\n hasConfiguration: boolean;\n hasProcessing: boolean;\n hasTmux: boolean;\n hasHelp: boolean;\n }> {\n this.ensureInitialized();\n\n const events = [];\n for (const [name, EventClass] of this._events) {\n const typedClass = EventClass as {\n metadata: EventMetadata;\n validation?: object;\n configuration?: object;\n processing?: object;\n tmux?: object;\n help?: object;\n };\n events.push({\n name,\n metadata: typedClass.metadata,\n hasValidation: !!typedClass.validation,\n hasConfiguration: !!typedClass.configuration,\n hasProcessing: !!typedClass.processing,\n hasTmux: !!typedClass.tmux,\n hasHelp: !!typedClass.help,\n });\n }\n\n return events;\n }\n\n /**\n * Ensure registry is initialized\n */\n private ensureInitialized(): void {\n if (!this._initialized) {\n throw new Error('EventRegistry must be initialized before use. Call initialize() first.');\n }\n }\n\n /**\n * Clear the registry (useful for testing)\n */\n clear(): void {\n this._events.clear();\n this._initialized = false;\n }\n}\n\n// Export singleton instance\nexport const EventRegistry = new EventRegistryClass();\n"],"mappings":"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","names":["File","File","spawn","spawn","spawn","spawn","spawn","input","spawn","input","confirm"]}
package/package.json CHANGED
@@ -1,43 +1,90 @@
1
1
  {
2
2
  "name": "workon",
3
- "version": "2.1.3",
3
+ "version": "3.0.0",
4
4
  "description": "Work on something great!",
5
- "main": "index.js",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "bin",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "bin": {
23
+ "workon": "bin/workon",
24
+ "wo": "bin/workon"
25
+ },
6
26
  "scripts": {
7
- "release": "standard-version"
27
+ "build": "tsup",
28
+ "dev": "tsx src/cli.ts",
29
+ "lint": "eslint src/",
30
+ "lint:fix": "eslint src/ --fix",
31
+ "format": "prettier --write \"src/**/*.ts\"",
32
+ "format:check": "prettier --check \"src/**/*.ts\"",
33
+ "type-check": "tsc --noEmit",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest",
36
+ "test:coverage": "vitest run --coverage",
37
+ "prepublishOnly": "pnpm run build",
38
+ "prepare": "husky"
8
39
  },
9
40
  "repository": {
10
41
  "type": "git",
11
42
  "url": "git+ssh://git@github.com/israelroldan/workon.git"
12
43
  },
13
44
  "keywords": [
14
- "productivity"
45
+ "productivity",
46
+ "cli",
47
+ "project-management",
48
+ "developer-tools"
15
49
  ],
16
50
  "author": "Israel Roldan (me@isro.me)",
17
51
  "license": "MIT",
18
- "devDependencies": {
19
- "cz-conventional-changelog": "^2.0.0",
20
- "standard-version": "^9.5.0"
52
+ "engines": {
53
+ "node": ">=20"
21
54
  },
22
- "config": {
23
- "commitizen": {
24
- "path": "./node_modules/cz-conventional-changelog"
25
- }
55
+ "packageManager": "pnpm@10.0.0",
56
+ "devDependencies": {
57
+ "@eslint/js": "^9.17.0",
58
+ "@types/node": "^22.10.2",
59
+ "@vitest/coverage-v8": "^2.1.8",
60
+ "eslint": "^9.17.0",
61
+ "eslint-config-prettier": "^9.1.0",
62
+ "husky": "^9.1.7",
63
+ "lint-staged": "^15.2.11",
64
+ "prettier": "^3.4.2",
65
+ "tsup": "^8.3.5",
66
+ "tsx": "^4.19.2",
67
+ "typescript": "^5.7.2",
68
+ "typescript-eslint": "^8.18.1",
69
+ "vitest": "^2.1.8"
26
70
  },
27
71
  "dependencies": {
28
- "conf": "^1.1.2",
29
- "deep-assign": "^2.0.0",
30
- "flat": "^2.0.1",
31
- "inquirer": "^3.1.1",
72
+ "@inquirer/prompts": "^7.2.1",
73
+ "chalk": "^5.4.1",
74
+ "commander": "^13.0.0",
75
+ "conf": "^13.0.1",
76
+ "deep-assign": "^3.0.0",
32
77
  "loog": "^1.4.0",
33
- "omelette": "^0.4.4",
78
+ "omelette": "^0.4.17",
34
79
  "openurl2": "^1.0.1",
80
+ "ora": "^8.1.1",
35
81
  "phylo": "^1.0.0-beta.7",
36
- "simple-git": "^1.73.0",
37
- "switchit": "^1.0.7"
82
+ "simple-git": "^3.27.0"
38
83
  },
39
- "bin": {
40
- "workon": "bin/workon",
41
- "wo": "bin/workon"
84
+ "lint-staged": {
85
+ "src/**/*.ts": [
86
+ "eslint --fix",
87
+ "prettier --write"
88
+ ]
42
89
  }
43
90
  }
@@ -1,11 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(echo \"TERM_PROGRAM: $TERM_PROGRAM\")",
5
- "Bash(echo \"LC_TERMINAL: $LC_TERMINAL\")",
6
- "Bash(echo \"ITERM_SESSION_ID: $ITERM_SESSION_ID\")",
7
- "Bash(echo \"TERM: $TERM\")"
8
- ],
9
- "deny": []
10
- }
11
- }
@@ -1,3 +0,0 @@
1
-
2
- # Don't index SpecStory auto-save files, but allow explicit context inclusion via @ references
3
- .specstory/**
@@ -1,30 +0,0 @@
1
- # ---> Node
2
- # Logs
3
- logs
4
- *.log
5
- npm-debug.log*
6
-
7
- # Runtime data
8
- pids
9
- *.pid
10
- *.seed
11
-
12
- # Directory for instrumented libs generated by jscoverage/JSCover
13
- lib-cov
14
-
15
- # Coverage directory used by tools like istanbul
16
- coverage
17
-
18
- # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
19
- .grunt
20
-
21
- # node-waf configuration
22
- .lock-wscript
23
-
24
- # Compiled binary addons (http://nodejs.org/api/addons.html)
25
- build/Release
26
-
27
- # Dependency directory
28
- # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
29
- node_modules
30
-
@@ -1,32 +0,0 @@
1
- # ---> Node
2
- # Logs
3
- logs
4
- *.log
5
- npm-debug.log*
6
-
7
- # Runtime data
8
- pids
9
- *.pid
10
- *.seed
11
-
12
- # Directory for instrumented libs generated by jscoverage/JSCover
13
- lib-cov
14
-
15
- # Coverage directory used by tools like istanbul
16
- coverage
17
-
18
- # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
19
- .grunt
20
-
21
- # node-waf configuration
22
- .lock-wscript
23
-
24
- # Compiled binary addons (http://nodejs.org/api/addons.html)
25
- build/Release
26
-
27
- # Dependency directory
28
- # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
29
- node_modules
30
-
31
- .history
32
- .specstory
@@ -1,32 +0,0 @@
1
- # ---> Node
2
- # Logs
3
- logs
4
- *.log
5
- npm-debug.log*
6
-
7
- # Runtime data
8
- pids
9
- *.pid
10
- *.seed
11
-
12
- # Directory for instrumented libs generated by jscoverage/JSCover
13
- lib-cov
14
-
15
- # Coverage directory used by tools like istanbul
16
- coverage
17
-
18
- # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
19
- .grunt
20
-
21
- # node-waf configuration
22
- .lock-wscript
23
-
24
- # Compiled binary addons (http://nodejs.org/api/addons.html)
25
- build/Release
26
-
27
- # Dependency directory
28
- # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git
29
- node_modules
30
-
31
- .history
32
- .specstory
@@ -1,109 +0,0 @@
1
- const { spawn } = require('child_process');
2
- const { promisify } = require('util');
3
- const exec = promisify(require('child_process').exec);
4
-
5
- class TmuxManager {
6
- constructor() {
7
- this.sessionPrefix = 'workon-';
8
- }
9
-
10
- async isTmuxAvailable() {
11
- try {
12
- await exec('which tmux');
13
- return true;
14
- } catch {
15
- return false;
16
- }
17
- }
18
-
19
- async sessionExists(sessionName) {
20
- try {
21
- await exec(`tmux -CC has-session -t "${sessionName}"`);
22
- return true;
23
- } catch {
24
- return false;
25
- }
26
- }
27
-
28
- getSessionName(projectName) {
29
- return `${this.sessionPrefix}${projectName}`;
30
- }
31
-
32
- async killSession(sessionName) {
33
- try {
34
- await exec(`tmux -CC kill-session -t "${sessionName}"`);
35
- return true;
36
- } catch {
37
- return false;
38
- }
39
- }
40
-
41
- async createSplitSession(projectName, projectPath, claudeArgs = []) {
42
- const sessionName = this.getSessionName(projectName);
43
-
44
- // Kill existing session if it exists
45
- if (await this.sessionExists(sessionName)) {
46
- await this.killSession(sessionName);
47
- }
48
-
49
- const claudeCommand = claudeArgs.length > 0
50
- ? `claude ${claudeArgs.join(' ')}`
51
- : 'claude';
52
-
53
- // Create new tmux session with claude in the first pane
54
- await exec(`tmux -CC new-session -d -s "${sessionName}" -c "${projectPath}" '${claudeCommand}'`);
55
-
56
- // Split window horizontally and run shell in second pane
57
- await exec(`tmux -CC split-window -h -t "${sessionName}" -c "${projectPath}"`);
58
-
59
- // Set focus on claude pane (left pane)
60
- await exec(`tmux -CC select-pane -t "${sessionName}:0.0"`);
61
-
62
- return sessionName;
63
- }
64
-
65
- async attachToSession(sessionName) {
66
- // Check if we're already in a tmux session
67
- if (process.env.TMUX) {
68
- // If we're already in tmux, switch to the session
69
- await exec(`tmux -CC switch-client -t "${sessionName}"`);
70
- } else {
71
- // If not in tmux, attach to the session
72
- spawn('tmux', ['-CC', 'attach-session', '-t', sessionName], {
73
- stdio: 'inherit'
74
- });
75
- }
76
- }
77
-
78
- buildShellCommands(projectName, projectPath, claudeArgs = []) {
79
- const sessionName = this.getSessionName(projectName);
80
- const claudeCommand = claudeArgs.length > 0
81
- ? `claude ${claudeArgs.join(' ')}`
82
- : 'claude';
83
-
84
- return [
85
- `# Create tmux split session for ${projectName}`,
86
- `tmux -CC has-session -t "${sessionName}" 2>/dev/null && tmux -CC kill-session -t "${sessionName}"`,
87
- `tmux -CC new-session -d -s "${sessionName}" -c "${projectPath}" '${claudeCommand}'`,
88
- `tmux -CC split-window -h -t "${sessionName}" -c "${projectPath}"`,
89
- `tmux -CC select-pane -t "${sessionName}:0.0"`,
90
- process.env.TMUX
91
- ? `tmux -CC switch-client -t "${sessionName}"`
92
- : `tmux -CC attach-session -t "${sessionName}"`
93
- ];
94
- }
95
-
96
- async listWorkonSessions() {
97
- try {
98
- const { stdout } = await exec('tmux -CC list-sessions -F "#{session_name}"');
99
- return stdout.trim()
100
- .split('\n')
101
- .filter(session => session.startsWith(this.sessionPrefix))
102
- .map(session => session.replace(this.sessionPrefix, ''));
103
- } catch {
104
- return [];
105
- }
106
- }
107
- }
108
-
109
- module.exports = TmuxManager;
@@ -1,109 +0,0 @@
1
- const { spawn } = require('child_process');
2
- const { promisify } = require('util');
3
- const exec = promisify(require('child_process').exec);
4
-
5
- class TmuxManager {
6
- constructor() {
7
- this.sessionPrefix = 'workon-';
8
- }
9
-
10
- async isTmuxAvailable() {
11
- try {
12
- await exec('which tmux');
13
- return true;
14
- } catch {
15
- return false;
16
- }
17
- }
18
-
19
- async sessionExists(sessionName) {
20
- try {
21
- await exec(`tmux has-session -t "${sessionName}"`);
22
- return true;
23
- } catch {
24
- return false;
25
- }
26
- }
27
-
28
- getSessionName(projectName) {
29
- return `${this.sessionPrefix}${projectName}`;
30
- }
31
-
32
- async killSession(sessionName) {
33
- try {
34
- await exec(`tmux kill-session -t "${sessionName}"`);
35
- return true;
36
- } catch {
37
- return false;
38
- }
39
- }
40
-
41
- async createSplitSession(projectName, projectPath, claudeArgs = []) {
42
- const sessionName = this.getSessionName(projectName);
43
-
44
- // Kill existing session if it exists
45
- if (await this.sessionExists(sessionName)) {
46
- await this.killSession(sessionName);
47
- }
48
-
49
- const claudeCommand = claudeArgs.length > 0
50
- ? `claude ${claudeArgs.join(' ')}`
51
- : 'claude';
52
-
53
- // Create new tmux session with claude in the first pane
54
- await exec(`tmux new-session -d -s "${sessionName}" -c "${projectPath}" '${claudeCommand}'`);
55
-
56
- // Split window horizontally and run shell in second pane
57
- await exec(`tmux split-window -h -t "${sessionName}" -c "${projectPath}"`);
58
-
59
- // Set focus on claude pane (left pane)
60
- await exec(`tmux select-pane -t "${sessionName}:0.0"`);
61
-
62
- return sessionName;
63
- }
64
-
65
- async attachToSession(sessionName) {
66
- // Check if we're already in a tmux session
67
- if (process.env.TMUX) {
68
- // If we're already in tmux, switch to the session
69
- await exec(`tmux switch-client -t "${sessionName}"`);
70
- } else {
71
- // If not in tmux, attach to the session
72
- spawn('tmux', ['', 'attach-session', '-t', sessionName], {
73
- stdio: 'inherit'
74
- });
75
- }
76
- }
77
-
78
- buildShellCommands(projectName, projectPath, claudeArgs = []) {
79
- const sessionName = this.getSessionName(projectName);
80
- const claudeCommand = claudeArgs.length > 0
81
- ? `claude ${claudeArgs.join(' ')}`
82
- : 'claude';
83
-
84
- return [
85
- `# Create tmux split session for ${projectName}`,
86
- `tmux has-session -t "${sessionName}" 2>/dev/null && tmux kill-session -t "${sessionName}"`,
87
- `tmux new-session -d -s "${sessionName}" -c "${projectPath}" '${claudeCommand}'`,
88
- `tmux split-window -h -t "${sessionName}" -c "${projectPath}"`,
89
- `tmux select-pane -t "${sessionName}:0.0"`,
90
- process.env.TMUX
91
- ? `tmux switch-client -t "${sessionName}"`
92
- : `tmux attach-session -t "${sessionName}"`
93
- ];
94
- }
95
-
96
- async listWorkonSessions() {
97
- try {
98
- const { stdout } = await exec('tmux list-sessions -F "#{session_name}"');
99
- return stdout.trim()
100
- .split('\n')
101
- .filter(session => session.startsWith(this.sessionPrefix))
102
- .map(session => session.replace(this.sessionPrefix, ''));
103
- } catch {
104
- return [];
105
- }
106
- }
107
- }
108
-
109
- module.exports = TmuxManager;