-
-
Notifications
You must be signed in to change notification settings - Fork 355
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CLI support #371
Comments
Hi @v-braun! Thanks for sharing this feedback! I'm not sure i get a clear picture of what that CLI would look like. Could you please specify it more? Like example commands you would need to build your workflow, and what they output, in more details? Currently there is none of that. The app is only usable through its GUI |
Hey, what I imagine is a CLI interface to query Windows, Apps and Spaces. This interface would be cool: # list all windows from all spaces
# options:
# -o / --output (table or json): specify output format
# -s / --space: filter by space
# -d / --display: filter by display
# -t : filter by title (regex??, fuzzysearch??)
#example:
alt-tab window list -o json
# output:
[{
"id": "unique window id",
"appId": "process id of the app",
"title": "window title",
"size": {
"height": 100,
"width": 100
}
}]
# activate a window
#example:
alt-tab window activate <<window id>>
Other subcommands could be:
|
That's interesting! I have a few questions:
Regarding filtering, you wrote:
I wonder if filtering wouldn't be better done by the user. Like doing regex search in titles or fuzzysearch could be done by piping Do you care about the windows order? Should it be ordered by latest-used like in the graphical AltTab? I'm wondering if this binary cli you want would be best as part of AltTab.app, or as a standalone binary. Some points to consider:
Another point is that AltTab builds an understanding of windows by listening to changes in apps, windows, user actions, permissions, etc. This means that cli you mention would only be a client, probably to an XPC server. Basically we would split the "system model" as an XPC server, and have a CLI frontend and the current GUI frontend query that backend. Finally, I'm quite curious, could you describe the Alfred Workflow you are trying to build? I'm curious as to what you will do in Alfred that the current UI doesn't do for you, or couldn't be improved to do |
a lot of questions, but looks like you like the idea wich is great 😀 The commands that I proposed are more general. For my specific workflow I need only a list of windows (id, title) and a subcommand to activate a window (focus). The workflow that I want to build is:
There is a already such a workflow wich is very slow and ... there we come to the XPC server. So let me try to recap your questions:
Youre right, forgot the app
Right again, I thought that could be optional and maybe could have a better performance if the cli is doing it already
I think a server is a great idea, a cli client that can be used from other apps would be very cool to automate things (like automatically rearange windows for coding/design tasks, etc.)
YEP! a XPC server and a client would be cool
type: win {query} will return a list of windows that match the query, user can select a window and it get focused. |
Yes, I tried Contexts for a while but wanted to have it integrated in alfred |
Interesting article about all the IPC solutions on macOS. A bit old but the author is also Alamofire's author and their skill shows in the writting. |
I was curious if supporting the AppleScript commands would be sufficient here. I don't really understand how the objects and interfaces are defined, but maybe it's a minimal object export of some kind? |
@ayroblu this sounds like equal or more work than a custom cli. The reason this ticket represents a large amount of work is because it requires a new architecture. Today, the app is a macOS app (i.e. a For this ticket, we would need to isolate the core of the app which processes these events, and keeps track of windows and other things. Then we would run this as an XPC process, in the background. Then we would write a new "client" cli app, which you can call from the cli. That app would be very short lived, and would be invoked with something like Writing the new cli is probably easy and fun. Refactoring the current app to act as a background stateful server, is a lot of work. Also there are performance considerations to take into account with the new design. As well as maintenance considerations (i.e. another repo for the cli? How to deal with changes in one or the other repo? Backward compatibility? Forward compatibility? etc) |
Okay, I'm not really sure how objects get exported for scripting by macOS, it did feel like less work than doing the rearchitecture, but I wouldn't know 🤷♂️ |
I don't know enough about this. I've never used it. If someone wants to explain and share a work plan, I'm interested. |
Just as context, how Reminders works: function run(args) {
var Reminders = Application("Reminders");
lists = Reminders.lists;
for (var i = 0; i < lists.length; ++i) {
console.log(lists[i].name());
}
} Then run Sadly this is extremely slow, like 4 seconds on my mac so I don't think this is a great solution |
Oh sorry for the repeated messages, I was thinking, the easiest way might actually just to persist it on disk somewhere? Just export a structured json when the underlying data changes? It might be slightly expensive, but not a crazy amount so |
That's a very interesting idea. We would need to define what's stored in more details, but probably a v1 of that feature could export windows with their details like which Space it's on, which screen it's on, the order of recently-used-ness, etc. A worry is the performance hit it could add. It would probably be an opt-in preference anyway, so that's probably fine. Another question is where that file would be stored. I think most places from Catalina onwards require a System permission to be granted first, which I can tell you from adding permission listening code before, is way harder to deal with than it should be. I would love to give that a try in a local build, but I think other issues are more important, and I'm basically overwhelmed with the amount of issues at the moment. I even have some PRs open I need to deal with. @ayroblu @v-braun are you interested in contributing perhaps? It's a nice scope for a first PR on the project |
After having played with the code, it's actually pretty easy to (theoretically) expose a port to connect to with an API which allows you to do RPC calls. I actually don't think there's much refactoring as such to do, it's all global static variables anyways. My diff is good enough for the alfred use case, but I think for a proper solution, rpc / http would be pretty straightforward. |
Technical infra to communicate between processes is fine I'm sure. As I've said, the hard part is to re-architect the app from a all-in-one, performant monolithic process, into a client + a background server. People who use the cli probably don't want the normal keyboard/mouse/trackpad event handling to happen. So we can't just add a cli client on top of the existing app. We have to have an architecture like this:
Both of them would communicate with a background server like We would probably wrap both experiences in 2 packaging:
It's that separation that creating lots of work. It's a whole new approach with lots of added complexities. It would mean different repositories, releasing the cli package in addition to the .app of today. It would mean 2 distributions to maintain, update, develop. How would updating the cli look like? Another homebrew target maybe only? Lots of questions, lots of work. It's a whole thing |
Just to be clear, theoretically you could do that, but I think we'd get pretty far without bothering with most of that.
Personally I don't think this is a big deal, I think simply having the control to list windows and perform actions from shell while keeping all the existing functionality is perfectly fine If you really want to create a cli client (I don't think it's necessary, just exposing an API is more than enough I think), monorepos are great, so it could just be another folder. Personally the lowest effort way is to use some third party (atleast it looks pretty hardcore to roll your own) server, stick a few routes, listen on a port based on a preference, publish an API schema of some kind and be done with it |
I estimate that effort to be multiple months of work. I may be wrong though. PR welcome ;p |
I just had the same Idea that the original author here (wanted to use this as a foundation for an Alfred workflow). For other people coming here with the same idea - I've found https://github.com/mandrigin/AlfredSwitchWindows which is similar but has a bunch of issues and not currently supported 🙁. It's unfortunate that it seems to require a lot of work. As a hacky approach that might work here for the use-case of Alfred WF - would it be possible to, if a certain setting enabled, regularly (every second/a few seconds) dump the "state of the world" (all the windows in the LRU order) into a file? The Alfred WF (and other integrating apps) can then read the file and use that info. @lwouis what do you think? |
Adding CLI support will unlock the possibility to use Aldred to switch windows :-). Please expose the same control over CLI. |
|
I looked into this today. ServerI think the main app, as it is, would be a good daemon for the CLI client. It means we leverage the existing, instead of building something new. It's also convenient that this daemon would have a nice UI, if the users want it. It already has everything from launch-at-login, to check permissions and prompting to grant them if needed, etc. ClientI'm hesitating about the CLI. I think it could be the app executable itself. The upside is again, nothing new to add, just leveraging the existing system. The downside could be that it's slow to query since the executable is a bit big. I think I'll play with it to see. Communication channelHere are the options I can see:
|
Ok I got a POC running with CFMessagePort. Now the tough part is designing the interface of what the commands look like, and what the results look like. There was drafts above, but I think they need refinement. The use case I think we could start with are:
The biggest hurdle, I think, is the format to output window in. It really depends on which tools are going to consume the output. If anyone wants to discuss this, now is the time 👍 Thank you |
@ayroblu I realize that my PoC is exactly what you came up with previously. Sorry about this. I think I didn't understand back then what your approach was. I was also probably busy fixing important part of the app. Everyone in this thread wants to build an Alfred workflow, I think. What's the best format to output? And what is the minimum viable set of commands for such a workflow? I'm not an Alfred user myself, so I'm not sure. Thank you |
Oh hey no worries. I have since learnt about hammerspoon, which pretty much exposes the interfaces that are desirable. |
Thank you @ayroblu So, you have an integrated solution you're happy with, using a fork. And if you wanted a programmatic flow, you'd use hammerspoon. Is there anyone else in this thread still wanting a CLI for AltTab? Thank you |
Here's a local build with 2 commands implemented: Any feedback is welcome 👍 I think it'll ship it in the next release |
list and select is a solid foundation to be able to build the Alfred workflow, ideally list would accept the query/filter parameter |
First: thanks for this app!
I tried HyperSwitch for long time but it was so annoying that the order of windows (most recent window) is based on the active space, if you switch windows between spaces the order is messed up (maybe something that you can to the compare table on your website).
No my question:
I wanted to built a Alfred Workflow to list and search within windows, this app would be a good starting point to get all windows if it would have a CLI.
Is there something like this?
The text was updated successfully, but these errors were encountered: