blacs30 / bitwarden-alfred-workflow Goto Github PK
View Code? Open in Web Editor NEWThis project forked from stuartcryan/lastpass-alfred-workflow
Simple Bitwarden Workflow for Alfred
License: MIT License
This project forked from stuartcryan/lastpass-alfred-workflow
Simple Bitwarden Workflow for Alfred
License: MIT License
This way, I can act like this:
I just downloaded and set up this workflow, i log in and everything's fine, after trying to do absolutely ANYTHING it always says im logged out, i dont have any knowledge when it comes to programming this is just a cry for help.
As demonstrated below, anytime I try to use the tool it automatically jumps to the login option. I am already logged in (confirmed at the CLI). If I go ahead and try to login via Alfred anyway, it asks for my password (I enter it) and then it should be the 2fa dialog even though I don't have 2fa enabled.
Hi! Love the Alfred workflow. Just updated to release 2.2.0 and found my passwords aren't copied correctly.
runtime error: slice bounds out of range [:32] with capacity 0
is copied to my clipboard instead.
Thanks.
Recently, any changes I made to Bitwarden entries aren’t reflected.
I’ve tried both uninstalling and reinstalling this workflow and the bw
CLI, but to no avail.
It seems like it never tries to update my secrets anymore either, FWIW.
The README states that set2famethod
is optional to set. However, the default value does not allow logging into Bitwarden if 2fa (with auth app) is set.
I had to set set2famethod
to "0" which worked for me.
When selecting an item where there are multiple items for the same site I don't get the password in my clipboard – I get an error.
I'm using bitwarden-cli 1.3.0 and bitwarden-alfred-workflow 1.2.2.
Select an item where there are multiple logins for one site and press enter. I have blurred my usernames but they are all different.
This is copied to my clipboard
More than one result was found. Try getting a specific object by `id` instead. The following objects were found:
56d6067b-35de-4703-a766-a942008409a4
48c3a343-fdec-400d-a995-a942008409a4
e7c0f431-374a-47b0-886f-a942008409a5
cfab1cdc-c2f7-4efb-91b1-a95900dd06cb
98cf272d-5c08-4d14-bd44-a942008409a4
800b6ccc-8bc9-4739-941f-a942008409a5
c1f19717-f58d-4fcc-8ba2-a95f00bd191f
71a6d990-c85f-46d8-a85f-a942008409a4
89f26395-d54e-4fd7-a6e7-a942008409a4
013b666a-46e2-4746-8163-a942008409a5
800fe1cc-85d0-426d-9e34-a942008409a5
da57cb75-20c5-4597-80ca-a942008409a5
3dac775c-8242-43a4-8412-a942008409a5
a6351a17-c71c-490e-89f2-a942008409a5
1225e4da-c29c-4479-be78-a942008409a4
5e389ccb-19f8-4592-9898-a942008409a5
667bab13-8b68-4ffc-b870-a942008409a4
f12a1f07-b5cd-477a-9741-a942008409a5
0b89a0e9-d757-467d-8f6b-a942008409a5
7c528581-325e-4a41-9246-a942008409a5
0dc96acf-d6a4-407e-b386-a942008409a5
cf252dbf-7a5a-4d01-bffa-a942008409a5
60909c7e-23b5-4ef8-9570-a942008409a5
3b4d3fb7-d950-4e9d-b079-a942008409a5
1166afe4-e0bd-4cd3-b4f1-a942008409a5
e1ea5d23-8e6d-4bab-a06f-a942008409a5
ef7bfe90-ce6c-45f2-92ee-a942008409a5
fbe82418-930d-484d-a6ae-a942008409a5
037f7dc6-00fd-4514-b0ad-a942008409a5
e790dc82-49e1-41f5-b75f-a942008409a4
fc09ad54-ee21-4fe9-973f-a942008409a5
a6b1c6ba-60f8-46ea-b806-a942008409a4
f87a8891-58d7-4d88-a15e-a942008409a4
7496233f-97ec-42f3-a599-a942008409a5
215352eb-f74d-4c5a-aa5f-a942008409a5
357e7ec7-91f1-4db8-9b75-a942008409a5
1c6043b7-42ce-4a25-9708-a942008409a5
9a7f6786-b326-47a3-b569-a942008409a5
de0daddb-c002-4b04-ba56-a942008409a5
80d6cc4a-2231-4a59-8b1f-a942008409a5
a007c866-0d98-4996-bfe7-a942008409a5
72ff4287-9108-4072-81fd-a942008409a4
f6130bda-9fe1-4135-bcdf-a942008409a5
db9890a7-a4bb-4936-b5de-a942008409a5
42d9ae52-7fbf-4d4c-aa0d-a942008409a4
5815f5a6-9b06-4f88-b4ab-a942008409a5
998de16d-a5c4-4dfc-af31-a942008409a4
c53013d8-f699-4538-8978-a942008409a5
8528bbd9-c589-4171-8356-a942008409a5
7685481d-86d7-43d2-b38f-a942008409a5
afe27519-563e-47c7-a0c7-a942008409a5
befe90d5-30ca-459e-9dac-a942008409a5
df4dfcd7-48c1-4b1d-b543-a942008409a4
741ae853-c19d-4189-8119-a942008409a4
8b77b39d-3005-483e-b2e8-a942008409a5
f2641646-c12d-4d57-9e97-a942008409a5
182e7949-9fea-49fb-9b8a-a942008409a5
3e408f99-2143-4ce3-9a71-a942008409a4
819254c8-35a4-45d8-a9da-a942008409a5
b89a3130-b5d7-4b95-b0a9-a942008409a5
74e88442-aa45-4762-8da0-a942008409a5
89956967-45bc-4288-8286-a942008409a5
ed46284e-8c7d-4f36-9d5f-a942008409a5
6df44ae0-11fa-4695-873e-a942008409a5
aceae15c-4219-42af-ad16-a942008409a5
b77902ba-0837-49d2-8bea-a942008409a5
199568ea-6243-4f67-b9bd-a942008409a5
8433d059-9637-4f9b-bdb7-a96700c9deec
This workflow throws errors for me now, and I suspect the only problem is that it references to Alfred 3
a bunch of places.
I also suspect a simple search and replace with Alfred 4 will solve the problems.
I might get a PR up on this later if I have the time.
For 2 or 3 days, i'm unable to login to my account. (connected to a specific server)
I'm using Alfred 4
It seems not store typed password.
No error message, nothing happens, either when I type a good or bad password or MFA code.
i.e. If I try to change server URL, it does not store it in info.plist
file => i have to set it directly in info.plist file manually.
Hi - would it be possible to add biometric unlock (Touch ID) with a fallback to PIN, similar to how Bitwarden mobile apps work? It can then require master password after new OS logins.
To give a better first impression of the workflow add a gif which shows some of the workflow functionality to the README.
Place the gif into the icons folder or better create a new, an assets folder, which needs to be copied during the actions into the workflow folder for packaging the Alfred workflow.
The catalina warning png should be moved also into the new assets folder .
Hi there!
Perhaps I'm mistaking and it is actually persisted to disk. What I would like is if it's possible to persist the items on disk so that I wouldn't have to sync every time. My passwords don't change that much so that would be perfect for me.
I can imagine there are other users that would find this useful as well :), most likely you'll use 20% of the passwords 80% of the time and those are fine if they aren't as up-to-date since they wouldn't change that much.
I would be open to creating a PR for this too if you could point me in the right direction.
Facing this error on Alfred v4.1[1167], latest v2 release of the workflow (as of Aug. 12).
.bw
(to search vault) automatically fills it to .bwauth login
, as if I'm not logged in.Logging out doesn't fix it, since I'm able to log in, but unable to search anything and am instead prompted to log in again (step 2).
I've been able to successfully log in and use it on another Mac, so not sure how to replicate this error.
Hi,
I had some troubles getting the workflow running. Seems that because I have installed the BW CLI via NPM (and NVM), that the workflow cannot find it.
I have tinkered with the code a bit;
def get_bw_exec():
cmd = "which bw"
proc = Popen(cmd.split(), env=my_env, stdout=PIPE, stderr=PIPE)
bw_exec, err = proc.communicate()
if "not found" in err.decode('utf8').strip():
print(json.dumps(error_result(type="install")))
exit(2)
return bw_exec
This seems to fix it really quickly. I also noticed some other hard references to /usr/local/bin/bw
.
Not sure if those are used. My best bet would be that in those cases it would also fail to work.
Python is not really my game, so I am unsure to put up a pull-request with some changes.
Would really appreciate for this to be fixed.
Installed bitwarden-cli via HomeBrew.
Downloaded and imported .alfred file from this repo.
Trying to set email but can't upon writing bwsetemail <email>
can't press 'Enter' or confirm in any way. Doesn't happen for other functions.
Thanks in advance!
Not sure what's causing this but since updating to 2.2.x I'm getting this error when trying to copy a password
runtime error: slice bounds out of range [:32] with capacity 0
I tried deleting my cache and refreshing, but no go...
Hi there,
First off: A big thank you for the workflow. I can only imagine how much work this must have been.
I do have two ideas which you could consider if they are of any use to you as well:
Thank you anyhow for your hard work on this. I enjoy using it and it already saved me tons of time.
Best,
Pascal
Hi blacs30, thanks for your awesome job. I run into error when login and the error message is:
Your account could not be logged in for [email protected] Error Message: /bin/bash: /Users/i308587/Library/Application: No such file or directory
/bin/bash: /Users/i308587/Library/Application: No such file or directory
error: option `--code <code>' argument missing
.
I use https://bitwarden.com as server.
Do you have any idea about it?
Hi, would it be possible to lock the bitwarden vault after a configurable timeout. I do not really like the token being in memory basically forever, at least if I don't lock on demand.
Running Alfred 4, allows login and pulls information from Bitwarden and returns results in Alfred window. Hitting enter after searching should copy password to clipboard but does nothing, no status message displayed from Alfred, nothing copied to clipboard.
Hitting shift and attempting to copy username to clipboard displays Alfred notification that the username has been copied, does not show up in clipboard.
Every now and then when I search for an item or try to do a sync, I get an 'ERROR: not logged in' notification. I login in using password and second factor - nothing happens.
Until I realised - when performing a search - that the vault was locked. All I needed to do was a bwunlock.
Perhaps the ERROR not logged in message could be a little more helpful, if the vault is simply locked?
Latest workflow package update breaks the workflow for Alfred version 3 (and probably earlier). Alfred complains of an incompatible workflow version and prompts user to upgrade to Alfred v. 4.
Hey @blacs30 👋
I played around with the auth tokens and figured out a way to make them play nice with each other. I only tested it minimally but I think this could be useful... see → luckman212/bitwarden-cli-helpers
With these helper functions in .bash_profile
(or .zshrc
if that's your thing) you can pass auth tokens back and forth between your Workflow and the bw
CLI without invalidating the other session key.
Let me know what you think. Hopefully we can close up this issue and #49 if everything's happy. Things have been working pretty well for me using 2.2.1-test5.
Originally posted by @luckman212 in #53 (comment)
I downloaded the latest version of this workflow and this error occurred when I first tried to run the command. I made sure to install the CLI and add Alfred to the list of security exceptions. I'm on Alfred version 4.1 and macOS Catalina 10.15.6
[17:57:20.894] Logging Stopped.
[17:58:15.175] Logging Started...
[17:58:21.024] Bitwarden v2[Script Filter] Queuing argument '(null)'
[17:58:21.213] Bitwarden v2[Script Filter] Script with argv '(null)' finished
[17:58:21.215] STDERR: Bitwarden v2[Script Filter] 17:58:21 config.go:73: BW DataPath /Users/gli/Library/Application Support/Bitwarden CLI/data.json
17:58:21 config.go:86: Got existing Bitwarden CLI data
🍺
17:58:21 workflow.go:328: -------- Bitwarden v2/2.0.4 (AwGo/0.26.2) --------
17:58:21 main.go:161: &main.options{Search:false, Config:false, SetConfigs:false, Auth:false, Sfa:false, Lock:false, Icons:false, Folder:false, Unlock:false, Login:false, Logout:false, Sync:false, Open:false, GetItem:false, Force:false, Totp:false, Last:false, Cache:false, Background:false, Id:"", Query:"", Previous:"", Attachment:"", Output:""}
17:58:21 main.go:163: args=[]string{} => []string{}
17:58:21 main.go:165: (main.config) {
AutoFetchIconCacheAge: (int) 1440,
AutoFetchIconMaxCacheAge: (time.Duration) 24h0m0s,
BwconfKeyword: (string) "",
BwauthKeyword: (string) "",
BwKeyword: (string) "",
BwExec: (string) (len=2) "bw",
CacheAge: (int) 1440,
Email: (string) "",
EmptyDetailResults: (bool) false,
IconCacheAge: (int) 43200,
IconCacheEnabled: (bool) true,
IconMaxCacheAge: (time.Duration) 720h0m0s,
MaxResults: (int) 1000,
MaxCacheAge: (time.Duration) 24h0m0s,
Mod1: (string) (len=3) "alt",
Mod2: (string) (len=5) "shift",
Mod3: (string) (len=4) "ctrl",
Mod4: (string) (len=7) "cmd,opt",
OutputFolder: (string) (len=21) "/Users/gli/Downloads/",
ReorderingDisabled: (bool) true,
Server: (string) (len=21) "https://bitwarden.com",
Sfa: (bool) true,
SfaMode: (int) 0,
SyncCacheAge: (int) 1440,
SyncMaxCacheAge: (time.Duration) 24h0m0s
}
17:58:21 feedback.go:482: Sent 1 result(s) to Alfred
17:58:21 workflow.go:405: ------------------ 148.306756ms ------------------
[17:58:21.218] Bitwarden v2[Script Filter] {
"variables": {
"AW_SESSION_ID": "2ZWLMTPLVE65Y6EXZS8Z9DDF"
},
"items": [
{
"title": "Error the Bitwarden command \"bw\" wasn't found.",
"subtitle": "Set \"BW_EXEC\" or \"PATH\" in the Workflow. Press ↩ or ⇥ for more info.",
"arg": "README.html",
"valid": true,
"icon": {
"path": "icons/warning.png"
},
"variables": {
"action": "-open"
}
}
]
}
Hello @blacs30,
Do you think it would be possible to add an additional option/command to manually trigger the syncing of the secrets?
I often find myself adding new passwords in bitwarden which I then need shortly after and throughout the day. I know I can lower the cache time for the syncing, but this results in too much syncing on days that I do not add any passwords.
Cheers
Hi,
Awesome that you updated to make it work with all bw installs!
However I am having this weird issue, even after complete removal and reinstallation. Where I cannot unlock, but I am logged in.
This is some of the logs;
[09:01:00.936] Bitwarden v2[Script Filter] Processing complete
[09:01:00.939] Bitwarden v2[Script Filter] Passing output '-background' to Conditional
[09:01:00.940] Bitwarden v2[Conditional] Processing complete
[09:01:00.940] Bitwarden v2[Conditional] Passing output '-background' to Arg and Vars
[09:01:00.941] Bitwarden v2[Arg and Vars] Processing complete
[09:01:00.942] Bitwarden v2[Arg and Vars] Passing output 'Syncing Bitwarden secrets cache…' to Post Notification
[09:01:00.964] Bitwarden v2[Conditional] Passing output '-background' to Run Script
[09:01:02.469] Bitwarden v2[Script Filter] Queuing argument 'unlock'
[09:01:02.497] STDERR: Bitwarden v2[Run Script] 🍺
09:01:00 workflow.go:328: -------- Bitwarden v2/2.0.0 (AwGo/0.26.2) --------
09:01:00 main.go:160: &main.options{Search:false, Config:false, SetConfigs:false, Auth:false, Sfa:false, Lock:false, Icons:false, Folder:false, Unlock:false, Login:false, Logout:false, Sync:true, Open:false, GetItem:false, Force:true, Totp:false, Last:false, Cache:false, Background:true, Id:"", Query:"", Previous:"", Attachment:"", Output:""}
09:01:00 main.go:162: args=[]string{"-sync", "-force", "-background"} => []string{}
09:01:00 main.go:163: Workflow configs => [email: [email protected] 2FA enabled: true 2FA Mode: Authenticator-app Server: https://bitwarden.com]
09:01:00 bitwarden.go:26: Clearing items cache.
09:01:02 utils.go:22: [ERROR] ==> [Vault is locked.]
09:01:02 utils.go:22: [ERROR] ==> Exit code 1. Not logged in. Need to login first. Err: Vault is locked.
09:01:02 utils.go:22: [ERROR] ==> Not logged in. Need to login first. Error:
Vault is locked.
09:01:02 utils.go:87: Search called with argument .bwauth unlock
09:01:02 workflow.go:405: ------------------ 1.514220232s ------------------
[09:01:02.499] Bitwarden v2[Run Script] Processing complete
[09:01:02.499] Bitwarden v2[Run Script] Passing output 'Not unlocked. Need to unlock first.
' to Post Notification
[09:01:02.500] Bitwarden v2[Script Filter] Script with argv 'unlock' finished
[09:01:02.501] STDERR: Bitwarden v2[Script Filter] 🍺
09:01:02 workflow.go:328: -------- Bitwarden v2/2.0.0 (AwGo/0.26.2) --------
09:01:02 main.go:160: &main.options{Search:false, Config:false, SetConfigs:false, Auth:true, Sfa:false, Lock:false, Icons:false, Folder:false, Unlock:false, Login:false, Logout:false, Sync:false, Open:false, GetItem:false, Force:false, Totp:false, Last:false, Cache:false, Background:false, Id:"", Query:"unlock", Previous:"", Attachment:"", Output:""}
09:01:02 main.go:162: args=[]string{"-auth", "--", "unlock"} => []string{"unlock"}
09:01:02 main.go:163: Workflow configs => [email: [email protected] 2FA enabled: true 2FA Mode: Authenticator-app Server: https://bitwarden.com]
09:01:02 cli.go:293: filtering auth config "unlock" ...
09:01:02 feedback.go:482: Sent 1 result(s) to Alfred
09:01:02 workflow.go:405: ------------------- 5.364639ms -------------------
[09:01:02.503] Bitwarden v2[Script Filter] {
"variables": {
"AW_SESSION_ID": "XXXXX"
},
"items": [
{
"title": "Unlock",
"subtitle": "Unlock Bitwarden",
"uid": "unlock",
"valid": true,
"icon": {
"path": "icons/on.png"
},
"variables": {
"action": "-unlock"
}
}
]
}
[09:01:05.057] Bitwarden v2[Script Filter] Processing complete
[09:01:05.061] Bitwarden v2[Script Filter] Passing output '' to Conditional
[09:01:05.062] Bitwarden v2[Conditional] Processing complete
[09:01:05.063] Bitwarden v2[Conditional] Passing output '' to Arg and Vars
[09:01:05.064] Bitwarden v2[Arg and Vars] Processing complete
[09:01:05.065] Bitwarden v2[Arg and Vars] Passing output '' to Post Notification
[09:01:05.066] Bitwarden v2[Conditional] Passing output '' to Run Script
[09:01:06.438] ERROR: Bitwarden v2[Run Script] 🍺
09:01:05 workflow.go:328: -------- Bitwarden v2/2.0.0 (AwGo/0.26.2) --------
09:01:05 main.go:160: &main.options{Search:false, Config:false, SetConfigs:false, Auth:false, Sfa:false, Lock:false, Icons:false, Folder:false, Unlock:true, Login:false, Logout:false, Sync:false, Open:false, GetItem:false, Force:false, Totp:false, Last:false, Cache:false, Background:false, Id:"", Query:"", Previous:"", Attachment:"", Output:""}
09:01:05 main.go:162: args=[]string{"-unlock"} => []string{}
09:01:05 main.go:163: Workflow configs => [email: [email protected] 2FA enabled: true 2FA Mode: Authenticator-app Server: https://bitwarden.com]
09:01:06 utils.go:22: [ERROR] ==> [Vault is locked.]
09:01:06 utils.go:22: [ERROR] ==> Exit code 1. Not logged in. Need to login first. Err: Vault is locked.
09:01:06 utils.go:22: [ERROR] ==> Not logged in. Need to login first. Error:
Vault is locked.
09:01:06 workflow.go:376: [ERROR] Unexpected error. Exit code -1.
So this says not logged in. But when using the .bwauth command, it tells me I am logged in. Not sure what to make of this.
Is there some other cache I can clear or something? Tried all the available options in the workflow. And I removed and reinstalled the workflow several times completely.
My BW cli is installed via npm, but the path is correctly set in the workflow.
Autolock isn't working for me. I've given LOCK_TIMEOUT
a value of 60, and successfully installed autolock with the keyword.
The ability to customize modified keys in the re-written workflow is wonderful; but I have been unable to customize the command executed without a modifier key. I had made some modifications to the previous version that allowed me to open the URL from a selected Bitwarden item without using a modifier key (thus changing the default behavior and making the experience more similar to Alfred's 1password integration). I don't see an easy way to make a similar modification to this version, so I wonder whether anyone else would find it convenient to open URLs without having to use a modifier key.
And thanks, Claas, for a faster, even more feature-packed version of software that was already very useful in previous versions!
When searching in the Bitwarden Browser extension or the Web Vault, they use wildcard searches so i can look for any word within the title, url or username of the specific vault item.
Unfortunately, the search within this workflow is very specific and doesnt find an item if i look for app.com, but the actual url and title of the item are account.app.com.
Maybe we could change that.
Not an issue, just wanted to open a discussion...
I got a little frustrated when calling up this workflow and waiting for it to sync when I needed a password right away. I know I am being impatient, but I thought it would be a better experience if there was a way to have this refresh automatically in the background.
I created a solution, which anyone can try: bw-cache-update
It's pretty simple to install (follow the README) but I think it would be better if this was made "native" by doing the following:
SYNC_CACHE_AGE
?)I am open to helping with this / submitting a PR but I wanted to get opinions first on whether this was a good idea or if anyone sees any problems with the implementation. Also if you encounter any problems please open an issue.
Big thank you as always to @blacs30 for this amazing workflow! 👍
Search Bitwarden
script filterExpected: Can do the Show More
action
Actual: When trying to Show More
, nothing happens and the Alfred search bar disappears
Hi,
I'd love to be able to generate a password through this workflow, perhaps with .bw genpwd
with options to select the complexity of the password.
Not able to login through the extension as getting this error. Tried login using the cli, was able to login but alfred extensions can't fetch passwords in that case.
Using latest version of alfred, bitwarden extension as well as cli.
[18:51:27.765] Bitwarden v2[Script Filter] Processing complete
[18:51:27.767] Bitwarden v2[Script Filter] Passing output '(
login,
"[email protected]",
0,
"Authenticator-app"
)' to Conditional
[18:51:27.770] Bitwarden v2[Conditional] Processing complete
[18:51:27.771] Bitwarden v2[Conditional] Passing output '(
login,
"[email protected]",
0,
"Authenticator-app"
)' to Run Script
[18:51:39.993] Bitwarden v2[Run Script] Processing complete
[18:51:39.994] Bitwarden v2[Run Script] Passing output 'Error: Email address is invalid.
' to Post Notification
VERSIONS
bw
CLI 1.11.0 cli installed from npmEXAMPLE
I have the following 3 items in my vault:
Searching using 'bw mic brav'
will return ALL 3 Microsoft- items. This is not ideal. Conversely, searching for 'brav micro'
returns both Microsoft Bravo AND Bravo Pizza. Also not what we want. The 2nd search term is simply ignored.
I looked at the debug output as well as the source code, and it looks like awgo accepts the args correctly, but only the first arg is passed to the bw
cli for searching.
I realize now that this seems to be a limitation of the bw cli itself, so I opened up issue #163 over at bitwarden/cli. Until (or if?) that's sorted, I wonder if it would be better to simply dump ALL results from bw cli into the cache and then use Alfred's Word Matching algorithm to handle the matching. That is more robust and allows for multiple search terms as well as arbitrary ordering of the keywords.
Any thoughts?
Hi @blacs30
Related to #49 (comment), I was hoping you could give a little info about the differences between these 3 parameters for bitwarden-alfred-workflow
:
-sync
-cache
-icons
I want to make sure the background refresh is optimized and not wasting time or bandwidth with unnecessary calls. Right now it passes -sync -force
parameters which I think is right for this situation (not sure about -force
tbh).
But I wonder what -cache
does? I assume icons are refreshed when running -sync
(but maybe not) Do we need to call that separately in order to keep the icons updated?
I'm happy that you added the auto-lock and auto-sync features. Auto-lock isn't working for me, however. The launchagent successfully installed, and I have set LOCK_TIMEOUT
to 15, but the workflow stays logged in all day. Any ideas on how to troubleshoot?
When the vault is locked, it would be nice if the user could unlock it by hitting return
, instead of entering bwunlock
again.
In v2.3.4 the keywords have changed, but the README still references the old keywords.
When I unlock bw from a command terminal, it seems to lock the vault for the workflow, and when I unlock in the workflow, it locks the command line.
Is there any way to use both without interfering with each other?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.